Skip to content

Commit acc0bc0

Browse files
Smarty: Improved tokenization (#3268)
1 parent 7bcc5da commit acc0bc0

15 files changed

+885
-140
lines changed

components.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components.json

+1
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,7 @@
12191219
"smarty": {
12201220
"title": "Smarty",
12211221
"require": "markup-templating",
1222+
"optional": "php",
12221223
"owner": "Golmote"
12231224
},
12241225
"sml": {

components/prism-smarty.js

+85-41
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,120 @@
1-
/* TODO
2-
Add support for variables inside double quoted strings
3-
Add support for {php}
4-
*/
5-
61
(function (Prism) {
72

83
Prism.languages.smarty = {
9-
'comment': /\{\*[\s\S]*?\*\}/,
4+
'comment': {
5+
pattern: /^\{\*[\s\S]*?\*\}/,
6+
greedy: true
7+
},
8+
'embedded-php': {
9+
pattern: /^\{php\}[\s\S]*?\{\/php\}/,
10+
greedy: true,
11+
inside: {
12+
'smarty': {
13+
pattern: /^\{php\}|\{\/php\}$/,
14+
inside: null // see below
15+
},
16+
'php': {
17+
pattern: /[\s\S]+/,
18+
alias: 'language-php',
19+
inside: Prism.languages.php
20+
}
21+
}
22+
},
23+
'string': [
24+
{
25+
pattern: /"(?:\\.|[^"\\\r\n])*"/,
26+
greedy: true,
27+
inside: {
28+
'interpolation': {
29+
pattern: /\{[^{}]*\}|`[^`]*`/,
30+
inside: {
31+
'interpolation-punctuation': {
32+
pattern: /^[{`]|[`}]$/,
33+
alias: 'punctuation'
34+
},
35+
'expression': {
36+
pattern: /[\s\S]+/,
37+
inside: null // see below
38+
}
39+
}
40+
},
41+
'variable': /\$\w+/
42+
}
43+
},
44+
{
45+
pattern: /'(?:\\.|[^'\\\r\n])*'/,
46+
greedy: true
47+
},
48+
],
49+
'keyword': {
50+
pattern: /(^\{\/?)[a-z_]\w*\b(?!\()/i,
51+
lookbehind: true,
52+
greedy: true
53+
},
1054
'delimiter': {
11-
pattern: /^\{|\}$/,
55+
pattern: /^\{\/?|\}$/,
56+
greedy: true,
1257
alias: 'punctuation'
1358
},
14-
'string': /(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,
1559
'number': /\b0x[\dA-Fa-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][-+]?\d+)?/,
1660
'variable': [
1761
/\$(?!\d)\w+/,
1862
/#(?!\d)\w+#/,
1963
{
20-
pattern: /(\.|->)(?!\d)\w+/,
64+
pattern: /(\.|->|\w\s*=)(?!\d)\w+\b(?!\()/,
2165
lookbehind: true
2266
},
2367
{
2468
pattern: /(\[)(?!\d)\w+(?=\])/,
2569
lookbehind: true
2670
}
2771
],
28-
'function': [
29-
{
30-
pattern: /(\|\s*)@?(?!\d)\w+/,
31-
lookbehind: true
32-
},
33-
/^\/?(?!\d)\w+/,
34-
/(?!\d)\w+(?=\()/
35-
],
36-
'attr-name': {
37-
// Value is made optional because it may have already been tokenized
38-
pattern: /\w+\s*=\s*(?:(?!\d)\w+)?/,
39-
inside: {
40-
'variable': {
41-
pattern: /(=\s*)(?!\d)\w+/,
42-
lookbehind: true
43-
},
44-
'operator': /=/
45-
}
72+
'function': {
73+
pattern: /(\|\s*)@?[a-z_]\w*|\b[a-z_]\w*(?=\()/i,
74+
lookbehind: true
4675
},
47-
'punctuation': [
48-
/[\[\]().,:`]|->/
49-
],
76+
'attr-name': /\b[a-z_]\w*(?=\s*=)/i,
77+
'boolean': /\b(?:false|no|off|on|true|yes)\b/,
78+
'punctuation': /[\[\](){}.,:`]|->/,
5079
'operator': [
5180
/[+\-*\/%]|==?=?|[!<>]=?|&&|\|\|?/,
5281
/\bis\s+(?:not\s+)?(?:div|even|odd)(?:\s+by)?\b/,
5382
/\b(?:and|eq|gt?e|gt|lt?e|lt|mod|neq?|not|or)\b/
54-
],
55-
'keyword': /\b(?:false|no|off|on|true|yes)\b/
83+
]
5684
};
5785

86+
Prism.languages.smarty['embedded-php'].inside.smarty.inside = Prism.languages.smarty;
87+
Prism.languages.smarty.string[0].inside.interpolation.inside.expression.inside = Prism.languages.smarty;
88+
89+
var string = /"(?:\\.|[^"\\\r\n])*"|'(?:\\.|[^'\\\r\n])*'/;
90+
var smartyPattern = RegExp(
91+
// comments
92+
/\{\*[\s\S]*?\*\}/.source +
93+
'|' +
94+
// php tags
95+
/\{php\}[\s\S]*?\{\/php\}/.source +
96+
'|' +
97+
// smarty blocks
98+
/\{(?:[^{}"']|<str>|\{(?:[^{}"']|<str>|\{(?:[^{}"']|<str>)*\})*\})*\}/.source
99+
.replace(/<str>/g, function () { return string.source; }),
100+
'g'
101+
);
102+
58103
// Tokenize all inline Smarty expressions
59104
Prism.hooks.add('before-tokenize', function (env) {
60-
var smartyPattern = /\{\*[\s\S]*?\*\}|\{[\s\S]+?\}/g;
61-
var smartyLitteralStart = '{literal}';
62-
var smartyLitteralEnd = '{/literal}';
63-
var smartyLitteralMode = false;
105+
var smartyLiteralStart = '{literal}';
106+
var smartyLiteralEnd = '{/literal}';
107+
var smartyLiteralMode = false;
64108

65109
Prism.languages['markup-templating'].buildPlaceholders(env, 'smarty', smartyPattern, function (match) {
66110
// Smarty tags inside {literal} block are ignored
67-
if (match === smartyLitteralEnd) {
68-
smartyLitteralMode = false;
111+
if (match === smartyLiteralEnd) {
112+
smartyLiteralMode = false;
69113
}
70114

71-
if (!smartyLitteralMode) {
72-
if (match === smartyLitteralStart) {
73-
smartyLitteralMode = true;
115+
if (!smartyLiteralMode) {
116+
if (match === smartyLiteralStart) {
117+
smartyLiteralMode = true;
74118
}
75119

76120
return true;

components/prism-smarty.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
{php}
2+
// including a php script directly from the template.
3+
include('/path/to/display_weather.php');
4+
{/php}
5+
6+
{* this template includes a {php} block that assign's the variable $varX *}
7+
{php}
8+
global $foo, $bar;
9+
if($foo == $bar){
10+
echo 'This will be sent to browser';
11+
}
12+
// assign a variable to Smarty
13+
$this->assign('varX','Toffee');
14+
{/php}
15+
{* output the variable *}
16+
<strong>{$varX}</strong> is my fav ice cream :-)
17+
18+
----------------------------------------------------
19+
20+
[
21+
["smarty", [
22+
["embedded-php", [
23+
["smarty", [
24+
["delimiter", "{"],
25+
["keyword", "php"],
26+
["delimiter", "}"]
27+
]],
28+
["php", [
29+
["comment", "// including a php script directly from the template."],
30+
31+
["keyword", "include"],
32+
["punctuation", "("],
33+
["string", "'/path/to/display_weather.php'"],
34+
["punctuation", ")"],
35+
["punctuation", ";"]
36+
]],
37+
["smarty", [
38+
["delimiter", "{/"],
39+
["keyword", "php"],
40+
["delimiter", "}"]
41+
]]
42+
]]
43+
]],
44+
45+
["smarty", [
46+
["comment", "{* this template includes a {php} block that assign's the variable $varX *}"]
47+
]],
48+
49+
["smarty", [
50+
["embedded-php", [
51+
["smarty", [
52+
["delimiter", "{"],
53+
["keyword", "php"],
54+
["delimiter", "}"]
55+
]],
56+
["php", [
57+
["keyword", "global"],
58+
["variable", "$foo"],
59+
["punctuation", ","],
60+
["variable", "$bar"],
61+
["punctuation", ";"],
62+
63+
["keyword", "if"],
64+
["punctuation", "("],
65+
["variable", "$foo"],
66+
["operator", "=="],
67+
["variable", "$bar"],
68+
["punctuation", ")"],
69+
["punctuation", "{"],
70+
71+
["keyword", "echo"],
72+
["string", "'This will be sent to browser'"],
73+
["punctuation", ";"],
74+
75+
["punctuation", "}"],
76+
77+
["comment", "// assign a variable to Smarty"],
78+
79+
["variable", "$this"],
80+
["operator", "->"],
81+
["function", ["assign"]],
82+
["punctuation", "("],
83+
["string", "'varX'"],
84+
["punctuation", ","],
85+
["string", "'Toffee'"],
86+
["punctuation", ")"],
87+
["punctuation", ";"]
88+
]],
89+
["smarty", [
90+
["delimiter", "{/"],
91+
["keyword", "php"],
92+
["delimiter", "}"]
93+
]]
94+
]]
95+
]],
96+
97+
["smarty", [
98+
["comment", "{* output the variable *}"]
99+
]],
100+
101+
["tag", [
102+
["tag", [
103+
["punctuation", "<"],
104+
"strong"
105+
]],
106+
["punctuation", ">"]
107+
]],
108+
["smarty", [
109+
["delimiter", "{"],
110+
["variable", "$varX"],
111+
["delimiter", "}"]
112+
]],
113+
["tag", [
114+
["tag", [
115+
["punctuation", "</"],
116+
"strong"
117+
]],
118+
["punctuation", ">"]
119+
]],
120+
" is my fav ice cream :-)"
121+
]

tests/languages/smarty/attr-name_feature.test

+11-17
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,25 @@
66
[
77
["smarty", [
88
["delimiter", "{"],
9-
["function", "assign"],
10-
["attr-name", [
11-
"var",
12-
["operator", "="],
13-
["variable", "foo"]
14-
]],
15-
["attr-name", [
16-
"value",
17-
["operator", "="]
18-
]],
19-
["string", "\"bar\""],
9+
["keyword", "assign"],
10+
["attr-name", "var"],
11+
["operator", "="],
12+
["variable", "foo"],
13+
["attr-name", "value"],
14+
["operator", "="],
15+
["string", ["\"bar\""]],
2016
["delimiter", "}"]
2117
]],
2218
["smarty", [
2319
["delimiter", "{"],
24-
["function", "foo"],
25-
["attr-name", [
26-
"bar ",
27-
["operator", "="]
28-
]],
20+
["keyword", "foo"],
21+
["attr-name", "bar"],
22+
["operator", "="],
2923
["number", "40"],
3024
["delimiter", "}"]
3125
]]
3226
]
3327

3428
----------------------------------------------------
3529

36-
Checks for attributes.
30+
Checks for attributes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{if false}
2+
{if off}
3+
{if on}
4+
{if no}
5+
{if true}
6+
{if yes}
7+
8+
----------------------------------------------------
9+
10+
[
11+
["smarty", [
12+
["delimiter", "{"],
13+
["keyword", "if"],
14+
["boolean", "false"],
15+
["delimiter", "}"]
16+
]],
17+
["smarty", [
18+
["delimiter", "{"],
19+
["keyword", "if"],
20+
["boolean", "off"],
21+
["delimiter", "}"]
22+
]],
23+
["smarty", [
24+
["delimiter", "{"],
25+
["keyword", "if"],
26+
["boolean", "on"],
27+
["delimiter", "}"]
28+
]],
29+
["smarty", [
30+
["delimiter", "{"],
31+
["keyword", "if"],
32+
["boolean", "no"],
33+
["delimiter", "}"]
34+
]],
35+
["smarty", [
36+
["delimiter", "{"],
37+
["keyword", "if"],
38+
["boolean", "true"],
39+
["delimiter", "}"]
40+
]],
41+
["smarty", [
42+
["delimiter", "{"],
43+
["keyword", "if"],
44+
["boolean", "yes"],
45+
["delimiter", "}"]
46+
]]
47+
]
48+
49+
----------------------------------------------------
50+
51+
Checks for keywords.

0 commit comments

Comments
 (0)