Skip to content

Commit 9f59f52

Browse files
JSX: Added support for general spread expressions (#2754)
1 parent 1dfc827 commit 9f59f52

File tree

7 files changed

+246
-43
lines changed

7 files changed

+246
-43
lines changed

components/prism-jsx.js

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,28 @@
22

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

5+
var space = /(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source;
6+
var braces = /(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source;
7+
var spread = /(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source;
8+
9+
/**
10+
* @param {string} source
11+
* @param {string} [flags]
12+
*/
13+
function re(source, flags) {
14+
source = source
15+
.replace(/<S>/g, function () { return space; })
16+
.replace(/<BRACES>/g, function () { return braces; })
17+
.replace(/<SPREAD>/g, function () { return spread; });
18+
return RegExp(source, flags);
19+
}
20+
21+
spread = re(spread).source;
22+
23+
524
Prism.languages.jsx = Prism.languages.extend('markup', javascript);
6-
Prism.languages.jsx.tag.pattern = RegExp(
7-
/<\/?(?:[\w.:-]+(?:<SP>+(?:[\w.:$-]+(?:=(?:"(?:\\[^]|[^\\"])*"|'(?:\\[^]|[^\\'])*'|[^\s{'"/>=]+|\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}))?|\{<SP>*\.{3}<SP>*[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*<SP>*\}))*<SP>*\/?)?>/.source
8-
.replace(/<SP>/g, function () { return /(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source }),
9-
'i'
25+
Prism.languages.jsx.tag.pattern = re(
26+
/<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[^]|[^\\"])*"|'(?:\\[^]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source
1027
);
1128

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

1734
Prism.languages.insertBefore('inside', 'attr-name', {
1835
'spread': {
19-
pattern: /\{\s*\.{3}\s*[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\s*\}/,
20-
inside: {
21-
'punctuation': /\.{3}|[{}.]/,
22-
'attr-value': /\w+/
23-
}
36+
pattern: re(/<SPREAD>/.source),
37+
inside: Prism.languages.jsx
2438
}
2539
}, Prism.languages.jsx.tag);
2640

2741
Prism.languages.insertBefore('inside', 'attr-value',{
2842
'script': {
2943
// Allow for two levels of nesting
30-
pattern: /=(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\})/i,
44+
pattern: re(/=<BRACES>/.source),
3145
inside: {
3246
'script-punctuation': {
3347
pattern: /^=(?={)/,

components/prism-jsx.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/languages/jsx/issue1236.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
]],
1111
["spread", [
1212
["punctuation", "{"],
13-
["punctuation", "..."],
14-
["attr-value", "this"],
13+
["operator", "..."],
14+
["keyword", "this"],
1515
["punctuation", "."],
16-
["attr-value", "props"],
16+
"props",
1717
["punctuation", "}"]
1818
]],
1919
["punctuation", ">"]

tests/languages/jsx/issue2753.test

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
const Test = () => {
2+
return (
3+
<div>
4+
<Button {...{onClick, disabled}}>
5+
Click (Wrong Highlighting)
6+
</Button>
7+
<Button onClick={onClick} disabled={disabled}>
8+
Click (Correct highlighting)
9+
</Button>
10+
</div>
11+
)
12+
}
13+
14+
----------------------------------------------------
15+
16+
[
17+
["keyword", "const"],
18+
["function-variable", "Test"],
19+
["operator", "="],
20+
["punctuation", "("],
21+
["punctuation", ")"],
22+
["operator", "=>"],
23+
["punctuation", "{"],
24+
25+
["keyword", "return"],
26+
["punctuation", "("],
27+
28+
["tag", [
29+
["tag", [
30+
["punctuation", "<"],
31+
"div"
32+
]],
33+
["punctuation", ">"]
34+
]],
35+
["plain-text", "\r\n "],
36+
["tag", [
37+
["tag", [
38+
["punctuation", "<"],
39+
["class-name", "Button"]
40+
]],
41+
["spread", [
42+
["punctuation", "{"],
43+
["operator", "..."],
44+
["punctuation", "{"],
45+
"onClick",
46+
["punctuation", ","],
47+
" disabled",
48+
["punctuation", "}"],
49+
["punctuation", "}"]
50+
]],
51+
["punctuation", ">"]
52+
]],
53+
["plain-text", "\r\n Click (Wrong Highlighting)\r\n "],
54+
["tag", [
55+
["tag", [
56+
["punctuation", "</"],
57+
["class-name", "Button"]
58+
]],
59+
["punctuation", ">"]
60+
]],
61+
["plain-text", "\r\n "],
62+
["tag", [
63+
["tag", [
64+
["punctuation", "<"],
65+
["class-name", "Button"]
66+
]],
67+
["attr-name", ["onClick"]],
68+
["script", [
69+
["script-punctuation", "="],
70+
["punctuation", "{"],
71+
"onClick",
72+
["punctuation", "}"]
73+
]],
74+
["attr-name", ["disabled"]],
75+
["script", [
76+
["script-punctuation", "="],
77+
["punctuation", "{"],
78+
"disabled",
79+
["punctuation", "}"]
80+
]],
81+
["punctuation", ">"]
82+
]],
83+
["plain-text", "\r\n Click (Correct highlighting)\r\n "],
84+
["tag", [
85+
["tag", [
86+
["punctuation", "</"],
87+
["class-name", "Button"]
88+
]],
89+
["punctuation", ">"]
90+
]],
91+
["plain-text", "\r\n "],
92+
["tag", [
93+
["tag", [
94+
["punctuation", "</"],
95+
"div"
96+
]],
97+
["punctuation", ">"]
98+
]],
99+
100+
["punctuation", ")"],
101+
102+
["punctuation", "}"]
103+
]

tests/languages/jsx/spread_in_tags.test

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<div {...foo}></div>
22
<div { ...foo }></div>
33
<div { ... foo }></div>
4+
<div {...{onClick, disabled}}></div>
5+
<div {...foo()}></div>
6+
<div {...(foo ?? bar)}></div>
47

58
----------------------------------------------------
69

@@ -12,8 +15,8 @@
1215
]],
1316
["spread", [
1417
["punctuation", "{"],
15-
["punctuation", "..."],
16-
["attr-value", "foo"],
18+
["operator", "..."],
19+
"foo",
1720
["punctuation", "}"]
1821
]],
1922
["punctuation", ">"]
@@ -25,15 +28,85 @@
2528
]],
2629
["punctuation", ">"]
2730
]],
31+
32+
["tag", [
33+
["tag", [
34+
["punctuation", "<"],
35+
"div"
36+
]],
37+
["spread", [
38+
["punctuation", "{"],
39+
["operator", "..."],
40+
"foo ",
41+
["punctuation", "}"]
42+
]],
43+
["punctuation", ">"]
44+
]],
45+
["tag", [
46+
["tag", [
47+
["punctuation", "</"],
48+
"div"
49+
]],
50+
["punctuation", ">"]
51+
]],
52+
53+
["tag", [
54+
["tag", [
55+
["punctuation", "<"],
56+
"div"
57+
]],
58+
["spread", [
59+
["punctuation", "{"],
60+
["operator", "..."],
61+
" foo ",
62+
["punctuation", "}"]
63+
]],
64+
["punctuation", ">"]
65+
]],
66+
["tag", [
67+
["tag", [
68+
["punctuation", "</"],
69+
"div"
70+
]],
71+
["punctuation", ">"]
72+
]],
73+
74+
["tag", [
75+
["tag", [
76+
["punctuation", "<"],
77+
"div"
78+
]],
79+
["spread", [
80+
["punctuation", "{"],
81+
["operator", "..."],
82+
["punctuation", "{"],
83+
"onClick",
84+
["punctuation", ","],
85+
" disabled",
86+
["punctuation", "}"],
87+
["punctuation", "}"]
88+
]],
89+
["punctuation", ">"]
90+
]],
91+
["tag", [
92+
["tag", [
93+
["punctuation", "</"],
94+
"div"
95+
]],
96+
["punctuation", ">"]
97+
]],
98+
2899
["tag", [
29100
["tag", [
30101
["punctuation", "<"],
31102
"div"
32103
]],
33104
["spread", [
34105
["punctuation", "{"],
35-
["punctuation", "..."],
36-
["attr-value", "foo"],
106+
["operator", "..."],
107+
["function", "foo"],
108+
["punctuation", "("],
109+
["punctuation", ")"],
37110
["punctuation", "}"]
38111
]],
39112
["punctuation", ">"]
@@ -45,15 +118,20 @@
45118
]],
46119
["punctuation", ">"]
47120
]],
121+
48122
["tag", [
49123
["tag", [
50124
["punctuation", "<"],
51125
"div"
52126
]],
53127
["spread", [
54128
["punctuation", "{"],
55-
["punctuation", "..."],
56-
["attr-value", "foo"],
129+
["operator", "..."],
130+
["punctuation", "("],
131+
"foo ",
132+
["operator", "??"],
133+
" bar",
134+
["punctuation", ")"],
57135
["punctuation", "}"]
58136
]],
59137
["punctuation", ">"]

tests/languages/jsx/tag_feature.test

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,24 @@ var myElement = <MyComponent someProperty={true} />;
3636
]],
3737
["attr-name", ["someProperty"]],
3838
["script", [
39-
["script-punctuation", "="],
40-
["punctuation", "{"],
41-
["boolean", "true"],
42-
["punctuation", "}"]
39+
["script-punctuation", "="],
40+
["punctuation", "{"],
41+
["boolean", "true"],
42+
["punctuation", "}"]
4343
]],
4444
["punctuation", "/>"]
4545
]],
4646
["punctuation", ";"],
47+
4748
["tag", [
4849
["tag", [
4950
["punctuation", "<"],
5051
"div"
5152
]],
5253
["spread", [
5354
["punctuation", "{"],
54-
["punctuation", "..."],
55-
["attr-value", "foo"],
55+
["operator", "..."],
56+
"foo",
5657
["punctuation", "}"]
5758
]],
5859
["punctuation", ">"]
@@ -64,6 +65,7 @@ var myElement = <MyComponent someProperty={true} />;
6465
]],
6566
["punctuation", ">"]
6667
]],
68+
6769
["tag", [
6870
["tag", [
6971
["punctuation", "<"]
@@ -77,17 +79,18 @@ var myElement = <MyComponent someProperty={true} />;
7779
]],
7880
["punctuation", ">"]
7981
]],
82+
8083
["tag", [
8184
["tag", [
8285
["punctuation", "<"],
8386
["class-name", "Tree.TreeNode.Item"]
8487
]],
8588
["attr-name", ["leaf"]],
8689
["script", [
87-
["script-punctuation", "="],
88-
["punctuation", "{"],
89-
["boolean", "true"],
90-
["punctuation", "}"]
90+
["script-punctuation", "="],
91+
["punctuation", "{"],
92+
["boolean", "true"],
93+
["punctuation", "}"]
9194
]],
9295
["punctuation", ">"]
9396
]],

0 commit comments

Comments
 (0)