@litsx/jsx-authoring 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -0
- package/dist/index.cjs +888 -0
- package/dist/index.cjs.map +1 -0
- package/dist/parser.cjs +184 -0
- package/dist/parser.cjs.map +1 -0
- package/package.json +47 -0
- package/src/index.js +878 -0
- package/src/parser.js +181 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,888 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var MagicString = require('magic-string');
|
|
4
|
+
|
|
5
|
+
const PREFIX_TO_KIND = {
|
|
6
|
+
"@": "event",
|
|
7
|
+
".": "prop",
|
|
8
|
+
"?": "bool",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const KIND_TO_PREFIX = {
|
|
12
|
+
event: "@",
|
|
13
|
+
prop: ".",
|
|
14
|
+
bool: "?",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const ATTR_NAME_CHAR = /[\w:-]/;
|
|
18
|
+
const TAG_NAME_START_CHAR = /[A-Za-z]/;
|
|
19
|
+
const TAG_NAME_CHAR = /[\w:.-]/;
|
|
20
|
+
const MACRO_NAME_START_CHAR = /[A-Za-z$_]/;
|
|
21
|
+
const MACRO_NAME_CHAR = /[A-Za-z0-9$_]/;
|
|
22
|
+
|
|
23
|
+
function isWhitespace(char) {
|
|
24
|
+
return char === " " || char === "\t" || char === "\n" || char === "\r";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isReservedVirtualAttributeName(name) {
|
|
28
|
+
return /^__litsx_(event|prop|bool)_/.test(name);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function sanitizeIdentifierTailChar(char) {
|
|
32
|
+
return /[A-Za-z0-9$_]/.test(char) ? char : "_";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function encodeEditorVirtualAttributeName(name) {
|
|
36
|
+
const prefix = name[0];
|
|
37
|
+
const localName = name.slice(1);
|
|
38
|
+
const encodedPrefix = prefix === "@" ? "e" : prefix === "." ? "p" : "b";
|
|
39
|
+
return `${encodedPrefix}${Array.from(localName, sanitizeIdentifierTailChar).join("")}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function encodeEditorStaticHoistName(originalName, macroName) {
|
|
43
|
+
return `$${macroName}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function scanQuotedString(sourceText, start, quote) {
|
|
47
|
+
let index = start + 1;
|
|
48
|
+
|
|
49
|
+
while (index < sourceText.length) {
|
|
50
|
+
const char = sourceText[index];
|
|
51
|
+
if (char === "\\") {
|
|
52
|
+
index += 2;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (char === quote) {
|
|
56
|
+
return index + 1;
|
|
57
|
+
}
|
|
58
|
+
index += 1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return index;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function scanLineComment(sourceText, start) {
|
|
65
|
+
let index = start + 2;
|
|
66
|
+
while (index < sourceText.length && sourceText[index] !== "\n") {
|
|
67
|
+
index += 1;
|
|
68
|
+
}
|
|
69
|
+
return index;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function scanBlockComment(sourceText, start) {
|
|
73
|
+
let index = start + 2;
|
|
74
|
+
while (index < sourceText.length) {
|
|
75
|
+
if (sourceText[index] === "*" && sourceText[index + 1] === "/") {
|
|
76
|
+
return index + 2;
|
|
77
|
+
}
|
|
78
|
+
index += 1;
|
|
79
|
+
}
|
|
80
|
+
return index;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function scanTemplateLiteral(sourceText, start) {
|
|
84
|
+
let index = start + 1;
|
|
85
|
+
|
|
86
|
+
while (index < sourceText.length) {
|
|
87
|
+
const char = sourceText[index];
|
|
88
|
+
if (char === "\\") {
|
|
89
|
+
index += 2;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (char === "`") {
|
|
93
|
+
return index + 1;
|
|
94
|
+
}
|
|
95
|
+
if (char === "$" && sourceText[index + 1] === "{") {
|
|
96
|
+
index = scanBalancedBraces(sourceText, index + 1);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
index += 1;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return index;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function scanBalancedBraces(sourceText, start) {
|
|
106
|
+
let depth = 0;
|
|
107
|
+
let index = start;
|
|
108
|
+
|
|
109
|
+
while (index < sourceText.length) {
|
|
110
|
+
const char = sourceText[index];
|
|
111
|
+
const next = sourceText[index + 1];
|
|
112
|
+
|
|
113
|
+
if (char === "'" || char === "\"") {
|
|
114
|
+
index = scanQuotedString(sourceText, index, char);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (char === "`") {
|
|
119
|
+
index = scanTemplateLiteral(sourceText, index);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (char === "/" && next === "/") {
|
|
124
|
+
index = scanLineComment(sourceText, index);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (char === "/" && next === "*") {
|
|
129
|
+
index = scanBlockComment(sourceText, index);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (char === "{") {
|
|
134
|
+
depth += 1;
|
|
135
|
+
index += 1;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (char === "}") {
|
|
140
|
+
depth -= 1;
|
|
141
|
+
index += 1;
|
|
142
|
+
if (depth <= 0) {
|
|
143
|
+
return index;
|
|
144
|
+
}
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
index += 1;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return index;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function scanBalancedBracesWithJsx(sourceText, start, replacements, encodeAttributeName) {
|
|
155
|
+
let depth = 0;
|
|
156
|
+
let index = start;
|
|
157
|
+
|
|
158
|
+
while (index < sourceText.length) {
|
|
159
|
+
const char = sourceText[index];
|
|
160
|
+
const next = sourceText[index + 1];
|
|
161
|
+
|
|
162
|
+
if (char === "'" || char === "\"") {
|
|
163
|
+
index = scanQuotedString(sourceText, index, char);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (char === "`") {
|
|
168
|
+
index = scanTemplateLiteral(sourceText, index);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (char === "/" && next === "/") {
|
|
173
|
+
index = scanLineComment(sourceText, index);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (char === "/" && next === "*") {
|
|
178
|
+
index = scanBlockComment(sourceText, index);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (char === "<" && isLikelyJsxTagStart(sourceText, index)) {
|
|
183
|
+
index = scanJsxElement(sourceText, index, replacements, encodeAttributeName);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (char === "{") {
|
|
188
|
+
depth += 1;
|
|
189
|
+
index += 1;
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (char === "}") {
|
|
194
|
+
depth -= 1;
|
|
195
|
+
index += 1;
|
|
196
|
+
if (depth <= 0) {
|
|
197
|
+
return index;
|
|
198
|
+
}
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
index += 1;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return index;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function trimTrailingWhitespaceAndComments(sourceText) {
|
|
209
|
+
let text = sourceText;
|
|
210
|
+
let changed = true;
|
|
211
|
+
|
|
212
|
+
while (changed) {
|
|
213
|
+
changed = false;
|
|
214
|
+
|
|
215
|
+
const trimmedWhitespace = text.replace(/\s+$/u, "");
|
|
216
|
+
if (trimmedWhitespace !== text) {
|
|
217
|
+
text = trimmedWhitespace;
|
|
218
|
+
changed = true;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const trimmedLineComment = text.replace(/\/\/[^\n\r]*$/u, "");
|
|
222
|
+
if (trimmedLineComment !== text) {
|
|
223
|
+
text = trimmedLineComment;
|
|
224
|
+
changed = true;
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const trimmedBlockComment = text.replace(/\/\*[\s\S]*?\*\/$/u, "");
|
|
229
|
+
if (trimmedBlockComment !== text) {
|
|
230
|
+
text = trimmedBlockComment;
|
|
231
|
+
changed = true;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return text;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function previousSignificantIndex(sourceText, start) {
|
|
239
|
+
let index = start - 1;
|
|
240
|
+
while (index >= 0 && isWhitespace(sourceText[index])) {
|
|
241
|
+
index -= 1;
|
|
242
|
+
}
|
|
243
|
+
return index;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function readPreviousWord(sourceText, endIndex) {
|
|
247
|
+
let index = endIndex;
|
|
248
|
+
while (index >= 0 && /[A-Za-z]/.test(sourceText[index])) {
|
|
249
|
+
index -= 1;
|
|
250
|
+
}
|
|
251
|
+
return sourceText.slice(index + 1, endIndex + 1);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function isLikelyJsxTagStart(sourceText, index) {
|
|
255
|
+
const next = sourceText[index + 1];
|
|
256
|
+
if (!TAG_NAME_START_CHAR.test(next || "")) {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const previousIndex = previousSignificantIndex(sourceText, index);
|
|
261
|
+
if (previousIndex < 0) {
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const previousChar = sourceText[previousIndex];
|
|
266
|
+
if ("=({[,!?:;>&|".includes(previousChar)) {
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const previousWord = readPreviousWord(sourceText, previousIndex);
|
|
271
|
+
return ["return", "case", "throw", "yield", "else"].includes(previousWord);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function readJsxTagName(sourceText, start) {
|
|
275
|
+
let index = start + 1;
|
|
276
|
+
const isClosing = sourceText[index] === "/";
|
|
277
|
+
|
|
278
|
+
if (isClosing) {
|
|
279
|
+
index += 1;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (!TAG_NAME_START_CHAR.test(sourceText[index] || "")) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const nameStart = index;
|
|
287
|
+
|
|
288
|
+
while (index < sourceText.length && TAG_NAME_CHAR.test(sourceText[index])) {
|
|
289
|
+
index += 1;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return {
|
|
293
|
+
name: sourceText.slice(nameStart, index),
|
|
294
|
+
isClosing,
|
|
295
|
+
end: index,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function scanJsxTag(sourceText, start, replacements, encodeAttributeName) {
|
|
300
|
+
const tag = readJsxTagName(sourceText, start);
|
|
301
|
+
|
|
302
|
+
if (!tag) {
|
|
303
|
+
return {
|
|
304
|
+
end: start + 1,
|
|
305
|
+
tagName: null,
|
|
306
|
+
isClosing: false,
|
|
307
|
+
selfClosing: false,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
let index = tag.end;
|
|
312
|
+
|
|
313
|
+
if (tag.isClosing) {
|
|
314
|
+
while (index < sourceText.length) {
|
|
315
|
+
if (sourceText[index] === ">") {
|
|
316
|
+
return {
|
|
317
|
+
end: index + 1,
|
|
318
|
+
tagName: tag.name,
|
|
319
|
+
isClosing: true,
|
|
320
|
+
selfClosing: false,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
index += 1;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return {
|
|
328
|
+
end: index,
|
|
329
|
+
tagName: tag.name,
|
|
330
|
+
isClosing: true,
|
|
331
|
+
selfClosing: false,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function scanAttributeValue(valueStart) {
|
|
336
|
+
let valueIndex = valueStart;
|
|
337
|
+
|
|
338
|
+
while (valueIndex < sourceText.length && isWhitespace(sourceText[valueIndex])) {
|
|
339
|
+
valueIndex += 1;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (valueIndex >= sourceText.length) {
|
|
343
|
+
return valueIndex;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const valueChar = sourceText[valueIndex];
|
|
347
|
+
if (valueChar === "{") {
|
|
348
|
+
return scanBalancedBracesWithJsx(
|
|
349
|
+
sourceText,
|
|
350
|
+
valueIndex,
|
|
351
|
+
replacements,
|
|
352
|
+
encodeAttributeName
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (valueChar === "'" || valueChar === "\"") {
|
|
357
|
+
return scanQuotedString(sourceText, valueIndex, valueChar);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
while (
|
|
361
|
+
valueIndex < sourceText.length &&
|
|
362
|
+
!isWhitespace(sourceText[valueIndex]) &&
|
|
363
|
+
sourceText[valueIndex] !== ">" &&
|
|
364
|
+
!(sourceText[valueIndex] === "/" && sourceText[valueIndex + 1] === ">")
|
|
365
|
+
) {
|
|
366
|
+
valueIndex += 1;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return valueIndex;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
while (index < sourceText.length) {
|
|
373
|
+
const char = sourceText[index];
|
|
374
|
+
const next = sourceText[index + 1];
|
|
375
|
+
|
|
376
|
+
if (char === ">") {
|
|
377
|
+
return {
|
|
378
|
+
end: index + 1,
|
|
379
|
+
tagName: tag.name,
|
|
380
|
+
isClosing: false,
|
|
381
|
+
selfClosing: false,
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (char === "/" && next === ">") {
|
|
386
|
+
return {
|
|
387
|
+
end: index + 2,
|
|
388
|
+
tagName: tag.name,
|
|
389
|
+
isClosing: false,
|
|
390
|
+
selfClosing: true,
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (isWhitespace(char)) {
|
|
395
|
+
index += 1;
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (char === "{") {
|
|
400
|
+
index = scanBalancedBracesWithJsx(
|
|
401
|
+
sourceText,
|
|
402
|
+
index,
|
|
403
|
+
replacements,
|
|
404
|
+
encodeAttributeName
|
|
405
|
+
);
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (char === "'" || char === "\"") {
|
|
410
|
+
index = scanQuotedString(sourceText, index, char);
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (Object.hasOwn(PREFIX_TO_KIND, char) && ATTR_NAME_CHAR.test(next || "")) {
|
|
415
|
+
const attrStart = index;
|
|
416
|
+
index += 1;
|
|
417
|
+
|
|
418
|
+
while (index < sourceText.length && ATTR_NAME_CHAR.test(sourceText[index])) {
|
|
419
|
+
index += 1;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const originalName = sourceText.slice(attrStart, index);
|
|
423
|
+
replacements.push({
|
|
424
|
+
start: attrStart,
|
|
425
|
+
end: index,
|
|
426
|
+
originalName,
|
|
427
|
+
replacement: encodeAttributeName(originalName),
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
while (index < sourceText.length && isWhitespace(sourceText[index])) {
|
|
431
|
+
index += 1;
|
|
432
|
+
}
|
|
433
|
+
if (sourceText[index] === "=") {
|
|
434
|
+
index = scanAttributeValue(index + 1);
|
|
435
|
+
}
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const attrStart = index;
|
|
440
|
+
while (
|
|
441
|
+
index < sourceText.length &&
|
|
442
|
+
!isWhitespace(sourceText[index]) &&
|
|
443
|
+
sourceText[index] !== "=" &&
|
|
444
|
+
sourceText[index] !== ">" &&
|
|
445
|
+
!(sourceText[index] === "/" && sourceText[index + 1] === ">")
|
|
446
|
+
) {
|
|
447
|
+
index += 1;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (index === attrStart) {
|
|
451
|
+
index += 1;
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
while (index < sourceText.length && isWhitespace(sourceText[index])) {
|
|
456
|
+
index += 1;
|
|
457
|
+
}
|
|
458
|
+
if (sourceText[index] === "=") {
|
|
459
|
+
index = scanAttributeValue(index + 1);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return {
|
|
464
|
+
end: index,
|
|
465
|
+
tagName: tag.name,
|
|
466
|
+
isClosing: false,
|
|
467
|
+
selfClosing: false,
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function scanJsxElement(sourceText, start, replacements, encodeAttributeName) {
|
|
472
|
+
const openingTag = scanJsxTag(sourceText, start, replacements, encodeAttributeName);
|
|
473
|
+
|
|
474
|
+
if (
|
|
475
|
+
openingTag.isClosing ||
|
|
476
|
+
openingTag.selfClosing ||
|
|
477
|
+
!openingTag.tagName
|
|
478
|
+
) {
|
|
479
|
+
return openingTag.end;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
let index = openingTag.end;
|
|
483
|
+
|
|
484
|
+
while (index < sourceText.length) {
|
|
485
|
+
const char = sourceText[index];
|
|
486
|
+
const next = sourceText[index + 1];
|
|
487
|
+
|
|
488
|
+
if (char === "'" || char === "\"") {
|
|
489
|
+
index = scanQuotedString(sourceText, index, char);
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (char === "`") {
|
|
494
|
+
index = scanTemplateLiteral(sourceText, index);
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (char === "/" && next === "/") {
|
|
499
|
+
index = scanLineComment(sourceText, index);
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (char === "/" && next === "*") {
|
|
504
|
+
index = scanBlockComment(sourceText, index);
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (char === "{") {
|
|
509
|
+
index = scanBalancedBracesWithJsx(
|
|
510
|
+
sourceText,
|
|
511
|
+
index,
|
|
512
|
+
replacements,
|
|
513
|
+
encodeAttributeName
|
|
514
|
+
);
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
if (char === "<") {
|
|
519
|
+
const nestedTag = readJsxTagName(sourceText, index);
|
|
520
|
+
|
|
521
|
+
if (!nestedTag) {
|
|
522
|
+
index += 1;
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (nestedTag.isClosing && nestedTag.name === openingTag.tagName) {
|
|
527
|
+
return scanJsxTag(sourceText, index, replacements, encodeAttributeName).end;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (!nestedTag.isClosing) {
|
|
531
|
+
index = scanJsxElement(sourceText, index, replacements, encodeAttributeName);
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
index += 1;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
return index;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
function encodeVirtualAttributeName(name) {
|
|
543
|
+
const prefix = name[0];
|
|
544
|
+
const localName = name.slice(1);
|
|
545
|
+
const kind = PREFIX_TO_KIND[prefix];
|
|
546
|
+
|
|
547
|
+
if (!kind) {
|
|
548
|
+
return name;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
return `__litsx_${kind}_${localName}`;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
function decodeVirtualAttributeName(name) {
|
|
555
|
+
const match = /^__litsx_(event|prop|bool)_(.+)$/.exec(name);
|
|
556
|
+
|
|
557
|
+
if (!match) {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const [, kind, localName] = match;
|
|
562
|
+
return `${KIND_TO_PREFIX[kind]}${localName}`;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function decodeVirtualStaticHoistName(name) {
|
|
566
|
+
const match = /^__litsx_static_([A-Za-z$_][A-Za-z0-9$_]*)$/.exec(name);
|
|
567
|
+
|
|
568
|
+
if (!match) {
|
|
569
|
+
return null;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
return `^${match[1]}`;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function remapVirtualText(text) {
|
|
576
|
+
if (typeof text !== "string") {
|
|
577
|
+
return text;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return text
|
|
581
|
+
.replace(/__litsx_(event|prop|bool)_[\w:-]+/g, (name) => (
|
|
582
|
+
decodeVirtualAttributeName(name) ?? name
|
|
583
|
+
))
|
|
584
|
+
.replace(/__litsx_static_[A-Za-z$_][A-Za-z0-9$_]*/g, (name) => (
|
|
585
|
+
decodeVirtualStaticHoistName(name) ?? name
|
|
586
|
+
));
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
function looksLikeLitsxJsx(sourceText) {
|
|
590
|
+
return (
|
|
591
|
+
/<[\w.-]+[^>]*\s(?:[@.?][\w:-]+)/m.test(sourceText) ||
|
|
592
|
+
/(?:^|[;{}]\s*)\^[A-Za-z$_][A-Za-z0-9$_]*/m.test(sourceText) ||
|
|
593
|
+
/^\s*\^[A-Za-z$_][A-Za-z0-9$_]*/m.test(sourceText)
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
function isLikelyStaticMacroStart(sourceText, index) {
|
|
598
|
+
const next = sourceText[index + 1];
|
|
599
|
+
if (!MACRO_NAME_START_CHAR.test(next || "")) {
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
const prefix = trimTrailingWhitespaceAndComments(sourceText.slice(0, index));
|
|
604
|
+
if (!prefix) {
|
|
605
|
+
return true;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
const previousChar = prefix[prefix.length - 1];
|
|
609
|
+
return previousChar === ";" || previousChar === "{" || previousChar === "}";
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
function scanStaticMacro(sourceText, start, replacements, encodeMacroName) {
|
|
613
|
+
let index = start + 1;
|
|
614
|
+
|
|
615
|
+
while (index < sourceText.length && MACRO_NAME_CHAR.test(sourceText[index])) {
|
|
616
|
+
index += 1;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
const originalName = sourceText.slice(start, index);
|
|
620
|
+
const macroName = originalName.slice(1);
|
|
621
|
+
|
|
622
|
+
if (macroName === "mixins") {
|
|
623
|
+
return index;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
replacements.push({
|
|
627
|
+
start,
|
|
628
|
+
end: index,
|
|
629
|
+
originalName,
|
|
630
|
+
replacement: encodeMacroName(originalName, macroName),
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
return index;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function createVirtualLitsxJsxSource(sourceText, options = {}) {
|
|
637
|
+
const strategy = options.strategy === "editor" ? "editor" : "compiler";
|
|
638
|
+
const includeSourceMap = options.sourceMap === true;
|
|
639
|
+
const encodeAttributeName =
|
|
640
|
+
strategy === "editor"
|
|
641
|
+
? encodeEditorVirtualAttributeName
|
|
642
|
+
: encodeVirtualAttributeName;
|
|
643
|
+
const encodeMacroName =
|
|
644
|
+
strategy === "editor"
|
|
645
|
+
? encodeEditorStaticHoistName
|
|
646
|
+
: (_originalName, macroName) => `__litsx_static_${macroName}`;
|
|
647
|
+
|
|
648
|
+
if (!sourceText || typeof sourceText !== "string") {
|
|
649
|
+
return {
|
|
650
|
+
code: sourceText,
|
|
651
|
+
map: null,
|
|
652
|
+
replacements: [],
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
if (strategy === "compiler" && sourceText.includes("__litsx_")) {
|
|
657
|
+
return {
|
|
658
|
+
code: sourceText,
|
|
659
|
+
map: null,
|
|
660
|
+
replacements: [],
|
|
661
|
+
collision: true,
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
if (!looksLikeLitsxJsx(sourceText)) {
|
|
666
|
+
return {
|
|
667
|
+
code: sourceText,
|
|
668
|
+
map: null,
|
|
669
|
+
replacements: [],
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
const replacements = [];
|
|
674
|
+
let index = 0;
|
|
675
|
+
|
|
676
|
+
while (index < sourceText.length) {
|
|
677
|
+
const char = sourceText[index];
|
|
678
|
+
const next = sourceText[index + 1];
|
|
679
|
+
|
|
680
|
+
if (char === "'" || char === "\"") {
|
|
681
|
+
index = scanQuotedString(sourceText, index, char);
|
|
682
|
+
continue;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
if (char === "`") {
|
|
686
|
+
index = scanTemplateLiteral(sourceText, index);
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
if (char === "/" && next === "/") {
|
|
691
|
+
index = scanLineComment(sourceText, index);
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (char === "/" && next === "*") {
|
|
696
|
+
index = scanBlockComment(sourceText, index);
|
|
697
|
+
continue;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
if (char === "<" && isLikelyJsxTagStart(sourceText, index)) {
|
|
701
|
+
index = scanJsxElement(sourceText, index, replacements, encodeAttributeName);
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
if (char === "^" && isLikelyStaticMacroStart(sourceText, index)) {
|
|
706
|
+
index = scanStaticMacro(sourceText, index, replacements, encodeMacroName);
|
|
707
|
+
continue;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
if (char === "{") {
|
|
711
|
+
index += 1;
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
if (char === "}") {
|
|
716
|
+
index += 1;
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
index += 1;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
if (!replacements.length) {
|
|
724
|
+
return {
|
|
725
|
+
code: sourceText,
|
|
726
|
+
map: null,
|
|
727
|
+
replacements: [],
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
let lastIndex = 0;
|
|
732
|
+
let transformed = "";
|
|
733
|
+
|
|
734
|
+
for (const replacement of replacements) {
|
|
735
|
+
transformed += sourceText.slice(lastIndex, replacement.start);
|
|
736
|
+
transformed += replacement.replacement;
|
|
737
|
+
lastIndex = replacement.end;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
transformed += sourceText.slice(lastIndex);
|
|
741
|
+
|
|
742
|
+
return {
|
|
743
|
+
code: transformed,
|
|
744
|
+
map: includeSourceMap
|
|
745
|
+
? createVirtualLitsxJsxSourceMap(sourceText, replacements, {
|
|
746
|
+
sourceFileName: options.sourceFileName,
|
|
747
|
+
})
|
|
748
|
+
: null,
|
|
749
|
+
replacements,
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
function createVirtualLitsxJsxSourceMap(
|
|
754
|
+
sourceText,
|
|
755
|
+
replacements = [],
|
|
756
|
+
options = {}
|
|
757
|
+
) {
|
|
758
|
+
const editable = new MagicString(sourceText);
|
|
759
|
+
applyVirtualAttributeReplacements(editable, replacements);
|
|
760
|
+
|
|
761
|
+
return editable.generateMap({
|
|
762
|
+
hires: true,
|
|
763
|
+
source: options.sourceFileName,
|
|
764
|
+
includeContent: true,
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
function findReplacementByVirtualPosition(position, replacements) {
|
|
769
|
+
let originalCursor = 0;
|
|
770
|
+
let virtualCursor = 0;
|
|
771
|
+
|
|
772
|
+
for (const replacement of replacements) {
|
|
773
|
+
const untouchedLength = replacement.start - originalCursor;
|
|
774
|
+
const replacementVirtualStart = virtualCursor + untouchedLength;
|
|
775
|
+
const replacementVirtualEnd =
|
|
776
|
+
replacementVirtualStart + replacement.replacement.length;
|
|
777
|
+
|
|
778
|
+
if (position >= replacementVirtualStart && position < replacementVirtualEnd) {
|
|
779
|
+
return {
|
|
780
|
+
replacement,
|
|
781
|
+
virtualStart: replacementVirtualStart,
|
|
782
|
+
virtualEnd: replacementVirtualEnd,
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
originalCursor = replacement.end;
|
|
787
|
+
virtualCursor = replacementVirtualEnd;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
return null;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
function mapOriginalPositionToVirtual(position, replacements = []) {
|
|
794
|
+
if (!replacements.length) {
|
|
795
|
+
return position;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
let offset = 0;
|
|
799
|
+
|
|
800
|
+
for (const replacement of replacements) {
|
|
801
|
+
if (position < replacement.start) {
|
|
802
|
+
break;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
const originalLength = replacement.end - replacement.start;
|
|
806
|
+
const replacementLength = replacement.replacement.length;
|
|
807
|
+
|
|
808
|
+
if (position < replacement.end) {
|
|
809
|
+
return replacement.start + offset;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
offset += replacementLength - originalLength;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
return position + offset;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
function remapTextSpanToOriginal(span, replacements = []) {
|
|
819
|
+
if (!span || !replacements.length) {
|
|
820
|
+
return span;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
const startMapping = findReplacementByVirtualPosition(span.start, replacements);
|
|
824
|
+
if (startMapping) {
|
|
825
|
+
return {
|
|
826
|
+
start: startMapping.replacement.start,
|
|
827
|
+
length: startMapping.replacement.end - startMapping.replacement.start,
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
let originalStart = span.start;
|
|
832
|
+
let originalEnd = span.start + span.length;
|
|
833
|
+
|
|
834
|
+
for (const replacement of replacements) {
|
|
835
|
+
const originalLength = replacement.end - replacement.start;
|
|
836
|
+
const replacementLength = replacement.replacement.length;
|
|
837
|
+
const delta = originalLength - replacementLength;
|
|
838
|
+
const virtualStart = mapOriginalPositionToVirtual(replacement.start, replacements);
|
|
839
|
+
const virtualEnd = virtualStart + replacementLength;
|
|
840
|
+
|
|
841
|
+
if (virtualEnd <= span.start) {
|
|
842
|
+
originalStart += delta;
|
|
843
|
+
originalEnd += delta;
|
|
844
|
+
continue;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
if (virtualStart < span.start) {
|
|
848
|
+
originalStart = replacement.start;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
if (virtualStart < span.start + span.length) {
|
|
852
|
+
originalEnd += delta;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
return {
|
|
857
|
+
start: originalStart,
|
|
858
|
+
length: Math.max(0, originalEnd - originalStart),
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
function remapVirtualPositionToOriginal(position, replacements = []) {
|
|
863
|
+
const span = remapTextSpanToOriginal({ start: position, length: 0 }, replacements);
|
|
864
|
+
return span.start;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
const mapVirtualPositionToOriginal = remapVirtualPositionToOriginal;
|
|
868
|
+
|
|
869
|
+
function applyVirtualAttributeReplacements(editable, replacements = []) {
|
|
870
|
+
for (const replacement of replacements) {
|
|
871
|
+
editable.overwrite(replacement.start, replacement.end, replacement.replacement);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
exports.applyVirtualAttributeReplacements = applyVirtualAttributeReplacements;
|
|
876
|
+
exports.createVirtualLitsxJsxSource = createVirtualLitsxJsxSource;
|
|
877
|
+
exports.createVirtualLitsxJsxSourceMap = createVirtualLitsxJsxSourceMap;
|
|
878
|
+
exports.decodeVirtualAttributeName = decodeVirtualAttributeName;
|
|
879
|
+
exports.decodeVirtualStaticHoistName = decodeVirtualStaticHoistName;
|
|
880
|
+
exports.encodeVirtualAttributeName = encodeVirtualAttributeName;
|
|
881
|
+
exports.isReservedVirtualAttributeName = isReservedVirtualAttributeName;
|
|
882
|
+
exports.looksLikeLitsxJsx = looksLikeLitsxJsx;
|
|
883
|
+
exports.mapOriginalPositionToVirtual = mapOriginalPositionToVirtual;
|
|
884
|
+
exports.mapVirtualPositionToOriginal = mapVirtualPositionToOriginal;
|
|
885
|
+
exports.remapTextSpanToOriginal = remapTextSpanToOriginal;
|
|
886
|
+
exports.remapVirtualPositionToOriginal = remapVirtualPositionToOriginal;
|
|
887
|
+
exports.remapVirtualText = remapVirtualText;
|
|
888
|
+
//# sourceMappingURL=index.cjs.map
|