Skip to content

Commit

Permalink
PHP: Add support for Heredoc and Nowdoc strings
Browse files Browse the repository at this point in the history
  • Loading branch information
Golmote committed Mar 3, 2018
1 parent 5e9c575 commit 5d7223c
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 11 deletions.
51 changes: 43 additions & 8 deletions components/prism-php.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* Adds the following new token classes:
* constant, delimiter, variable, function, package
*/

(function (Prism) {
Prism.languages.php = Prism.languages.extend('clike', {
'keyword': /\b(?:and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i,
'constant': /\b[A-Z0-9_]{2,}\b/,
Expand Down Expand Up @@ -54,6 +54,35 @@ Prism.languages.insertBefore('php', 'operator', {
});

Prism.languages.insertBefore('php', 'string', {
'nowdoc-string': {
pattern: /<<<'([^']+)'(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;/,
greedy: true,
alias: 'string',
inside: {
'delimiter': {
pattern: /^<<<'[^']+'|[a-z_]\w*;$/i,
alias: 'symbol',
inside: {
'punctuation': /^<<<'?|[';]$/
}
}
}
},
'heredoc-string': {
pattern: /<<<(?:"([^"]+)"(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;|([a-z_]\w*)(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\2;)/i,
greedy: true,
alias: 'string',
inside: {
'delimiter': {
pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,
alias: 'symbol',
inside: {
'punctuation': /^<<<"?|[";]$/
}
},
'interpolation': null // See below
}
},
'single-quoted-string': {
pattern: /'(?:\\[\s\S]|[^\\'])*'/,
greedy: true,
Expand All @@ -64,18 +93,23 @@ Prism.languages.insertBefore('php', 'string', {
greedy: true,
alias: 'string',
inside: {
interpolation: {
pattern: /{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/,
lookbehind: true,
inside: {
rest: Prism.languages.php
}
}
'interpolation': null // See below
}
}
});
// The different types of PHP strings "replace" the C-like standard string
delete Prism.languages.php['string'];

var string_interpolation = {
pattern: /{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/,
lookbehind: true,
inside: {
rest: Prism.languages.php
}
};
Prism.languages.php['heredoc-string'].inside['interpolation'] = string_interpolation;
Prism.languages.php['double-quoted-string'].inside['interpolation'] = string_interpolation;

// Add HTML support if the markup language exists
if (Prism.languages.markup) {

Expand Down Expand Up @@ -136,3 +170,4 @@ if (Prism.languages.markup) {
env.element.innerHTML = env.highlightedCode;
});
}
}(Prism));
2 changes: 1 addition & 1 deletion components/prism-php.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 14 additions & 2 deletions examples/prism-php.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ <h2>Comments</h2>
<h2>Strings</h2>
<pre><code>'foo \'bar\' baz'
"foo \"bar\" baz"
"a string # containing an hash"</code></pre>
"a string # containing an hash"
$foo = &lt;&lt;&lt;FOO
Heredoc strings are supported too!
FOO;
$bar = &lt;&lt;&lt;'BAR'
And also Nowdoc strings
BAR;</code></pre>

<h2>Variables</h2>
<pre><code>$some_var = 5;
Expand Down Expand Up @@ -55,7 +61,13 @@ <h2>PHP embedded in HTML</h2>

<h2>String interpolation</h2>
<pre><code>$str = "This is $great!";
$foobar = "{${$foo->bar()}}";</code></pre>
$foobar = "Another example: {${$foo->bar()}}";
$a = &lt;&lt;&lt;FOO
Hello $world!
FOO;
$b = &lt;&lt;&lt;"FOOBAR"
Interpolation inside Heredoc strings {$obj->values[3]->name}
FOOBAR;</code></pre>

<h2>Known failures</h2>
<p>There are certain edge cases where Prism will fail.
Expand Down
37 changes: 37 additions & 0 deletions tests/languages/php/string-interpolation_feature.test
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
"the return value of getName(): {${getName()}}"
"the return value of \$object->getName(): {${$object->getName()}}"
"{$foo->$bar}, {$foo->{$baz[1]}}"
<<<FOO
Heredoc strings $also->support {${$string->interpolation()}}
FOO;
<<<"FOO_BAR"
{${$name}}, but not {\${\$name}}
FOO_BAR;

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

Expand Down Expand Up @@ -95,6 +101,37 @@
["punctuation", "}"]
]],
"\""
]],
["heredoc-string", [
["delimiter", [
["punctuation", "<<<"], "FOO"
]],
"\r\nHeredoc strings ",
["interpolation", [
["variable", "$also"], ["operator", "-"], ["operator", ">"], ["property", "support"]
]],
["interpolation", [
["punctuation", "{"], ["variable", "$"], ["punctuation", "{"],
["variable", "$string"], ["operator", "-"], ["operator", ">"], ["function", "interpolation"], ["punctuation", "("], ["punctuation", ")"],
["punctuation", "}"], ["punctuation", "}"]
]],
["delimiter", [
"FOO", ["punctuation", ";"]
]]
]],
["heredoc-string", [
["delimiter", [
["punctuation", "<<<\""], "FOO_BAR", ["punctuation", "\""]
]],
["interpolation", [
["punctuation", "{"], ["variable", "$"], ["punctuation", "{"],
["variable", "$name"],
["punctuation", "}"], ["punctuation", "}"]
]],
", but not {\\${\\$name}}\r\n",
["delimiter", [
"FOO_BAR", ["punctuation", ";"]
]]
]]
]

Expand Down
37 changes: 37 additions & 0 deletions tests/languages/php/string_feature.test
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
<<<FOO_BAR
Heredoc string
FOO_BAR;
<<<"FOO"
some
content
FOO;
<<<'NOWDOC'
This is a nowdoc string
NOWDOC;
"https://example.com"
" /* not a comment */ "
"multi-line
Expand All @@ -8,6 +18,33 @@ string'
----------------------------------------------------

[
["heredoc-string", [
["delimiter", [
["punctuation", "<<<"], "FOO_BAR"
]],
"\r\nHeredoc string\r\n",
["delimiter", [
"FOO_BAR", ["punctuation", ";"]
]]
]],
["heredoc-string", [
["delimiter", [
["punctuation", "<<<\""], "FOO", ["punctuation", "\""]
]],
"\r\n\tsome\r\n\tcontent\r\n",
["delimiter", [
"FOO", ["punctuation", ";"]
]]
]],
["nowdoc-string", [
["delimiter", [
["punctuation", "<<<'"], "NOWDOC", ["punctuation", "'"]
]],
"\r\nThis is a nowdoc string\r\n",
["delimiter", [
"NOWDOC", ["punctuation", ";"]
]]
]],
["double-quoted-string", ["\"https://example.com\""]],
["double-quoted-string", ["\" /* not a comment */ \""]],
["double-quoted-string", ["\"multi-line\r\nstring\""]],
Expand Down

0 comments on commit 5d7223c

Please sign in to comment.