@vanduo-oss/vd3-cbun 1.3.2 → 1.4.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.
@@ -2,6 +2,26 @@
2
2
  import { defineComponent, h, ref, onMounted, onBeforeUnmount, watch } from "vue";
3
3
 
4
4
  // src/code-editor/tokenizer/scanner.js
5
+ function matchRule(source, i, rules) {
6
+ for (let r = 0; r < rules.length; r++) {
7
+ const rule = rules[r];
8
+ if (rule.when && !rule.when(source, i)) continue;
9
+ let value;
10
+ if (rule.consume) {
11
+ const got = rule.consume(source, i);
12
+ if (!got || !got.value || got.value.length === 0) continue;
13
+ value = got.value;
14
+ } else {
15
+ rule.re.lastIndex = i;
16
+ const m = rule.re.exec(source);
17
+ if (!m || m[0].length === 0) continue;
18
+ value = m[0];
19
+ }
20
+ const tokens = rule.expand ? rule.expand(value) : [{ type: rule.type, value }];
21
+ return { tokens, length: value.length, value };
22
+ }
23
+ return null;
24
+ }
5
25
  function scan(source, rules) {
6
26
  const tokens = [];
7
27
  const n = source.length;
@@ -14,26 +34,12 @@ function scan(source, rules) {
14
34
  plainStart = -1;
15
35
  };
16
36
  while (i < n) {
17
- let matched = false;
18
- for (let r = 0; r < rules.length; r++) {
19
- const rule = rules[r];
20
- rule.re.lastIndex = i;
21
- const m = rule.re.exec(source);
22
- if (m && m[0].length > 0) {
23
- flushPlain(i);
24
- const value = m[0];
25
- if (rule.expand) {
26
- const sub = rule.expand(value);
27
- for (let k = 0; k < sub.length; k++) tokens.push(sub[k]);
28
- } else {
29
- tokens.push({ type: rule.type, value });
30
- }
31
- i += value.length;
32
- matched = true;
33
- break;
34
- }
35
- }
36
- if (!matched) {
37
+ const hit = matchRule(source, i, rules);
38
+ if (hit) {
39
+ flushPlain(i);
40
+ for (let k = 0; k < hit.tokens.length; k++) tokens.push(hit.tokens[k]);
41
+ i += hit.length;
42
+ } else {
37
43
  if (plainStart === -1) plainStart = i;
38
44
  i++;
39
45
  }
@@ -165,14 +171,194 @@ var BUILTINS = [
165
171
  "NaN",
166
172
  "Infinity"
167
173
  ];
174
+ var REGEX_AFTER_KEYWORD = /* @__PURE__ */ new Set([
175
+ "return",
176
+ "throw",
177
+ "case",
178
+ "in",
179
+ "of",
180
+ "typeof",
181
+ "void",
182
+ "delete",
183
+ "new",
184
+ "else",
185
+ "do",
186
+ "yield",
187
+ "await",
188
+ "extends"
189
+ ]);
190
+ function isWs(c) {
191
+ return c === 32 || c === 9 || c === 10 || c === 13;
192
+ }
193
+ function isWord(c) {
194
+ return c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 36 || c === 95;
195
+ }
196
+ function canStartRegex(source, i) {
197
+ let j = i - 1;
198
+ while (j >= 0 && isWs(source.charCodeAt(j))) j--;
199
+ if (j < 0) return true;
200
+ const c = source.charCodeAt(j);
201
+ if (c === 41 || c === 93) return false;
202
+ if ((c === 43 || c === 45) && j > 0 && source.charCodeAt(j - 1) === c) return false;
203
+ if (isWord(c)) {
204
+ let start = j;
205
+ while (start > 0 && isWord(source.charCodeAt(start - 1))) start--;
206
+ return REGEX_AFTER_KEYWORD.has(source.slice(start, j + 1));
207
+ }
208
+ return true;
209
+ }
210
+ function isRegexFlag(c) {
211
+ return c === 100 || c === 103 || c === 105 || c === 109 || c === 115 || c === 117 || c === 118 || c === 121;
212
+ }
213
+ function consumeRegex(source, i) {
214
+ const n = source.length;
215
+ let j = i + 1;
216
+ let inClass = false;
217
+ while (j < n) {
218
+ const c = source.charCodeAt(j);
219
+ if (c === 10) return null;
220
+ if (c === 92) {
221
+ j += 2;
222
+ continue;
223
+ }
224
+ if (inClass) {
225
+ if (c === 93) inClass = false;
226
+ j++;
227
+ continue;
228
+ }
229
+ if (c === 91) {
230
+ inClass = true;
231
+ j++;
232
+ continue;
233
+ }
234
+ if (c === 47) {
235
+ j++;
236
+ while (j < n && isRegexFlag(source.charCodeAt(j))) j++;
237
+ return { value: source.slice(i, j) };
238
+ }
239
+ j++;
240
+ }
241
+ return null;
242
+ }
243
+ function skipQuoted(s, i) {
244
+ const q = s.charCodeAt(i);
245
+ let j = i + 1;
246
+ const n = s.length;
247
+ while (j < n) {
248
+ const c = s.charCodeAt(j);
249
+ if (c === 92) {
250
+ j += 2;
251
+ continue;
252
+ }
253
+ if (c === q) return j + 1;
254
+ if (c === 10) return j;
255
+ j++;
256
+ }
257
+ return n;
258
+ }
259
+ function findTemplateInterpEnd(s, start) {
260
+ let depth = 1;
261
+ let i = start;
262
+ const n = s.length;
263
+ while (i < n && depth > 0) {
264
+ const c = s.charCodeAt(i);
265
+ if (c === 47 && s.charCodeAt(i + 1) === 47) {
266
+ const nl = s.indexOf("\n", i + 2);
267
+ if (nl < 0) return n;
268
+ i = nl;
269
+ continue;
270
+ }
271
+ if (c === 47 && s.charCodeAt(i + 1) === 42) {
272
+ const end = s.indexOf("*/", i + 2);
273
+ i = end < 0 ? n : end + 2;
274
+ continue;
275
+ }
276
+ if (c === 34 || c === 39) {
277
+ i = skipQuoted(s, i);
278
+ continue;
279
+ }
280
+ if (c === 96) {
281
+ i = skipTemplate(s, i);
282
+ continue;
283
+ }
284
+ if (c === 123) depth++;
285
+ else if (c === 125) {
286
+ depth--;
287
+ if (depth === 0) return i;
288
+ }
289
+ i++;
290
+ }
291
+ return n;
292
+ }
293
+ function skipTemplate(s, i) {
294
+ let j = i + 1;
295
+ const n = s.length;
296
+ while (j < n) {
297
+ const c = s.charCodeAt(j);
298
+ if (c === 92) {
299
+ j += 2;
300
+ continue;
301
+ }
302
+ if (c === 96) return j + 1;
303
+ if (c === 36 && s.charCodeAt(j + 1) === 123) {
304
+ const end = findTemplateInterpEnd(s, j + 2);
305
+ j = end < n && s.charCodeAt(end) === 125 ? end + 1 : end;
306
+ continue;
307
+ }
308
+ j++;
309
+ }
310
+ return n;
311
+ }
312
+ function expandTemplateLiteral(value, rules) {
313
+ const out = [];
314
+ const n = value.length;
315
+ let i = 1;
316
+ let strStart = 0;
317
+ const flushString = (end) => {
318
+ if (end > strStart) out.push({ type: "string", value: value.slice(strStart, end) });
319
+ };
320
+ while (i < n) {
321
+ const c = value.charCodeAt(i);
322
+ if (c === 92) {
323
+ i += i + 1 < n ? 2 : 1;
324
+ continue;
325
+ }
326
+ if (c === 96) {
327
+ flushString(i + 1);
328
+ return out;
329
+ }
330
+ if (c === 36 && i + 1 < n && value.charCodeAt(i + 1) === 123) {
331
+ flushString(i);
332
+ out.push({ type: "operator", value: "${" });
333
+ const innerStart = i + 2;
334
+ const innerEnd = findTemplateInterpEnd(value, innerStart);
335
+ const inner = value.slice(innerStart, innerEnd);
336
+ if (inner) {
337
+ const parts = scan(inner, rules);
338
+ for (let k = 0; k < parts.length; k++) out.push(parts[k]);
339
+ }
340
+ if (innerEnd < n && value.charCodeAt(innerEnd) === 125) {
341
+ out.push({ type: "punctuation", value: "}" });
342
+ i = innerEnd + 1;
343
+ } else {
344
+ i = innerEnd;
345
+ }
346
+ strStart = i;
347
+ continue;
348
+ }
349
+ i++;
350
+ }
351
+ flushString(n);
352
+ return out;
353
+ }
168
354
  function makeRules(keywords) {
169
- return [
355
+ const rules = [
170
356
  { type: "comment", re: /\/\/[^\n]*/y },
171
357
  { type: "comment", re: /\/\*[\s\S]*?(?:\*\/|$)/y },
172
358
  // unterminated -> comment to EOF
173
359
  { type: "string", re: /"(?:[^"\\\n]|\\.)*"?/y },
174
360
  { type: "string", re: /'(?:[^'\\\n]|\\.)*'?/y },
175
- { type: "string", re: /`(?:[^`\\]|\\.)*`?/y },
361
+ { expand: (value) => expandTemplateLiteral(value, rules), re: /`(?:[^`\\]|\\.)*`?/y },
176
362
  {
177
363
  type: "number",
178
364
  re: /0[xX][\da-fA-F_]+n?|0[bB][01_]+n?|0[oO][0-7_]+n?|(?:\d[\d_]*\.?[\d_]*|\.\d[\d_]*)(?:[eE][+-]?\d+)?n?/y
@@ -183,9 +369,15 @@ function makeRules(keywords) {
183
369
  { type: "builtin", re: wordRegex(BUILTINS) },
184
370
  { type: "function", re: /[A-Za-z_$][\w$]*(?=\s*\()/y },
185
371
  { type: "plain", re: /[A-Za-z_$][\w$]*/y },
372
+ {
373
+ type: "regex",
374
+ when: (source, i) => source.charCodeAt(i) === 47 && canStartRegex(source, i),
375
+ consume: consumeRegex
376
+ },
186
377
  { type: "operator", re: /\.{3}|=>|[+\-*/%=<>!&|^~?]+/y },
187
378
  { type: "punctuation", re: /[{}()[\];,.:]/y }
188
379
  ];
380
+ return rules;
189
381
  }
190
382
  var JS_RULES = makeRules(JS_KEYWORDS);
191
383
  var TS_RULES = makeRules(TS_KEYWORDS);
@@ -196,8 +388,304 @@ function tokenizeTypeScript(source) {
196
388
  return scan(source, TS_RULES);
197
389
  }
198
390
 
391
+ // src/code-editor/tokenizer/css.js
392
+ var PROPERTIES = [
393
+ "align-content",
394
+ "align-items",
395
+ "align-self",
396
+ "all",
397
+ "animation",
398
+ "animation-delay",
399
+ "animation-direction",
400
+ "animation-duration",
401
+ "animation-fill-mode",
402
+ "animation-iteration-count",
403
+ "animation-name",
404
+ "animation-play-state",
405
+ "animation-timing-function",
406
+ "appearance",
407
+ "aspect-ratio",
408
+ "backdrop-filter",
409
+ "backface-visibility",
410
+ "background",
411
+ "background-attachment",
412
+ "background-blend-mode",
413
+ "background-clip",
414
+ "background-color",
415
+ "background-image",
416
+ "background-origin",
417
+ "background-position",
418
+ "background-repeat",
419
+ "background-size",
420
+ "block-size",
421
+ "border",
422
+ "border-block",
423
+ "border-block-end",
424
+ "border-block-start",
425
+ "border-bottom",
426
+ "border-bottom-color",
427
+ "border-bottom-left-radius",
428
+ "border-bottom-right-radius",
429
+ "border-bottom-style",
430
+ "border-bottom-width",
431
+ "border-collapse",
432
+ "border-color",
433
+ "border-end-end-radius",
434
+ "border-end-start-radius",
435
+ "border-image",
436
+ "border-inline",
437
+ "border-inline-end",
438
+ "border-inline-start",
439
+ "border-left",
440
+ "border-left-color",
441
+ "border-left-style",
442
+ "border-left-width",
443
+ "border-radius",
444
+ "border-right",
445
+ "border-right-color",
446
+ "border-right-style",
447
+ "border-right-width",
448
+ "border-spacing",
449
+ "border-start-end-radius",
450
+ "border-start-start-radius",
451
+ "border-style",
452
+ "border-top",
453
+ "border-top-color",
454
+ "border-top-left-radius",
455
+ "border-top-right-radius",
456
+ "border-top-style",
457
+ "border-top-width",
458
+ "border-width",
459
+ "bottom",
460
+ "box-decoration-break",
461
+ "box-shadow",
462
+ "box-sizing",
463
+ "break-after",
464
+ "break-before",
465
+ "break-inside",
466
+ "caption-side",
467
+ "caret-color",
468
+ "clear",
469
+ "clip",
470
+ "clip-path",
471
+ "color",
472
+ "color-scheme",
473
+ "column-count",
474
+ "column-fill",
475
+ "column-gap",
476
+ "column-rule",
477
+ "column-span",
478
+ "column-width",
479
+ "columns",
480
+ "contain",
481
+ "container",
482
+ "content",
483
+ "counter-increment",
484
+ "counter-reset",
485
+ "cursor",
486
+ "direction",
487
+ "display",
488
+ "empty-cells",
489
+ "filter",
490
+ "flex",
491
+ "flex-basis",
492
+ "flex-direction",
493
+ "flex-flow",
494
+ "flex-grow",
495
+ "flex-shrink",
496
+ "flex-wrap",
497
+ "float",
498
+ "font",
499
+ "font-family",
500
+ "font-feature-settings",
501
+ "font-kerning",
502
+ "font-size",
503
+ "font-size-adjust",
504
+ "font-stretch",
505
+ "font-style",
506
+ "font-synthesis",
507
+ "font-variant",
508
+ "font-variation-settings",
509
+ "font-weight",
510
+ "gap",
511
+ "grid",
512
+ "grid-area",
513
+ "grid-auto-columns",
514
+ "grid-auto-flow",
515
+ "grid-auto-rows",
516
+ "grid-column",
517
+ "grid-column-end",
518
+ "grid-column-start",
519
+ "grid-row",
520
+ "grid-row-end",
521
+ "grid-row-start",
522
+ "grid-template",
523
+ "grid-template-areas",
524
+ "grid-template-columns",
525
+ "grid-template-rows",
526
+ "hanging-punctuation",
527
+ "height",
528
+ "hyphens",
529
+ "image-rendering",
530
+ "inline-size",
531
+ "inset",
532
+ "inset-block",
533
+ "inset-inline",
534
+ "isolation",
535
+ "justify-content",
536
+ "justify-items",
537
+ "justify-self",
538
+ "left",
539
+ "letter-spacing",
540
+ "line-break",
541
+ "line-clamp",
542
+ "line-height",
543
+ "list-style",
544
+ "list-style-image",
545
+ "list-style-position",
546
+ "list-style-type",
547
+ "margin",
548
+ "margin-block",
549
+ "margin-block-end",
550
+ "margin-block-start",
551
+ "margin-bottom",
552
+ "margin-inline",
553
+ "margin-inline-end",
554
+ "margin-inline-start",
555
+ "margin-left",
556
+ "margin-right",
557
+ "margin-top",
558
+ "mask",
559
+ "mask-image",
560
+ "max-block-size",
561
+ "max-height",
562
+ "max-inline-size",
563
+ "max-width",
564
+ "min-block-size",
565
+ "min-height",
566
+ "min-inline-size",
567
+ "min-width",
568
+ "mix-blend-mode",
569
+ "object-fit",
570
+ "object-position",
571
+ "offset",
572
+ "opacity",
573
+ "order",
574
+ "orphans",
575
+ "outline",
576
+ "outline-color",
577
+ "outline-offset",
578
+ "outline-style",
579
+ "outline-width",
580
+ "overflow",
581
+ "overflow-anchor",
582
+ "overflow-wrap",
583
+ "overflow-x",
584
+ "overflow-y",
585
+ "overscroll-behavior",
586
+ "padding",
587
+ "padding-block",
588
+ "padding-block-end",
589
+ "padding-block-start",
590
+ "padding-bottom",
591
+ "padding-inline",
592
+ "padding-inline-end",
593
+ "padding-inline-start",
594
+ "padding-left",
595
+ "padding-right",
596
+ "padding-top",
597
+ "page-break-after",
598
+ "page-break-before",
599
+ "page-break-inside",
600
+ "perspective",
601
+ "place-content",
602
+ "place-items",
603
+ "place-self",
604
+ "pointer-events",
605
+ "position",
606
+ "quotes",
607
+ "resize",
608
+ "right",
609
+ "rotate",
610
+ "row-gap",
611
+ "scale",
612
+ "scroll-behavior",
613
+ "scroll-margin",
614
+ "scroll-padding",
615
+ "scroll-snap-align",
616
+ "scroll-snap-type",
617
+ "shape-outside",
618
+ "tab-size",
619
+ "table-layout",
620
+ "text-align",
621
+ "text-align-last",
622
+ "text-decoration",
623
+ "text-decoration-color",
624
+ "text-decoration-line",
625
+ "text-decoration-style",
626
+ "text-decoration-thickness",
627
+ "text-emphasis",
628
+ "text-indent",
629
+ "text-overflow",
630
+ "text-rendering",
631
+ "text-shadow",
632
+ "text-transform",
633
+ "text-underline-offset",
634
+ "text-wrap",
635
+ "top",
636
+ "touch-action",
637
+ "transform",
638
+ "transform-origin",
639
+ "transition",
640
+ "transition-delay",
641
+ "transition-duration",
642
+ "transition-property",
643
+ "transition-timing-function",
644
+ "translate",
645
+ "unicode-bidi",
646
+ "user-select",
647
+ "vertical-align",
648
+ "visibility",
649
+ "white-space",
650
+ "widows",
651
+ "width",
652
+ "will-change",
653
+ "word-break",
654
+ "word-spacing",
655
+ "word-wrap",
656
+ "writing-mode",
657
+ "z-index"
658
+ ];
659
+ function cssPropRegex(names) {
660
+ const sorted = [...names].sort((a, b) => b.length - a.length);
661
+ return new RegExp("(?:" + sorted.join("|") + ")(?=\\s*:)", "y");
662
+ }
663
+ var RULES = [
664
+ { type: "comment", re: /\/\*[\s\S]*?(?:\*\/|$)/y },
665
+ // unterminated -> comment to EOF
666
+ { type: "string", re: /"(?:[^"\\\n]|\\.)*"?|'(?:[^'\\\n]|\\.)*'?/y },
667
+ { type: "meta", re: /@[a-zA-Z-]+/y },
668
+ { type: "keyword", re: /!important\b/y },
669
+ { type: "number", re: /#[0-9a-fA-F]{3,8}\b/y },
670
+ { type: "number", re: /-?(?:\d*\.\d+|\d+)(?:%|[a-zA-Z]{1,4})?/y },
671
+ { type: "property", re: /--[\w-]+/y },
672
+ { type: "property", re: cssPropRegex(PROPERTIES) },
673
+ { type: "attribute", re: /[.#][a-zA-Z_-][\w-]*/y },
674
+ { type: "meta", re: /::?[a-zA-Z_-][\w-]*/y },
675
+ { type: "function", re: /[-a-zA-Z][\w-]*(?=\()/y },
676
+ { type: "punctuation", re: /[{}()[\];:,]/y },
677
+ { type: "operator", re: /[>+~*]/y },
678
+ // Catch-all: consume an identifier/dash run (or whitespace) in one match so
679
+ // the greedy property/function look-ahead rules run once per run, not once
680
+ // per character (keeps scanning linear).
681
+ { type: "plain", re: /[-\w$]+|\s+/y }
682
+ ];
683
+ function tokenizeCss(source) {
684
+ return scan(source, RULES);
685
+ }
686
+
199
687
  // src/code-editor/tokenizer/html.js
200
- function expandTag(value) {
688
+ function expandTag(value, vue) {
201
689
  const out = [];
202
690
  const open = /^<\/?/.exec(value)[0];
203
691
  out.push({ type: "punctuation", value: open });
@@ -208,55 +696,186 @@ function expandTag(value) {
208
696
  rest = rest.slice(name[0].length);
209
697
  }
210
698
  if (rest) {
211
- const inner = scan(rest, [
699
+ const attrRules = vue ? [
700
+ { type: "string", re: /"[^"]*"?|'[^']*'?/y },
701
+ { type: "operator", re: /=/y },
702
+ { type: "punctuation", re: /\/?>/y },
703
+ { type: "meta", re: /(?:v-[\w:.@-]+|[@:][\w:.@-]*)/y },
704
+ { type: "attribute", re: /[a-zA-Z_][\w:.-]*/y }
705
+ ] : [
212
706
  { type: "string", re: /"[^"]*"?|'[^']*'?/y },
213
707
  { type: "operator", re: /=/y },
214
708
  { type: "punctuation", re: /\/?>/y },
215
709
  { type: "attribute", re: /[a-zA-Z_:@][\w:.-]*/y }
216
- ]);
710
+ ];
711
+ const inner = scanSlice(rest, attrRules);
217
712
  for (let i = 0; i < inner.length; i++) out.push(inner[i]);
218
713
  }
219
714
  return out;
220
715
  }
221
- var RULES = [
222
- { type: "comment", re: /<!--[\s\S]*?-->/y },
223
- { type: "meta", re: /<!\[CDATA\[[\s\S]*?\]\]>/y },
224
- { type: "meta", re: /<!DOCTYPE[^>]*>/iy },
225
- {
226
- expand: expandTag,
227
- re: /<\/?[a-zA-Z][\w:-]*(?:\s+[^\s/>"'=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?)*\s*\/?>/y
228
- },
229
- { expand: expandTag, re: /<\/?[a-zA-Z][\w:-]*/y },
230
- { type: "meta", re: /&[a-zA-Z][a-zA-Z0-9]*;|&#\d+;|&#x[0-9a-fA-F]+;/y }
231
- ];
716
+ function scanSlice(source, rules) {
717
+ const tokens = [];
718
+ const n = source.length;
719
+ let i = 0;
720
+ let plainStart = -1;
721
+ const flushPlain = (end) => {
722
+ if (plainStart !== -1 && end > plainStart) {
723
+ tokens.push({ type: "plain", value: source.slice(plainStart, end) });
724
+ }
725
+ plainStart = -1;
726
+ };
727
+ while (i < n) {
728
+ const hit = matchRule(source, i, rules);
729
+ if (hit) {
730
+ flushPlain(i);
731
+ for (let k = 0; k < hit.tokens.length; k++) tokens.push(hit.tokens[k]);
732
+ i += hit.length;
733
+ } else {
734
+ if (plainStart === -1) plainStart = i;
735
+ i++;
736
+ }
737
+ }
738
+ flushPlain(n);
739
+ return tokens;
740
+ }
741
+ function ieqChar(a, b) {
742
+ if (a === b) return true;
743
+ if (a >= 65 && a <= 90) return a + 32 === b;
744
+ if (b >= 65 && b <= 90) return b + 32 === a;
745
+ return false;
746
+ }
747
+ function findCloseTag(source, start, tagName) {
748
+ const n = source.length;
749
+ const tlen = tagName.length;
750
+ for (let i = start; i < n; i++) {
751
+ if (source.charCodeAt(i) !== 60) continue;
752
+ if (source.charCodeAt(i + 1) !== 47) continue;
753
+ let ok = true;
754
+ for (let k = 0; k < tlen; k++) {
755
+ if (!ieqChar(source.charCodeAt(i + 2 + k), tagName.charCodeAt(k))) {
756
+ ok = false;
757
+ break;
758
+ }
759
+ }
760
+ if (!ok) continue;
761
+ let j = i + 2 + tlen;
762
+ while (j < n) {
763
+ const c = source.charCodeAt(j);
764
+ if (c === 32 || c === 9 || c === 10 || c === 13) j++;
765
+ else break;
766
+ }
767
+ if (j < n && source.charCodeAt(j) === 62) return { start: i, end: j + 1 };
768
+ }
769
+ return null;
770
+ }
771
+ function embedInfo(tagValue) {
772
+ const open = /^<(script|style)\b/i.exec(tagValue);
773
+ if (!open) return null;
774
+ if (!tagValue.endsWith(">") || tagValue.endsWith("/>")) return null;
775
+ const tag = open[1].toLowerCase();
776
+ if (tag === "style") return { tag: "style", lang: "css" };
777
+ const lang = /\blang\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i.exec(tagValue);
778
+ const id = (lang && (lang[1] || lang[2] || lang[3]) || "").toLowerCase();
779
+ if (id === "ts" || id === "tsx" || id === "typescript")
780
+ return { tag: "script", lang: "typescript" };
781
+ return { tag: "script", lang: "javascript" };
782
+ }
783
+ function tokenizeEmbed(source, lang) {
784
+ if (lang === "typescript") return tokenizeTypeScript(source);
785
+ if (lang === "css") return tokenizeCss(source);
786
+ return tokenizeJavaScript(source);
787
+ }
788
+ function expandMustache(value) {
789
+ const out = [{ type: "meta", value: "{{" }];
790
+ let inner = value.slice(2);
791
+ let close = "";
792
+ if (value.length >= 4 && inner.endsWith("}}")) {
793
+ close = "}}";
794
+ inner = inner.slice(0, -2);
795
+ }
796
+ if (inner) {
797
+ const parts = tokenizeJavaScript(inner);
798
+ for (let i = 0; i < parts.length; i++) out.push(parts[i]);
799
+ }
800
+ if (close) out.push({ type: "meta", value: close });
801
+ return out;
802
+ }
803
+ function makeMarkupRules(vue) {
804
+ const expand = (value) => expandTag(value, vue);
805
+ const rules = [
806
+ { type: "comment", re: /<!--[\s\S]*?-->/y },
807
+ { type: "meta", re: /<!\[CDATA\[[\s\S]*?\]\]>/y },
808
+ { type: "meta", re: /<!DOCTYPE[^>]*>/iy },
809
+ {
810
+ expand,
811
+ re: /<\/?[a-zA-Z][\w:-]*(?:\s+[^\s/>"'=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?)*\s*\/?>/y
812
+ },
813
+ { expand, re: /<\/?[a-zA-Z][\w:-]*/y },
814
+ { type: "meta", re: /&[a-zA-Z][a-zA-Z0-9]*;|&#\d+;|&#x[0-9a-fA-F]+;/y }
815
+ ];
816
+ if (vue) {
817
+ rules.splice(1, 0, { expand: expandMustache, re: /\{\{[\s\S]*?(?:\}\}|$)/y });
818
+ }
819
+ return rules;
820
+ }
821
+ var HTML_RULES = makeMarkupRules(false);
822
+ var VUE_RULES = makeMarkupRules(true);
823
+ function tokenizeMarkup(source, options) {
824
+ const vue = !!(options && options.vue);
825
+ const rules = vue ? VUE_RULES : HTML_RULES;
826
+ const tokens = [];
827
+ const n = source.length;
828
+ let i = 0;
829
+ let plainStart = -1;
830
+ const flushPlain = (end) => {
831
+ if (plainStart !== -1 && end > plainStart) {
832
+ tokens.push({ type: "plain", value: source.slice(plainStart, end) });
833
+ }
834
+ plainStart = -1;
835
+ };
836
+ while (i < n) {
837
+ const hit = matchRule(source, i, rules);
838
+ if (hit) {
839
+ flushPlain(i);
840
+ const embed = embedInfo(hit.value);
841
+ if (embed) {
842
+ for (let k = 0; k < hit.tokens.length; k++) tokens.push(hit.tokens[k]);
843
+ i += hit.length;
844
+ const close = findCloseTag(source, i, embed.tag);
845
+ const bodyEnd = close ? close.start : n;
846
+ const body = source.slice(i, bodyEnd);
847
+ if (body) {
848
+ const inner = tokenizeEmbed(body, embed.lang);
849
+ for (let k = 0; k < inner.length; k++) tokens.push(inner[k]);
850
+ }
851
+ if (close) {
852
+ const closeTokens = expandTag(source.slice(close.start, close.end), vue);
853
+ for (let k = 0; k < closeTokens.length; k++) tokens.push(closeTokens[k]);
854
+ i = close.end;
855
+ } else {
856
+ i = n;
857
+ }
858
+ continue;
859
+ }
860
+ for (let k = 0; k < hit.tokens.length; k++) tokens.push(hit.tokens[k]);
861
+ i += hit.length;
862
+ } else {
863
+ if (plainStart === -1) plainStart = i;
864
+ i++;
865
+ }
866
+ }
867
+ flushPlain(n);
868
+ return coalesce(tokens);
869
+ }
232
870
  function tokenizeHtml(source) {
233
- return scan(source, RULES);
871
+ return tokenizeMarkup(source, { vue: false });
234
872
  }
235
-
236
- // src/code-editor/tokenizer/css.js
237
- var RULES2 = [
238
- { type: "comment", re: /\/\*[\s\S]*?(?:\*\/|$)/y },
239
- // unterminated -> comment to EOF
240
- { type: "string", re: /"(?:[^"\\\n]|\\.)*"?|'(?:[^'\\\n]|\\.)*'?/y },
241
- { type: "meta", re: /@[a-zA-Z-]+/y },
242
- { type: "keyword", re: /!important\b/y },
243
- { type: "number", re: /#[0-9a-fA-F]{3,8}\b/y },
244
- { type: "number", re: /-?(?:\d*\.\d+|\d+)(?:%|[a-zA-Z]{1,4})?/y },
245
- { type: "property", re: /[-a-zA-Z]+(?=\s*:)/y },
246
- { type: "function", re: /[-a-zA-Z][\w-]*(?=\()/y },
247
- { type: "punctuation", re: /[{}()[\];:,]/y },
248
- { type: "operator", re: /[>+~*]/y },
249
- // Catch-all: consume an identifier/dash run (or whitespace) in one match so
250
- // the greedy property/function look-ahead rules run once per run, not once
251
- // per character (keeps scanning linear).
252
- { type: "plain", re: /[-\w$]+|\s+/y }
253
- ];
254
- function tokenizeCss(source) {
255
- return scan(source, RULES2);
873
+ function tokenizeVue(source) {
874
+ return tokenizeMarkup(source, { vue: true });
256
875
  }
257
876
 
258
877
  // src/code-editor/tokenizer/json.js
259
- var RULES3 = [
878
+ var RULES2 = [
260
879
  { type: "property", re: /"(?:[^"\\]|\\.)*"(?=\s*:)/y },
261
880
  { type: "string", re: /"(?:[^"\\]|\\.)*"?/y },
262
881
  { type: "number", re: /-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/y },
@@ -265,11 +884,11 @@ var RULES3 = [
265
884
  { type: "punctuation", re: /[{}[\]:,]/y }
266
885
  ];
267
886
  function tokenizeJson(source) {
268
- return scan(source, RULES3);
887
+ return scan(source, RULES2);
269
888
  }
270
889
 
271
890
  // src/code-editor/tokenizer/markdown.js
272
- var RULES4 = [
891
+ var RULES3 = [
273
892
  { type: "string", re: /```[\s\S]*?```|~~~[\s\S]*?~~~|`[^`\n]*`/y },
274
893
  { type: "keyword", re: /^ {0,3}#{1,6} [^\n]*/my },
275
894
  { type: "comment", re: /^ {0,3}>[^\n]*/my },
@@ -280,7 +899,7 @@ var RULES4 = [
280
899
  { type: "meta", re: /\*[^*\n]+?\*|_[^_\n]+?_/y }
281
900
  ];
282
901
  function tokenizeMarkdown(source) {
283
- return scan(source, RULES4);
902
+ return scan(source, RULES3);
284
903
  }
285
904
 
286
905
  // src/code-editor/tokenizer/shell.js
@@ -362,7 +981,7 @@ var BUILTINS2 = [
362
981
  "tar",
363
982
  "ssh"
364
983
  ];
365
- var RULES5 = [
984
+ var RULES4 = [
366
985
  { type: "comment", re: /#[^\n]*/y },
367
986
  { type: "string", re: /"(?:[^"\\]|\\.)*"?/y },
368
987
  { type: "string", re: /'[^']*'?/y },
@@ -375,7 +994,7 @@ var RULES5 = [
375
994
  { type: "punctuation", re: /[(){}[\]]/y }
376
995
  ];
377
996
  function tokenizeShell(source) {
378
- return scan(source, RULES5);
997
+ return scan(source, RULES4);
379
998
  }
380
999
 
381
1000
  // src/code-editor/tokenizer/python.js
@@ -458,7 +1077,7 @@ var BUILTINS3 = [
458
1077
  "AttributeError",
459
1078
  "RuntimeError"
460
1079
  ];
461
- var RULES6 = [
1080
+ var RULES5 = [
462
1081
  { type: "comment", re: /#[^\n]*/y },
463
1082
  {
464
1083
  type: "string",
@@ -481,7 +1100,7 @@ var RULES6 = [
481
1100
  { type: "plain", re: /\w+|\s+/y }
482
1101
  ];
483
1102
  function tokenizePython(source) {
484
- return scan(source, RULES6);
1103
+ return scan(source, RULES5);
485
1104
  }
486
1105
 
487
1106
  // src/code-editor/tokenizer/index.js
@@ -489,6 +1108,7 @@ var TOKENIZERS = {
489
1108
  javascript: tokenizeJavaScript,
490
1109
  typescript: tokenizeTypeScript,
491
1110
  html: tokenizeHtml,
1111
+ vue: tokenizeVue,
492
1112
  css: tokenizeCss,
493
1113
  json: tokenizeJson,
494
1114
  markdown: tokenizeMarkdown,
@@ -500,6 +1120,7 @@ var LANGUAGES = Object.freeze([
500
1120
  "javascript",
501
1121
  "typescript",
502
1122
  "html",
1123
+ "vue",
503
1124
  "css",
504
1125
  "json",
505
1126
  "markdown",
@@ -515,7 +1136,6 @@ var ALIASES = Object.freeze({
515
1136
  tsx: "typescript",
516
1137
  htm: "html",
517
1138
  xml: "html",
518
- vue: "html",
519
1139
  svg: "html",
520
1140
  sh: "shell",
521
1141
  bash: "shell",
@@ -569,9 +1189,12 @@ function renderTokensToHtml(tokens) {
569
1189
  }
570
1190
  return html;
571
1191
  }
572
- function highlight(source, language) {
1192
+ function highlight(source, language, options) {
573
1193
  const html = renderTokensToHtml(tokenize(source, language));
574
- return source.endsWith("\n") || source === "" ? html + "\n" : html;
1194
+ if (options && options.trailingNewline && (source.endsWith("\n") || source === "")) {
1195
+ return html + "\n";
1196
+ }
1197
+ return html;
575
1198
  }
576
1199
  function renderTokensToDom(tokens, doc) {
577
1200
  const frag = doc.createDocumentFragment();
@@ -725,7 +1348,7 @@ function handleBackspacePair(value, start, end) {
725
1348
  }
726
1349
 
727
1350
  // src/code-editor/core.js
728
- var VD_CODE_EDITOR_VERSION = "1.0.1";
1351
+ var VD_CODE_EDITOR_VERSION = "1.1.0";
729
1352
  var DEFAULTS = {
730
1353
  value: "",
731
1354
  language: "plaintext",
@@ -1325,6 +1948,7 @@ export {
1325
1948
  VdCodeEditor2 as VdCodeEditor,
1326
1949
  VdCodeEditor as VdCodeEditorCore,
1327
1950
  highlight,
1951
+ renderTokensToHtml,
1328
1952
  tokenize
1329
1953
  };
1330
1954
  //# sourceMappingURL=index.js.map