-
Notifications
You must be signed in to change notification settings - Fork 847
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
block/template/extend support for ejs #252
Comments
PR, any suggestions are welcome: #251 |
Is anything happening with this? |
See #251 for discussion; I'm not going to merge anything on this front without permission from the other maintainers. |
Compare to the original solution (to invent "block"/"blocks" directives), I now have a updated idea: invent nothing new, but only one non-breaking change:
there are several advantages:
template.ejs <%- include(content, {foo: 'Foo'}) %> page.ejs <% const content = ({foo}) => {%>
<div><%=foo%></div>
<% }; %>
<%- include('./template', { content })%> I'm able to get a local modification running, however the code is not prod ready. if @RyanZim and @mde agree on this, I'll happy to work on this. Comments & thoughts are welcome! |
This could definitely work. One thing to keep in mind is that we ultimately want to support async/await for |
Hello @mde @RyanZim . Good part:
Issues:
|
Hi @huxia, does this feature is still planned ? |
Hi, Meanwhile I've made a workaround/hack in order to avoid extending - in my case I just needed the inheritance behavior (and it works with expressjs). // ... expressjs bootstrap & routing ...
var layoutPath = path.join(__dirname, 'views', 'layouts');
var ejs = require('ejs');
var compile = ejs.compile;
ejs.compile = function(template, opts) {
var fn = compile(template, opts);
return function(locals) {
var layout = null;
locals.layout = function(name) {
layout = name;
};
var output = fn.apply(this, arguments);
if (layout) {
var ext = path.extname(layout);
if (!ext) {
layout += '.ejs';
}
locals.contents = output;
layout = path.resolve(layoutPath, layout);
ejs.renderFile(layout, locals, opts, function(err, out) {
if (err) {
throw err;
} else {
output = out;
}
});
}
return output;
};
}; And here the usage from an <%_ layout("default"); _%>
<h1>Welcome</html> And here my layout <html>...
<body>
....
<%- contents; -%>
...
</body>
</html> This little snippet not so intrusive and avoids extra dependencies but may break if renderFile executes the cb argument async (as it may should but it doesn't today)... I think the simplest thing to do is to introduce on ejs an hook system on compile and then it would provide a way to implement new functions like inhertance or blocks out of the box... I've made a quick & dirty prototype in order to see how the API could be, you can take a look at it here : https://github.com/ichiriac/ejs-decorator - tell me if you're interested in a PR |
A hook system, meaning make the Template class an EventEmitter? |
Hi @mde, not yet sure how to achieve this, at the time I've started the comment I did not fully grasp the syntax capabilities, now I'm not so sure that would be a clean way to achieve layouts decoration. I'm still prototyping, and searching a solution... BTW you may be interested in this : https://github.com/ichiriac/ejs-next - same syntax but with promises support on files or outputs. The parser is about 10 times more efficient than regex, but I need to work on execution. I want to avoid reference errors when strict=false mode - and just fallback on empty entries, so I'm using slow Proxy traps 😄 |
I think the best approach it @huxia's one, with a slightly difference. Actually the problem comes from how to buffer inner output in order to redirect it into a variable or option, and pass it to the layout, or anywhere else. EJS<% var contents = () => {@ %>
Hello <%= name %>
<% @} %>
or
<% var contents = function() {@ %>
Hello <%= name %>
<% @} %> It's intuitive and keeps the idea of plain JS JSvar contents = function(data) {
var locals = locals.push(data);
with(locals) {
echo(`Hello `);
echo(name);
}
return locals.resolveOutput();
}; May introduce changes on compiler, based on the following rule :
Also for the start part you need to detect the function prefix in order to rewrite it. USAGE<%= contents %>
<%= contents({ name: 'John Doe' }) %>
<%- include('layout.ejs', { contents }) %>
<%-
include('layout.ejs', {
contents: function() {@ %>
Something here ...
<% @},
header: function() {@ %>
Something here ...
<% @}
})
%> That will be my approach, it avoids extra syntax with Next it will be easy to implement helpers like blocks dirrectly from a custom function ... |
sorry for the late reply, I would be glad to help with the code & pr, as long as @mde @RyanZim and other maintainer agrees on this approach. @ichiriac agrees with you, I think there should be as little avoids extra syntax as possible
@mde my approach here is to introduce a global output stack, which could be toggled at runtime. I guess by some feather modification, it could become something like a EventEmitter. there maybe some cool features could come from it, the only problem is, it looks like a big rewrite here -- which I'm not so sure, however I'll be willing to help if you guys can give a specific task 😄 . |
Hi there, I've finished a first prototype of that implementation, with layout, blocks & async support - you can checkout the code here : https://github.com/ichiriac/ejs-next I wanted to avoid overhead on the hook/decorator so I've keeped my implementation kiss/stupid : https://github.com/ichiriac/ejs-next/blob/master/lib/ejs.js#L103 / https://github.com/ichiriac/ejs-next/blob/master/lib/ejs.js#L188 |
One way to use extends/block in existing versions: page.ejs
base.ejs
|
This is why I like ejs |
Without this being supported on the official library, is the any library that extends ejs and supports it? @mde is there any comments on this proposal? |
Any update to this conversation? |
I'm also interested in this, currently using huzunjie's method, but would like to avoid using the |
Still considering this, but right now focused on a v4 update to use ESM in the EJS source code. |
Currently ejs doesn't have any block/template/extend features.
existing solutions:
this approach:
page implementation (home.ejs):
template/layout declaration (layout.ejs):
advantages
The text was updated successfully, but these errors were encountered: