Skip to content

Commit 38808e6

Browse files
authored
PHP: Added support for PHP 7.4 + other major improvements (#2566)
1 parent 38f42dd commit 38808e6

20 files changed

+697
-242
lines changed

components/prism-php.js

+174-87
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,205 @@
11
/**
22
* Original by Aaron Harun: http://aahacreative.com/2012/07/31/php-syntax-highlighting-prism/
33
* Modified by Miles Johnson: http://milesj.me
4+
* Rewritten by Tom Pavelec
45
*
5-
* Supports the following:
6-
* - Extends clike syntax
7-
* - Support for PHP 5.3+ (namespaces, traits, generators, etc)
8-
* - Smarter constant and function matching
9-
*
10-
* Adds the following new token classes:
11-
* constant, delimiter, variable, function, package
6+
* Supports PHP 5.3 - 7.4
127
*/
138
(function (Prism) {
14-
Prism.languages.php = Prism.languages.extend('clike', {
15-
'keyword': /\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|new|or|parent|print|private|protected|public|require|require_once|return|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,
16-
'boolean': {
17-
pattern: /\b(?:false|true)\b/i,
18-
alias: 'constant'
19-
},
20-
'constant': [
21-
/\b[A-Z_][A-Z0-9_]*\b/,
22-
/\b(?:null)\b/i,
23-
],
24-
'comment': {
25-
pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,
26-
lookbehind: true
27-
}
28-
});
29-
30-
Prism.languages.insertBefore('php', 'string', {
31-
'shell-comment': {
32-
pattern: /(^|[^\\])#.*/,
33-
lookbehind: true,
34-
alias: 'comment'
35-
}
36-
});
37-
38-
Prism.languages.insertBefore('php', 'comment', {
9+
Prism.languages.php = {
3910
'delimiter': {
4011
pattern: /\?>$|^<\?(?:php(?=\s)|=)?/i,
4112
alias: 'important'
42-
}
43-
});
44-
45-
Prism.languages.insertBefore('php', 'keyword', {
13+
},
14+
'comment': [
15+
/\/\*[\s\S]*?\*\/|\/\/.*|#.*/
16+
],
4617
'variable': /\$+(?:\w+\b|(?={))/i,
4718
'package': {
48-
pattern: /(\\|namespace\s+|use\s+)[\w\\]+/,
19+
pattern: /(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
4920
lookbehind: true,
5021
inside: {
51-
punctuation: /\\/
22+
'punctuation': /\\/
5223
}
53-
}
54-
});
55-
56-
// Must be defined after the function pattern
57-
Prism.languages.insertBefore('php', 'operator', {
24+
},
25+
'keyword': [
26+
{
27+
pattern: /(\(\s*)\b(?:bool|boolean|int|integer|float|string|object|array)\b(?=\s*\))/i,
28+
alias: 'type-casting',
29+
greedy: true,
30+
lookbehind: true
31+
},
32+
{
33+
pattern: /([(,?]\s*)\b(?:bool|boolean|int|integer|float|string|object|array(?!\s*\()|mixed|self|static|callable|iterable)\b(?=\s*\$)/i,
34+
alias: 'type-hint',
35+
greedy: true,
36+
lookbehind: true
37+
},
38+
{
39+
pattern: /(\)\s*:\s*\?*\s*)\b(?:bool|boolean|int|integer|float|string|object|void|array(?!\s*\()|mixed|self|static|callable|iterable)\b/i,
40+
alias: 'return-type',
41+
greedy: true,
42+
lookbehind: true
43+
},
44+
{
45+
pattern: /\b(?:bool|boolean|int|integer|float|string|object|void|array(?!\s*\()|mixed|iterable)\b/i,
46+
alias: 'type-declaration',
47+
greedy: true
48+
},
49+
{
50+
pattern: /\b(?:parent|self|static)(?=\s*::)/i,
51+
alias: 'static-context',
52+
greedy: true
53+
},
54+
/\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|match|new|or|parent|print|private|protected|public|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i
55+
],
56+
'class-name': [
57+
{
58+
pattern: /(\b(?:class|interface|extends|implements|trait|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s+\()\b[a-z_]\w*(?!\\)\b/i,
59+
greedy: true,
60+
lookbehind: true
61+
},
62+
{
63+
pattern: /(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s+\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
64+
alias: 'class-name-fully-qualified',
65+
greedy: true,
66+
lookbehind: true,
67+
inside: {
68+
'punctuation': /\\/
69+
}
70+
},
71+
{
72+
pattern: /\b[a-z_]\w*(?=\s*\$)/i,
73+
alias: 'type-declaration',
74+
greedy: true
75+
},
76+
{
77+
pattern: /(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,
78+
alias: ['class-name-fully-qualified', 'type-declaration'],
79+
greedy: true,
80+
inside: {
81+
'punctuation': /\\/
82+
}
83+
},
84+
{
85+
pattern: /\b[a-z_]\w*(?=\s*::)/i,
86+
alias: 'static-context',
87+
greedy: true
88+
},
89+
{
90+
pattern: /(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,
91+
alias: ['class-name-fully-qualified', 'static-context'],
92+
greedy: true,
93+
inside: {
94+
'punctuation': /\\/
95+
}
96+
},
97+
{
98+
pattern: /([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,
99+
alias: 'type-hint',
100+
greedy: true,
101+
lookbehind: true
102+
},
103+
{
104+
pattern: /([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,
105+
alias: ['class-name-fully-qualified', 'type-hint'],
106+
greedy: true,
107+
lookbehind: true,
108+
inside: {
109+
'punctuation': /\\/
110+
}
111+
},
112+
{
113+
pattern: /(\)\s*:\s*\?*\s*)\b[a-z_]\w*(?!\\)\b/i,
114+
alias: 'return-type',
115+
greedy: true,
116+
lookbehind: true
117+
},
118+
{
119+
pattern: /(\)\s*:\s*\?*\s*)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
120+
alias: ['class-name-fully-qualified', 'return-type'],
121+
greedy: true,
122+
lookbehind: true,
123+
inside: {
124+
'punctuation': /\\/
125+
}
126+
}
127+
],
128+
'constant': [
129+
{
130+
pattern: /\b(?:false|true)\b/i,
131+
alias: 'boolean'
132+
},
133+
/\b[A-Z_][A-Z0-9_]*\b/,
134+
/\b(?:null)\b/i,
135+
],
136+
'function': /\w+\s*(?=\()/,
58137
'property': {
59138
pattern: /(->)[\w]+/,
60139
lookbehind: true
61-
}
62-
});
140+
},
141+
'number': /\b0b[01]+\b|\b0x[\da-f]+\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)*|\B\.\d+)(?:e[+-]?\d+)?/i,
142+
'operator': /<?=>|\?\?=?|\.{3}|->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||[?~]|[/^|%*&<>.+-]=?/,
143+
'punctuation': /[{}\[\](),:;]/
144+
};
63145

64146
var string_interpolation = {
65147
pattern: /{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)*)/,
66148
lookbehind: true,
67149
inside: Prism.languages.php
68150
};
69151

70-
Prism.languages.insertBefore('php', 'string', {
71-
'nowdoc-string': {
72-
pattern: /<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,
73-
greedy: true,
74-
alias: 'string',
75-
inside: {
76-
'delimiter': {
77-
pattern: /^<<<'[^']+'|[a-z_]\w*;$/i,
78-
alias: 'symbol',
79-
inside: {
80-
'punctuation': /^<<<'?|[';]$/
152+
Prism.languages.insertBefore('php', 'variable', {
153+
'string': [
154+
{
155+
pattern: /<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,
156+
alias: 'nowdoc-string',
157+
greedy: true,
158+
inside: {
159+
'delimiter': {
160+
pattern: /^<<<'[^']+'|[a-z_]\w*;$/i,
161+
alias: 'symbol',
162+
inside: {
163+
'punctuation': /^<<<'?|[';]$/
164+
}
81165
}
82166
}
167+
},
168+
{
169+
pattern: /<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,
170+
alias: 'heredoc-string',
171+
greedy: true,
172+
inside: {
173+
'delimiter': {
174+
pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,
175+
alias: 'symbol',
176+
inside: {
177+
'punctuation': /^<<<"?|[";]$/
178+
}
179+
},
180+
'interpolation': string_interpolation // See below
181+
}
182+
},
183+
{
184+
pattern: /`(?:\\[\s\S]|[^\\`])*`/,
185+
alias: 'backtick-quoted-string',
186+
greedy: true
187+
},
188+
{
189+
pattern: /'(?:\\[\s\S]|[^\\'])*'/,
190+
alias: 'single-quoted-string',
191+
greedy: true
192+
},
193+
{
194+
pattern: /"(?:\\[\s\S]|[^\\"])*"/,
195+
alias: 'double-quoted-string',
196+
greedy: true,
197+
inside: {
198+
'interpolation': string_interpolation // See below
199+
}
83200
}
84-
},
85-
'heredoc-string': {
86-
pattern: /<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,
87-
greedy: true,
88-
alias: 'string',
89-
inside: {
90-
'delimiter': {
91-
pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,
92-
alias: 'symbol',
93-
inside: {
94-
'punctuation': /^<<<"?|[";]$/
95-
}
96-
},
97-
'interpolation': string_interpolation // See below
98-
}
99-
},
100-
'single-quoted-string': {
101-
pattern: /'(?:\\[\s\S]|[^\\'])*'/,
102-
greedy: true,
103-
alias: 'string'
104-
},
105-
'double-quoted-string': {
106-
pattern: /"(?:\\[\s\S]|[^\\"])*"/,
107-
greedy: true,
108-
alias: 'string',
109-
inside: {
110-
'interpolation': string_interpolation // See below
111-
}
112-
}
201+
],
113202
});
114-
// The different types of PHP strings "replace" the C-like standard string
115-
delete Prism.languages.php['string'];
116203

117204
Prism.hooks.add('before-tokenize', function(env) {
118205
if (!/<\?/.test(env.code)) {

components/prism-php.min.js

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

tests/languages/latte/html_feature.test

+10-10
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,35 @@
1515
["tag", [["tag", [["punctuation", "<"], "a"]],
1616
["attr-name", ["href"]], ["attr-value", [["punctuation", "="], ["punctuation", "\""],
1717
["latte", [["ld", [["punctuation", "{"], ["tag", "link"]]],
18-
["php", ["Post", ["punctuation", ":"], "show ", ["variable", "$post"], ["operator", "-"], ["operator", ">"], ["property", "id"]]],
18+
["php", ["Post", ["punctuation", ":"], ["class-name", "show"], ["variable", "$post"], ["operator", "->"], ["property", "id"]]],
1919
["rd", [["punctuation", "}"]]]]],
2020
["punctuation", "\""]]], ["punctuation", ">"]]],
21-
["latte", [["ld", [["punctuation", "{"]]], ["php", [["variable", "$post"], ["operator", "-"], ["operator", ">"], ["property", "title"]]], ["rd", [["punctuation", "}"]]]]],
21+
["latte", [["ld", [["punctuation", "{"]]], ["php", [["variable", "$post"], ["operator", "->"], ["property", "title"]]], ["rd", [["punctuation", "}"]]]]],
2222
["tag", [["tag", [["punctuation", "</"], "a"]], ["punctuation", ">"]]],
2323

2424
["tag", [["tag", [["punctuation", "<"], "a"]],
2525
["attr-name",
26-
[["latte", [["ld", [["punctuation", "{"], ["tag", "if"]]], ["php", [["variable", "$post"], ["operator", "-"], ["operator", ">"], ["property", "id"]]], ["rd", [["punctuation", "}"]]]]], "title"]
26+
[["latte", [["ld", [["punctuation", "{"], ["tag", "if"]]], ["php", [["variable", "$post"], ["operator", "->"], ["property", "id"]]], ["rd", [["punctuation", "}"]]]]], "title"]
2727
],
2828
["attr-value", [["punctuation", "="], ["punctuation", "\""], "ahoj", ["punctuation", "\""]]],
2929
["attr-name", [["latte", [["ld", [["punctuation", "{/"], ["tag", "if"]]], ["rd", [["punctuation", "}"]]]]]]],
3030
["punctuation", ">"]]],
31-
["latte", [["ld", [["punctuation", "{"]]], ["php", [["variable", "$post"], ["operator", "-"], ["operator", ">"], ["property", "title"]]], ["rd", [["punctuation", "}"]]]]],
31+
["latte", [["ld", [["punctuation", "{"]]], ["php", [["variable", "$post"], ["operator", "->"], ["property", "title"]]], ["rd", [["punctuation", "}"]]]]],
3232
["tag", [["tag", [["punctuation", "</"], "a"]], ["punctuation", ">"]]],
3333

34-
["latte", [["ld", [["punctuation", "{"], ["tag", "tag"]]], ["php", [["variable", "$a"], ["operator", "="], ["boolean", "true"], ["operator", "?"], ["number", "10"], ["operator", "*"], ["number", "5"]]], ["rd", [["punctuation", "}"]]]]],
34+
["latte", [["ld", [["punctuation", "{"], ["tag", "tag"]]], ["php", [["variable", "$a"], ["operator", "="], ["constant", "true"], ["operator", "?"], ["number", "10"], ["operator", "*"], ["number", "5"]]], ["rd", [["punctuation", "}"]]]]],
3535

3636
["tag", [["tag", [["punctuation", "<"], "div"]],
37-
["n-attr", [["attr-name", "n:attr"], ["attr-value", [["punctuation", "="], ["punctuation", "\""], ["php", [["variable", "$a"], ["operator", "="], ["boolean", "true"], ["operator", "?"], ["number", "10"], ["operator", "*"], ["number", "5"]]], ["punctuation", "\""]]]]],
37+
["n-attr", [["attr-name", "n:attr"], ["attr-value", [["punctuation", "="], ["punctuation", "\""], ["php", [["variable", "$a"], ["operator", "="], ["constant", "true"], ["operator", "?"], ["number", "10"], ["operator", "*"], ["number", "5"]]], ["punctuation", "\""]]]]],
3838
["punctuation", ">"]]],
3939

40-
["latte", [["ld", [["punctuation", "{"], ["tag", "php"]]], ["php", [["single-quoted-string", "''"]]], ["rd", [["punctuation", "}"]]]]],
40+
["latte", [["ld", [["punctuation", "{"], ["tag", "php"]]], ["php", [["string", "''"]]], ["rd", [["punctuation", "}"]]]]],
4141

42-
["latte", [["ld", [["punctuation", "{"], ["tag", "php"]]], ["php", [["double-quoted-string", ["\"\""]]]], ["rd", [["punctuation", "}"]]]]],
42+
["latte", [["ld", [["punctuation", "{"], ["tag", "php"]]], ["php", [["string", ["\"\""]]]], ["rd", [["punctuation", "}"]]]]],
4343

44-
["latte", [["ld", [["punctuation", "{"], ["tag", "php"]]], ["php", [["double-quoted-string", ["\"ba\\\"r\""]]]], ["rd", [["punctuation", "}"]]]]],
44+
["latte", [["ld", [["punctuation", "{"], ["tag", "php"]]], ["php", [["string", ["\"ba\\\"r\""]]]], ["rd", [["punctuation", "}"]]]]],
4545

46-
["latte", [["ld", [["punctuation", "{"], ["tag", "php"]]], ["php", [["single-quoted-string", "'ba\\'z'"]]], ["rd", [["punctuation", "}"]]]]],
46+
["latte", [["ld", [["punctuation", "{"], ["tag", "php"]]], ["php", [["string", "'ba\\'z'"]]], ["rd", [["punctuation", "}"]]]]],
4747

4848
["latte", [["ld", [["punctuation", "{"], ["tag", "php"]]], ["php", [["comment", "/* \" */"]]], ["rd", [["punctuation", "}"]]]]]
4949
]

0 commit comments

Comments
 (0)