@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/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