Skip to content

Commit f35f11d

Browse files
Transform javascript
1 parent a5e50ee commit f35f11d

File tree

1 file changed

+134
-130
lines changed

1 file changed

+134
-130
lines changed

src/languages/javascript.js

Lines changed: 134 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { JS_TEMPLATE, JS_TEMPLATE_INTERPOLATION } from '../shared/languages/patterns.js';
22
import { toArray } from '../util/iterables.js';
3-
import { insertBefore } from '../util/language-util.js';
43
import clike from './clike.js';
54

65
/** @type {import('../types.d.ts').LanguageProto<'javascript'>} */
@@ -9,135 +8,10 @@ export default {
98
base: clike,
109
optional: 'js-templates',
1110
alias: 'js',
12-
grammar ({ base, getOptionalLanguage }) {
13-
insertBefore(base, 'comment', {
14-
'doc-comment': {
15-
pattern: /\/\*\*(?!\/)[\s\S]*?(?:\*\/|$)/,
16-
greedy: true,
17-
inside: 'jsdoc',
18-
},
19-
});
20-
21-
insertBefore(base, 'keyword', {
22-
'regex': {
23-
pattern: RegExp(
24-
// lookbehind
25-
// eslint-disable-next-line regexp/no-dupe-characters-character-class
26-
/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source +
27-
// Regex pattern:
28-
// There are 2 regex patterns here. The RegExp set notation proposal added support for nested character
29-
// classes if the `v` flag is present. Unfortunately, nested CCs are both context-free and incompatible
30-
// with the only syntax, so we have to define 2 different regex patterns.
31-
/\//.source +
32-
'(?:' +
33-
/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source +
34-
'|' +
35-
// `v` flag syntax. This supports 3 levels of nested character classes.
36-
/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/
37-
.source +
38-
')' +
39-
// lookahead
40-
/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source
41-
),
42-
lookbehind: true,
43-
greedy: true,
44-
inside: {
45-
'regex-source': {
46-
pattern: /^(\/)[\s\S]+(?=\/[a-z]*$)/,
47-
lookbehind: true,
48-
alias: 'language-regex',
49-
inside: 'regex',
50-
},
51-
'regex-delimiter': /^\/|\/$/,
52-
'regex-flags': /^[a-z]+$/,
53-
},
54-
},
55-
// This must be declared before keyword because we use "function" inside the look-forward
56-
'function-variable': {
57-
pattern:
58-
/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,
59-
alias: 'function',
60-
},
61-
'parameter': [
62-
{
63-
pattern:
64-
/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,
65-
lookbehind: true,
66-
inside: 'javascript',
67-
},
68-
{
69-
pattern:
70-
/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,
71-
lookbehind: true,
72-
inside: 'javascript',
73-
},
74-
{
75-
pattern: /(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,
76-
lookbehind: true,
77-
inside: 'javascript',
78-
},
79-
{
80-
pattern:
81-
/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,
82-
lookbehind: true,
83-
inside: 'javascript',
84-
},
85-
],
86-
'constant': /\b[A-Z](?:[A-Z_]|\dx?)*\b/,
87-
});
88-
89-
const jsTemplates = getOptionalLanguage('js-templates')?.['template-string'];
90-
91-
insertBefore(base, 'string', {
92-
'hashbang': {
93-
pattern: /^#!.*/,
94-
greedy: true,
95-
alias: 'comment',
96-
},
97-
'template-string': [
98-
...toArray(jsTemplates),
99-
{
100-
pattern: JS_TEMPLATE,
101-
greedy: true,
102-
inside: /** @type {Grammar} */ ({
103-
'template-punctuation': {
104-
pattern: /^`|`$/,
105-
alias: 'string',
106-
},
107-
'interpolation': {
108-
pattern: RegExp(
109-
/((?:^|[^\\])(?:\\{2})*)/.source + JS_TEMPLATE_INTERPOLATION.source
110-
),
111-
lookbehind: true,
112-
inside: {
113-
'interpolation-punctuation': {
114-
pattern: /^\$\{|\}$/,
115-
alias: 'punctuation',
116-
},
117-
$rest: /** @type {Grammar['$rest']} */ ('javascript'),
118-
},
119-
},
120-
'string': /[\s\S]+/,
121-
}),
122-
},
123-
],
124-
'string-property': {
125-
pattern:
126-
/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,
127-
lookbehind: true,
128-
greedy: true,
129-
alias: 'property',
130-
},
131-
});
132-
133-
insertBefore(base, 'operator', {
134-
'literal-property': {
135-
pattern:
136-
/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,
137-
lookbehind: true,
138-
alias: 'property',
139-
},
140-
});
11+
grammar ({ getOptionalLanguage }) {
12+
const jsTemplates = /** @type {GrammarTokens} */ (getOptionalLanguage('js-templates'))?.[
13+
'template-string'
14+
];
14115

14216
return {
14317
'class-name': [
@@ -210,10 +84,140 @@ export default {
21084
},
21185
'operator':
21286
/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/,
87+
$insertBefore: {
88+
'comment': {
89+
'doc-comment': {
90+
pattern: /\/\*\*(?!\/)[\s\S]*?(?:\*\/|$)/,
91+
greedy: true,
92+
inside: 'jsdoc',
93+
},
94+
},
95+
'keyword': {
96+
'regex': {
97+
pattern: RegExp(
98+
// lookbehind
99+
// eslint-disable-next-line regexp/no-dupe-characters-character-class
100+
/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source +
101+
// Regex pattern:
102+
// There are 2 regex patterns here. The RegExp set notation proposal added support for nested character
103+
// classes if the `v` flag is present. Unfortunately, nested CCs are both context-free and incompatible
104+
// with the only syntax, so we have to define 2 different regex patterns.
105+
/\//.source +
106+
'(?:' +
107+
/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/
108+
.source +
109+
'|' +
110+
// `v` flag syntax. This supports 3 levels of nested character classes.
111+
/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/
112+
.source +
113+
')' +
114+
// lookahead
115+
/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/
116+
.source
117+
),
118+
lookbehind: true,
119+
greedy: true,
120+
inside: {
121+
'regex-source': {
122+
pattern: /^(\/)[\s\S]+(?=\/[a-z]*$)/,
123+
lookbehind: true,
124+
alias: 'language-regex',
125+
inside: 'regex',
126+
},
127+
'regex-delimiter': /^\/|\/$/,
128+
'regex-flags': /^[a-z]+$/,
129+
},
130+
},
131+
// This must be declared before keyword because we use "function" inside the look-forward
132+
'function-variable': {
133+
pattern:
134+
/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,
135+
alias: 'function',
136+
},
137+
'parameter': [
138+
{
139+
pattern:
140+
/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,
141+
lookbehind: true,
142+
inside: 'javascript',
143+
},
144+
{
145+
pattern:
146+
/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,
147+
lookbehind: true,
148+
inside: 'javascript',
149+
},
150+
{
151+
pattern:
152+
/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,
153+
lookbehind: true,
154+
inside: 'javascript',
155+
},
156+
{
157+
pattern:
158+
/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,
159+
lookbehind: true,
160+
inside: 'javascript',
161+
},
162+
],
163+
'constant': /\b[A-Z](?:[A-Z_]|\dx?)*\b/,
164+
},
165+
'string': {
166+
'hashbang': {
167+
pattern: /^#!.*/,
168+
greedy: true,
169+
alias: 'comment',
170+
},
171+
'template-string': [
172+
...toArray(jsTemplates),
173+
{
174+
pattern: JS_TEMPLATE,
175+
greedy: true,
176+
inside: /** @type {Grammar} */ ({
177+
'template-punctuation': {
178+
pattern: /^`|`$/,
179+
alias: 'string',
180+
},
181+
'interpolation': {
182+
pattern: RegExp(
183+
/((?:^|[^\\])(?:\\{2})*)/.source +
184+
JS_TEMPLATE_INTERPOLATION.source
185+
),
186+
lookbehind: true,
187+
inside: {
188+
'interpolation-punctuation': {
189+
pattern: /^\$\{|\}$/,
190+
alias: 'punctuation',
191+
},
192+
$rest: /** @type {Grammar['$rest']} */ ('javascript'),
193+
},
194+
},
195+
'string': /[\s\S]+/,
196+
}),
197+
},
198+
],
199+
'string-property': {
200+
pattern:
201+
/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,
202+
lookbehind: true,
203+
greedy: true,
204+
alias: 'property',
205+
},
206+
},
207+
'operator': {
208+
'literal-property': {
209+
pattern:
210+
/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,
211+
lookbehind: true,
212+
alias: 'property',
213+
},
214+
},
215+
},
213216
};
214217
},
215218
};
216219

217220
/**
218221
* @typedef {import('../types.d.ts').Grammar} Grammar
222+
* @typedef {import('../types.d.ts').GrammarTokens} GrammarTokens
219223
*/

0 commit comments

Comments
 (0)