1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
(function (Prism) {
// https://freemarker.apache.org/docs/dgui_template_exp.html
// FTL expression with 4 levels of nesting supported
var FTL_EXPR =
/[^<()"']|\((?:<expr>)*\)|<(?!#--)|<#--(?:[^-]|-(?!->))*-->|"(?:[^\\"]|\\.)*"|'(?:[^\\']|\\.)*'/
.source;
for (var i = 0; i < 2; i++) {
FTL_EXPR = FTL_EXPR.replace(/<expr>/g, function () {
return FTL_EXPR;
});
}
FTL_EXPR = FTL_EXPR.replace(/<expr>/g, /[^\s\S]/.source);
var ftl = {
comment: /<#--[\s\S]*?-->/,
string: [
{
// raw string
pattern: /\br("|')(?:(?!\1)[^\\]|\\.)*\1/,
greedy: true,
},
{
pattern: RegExp(
/("|')(?:(?!\1|\$\{)[^\\]|\\.|\$\{(?:(?!\})(?:<expr>))*\})*\1/.source.replace(
/<expr>/g,
function () {
return FTL_EXPR;
}
)
),
greedy: true,
inside: {
interpolation: {
pattern: RegExp(
/((?:^|[^\\])(?:\\\\)*)\$\{(?:(?!\})(?:<expr>))*\}/.source.replace(
/<expr>/g,
function () {
return FTL_EXPR;
}
)
),
lookbehind: true,
inside: {
'interpolation-punctuation': {
pattern: /^\$\{|\}$/,
alias: 'punctuation',
},
rest: null,
},
},
},
},
],
keyword: /\b(?:as)\b/,
boolean: /\b(?:false|true)\b/,
'builtin-function': {
pattern: /((?:^|[^?])\?\s*)\w+/,
lookbehind: true,
alias: 'function',
},
function: /\b\w+(?=\s*\()/,
number: /\b\d+(?:\.\d+)?\b/,
operator:
/\.\.[<*!]?|->|--|\+\+|&&|\|\||\?{1,2}|[-+*/%!=<>]=?|\b(?:gt|gte|lt|lte)\b/,
punctuation: /[,;.:()[\]{}]/,
};
ftl.string[1].inside.interpolation.inside.rest = ftl;
Prism.languages.ftl = {
'ftl-comment': {
// the pattern is shortened to be more efficient
pattern: /^<#--[\s\S]*/,
alias: 'comment',
},
'ftl-directive': {
pattern: /^<[\s\S]+>$/,
inside: {
directive: {
pattern: /(^<\/?)[#@][a-z]\w*/i,
lookbehind: true,
alias: 'keyword',
},
punctuation: /^<\/?|\/?>$/,
content: {
pattern: /\s*\S[\s\S]*/,
alias: 'ftl',
inside: ftl,
},
},
},
'ftl-interpolation': {
pattern: /^\$\{[\s\S]*\}$/,
inside: {
punctuation: /^\$\{|\}$/,
content: {
pattern: /\s*\S[\s\S]*/,
alias: 'ftl',
inside: ftl,
},
},
},
};
Prism.hooks.add('before-tokenize', function (env) {
// eslint-disable-next-line regexp/no-useless-lazy
var pattern = RegExp(
/<#--[\s\S]*?-->|<\/?[#@][a-zA-Z](?:<expr>)*?>|\$\{(?:<expr>)*?\}/.source.replace(
/<expr>/g,
function () {
return FTL_EXPR;
}
),
'gi'
);
Prism.languages['markup-templating'].buildPlaceholders(env, 'ftl', pattern);
});
Prism.hooks.add('after-tokenize', function (env) {
Prism.languages['markup-templating'].tokenizePlaceholders(env, 'ftl');
});
})(Prism);
|