Skip to content

Commit

Permalink
wip: adjustments for integrating handlebars rules
Browse files Browse the repository at this point in the history
- hash-parameters
- subexpressions

wip: adjustments for integrating handlebars rules

- hash-parameters
- subexpressions

wip: update tests

some minor adaptions

wip: fix test cases

wip: try to honor path expressions correctly

wip: fix tests and refactor language definition

wip: update keywords, remove debug output

wip: {{else}} is a keyword and not a helper call

wip: fix test for else-variants

- else is not a built-in (except for the keyword {{else}})

wip: fix hashes and number literals, add string literals

- the hash-value must start after the equals-sign
- number and string modes must be in front of identifiers, because they are a subset

wip: make "as" in block-parameters a "keyword"
  • Loading branch information
nknapp committed Apr 10, 2020
1 parent 512ae5f commit 6a40323
Show file tree
Hide file tree
Showing 44 changed files with 595 additions and 262 deletions.
144 changes: 123 additions & 21 deletions src/languages/handlebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,133 @@ Description: Matcher for Handlebars as well as EmberJS additions.
Website: https://handlebarsjs.com
Category: template
*/
export default function (hljs) {

export default function(hljs) {
var BUILT_INS = {'builtin-name': 'each in with if else unless bindattr action collection debugger log outlet template unbound view yield lookup'};
var BUILT_INS = {
'builtin-name': 'action bindattr collection component concat debugger '
+ 'each each-in get hash if in input link-to loc log lookup '
+ 'mut outlet partial query-params render template textarea unbound '
+ 'unless view with yield'
};

var IDENTIFIER_PLAIN_OR_QUOTED = {
begin: /".*?"|'.*?'|\[.*?\]|\w+/
var LITERALS = {
'literal': 'true false undefined null'
};

var EXPRESSION_OR_HELPER_CALL = hljs.inherit(IDENTIFIER_PLAIN_OR_QUOTED, {
keywords: BUILT_INS,
// as defined in https://handlebarsjs.com/guide/expressions.html#literal-segments
// this regex matches literal segments like ' abc ' or [ abc ] as well as helpers and paths
// like a/b, ./abc/cde, and abc.bcd
var IDENFIFIER_REGEX = /(".*?"|'.*?'|\[.*?\]|[^\s!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]+|\.|\/)+/;

// identifier followed by a equal-sign (without the equal sign)
var HASH_PARAM_REGEX = /(".*?"|'.*?'|\[.*?\]|[^\s!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]+)(?==)/;

var HELPER_NAME_OR_PATH_EXPRESSION = {
begin: IDENFIFIER_REGEX,
lexemes: /[\w.\/]+/
};

var HELPER_PARAMETER = hljs.inherit(HELPER_NAME_OR_PATH_EXPRESSION, {
keywords: LITERALS
});

var SUB_EXPRESSION = {
illegal: /\}\}/,
begin: /\(/, end: /\)/
// the "contains" is added below when all necessary sub-modes are defined
};

var HASH = {
// fka "attribute-assignment", parameters of the form 'key=value'
className: 'attr',
illegal: /\}\}/,
begin: HASH_PARAM_REGEX,
relevance: 0,
starts: {
// helper params
endsWithParent: true,
relevance: 0,
contains: [hljs.inherit(IDENTIFIER_PLAIN_OR_QUOTED, {relevance: 0})]
begin: /=/,
end: /=/,
starts: {
contains: [
hljs.NUMBER_MODE,
hljs.QUOTE_STRING_MODE,
hljs.APOS_STRING_MODE,
HELPER_PARAMETER,
SUB_EXPRESSION
]
}
}
};

var BLOCK_PARAMS = {
// parameters of the form '{{#with x as | y |}}...{{/with}}'
begin: /as\s+\|/,
keywords: { keyword: 'as' },
end: /\|/,
contains: [
{
// define sub-mode in order to prevent highlighting of block-parameter named "as"
begin: /\w+/,
keywords: ''
}
]
}

var HELPER_PARAMETERS = {
contains: [
hljs.NUMBER_MODE,
hljs.QUOTE_STRING_MODE,
hljs.APOS_STRING_MODE,
BLOCK_PARAMS,
HASH,
HELPER_PARAMETER,
SUB_EXPRESSION
],
returnEnd: true
// the property "end" is defined through inheritance when the mode is used. If depends
// on the surrounding mode, but "endsWithParent" does not work here (i.e. it includes the
// end-token of the surrounding mode)
};

var SUB_EXPRESSION_CONTENTS = hljs.inherit(HELPER_NAME_OR_PATH_EXPRESSION, {
className: 'name',
keywords: BUILT_INS,
starts: hljs.inherit(HELPER_PARAMETERS, {
end: /\)/,
})
});

SUB_EXPRESSION.contains = [
SUB_EXPRESSION_CONTENTS
];

var OPENING_BLOCK_MUSTACHE_CONTENTS = hljs.inherit(HELPER_NAME_OR_PATH_EXPRESSION, {
keywords: BUILT_INS,
className: 'name',
starts: hljs.inherit(HELPER_PARAMETERS, {
end: /}}/,
})
});

var BLOCK_MUSTACHE_CONTENTS = hljs.inherit(EXPRESSION_OR_HELPER_CALL, {
var CLOSING_BLOCK_MUSTACHE_CONTENTS = hljs.inherit(HELPER_NAME_OR_PATH_EXPRESSION, {
keywords: BUILT_INS,
className: 'name'
});

var BASIC_MUSTACHE_CONTENTS = hljs.inherit(EXPRESSION_OR_HELPER_CALL, {
// relevance 0 for backward compatibility concerning auto-detection
relevance: 0

var BASIC_MUSTACHE_CONTENTS = hljs.inherit(HELPER_NAME_OR_PATH_EXPRESSION, {
className: 'name',
keywords: BUILT_INS,
starts: hljs.inherit(HELPER_PARAMETERS, {
end: /}}/,
})
});

var ESCAPE_MUSTACHE_WITH_PRECEEDING_BACKSLASH = {begin: /\\\{\{/, skip: true};
var PREVENT_ESCAPE_WITH_ANOTHER_PRECEEDING_BACKSLASH = {begin: /\\\\(?=\{\{)/, skip: true};

return {
name: 'Handlebars',
aliases: ['hbs', 'html.hbs', 'html.handlebars'],
aliases: ['hbs', 'html.hbs', 'html.handlebars', 'htmlbars'],
case_insensitive: true,
subLanguage: 'xml',
contains: [
Expand All @@ -50,33 +144,41 @@ export default function(hljs) {
// open raw block "{{{{raw}}}} content not evaluated {{{{/raw}}}}"
className: 'template-tag',
begin: /\{\{\{\{(?!\/)/, end: /\}\}\}\}/,
contains: [BLOCK_MUSTACHE_CONTENTS],
contains: [OPENING_BLOCK_MUSTACHE_CONTENTS],
starts: {end: /\{\{\{\{\//, returnEnd: true, subLanguage: 'xml'}
},
{
// close raw block
className: 'template-tag',
begin: /\{\{\{\{\//, end: /\}\}\}\}/,
contains: [BLOCK_MUSTACHE_CONTENTS]
contains: [CLOSING_BLOCK_MUSTACHE_CONTENTS]
},
{
// open block statement
className: 'template-tag',
begin: /\{\{[#\/]/, end: /\}\}/,
contains: [BLOCK_MUSTACHE_CONTENTS],
begin: /\{\{#/, end: /\}\}/,
contains: [OPENING_BLOCK_MUSTACHE_CONTENTS],
},
{
className: 'keyword',
begin: /\{\{else\}\}/
},
{
// closing block statement
className: 'template-tag',
begin: /\{\{\//, end: /\}\}/,
contains: [CLOSING_BLOCK_MUSTACHE_CONTENTS],
},
{
// template variable or helper-call that is NOT html-escaped
className: 'template-variable',
begin: /\{\{\{/, end: /\}\}\}/,
keywords: BUILT_INS,
contains: [BASIC_MUSTACHE_CONTENTS]
},
{
// template variable or helper-call that is html-escaped
className: 'template-variable',
begin: /\{\{/, end: /\}\}/,
keywords: BUILT_INS,
contains: [BASIC_MUSTACHE_CONTENTS]
}
]
Expand Down
80 changes: 0 additions & 80 deletions src/languages/htmlbars.js

This file was deleted.

9 changes: 0 additions & 9 deletions test/detect/htmlbars/default.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<span class="xml">text </span><span class="hljs-template-tag">{{#<span class="hljs-name">abc</span> abcd.[lite"'ral}}segment] }}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">abc</span>}}</span><span class="xml">

text </span><span class="hljs-template-tag">{{#<span class="hljs-name">abc</span> abcd."lite]'ral}}segment" }}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">abc</span>}}</span><span class="xml">

text </span><span class="hljs-template-tag">{{#<span class="hljs-name">abc</span> abcd.'lite]"ral}}segment' }}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">abc</span>}}</span><span class="xml">

text

<span class="xml">Block expression variants with literal segments in paths:
...
</span><span class="hljs-template-tag">{{#<span class="hljs-name">abc</span> abcd.[lite"'ral}}segment] }}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">abc</span>}}</span><span class="xml">
...
</span><span class="hljs-template-tag">{{#<span class="hljs-name">abc</span> abcd."lite]'ral}}segment" }}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">abc</span>}}</span><span class="xml">
...
</span><span class="hljs-template-tag">{{#<span class="hljs-name">abc</span> abcd.'lite]"ral}}segment' }}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">abc</span>}}</span><span class="xml">
...
Done
</span>
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
text {{#abc abcd.[lite"'ral}}segment] }}a{{/abc}}

text {{#abc abcd."lite]'ral}}segment" }}a{{/abc}}

text {{#abc abcd.'lite]"ral}}segment' }}a{{/abc}}

text

Block expression variants with literal segments in paths:
...
{{#abc abcd.[lite"'ral}}segment] }}a{{/abc}}
...
{{#abc abcd."lite]'ral}}segment" }}a{{/abc}}
...
{{#abc abcd.'lite]"ral}}segment' }}a{{/abc}}
...
Done
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
<span class="xml">text </span><span class="hljs-template-tag">{{#<span class="hljs-name">[ab}}c]</span> param }}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">[ab}}c]</span>}}</span><span class="xml">
<span class="xml">Block expression variants with literal segments in helper name:

text </span><span class="hljs-template-tag">{{#<span class="hljs-name">'ab}}c'</span> param}}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">'ab}}c'</span>}}</span><span class="xml">

text </span><span class="hljs-template-tag">{{#<span class="hljs-name">"ab}}c"</span> param}}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">"ab}}c"</span>}}</span><span class="xml">

text </span><span class="hljs-template-tag">{{#<span class="hljs-name">""</span> param}}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">""</span>}}</span><span class="xml">

text </span><span class="hljs-template-tag">{{#<span class="hljs-name">''</span> param}}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">''</span>}}</span><span class="xml">

text </span><span class="hljs-template-tag">{{#<span class="hljs-name">[]</span> param}}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">[]</span>}}</span><span class="xml">

text
</span><span class="hljs-template-tag">{{#<span class="hljs-name">[ab}}c]</span> param }}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">[ab}}c]</span>}}</span><span class="xml">
...
</span><span class="hljs-template-tag">{{#<span class="hljs-name">'ab}}c'</span> param}}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">'ab}}c'</span>}}</span><span class="xml">
...
</span><span class="hljs-template-tag">{{#<span class="hljs-name">"ab}}c"</span> param}}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">"ab}}c"</span>}}</span><span class="xml">
...
</span><span class="hljs-template-tag">{{#<span class="hljs-name">""</span> param}}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">""</span>}}</span><span class="xml">
...
</span><span class="hljs-template-tag">{{#<span class="hljs-name">''</span> param}}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">''</span>}}</span><span class="xml">
...
</span><span class="hljs-template-tag">{{#<span class="hljs-name">[]</span> param}}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">[]</span>}}</span><span class="xml">
...
Done
</span>
28 changes: 15 additions & 13 deletions test/markup/handlebars/block-expression-variants-in-helper-name.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
text {{#[ab}}c] param }}a{{/[ab}}c]}}

text {{#'ab}}c' param}}a{{/'ab}}c'}}

text {{#"ab}}c" param}}a{{/"ab}}c"}}

text {{#"" param}}a{{/""}}

text {{#'' param}}a{{/''}}

text {{#[] param}}a{{/[]}}

text
Block expression variants with literal segments in helper name:

{{#[ab}}c] param }}a{{/[ab}}c]}}
...
{{#'ab}}c' param}}a{{/'ab}}c'}}
...
{{#"ab}}c" param}}a{{/"ab}}c"}}
...
{{#"" param}}a{{/""}}
...
{{#'' param}}a{{/''}}
...
{{#[] param}}a{{/[]}}
...
Done
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<span class="xml">text </span><span class="hljs-template-tag">{{#<span class="hljs-name">abc</span> "lite]'ral}}segment" }}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">abc</span>}}</span><span class="xml">
<span class="xml">Block expression variants with literal segments in helper param:

text </span><span class="hljs-template-tag">{{#<span class="hljs-name">abc</span> 'lite]"ral}}segment' }}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">abc</span>}}</span><span class="xml">

text </span><span class="hljs-template-tag">{{#<span class="hljs-name">abc</span> [lite"'ral}}segment] }}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">abc</span>}}</span><span class="xml">

text
</span><span class="hljs-template-tag">{{#<span class="hljs-name">abc</span> [lite"'ral}}segment] }}</span><span class="xml">a</span><span class="hljs-template-tag">{{/<span class="hljs-name">abc</span>}}</span><span class="xml">
...
Done
</span>
Loading

0 comments on commit 6a40323

Please sign in to comment.