Skip to content

Commit

Permalink
JSX: Added support for general spread expressions (#2754)
Browse files Browse the repository at this point in the history
  • Loading branch information
RunDevelopment committed Feb 7, 2021
1 parent 1dfc827 commit 9f59f52
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 43 deletions.
34 changes: 24 additions & 10 deletions components/prism-jsx.js
Expand Up @@ -2,11 +2,28 @@

var javascript = Prism.util.clone(Prism.languages.javascript);

var space = /(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source;
var braces = /(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source;
var spread = /(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source;

/**
* @param {string} source
* @param {string} [flags]
*/
function re(source, flags) {
source = source
.replace(/<S>/g, function () { return space; })
.replace(/<BRACES>/g, function () { return braces; })
.replace(/<SPREAD>/g, function () { return spread; });
return RegExp(source, flags);
}

spread = re(spread).source;


Prism.languages.jsx = Prism.languages.extend('markup', javascript);
Prism.languages.jsx.tag.pattern = RegExp(
/<\/?(?:[\w.:-]+(?:<SP>+(?:[\w.:$-]+(?:=(?:"(?:\\[^]|[^\\"])*"|'(?:\\[^]|[^\\'])*'|[^\s{'"/>=]+|\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}))?|\{<SP>*\.{3}<SP>*[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*<SP>*\}))*<SP>*\/?)?>/.source
.replace(/<SP>/g, function () { return /(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source }),
'i'
Prism.languages.jsx.tag.pattern = re(
/<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[^]|[^\\"])*"|'(?:\\[^]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source
);

Prism.languages.jsx.tag.inside['tag'].pattern = /^<\/?[^\s>\/]*/i;
Expand All @@ -16,18 +33,15 @@ Prism.languages.jsx.tag.inside['comment'] = javascript['comment'];

Prism.languages.insertBefore('inside', 'attr-name', {
'spread': {
pattern: /\{\s*\.{3}\s*[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\s*\}/,
inside: {
'punctuation': /\.{3}|[{}.]/,
'attr-value': /\w+/
}
pattern: re(/<SPREAD>/.source),
inside: Prism.languages.jsx
}
}, Prism.languages.jsx.tag);

Prism.languages.insertBefore('inside', 'attr-value',{
'script': {
// Allow for two levels of nesting
pattern: /=(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\})/i,
pattern: re(/=<BRACES>/.source),
inside: {
'script-punctuation': {
pattern: /^=(?={)/,
Expand Down
2 changes: 1 addition & 1 deletion components/prism-jsx.min.js

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

6 changes: 3 additions & 3 deletions tests/languages/jsx/issue1236.test
Expand Up @@ -10,10 +10,10 @@
]],
["spread", [
["punctuation", "{"],
["punctuation", "..."],
["attr-value", "this"],
["operator", "..."],
["keyword", "this"],
["punctuation", "."],
["attr-value", "props"],
"props",
["punctuation", "}"]
]],
["punctuation", ">"]
Expand Down
103 changes: 103 additions & 0 deletions tests/languages/jsx/issue2753.test
@@ -0,0 +1,103 @@
const Test = () => {
return (
<div>
<Button {...{onClick, disabled}}>
Click (Wrong Highlighting)
</Button>
<Button onClick={onClick} disabled={disabled}>
Click (Correct highlighting)
</Button>
</div>
)
}

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

[
["keyword", "const"],
["function-variable", "Test"],
["operator", "="],
["punctuation", "("],
["punctuation", ")"],
["operator", "=>"],
["punctuation", "{"],

["keyword", "return"],
["punctuation", "("],

["tag", [
["tag", [
["punctuation", "<"],
"div"
]],
["punctuation", ">"]
]],
["plain-text", "\r\n "],
["tag", [
["tag", [
["punctuation", "<"],
["class-name", "Button"]
]],
["spread", [
["punctuation", "{"],
["operator", "..."],
["punctuation", "{"],
"onClick",
["punctuation", ","],
" disabled",
["punctuation", "}"],
["punctuation", "}"]
]],
["punctuation", ">"]
]],
["plain-text", "\r\n Click (Wrong Highlighting)\r\n "],
["tag", [
["tag", [
["punctuation", "</"],
["class-name", "Button"]
]],
["punctuation", ">"]
]],
["plain-text", "\r\n "],
["tag", [
["tag", [
["punctuation", "<"],
["class-name", "Button"]
]],
["attr-name", ["onClick"]],
["script", [
["script-punctuation", "="],
["punctuation", "{"],
"onClick",
["punctuation", "}"]
]],
["attr-name", ["disabled"]],
["script", [
["script-punctuation", "="],
["punctuation", "{"],
"disabled",
["punctuation", "}"]
]],
["punctuation", ">"]
]],
["plain-text", "\r\n Click (Correct highlighting)\r\n "],
["tag", [
["tag", [
["punctuation", "</"],
["class-name", "Button"]
]],
["punctuation", ">"]
]],
["plain-text", "\r\n "],
["tag", [
["tag", [
["punctuation", "</"],
"div"
]],
["punctuation", ">"]
]],

["punctuation", ")"],

["punctuation", "}"]
]
90 changes: 84 additions & 6 deletions tests/languages/jsx/spread_in_tags.test
@@ -1,6 +1,9 @@
<div {...foo}></div>
<div { ...foo }></div>
<div { ... foo }></div>
<div {...{onClick, disabled}}></div>
<div {...foo()}></div>
<div {...(foo ?? bar)}></div>

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

Expand All @@ -12,8 +15,8 @@
]],
["spread", [
["punctuation", "{"],
["punctuation", "..."],
["attr-value", "foo"],
["operator", "..."],
"foo",
["punctuation", "}"]
]],
["punctuation", ">"]
Expand All @@ -25,15 +28,85 @@
]],
["punctuation", ">"]
]],

["tag", [
["tag", [
["punctuation", "<"],
"div"
]],
["spread", [
["punctuation", "{"],
["operator", "..."],
"foo ",
["punctuation", "}"]
]],
["punctuation", ">"]
]],
["tag", [
["tag", [
["punctuation", "</"],
"div"
]],
["punctuation", ">"]
]],

["tag", [
["tag", [
["punctuation", "<"],
"div"
]],
["spread", [
["punctuation", "{"],
["operator", "..."],
" foo ",
["punctuation", "}"]
]],
["punctuation", ">"]
]],
["tag", [
["tag", [
["punctuation", "</"],
"div"
]],
["punctuation", ">"]
]],

["tag", [
["tag", [
["punctuation", "<"],
"div"
]],
["spread", [
["punctuation", "{"],
["operator", "..."],
["punctuation", "{"],
"onClick",
["punctuation", ","],
" disabled",
["punctuation", "}"],
["punctuation", "}"]
]],
["punctuation", ">"]
]],
["tag", [
["tag", [
["punctuation", "</"],
"div"
]],
["punctuation", ">"]
]],

["tag", [
["tag", [
["punctuation", "<"],
"div"
]],
["spread", [
["punctuation", "{"],
["punctuation", "..."],
["attr-value", "foo"],
["operator", "..."],
["function", "foo"],
["punctuation", "("],
["punctuation", ")"],
["punctuation", "}"]
]],
["punctuation", ">"]
Expand All @@ -45,15 +118,20 @@
]],
["punctuation", ">"]
]],

["tag", [
["tag", [
["punctuation", "<"],
"div"
]],
["spread", [
["punctuation", "{"],
["punctuation", "..."],
["attr-value", "foo"],
["operator", "..."],
["punctuation", "("],
"foo ",
["operator", "??"],
" bar",
["punctuation", ")"],
["punctuation", "}"]
]],
["punctuation", ">"]
Expand Down
23 changes: 13 additions & 10 deletions tests/languages/jsx/tag_feature.test
Expand Up @@ -36,23 +36,24 @@ var myElement = <MyComponent someProperty={true} />;
]],
["attr-name", ["someProperty"]],
["script", [
["script-punctuation", "="],
["punctuation", "{"],
["boolean", "true"],
["punctuation", "}"]
["script-punctuation", "="],
["punctuation", "{"],
["boolean", "true"],
["punctuation", "}"]
]],
["punctuation", "/>"]
]],
["punctuation", ";"],

["tag", [
["tag", [
["punctuation", "<"],
"div"
]],
["spread", [
["punctuation", "{"],
["punctuation", "..."],
["attr-value", "foo"],
["operator", "..."],
"foo",
["punctuation", "}"]
]],
["punctuation", ">"]
Expand All @@ -64,6 +65,7 @@ var myElement = <MyComponent someProperty={true} />;
]],
["punctuation", ">"]
]],

["tag", [
["tag", [
["punctuation", "<"]
Expand All @@ -77,17 +79,18 @@ var myElement = <MyComponent someProperty={true} />;
]],
["punctuation", ">"]
]],

["tag", [
["tag", [
["punctuation", "<"],
["class-name", "Tree.TreeNode.Item"]
]],
["attr-name", ["leaf"]],
["script", [
["script-punctuation", "="],
["punctuation", "{"],
["boolean", "true"],
["punctuation", "}"]
["script-punctuation", "="],
["punctuation", "{"],
["boolean", "true"],
["punctuation", "}"]
]],
["punctuation", ">"]
]],
Expand Down

0 comments on commit 9f59f52

Please sign in to comment.