-
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
How should it work? => literal <%% %%> handling / ignored unmatched closing %> tags #284
Comments
This is the discussion I would ideally like to have about the spec for closing tags. @RyanZim do you have thoughts about the desired behavior here? |
I'm not as familiar with the parsing logic as I should be, so perhaps some of this is impractical, but here goes: Literals:Literal handling is currently pretty crazy. I propose we substitute IMO, if you're using anything that looks like a literal or a closing tag inside your JS, you're doing something wrong. HTML parsing breaks out of scripts if I do not see the need for "Literal Blocks" personally. You can change the delimiter if you have too many conflicts with EJS tags. HTML doesn't allow you to configure anything, you've got to do Closing tags:I'm not sure how dangling closing tags should be handled; I'm willing to tolerate a bit of odd behavior for a boost in parsing speed. |
just to give some examples current regexp:
Making literals simple (no longer look for closing tags) and remove extra closing, but no longer slurpreduces the big regexp to
However I could not measure any improve in speed. Removing literal support from within javascript expressionsI run 2 versions of this
In both cases the savings where 8% to 10% (eg from 1.9 sec to 1.7 sec) For the 2nd one Regexp got simpler
In both cases
Those savings where also archived if I made applying the regexp conditional on it being defined. allowing user choicesAll of those changes can be made by changing regexp, or setting them to undefined (in that case, also adding if statements, where they would be applied.) since createRegex could be overwritten by plugins, they could substitute regex for other needs. (assuming we add the This also means that we can ship with 2 sets of regexp. The long ones for current behaviour, and the new ones (whatever they will be). And then allow a choose by option (global, or per template) extra closing tags. (no opening)I think that in debugCompile (or make it an extra option opts.strictTags) they should give an error. If speed changes are low enough, then they could always give an error, otherwise silently be dropped, From a user point of view, I think that an unmatched closing tag is as much an error as an unmatched opening tag (and the latter give an error) |
R̗͖̬͔̱̐ͤ̋e͓̘̠g̃͑͌͝ẻ̴͎̫͕͎̳x̖͕͕̓̔ ̹H̫̔ͤ̈́̊ọ̝̭̍̄̔́ͅr̺̥̝̲ͬ̅ͥ̀ṝ̩̫ͤ̿o̠̟͜r͑̂̇́ṡ̠̂!̻̟̘̣̌ͣ̌ Lets keep this as simple as possible, but no simpler. I am not in favor of allowing user choices. EJS already has almost too many options, we need to keep things simple. Also, by exposing this, we limit ourselves in refactoring the parser, since we need to use the user-supplied regexes without breaking backwards compat. If we can error on extra closing tags, that's great IMO. |
I added the following changes:
The commit is in Making unmatched closing tags throw on error is only consequent. I added tests. About the docs. I only changed them to describe the new behaviour. I assume that the fact that the behaviour changed goes into the changelog. I wasn't sure if I should update the changelog, or if that is deferred until release. If this change is ok, I can create a pull request for this. @mde Do you prefer to merge my work in (small) steps? Or should I wait until all changes are ready and make one big pull request then? Currently the first to steps from #288 would be ready from my side. |
Added a small speed improvement to https://github.com/User4martin/ejs/tree/refactor-generate-source-full-tokens We have a regex scanning for the open (or close) tag. The extend of the speed gain, depends on how many literals there a present. Without the check
With the check
|
I'm not @mde but I'd prefer if we started a |
Branch is fine with me. We can also leave it in my fork, until ready. I would like some feedback though on https://github.com/User4martin/ejs/tree/refactor-generate-source-full-tokens (including https://github.com/User4martin/ejs/tree/refactor-generate-source ) Just the concept. For example
Small bits like formatting, variable names,... can be done on the final version I will base all other work on them. |
Apologies for the delay in circling back to this. This is awesome work, and discussion. I wanted to make sure I have a thorough understanding of the various issues and questions before I chime in with feedback. It seems to me we have two possible approaches:
In my view, the very specific behavior for literal tags discussed here is not documented at all, and use of literals is far enough outside the mainstream usage that these changes could very well be shipped as part of a minor-version update. Backward compatibility under semver IMO should generally relate to documented features, or areas which, even if not specifically documented, are likely to be heavily used. So this:
Could actually ship as a minor version bump. Some other general feedback: Yes, that new set of regexes is pretty crazy/complicated. At a high level, I think we should support some level of customization, but through specific APIs (e.g., overriding Any customization API should be designed initially from the point of view of an end-user developer, not just by conveniently making specific implementation details into publicly accessible/overrideable properties. |
Thanks for the feedback. I am currently away from home. I will look into details when I am back. The regex are currently not public. This was merely an idea, but was not pursuit. Since I added code for adding open tag modifiers (#=-_) there is code that allows handling regex. This can later be extended (for closing tags) Methods on the template class are from a technical point all accessible to users. But that does not make them part of the supported API. I added a md doc that details any method that is meant to be available for 3rd parties. More later. |
I have to disagree here. EJS is one of the highly depended-upon packages on npm (currently the 51st most depended-upon npm package). We should make an effort to never ship any kind of possibly-breaking changes except in a major release. That may mean making major releases more often, but why fear the major release? It's just a number, after all.
I'm 💯 with you here. |
This is a request to discuss/define the desired behaviour.
I might (depending on the outcome) be willing to work on it.
I don't think the current behaviour is desired.
ejs.render(' %%> _%> -%>')
=> ' %> _%>'(1) seems just wrong to me.
I could see
ejs.render('<%% foo %>')
=> '<% foo %>' making sense. (See #235 #185 )But it does not work, as it stops on any tag:
ejs.render('<%% foo <%= "bar" %> %%>')
=> '<% foo bar %>'"bar" is evaluated by <%=, that is why the " are gone in the result.
Also what is the wanted behaviour, if they occur inside a tag (e.g inside an eval)?
It may be needed that a piece of javascript contains a <%, but that is currently not possible
ejs.render(' <%= "bar <%%" %> ')
ejs.render(' <%= "bar <%%" %> %>')
both give: Error: Could not find matching close tag for "<%=".
So the question is: Are <%% and %%>
My opinion would be to make them single escapes for <% and %>.
That is an incompatible change, but I don't really see any way to make them consistent (in any way) without breaking compatibility.
If a "literal block" is wanted, a different syntax would be needed.
But I really don't see the need for that. Either
Loosely related: The ignorance of extra closing tags:
ejs.render('foo -%>\nbar')
=> 'foo bar'IMHO closing tags that have no matching opening tag should NOT be ignored, but give an error.
That can however be archived as an option.
So the default behaviour can be kept, and they can be ignored.
But if they are ignored, is it really desired that they have the same "slurp" effects as proper tags?
If a matched
<% ... -%>
is encountered, it is handled as a closing tag, and it slurps the next new line.But in the above example
ejs.render('foo -%>\nbar')
=> 'foo bar'It is not a tag. It is ignored. Should it slurp the new line?
I also have a few pending patches that might depend on this
https://github.com/User4martin/ejs/tree/refactor-generate-source-full-tokens
I will discuss it later, and in its own thread.
It's main objective is to reduce the amount of calls to scanLine;
It currently keeps the above behaviour (except, it may change things for <%% inside other tags => but that does not matter, is it currently always gives an error)
But keeping the behaviour gives insane regex. (Still it speeds up compiling even with those regex).
The text was updated successfully, but these errors were encountered: