Skip to content
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

Support for Template Toolkit 2 #1418

Merged
merged 17 commits into from
May 10, 2018
Merged

Support for Template Toolkit 2 #1418

merged 17 commits into from
May 10, 2018

Conversation

gflohr
Copy link
Contributor

@gflohr gflohr commented May 4, 2018

This pull requests adds support for the Template Toolkit version 2.

The implementation assumes that the template processor is instantiated with default options. The options "INTERPOLATE", "START_TAG", "END_TAG", "TAG_STYLE", "OUTLINE_TAGS", and "ANYCASE" which signficantly change the default syntax, are not, or not fully supported.

Copy link
Contributor

@Golmote Golmote left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! Thanks for opening this new PR!

Could you take a look at my comments? There are quite a lot of them but it's mostly nitpicking.

Also, could you please run gulp and include the following generated files:

  • components.js
  • components/prism-tt2.min.js
  • plugins/autoloader/prism-autoloader.js
  • plugins/autoloader/prism-autoloader.min.js
  • plugins/show-language/prism-show-language.js
  • plugins/show-language/prism-show-language.min.js

(This should be all files modified by the gulp command, if I did not forget any...)

// A colon is not allowed inside variables but we want to catch things
// like [% USE Project::Specials %]
variable: {
pattern: /[a-z][:_a-z0-9]*(?:[\011-\015\040]*\.[\011-\015\040]*(?:\d+|\$?[a-z][:_a-z0-9]*))*/i,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't [\011-\015\040] be replaced with \s? Both don't have exactly the same meaning but it would make the regexp more clear I think.
Also, you can replace _a-z0-9 with \w.
Do you need the colon : inside the second part too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, with syntactically correct code \s is equivalent. Same for\w. I will change it to your preferences.

The colon was for fully qualified plug-in names (Foo::Bar). I thought they are supported but it looks like they actually don't work. So I will remove the colons. Even if they did work, the colons will then be highlighted as punctuation which is also okay.


Prism.languages.tt2 = Prism.languages.extend('clike', {
comment: {
pattern: /#.*|\[%#[^]*?%\]/,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've decided to use [\s\S] instead of [^] in #1107. Could you change this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I didn't know that.

pattern: /#.*|\[%#[^]*?%\]/,
lookbehind: true
},
keyword: /\b(?:GET|CALL|SET|DEFAULT|INSERT|INCLUDE|PROCESS|WRAPPER|BLOCK|IF|UNLESS|ELSIF|ELSE|SWITCH|CASE|FOREACH|IN|WHILE|FILTER|USE|MACRO|RAWPERL|PERL|TRY|THROW|CATCH|FINAL|NEXT|LAST|RETURN|STOP|CLEAR|META|TAGS|DEBUG|END)\b/,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering the large number of keywords here, you might want to consider ordering them alphabetically, for easier addition/removal in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are in the order of the directives documentation. Switch to alphabetical or go with the docs?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, could you then add a link to this doc page, in a comment above the regexp?


var operatorRE = /(?:=>|==|!=|<=|<|>=|>|=|&&|\|\||\||!|and|or|not)/;

Prism.languages.insertBefore('tt2', 'number', {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should add a line like delete Prism.languages.tt2['operator']; before you call insertBefore, so that the operator property can effectively be inserted. If it already exists, it will have unexpected behaviour.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I didn't know that and see whether that also fixes the FIXME below.

}
});

// FIXME! Is this repetition really necessary?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my previous comment regarding the deletion of the operator property. It should allow you to remove those lines.

[% META title = 'Hello!' %]
[% TAGS [@ @] %]
[% DEBUG on %]
[% DEBUG off %]
Copy link
Contributor

@Golmote Golmote May 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you were to reorder the keywords in the regexp, it would be nice to reorder the tests alphabetically too. Note that tests do not need to be valid structures in TT2.
It's perfectly ok if you test something like:

...
[% ELSE %]
[% ELSIF %]
[% END %]
...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understood that but I found a bug or two because of the more realistic test cases. Is that really a problem? It's better test coverage in the end.

Reordering: see above, whatever you prefer. Although ELSE before IF looks really strange to me. ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it's not really a problem. It was just a suggestion, feel free to let it as it is.


[
["tt2", [["delimiter", "[%"], ["keyword", "GET"],
["variable", "foo"], ["delimiter", "%]"]]],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identation is a bit weird in this file. Maybe you can keep it concise (I guess it was the intention here) doing something like:

[
	["tt2", [
		["delimiter", "[%"], ["keyword", "GET"], 
		["variable", "foo"], ["delimiter", "%]"]
	]],

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is the tabwidth. I had assumed 4 here. I will reformat with 8 (also for your other remarks on that issue).

[
["tt2", [["delimiter", "[%"],
["variable", "fat"], ["operator", "=>"], ["variable", "comma"],
["delimiter", "%]"]]],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here regarding indentation.

["double-quoted-string",
["\"Hello, ",
["variable", "$name"],
"!\""]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation seems a bit off here too.
Something like the following would be easier to read:

["double-quoted-string", [
	"\"Hello, ",
	["variable", "$name"],
	"!\""
],

world
hands
knots
%]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a test for the Project::Specials kind of variables here? I know it's technically already tested in the test for keywords, but since it's handled by the variable pattern, it definitely belongs here too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it's not supported anyway, see above. So I'll remove the colons from the variable regex as well.

@gflohr gflohr changed the title Supprt for Template Toolkit 2 Support for Template Toolkit 2 May 4, 2018
@gflohr
Copy link
Contributor Author

gflohr commented May 5, 2018

I think I am through now except for the generated files which I will push as soon as I have your okay.

I have ordered the keywords alphabetically, easier to maintain.

And I have removed the Namespace::Plugin feature as it seems not to work in templates.

Copy link
Contributor

@Golmote Golmote left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I think you missed some of my comments, maybe because of the "Hidden conversation" ellipsis Github adds. I reposted them, so that they appear again below. Can you take a look?

delete Prism.languages.tt2['operator'];
delete Prism.languages.tt2['variable'];
Prism.languages.insertBefore('tt2', 'number', {
operator: /(?:=>|==|!=|<=|<|>=|>|=|&&|\|\||\||!|and|or|not)/,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could probably combine some patterns here to avoid backtracking.
Also, the parentheses around the whole regexp are not needed.
Finally, wouldn't it be safer to add \b assertions around the keyword operators?

Something like /=[>=]?|!=?|<=?|>=?|&&|\|\|?|\b(?:and|or|not)\b/?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, that's more efficient and the \b also makes the greedy variables unnecessary, see below.

But - sorry for being a smart ass ;) - matching a 58 million character string without any space against \s takes about 50 % longer than matching against the more correct /[\011-\015\040]/, both in Firefox and Chrome.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hahaha. I take good note of this. And if you really want to revert this change, you might. But you'd have to add a comment above the regexp, specifying what are those characters, something like
// [\011-\015\040] -> Tab, LF, vertical tab, form feed, CR and space
or use the character escapes /[\t\n\v\f\r ]/. Just so that the meaning is obvious without looking at an ASCII reference table. 😉

%]
[% # this is a comment
theta = 20 # so is this
rho = 30 # <aol>me too!</aol>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll probably need to escape the < characters using &lt; in <aol> and </aol>.

as variables here.</li>
<li>The
<a href="http://template-toolkit.org/docs/manual/Config.html#section_ANYCASE">ANYCASE</a>
option is not supprted.</li>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a typo here: "supported".

----------------------------------------------------

[
["tt2",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please indent this line with a tab.

operator: /(?:=>|==|!=|<=|<|>=|>|=|&&|\|\||\||!|and|or|not)/,
variable: {
pattern: /[a-z]\w*(?:\s*\.\s*(?:\d+|\$?[a-z]\w*))*/i,
greedy: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do variables really need to be greedy? The greedy behaviour has a bit of a performance hit, so you should make sure you actually require it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the \b around the keyword-like operators and|or|not it is no longer needed. Thanks for the hint.

alias: 'string',
inside: {
variable: {
pattern: /\$(?:[a-z][_a-z0-9]*(?:\.(?:\d+|\$?[a-z][_a-z0-9]*))*)/i,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can replace [_a-z0-9] with \w.

inside: {
variable: {
pattern: /\$(?:[a-z][_a-z0-9]*(?:\.(?:\d+|\$?[a-z][_a-z0-9]*))*)/i,
greedy: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here about the greedy feature.

@gflohr
Copy link
Contributor Author

gflohr commented May 9, 2018

I have applied all your changes. Push the generated stuff now?

@Golmote
Copy link
Contributor

Golmote commented May 9, 2018

Yes please!

@gflohr
Copy link
Contributor Author

gflohr commented May 10, 2018

Pushed.

And thanks for the review process. That was very instructive for me.

@Golmote Golmote merged commit e063992 into PrismJS:gh-pages May 10, 2018
@Golmote
Copy link
Contributor

Golmote commented May 10, 2018

Thanks for contributing!

mAAdhaTTah added a commit that referenced this pull request Jun 5, 2018
* gh-pages: (33 commits)
  Add double-class specificity hack (#1435)
  Moved tutorial link to the end of the list
  Make line-numbers styles more specific
  Fix mixed content warning
  Create CNAME
  Delete CNAME
  Update documentation for node & webpack usage
  Handle optional dependencies in `loadLanguages()` (#1417)
  Add `objectpascal` as an alias to `pascal` (see #1426)
  Add support for XQuery. Fix #1405 (#1411)
  Website: Fix Download page not handling multiple dependencies when from Redownload URL
  JSX: Add support for fragments short syntax. Fix #1421
  Support for Template Toolkit 2 (#1418)
  ASP.NET should require C#
  Run gulp
  Move guard into conditional and check for language
  Don't process language if block language not set
  JSX: Allow for two levels of nesting inside JSX tags. Fix #1408
  Add missing reference to issue in specific test.
  Powershell: Allow for one level of nesting in expressions inside strings. Fix #1407
  ...

# Conflicts:
#	components/prism-kotlin.js
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants