Comments (3)
First off, I apologize for completely missing this issue; github occasionally drops email notifications and I rely on them completely
One solution is to use the html_box!
macro, this will Box
the resulting template so you should always get the same type out.
I wrote a template!
macro for creating named templates for cases like this (where you want something with a fixed type) however, it currently borrows it's the captured variables so that won't help here either.
Personally, I recommend inverting this and not using map/fold:
fn list_directories_recursive(&self, path: &Path) -> Option<String> {
let entries = path.read_dir().unwrap()
.filter_map(|de| de.ok()) // remove invalid paths
.map(|de| de.path()) // DirectoryEntry -> Path
.filter(|p| self.visible_path(p)) // remove invisible paths
.map(|path| {
let (href, name) = match (
path.as_os_str().to_str(),
path.file_name().and_then(|f|f.to_str())
) {
(Some(href), Some(name)) => {
let href = href.replacen(".", "", 1); // ./thing -> /thing
let name = name.replacen("/", "", 1); // ./dir/thing -> thing
(href, name)
}
_ => return None,
};
return Some((path, href, name))
})
.filter_map(|s| s);
let listings = (html! {
@ for (path, href, name) in entries {
@ if self.list_recursively && path.is_dir() {
// No need to check if None. None renders as ""
: self.list_directories_recursive(&path)
}
tr {
td {
a(href=&href) : name
}
}
}
}).into_string().unwrap();
if listings.len() != 0 {
Some(listings)
} else {
None
}
}
The other way to do this is an embedded closure:
fn list_directories_recursive(&self, path: &Path) -> Option<String> {
let listings = (html! {
|tmpl| path.read_dir().unwrap()
.filter_map(|de| de.ok()) // remove invalid paths
.map(|de| de.path()) // DirectoryEntry -> Path
.filter(|p| self.visible_path(p)) // remove invisible paths
.map(|path| {
let (href, name) = match (
path.as_os_str().to_str(),
path.file_name().and_then(|f|f.to_str())
) {
(Some(href), Some(name)) => {
let href = href.replacen(".", "", 1); // ./thing -> /thing
let name = name.replacen("/", "", 1); // ./dir/thing -> thing
(href, name)
}
_ => return None,
};
return Some((path, href, name))
})
.filter_map(|s| s)
.for_each(|(path, href, name)| &mut *tmpl << html! {
@ if self.list_recursively && path.is_dir() {
// No need to check if None. None renders as ""
: self.list_directories_recursive(&path)
}
tr {
td {
a(href=&href) : name
}
}
})
}).into_string().unwrap();
if listings.len() != 0 {
Some(listings)
} else {
None
}
}
but I prefer the first way.
from horrorshow-rs.
Actually, you could also use the following to avoid turning any intermediate templates into strings:
template! {
// Where Context is the "Self" type.
ListDirectories(ctx: &Context, path: &Path) {
|tmpl| path.read_dir().unwrap()
.filter_map(|de| de.ok()) // remove invalid paths
.map(|de| de.path()) // DirectoryEntry -> Path
.filter(|p| ctx.visible_path(p)) // remove invisible paths
.map(|path| {
let (href, name) = match (
path.as_os_str().to_str(),
path.file_name().and_then(|f|f.to_str())
) {
(Some(href), Some(name)) => {
let href = href.replacen(".", "", 1); // ./thing -> /thing
let name = name.replacen("/", "", 1); // ./dir/thing -> thing
(href, name)
}
_ => return None,
};
return Some((path, href, name))
})
.filter_map(|s| s)
.for_each(|(path, href, name)| &mut *tmpl << html! {
@ if ctx.list_recursively && path.is_dir() {
: ListDirectories::new(ctx, &path)
}
tr {
td {
a(href=&href) : name
}
}
})
}
}
You can use this by, e.g., calling ListDirectories::new(ctx, some_path).into_string().unwrap()
.
from horrorshow-rs.
Closing as there's really nothing I can do about this.
from horrorshow-rs.
Related Issues (20)
- Missing Fragment Specifier Warning HOT 2
- Context-aware escaping HOT 3
- Indenting / nesting content macro HOT 7
- error: no rules expected the token `tmpl` HOT 6
- Nice error messages
- improving example HOT 17
- no std support? + specify Cargo.toml in README HOT 2
- Infinite recursion with RenderOnce::size_hint HOT 1
- escaping converts foreign letters to < > HOT 1
- Add #[macro_export(local_inner_macros)] attribute to support Rust 2018 HOT 1
- Callbacks/passing values from the DOM back into Rust? HOT 2
- Empty div not closing properly HOT 4
- Indenting/reformatting in IntelliJ doesn't fix indentation HOT 2
- HTML boolean attribute support? HOT 1
- How to make a layout that accepts content? HOT 3
- Possibility for custom tags with hyphenated names? HOT 1
- Implement template into ActixWeb HOT 2
- wishlist: Explore applicability to DOM creation HOT 3
- Feature request: render to `Bytes` HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from horrorshow-rs.