Closed user4815162342 closed 2 years ago
The interface of minijinja requires ahead of time loading. Changing this would remove some of the useful properties of how the environment currently functions. You can load manually into the source the things you want to load. The source already only loads things that have the right extension.
Okay, I understand.
To be clear, the reason I would like to see this is that right now, my users have to specify the include files twice: once in the template file and once in the parameters for the tool I'm building. Although the source object load_from_path can make this easier, it doesn't load files outside of that path (if the included file is in a sibling directory, for example), and it loads every file whether that template is needed or not, which seems like overkill to me.
All I really need is some access to the internal structure of the compiled template that lets me review the include and extend commands and their parameters. I can then load the files myself before rendering. I assume this wouldn't work if the filenames are loaded from a non-literal expression, but the users would be able to accept that limitation.
For now, I can parse them out with a regular expression.
@user4815162342 I don't think your users need to specify the file twice for as long as they use consistent file extensions. It would also be possible to add a function to extract all references like you can do with Jinja2's find_referenced_templates
.
A find_reference_templates
function is exactly what I was thinking of in my last comment.
The problem with this is that since include directives can include variables, you can't canonically resolve all includes without fully rendering the template. @mitsuhiko Would it be possible to "trap" include directives, such that unresolved includes execute a callback of some sort? I'm struggling with dynamic include directives, which appear impossible to support with minijinja.
@bkeroack I feel like the main question I have is why you cannot load all templates at once. I'm sure there is a reason but I want to understand the use case a bit. Trapping would be possible, but the challenges you're running into is that it's unclear what you do with that information.
This is now possible:
fn create_env() -> Environment<'static> {
let mut env = Environment::new();
env.set_source(Source::with_loader(|name| {
if name == "layout.html" {
Ok(Some("...".into()))
} else {
Ok(None)
}
}));
env
}
@mitsuhiko That works perfectly! Thank you!
Would it be possible to add some sort of hook to allow my code to resolve the include files when they are needed, instead of adding them in ahead of time?
Right now, as far as I can tell, I have to know the names of all the files that are needed before-hand and add them to the environment, which requires my users to have to keep track of these and pass a list to me. I do see the Source struct which allows loading all templates in a path, but then the code would load all sorts of files that it doesn't need to load.