-
Notifications
You must be signed in to change notification settings - Fork 641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extensionless extends, includes and imports #475
Comments
Expresses imposes a weird relationship with a templating engine, as it wants to do these kinds of things itself. I'm not against supporting it natively though. If you would like to add it, open a PR. |
Closing this issue due to lack of follow-up. I think it's low priority, and it doesn't exist in Jinja2. |
:( I hopped that there is easy way to hook up it from Express-only to regular Nunjucks, but, unfortunately, didn't have enough time to look into it. |
@carljm posted in #691 (comment):
It's very minor thing, I agree. But it's just somehow wrong to ask developer specify extension every single time while importing or including something when you're clearly working in unified environment. I think closest example here is ES2016, babel, systemjs. When you're importing other modules, you do not specify Same principle used in many other modern systems. Option to drop extension just makes Nunjucks more unified with them. |
I think nunjucks already provides the flexibility necessary to implement this, though; it would just require a custom loader. |
Just to ensure — you don't see it as part of Nunjucks core? Otherwise, would be better to reopen issue. |
No, I don't see it as part of Nunjucks core. I can see why someone might want it, but I've also worked on plenty of projects where templates didn't use a consistent dedicated extension, but rather just the extension of their ultimate type ( |
Sure, you're the boss :)
That had to be extension-agnostic. You should be able to specify your extension or set of extensions during configuring environment. Besides, it shouldn't affect imports and includes, which already had hardcoded extensions.
True, but more loaders and deviations from vendor aren't good thing too. So, I think for now that issue should stay dead. |
@carljm I've played around with Nunjucks internals and loaders, and came up with that solution: https://github.com/mozilla/nunjucks/blob/master/src/node-loaders.js#L54: getSource: function(name) {
....
for(var i=0; i<paths.length; i++) {
var basePath = path.resolve(paths[i]);
var p = path.resolve(paths[i], name);
// Here is where magic happens
// We add extension only if it wasn't specified
if (path.extname(p) != '.nj') {
p += '.nj'
}
....
}
....
}); Now I wonder, is basic approach here okay? And besides I wonder, is there any way to extend I also somehow dislike, that in fact here we're hijacking all incoming filenames, even for base layouts. In other words, it makes The only way so far to do it only for includes, imports and extends is monkeypatching https://github.com/mozilla/nunjucks/blob/master/src/parser.js#L429 parseInclude: function() {
var tagName = 'include';
var tag = this.peekToken();
if(!this.skipSymbol(tagName)) {
this.fail('parseInclude: expected '+ tagName);
}
var node = new nodes.Include(tag.lineno, tag.colno);
node.template = this.parseExpression();
node.template.value += '.nj'; // <--------- Here is crude example
if(this.skipSymbol('ignore') && this.skipSymbol('missing')) {
node.ignoreMissing = true;
}
this.advanceAfterBlockEnd(tag.value);
return node;
}, Am I missing something? |
I apparently didn't understand the details of the feature that you wanted, and I'm afraid I don't understand why you want it that way. What is the benefit of having includes, extends and imports have optional extensions, while extensions are required for the original render? That seems to me like a recipe for confusion. Whatever the rules are for referencing a template in a given environment, those rules should be consistent for everywhere templates are referenced. |
Just for the clarification, I don't think that feature is vitally needed, but I've already tried to explain that it will make imports, includes and extends more consistent with similar entities from close environments. Node.js requires: var Something = require('fileName') ES2016 imports: import Something from fileName Python imports: from fileName import Something It doesn't seem to make systems more confusing. |
But the difference is that in all of those environments, you always leave off the extension. What I'm not understanding is why you want to include the extension when calling |
Not always. You will need to specify extension, if you requiring or importing something, that isn't specific for that environment. For example, with SystemJS loader: import './style.scss!' You need to specify extension here, because it isn't specific for current environment file, it's custom one, so system can't know what you want to import here. It can make assumptions about
Few paragraphs above is the reason. For Nunjucks, where includes, imports and extends executed, our predefined extensions ( But for JavaScript those extensions aren't native.
Well, after giving it a thought, even despite what I've said above, I think it's ok. Not something I would expect in
Yes, it's possible. But I've already mentioned, that overriding But to be honest, I'd insist it to be part of default loader. It is very simple thing, but it will unify imports, includes and extends behavior with Node.js and ES2016 imports behavior, which is something you might expect as part of JS ecosystem and good design. To summarize, what technically I want here to implement, is make templates loading much more intelligent and predictable, like it's done in Node.js. Crude examples: // In environment configuration settings we set `ext` to be `['.njk', '.nj', '.html']`
{% include 'base' %} Will look in following order for:
{% include 'base.njk' %} Will look in following order for:
{% include 'base/' %} Will look in following order for:
Otherwise it would be great at least to have access to |
I hear your arguments, but I am afraid I am still not convinced of the value of having this in core. I just don't think the parallel to the JS or Python environment holds, mostly because the use of certain well-known extensions for Nunjucks templates is barely even a convention yet, whereas in JS and Python it is required. Basically, if you want this in core Nunjucks, you're going to have to get it into Jinja2 first. Or maybe come back to it in a year or so, once the use of a standard common extension for Nunjucks templates is much more strongly established. In the meantime, I see your issue with overriding |
I do not propose to predefine out of box any extension in Nunjucks. I propose to make configuration during environment setup possible out of box. So, it's independent from whether we have established extension or no. It's more question of do we want to have such feature or no. In other words, we need to look for other reasons to deny or approve such addition.
I might be wrong, but according to what I've researched regarding Jinja2, there is nothing to get in Jinja2 first. Like Nunjucks, Jinja2 supports different loaders out of box, as well as custom loaders. So, basically, you can do anything you want there, and not rarely it more dependent on by which framework it's used. For example, if I'm not mistaken, usage of Django with Django-Jinja allows to set those extensions in configuration. Some might arise question about compatibility of such loader with Jinja2. I've thought about it a while. But seems that it is one of those domains, where we can't maintain literal compatibility with Jinja2. Nunjucks has different (in future) extension, it's loading environment is different too, some applied in Python practices aren't applicable in JS and vica-versa, so how could we guarantee here that default Nunjucks loaders, which are for JS and Node, will behave exactly like Jinja2 loaders for Python and Django?
If such changes to extends, imports and includes, will be forbidden for eternity, I will try to figure out good solution for this. Otherwise, it seems to be unneeded for most cases, and will only complicate API |
Yes, I understand that you intend to make it configurable, with no default. But I think this is precisely why it is not the same as JS or Python; because there is no standard assumed extension throughout the entire ecosystem. So when you see an extension-less nunjucks import, you have to refer back to the environment configuration (and in some cases that may not be trivial to find, especially for a template author who perhaps didn't set up the environment code themselves) to have a clue what the actual filename might be. Now, for working on a particular project, that's something you would get used to. But in terms of the overall nunjucks ecosystem, it makes it harder, not easier, to come into a new project and quickly find your away around the templates. On the level of the entire language ecosystem, it is an absolute given (a requirement, practically) that a JS file will have the extension I personally frequently use It is true that in Jinja you could write a custom template loader that would allow eliding the extension (though I've never personally seen one); I would be happy to make this equally possible in Nunjucks. Jinja does not include out of the box any loader that allows eliding template extensions; similarly I do not wish to include such a loader out of the box in Nunjucks. (Your django-jinja example is unrelated; the extensions you configure there are for the purpose of allowing Django's generic template rendering API to decide which template engine should be used to render a given template, based on its extension. You still have to provide the full filename, including extension, in all imports/extends/includes.) |
You can leave off the extension when pointing to a template and it will take the value of opts.defaultEngine as the default extension to use right? So this same default extension mechanism should be allowed for |
|
@carljm Sorry for delay, still don't have enough time to fully reply on your previous message. Just an interesting additional info — ConsolidateJS seems to use extensionless templates too, and it doesn't seem like anybody suffering from it: // set .html as the default extension
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
app.get('/', function(req, res){
res.render('index', {
title: 'Consolidate.js'
});
});
app.get('/users', function(req, res){
res.render('users', {
title: 'Users',
users: users
});
}); |
+1 since |
@ArmorDarks @carljm Any progress on this? |
Is there any way to provide nunjucks with templates files extension name, so we could drop it in extends, includes and imports.
For example, Instead of
use
I've heard that it's possible to configure extension name when Nunjucks used in conjuration with Express. But what about other use cases, when Nunjucks used on it's own, or with Grunt?
The text was updated successfully, but these errors were encountered: