@yadsh/dsh-qa-surface 0.7.4 → 0.8.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.
Files changed (146) hide show
  1. package/README.md +56 -9
  2. package/lib/access/model.js +24 -4
  3. package/lib/access/model.js.map +1 -1
  4. package/lib/access/role-repository.js +199 -91
  5. package/lib/access/role-repository.js.map +1 -1
  6. package/lib/access/service.js +194 -6
  7. package/lib/access/service.js.map +1 -1
  8. package/lib/account-remotes.js +2 -4
  9. package/lib/account-remotes.js.map +1 -1
  10. package/lib/accounts/database.js +447 -0
  11. package/lib/accounts/database.js.map +1 -0
  12. package/lib/accounts/file.js +27 -90
  13. package/lib/accounts/file.js.map +1 -1
  14. package/lib/accounts/store.js +210 -59
  15. package/lib/accounts/store.js.map +1 -1
  16. package/lib/admin/quality-store.js +199 -54
  17. package/lib/admin/quality-store.js.map +1 -1
  18. package/lib/admin/service.js +39 -6
  19. package/lib/admin/service.js.map +1 -1
  20. package/lib/cli.js +2 -1
  21. package/lib/cli.js.map +1 -1
  22. package/lib/client/QaSessionController.js +20 -2
  23. package/lib/client/QaSessionController.js.map +1 -1
  24. package/lib/client/QaSurface.js +69 -31
  25. package/lib/client/QaSurface.js.map +1 -1
  26. package/lib/client/QaTranscriptAdapter.js +4 -0
  27. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  28. package/lib/client/admin/QaAdmin.js +17 -7
  29. package/lib/client/admin/QaAdmin.js.map +1 -1
  30. package/lib/client/admin/{format.js → copy.js} +1 -1
  31. package/lib/client/admin/copy.js.map +1 -0
  32. package/lib/client/admin/pages/Conversations.js +1 -1
  33. package/lib/client/admin/pages/Conversations.js.map +1 -1
  34. package/lib/client/admin/pages/Overview.js +1 -1
  35. package/lib/client/admin/pages/Overview.js.map +1 -1
  36. package/lib/client/admin/pages/Quality.js +1 -1
  37. package/lib/client/admin/pages/Quality.js.map +1 -1
  38. package/lib/client/admin/pages/Review.js +1 -1
  39. package/lib/client/admin/pages/Review.js.map +1 -1
  40. package/lib/client/admin/pages/Users.js +6 -2
  41. package/lib/client/admin/pages/Users.js.map +1 -1
  42. package/lib/client/admin/shared.js +1 -1
  43. package/lib/client/admin/shared.js.map +1 -1
  44. package/lib/client/components/Markdown.js +14 -206
  45. package/lib/client/components/Markdown.js.map +1 -1
  46. package/lib/client/components/QaChangelog.js +48 -0
  47. package/lib/client/components/QaChangelog.js.map +1 -1
  48. package/lib/client/components/QaHeader.js +1 -3
  49. package/lib/client/components/QaHeader.js.map +1 -1
  50. package/lib/client/components/QaMessage.js +9 -4
  51. package/lib/client/components/QaMessage.js.map +1 -1
  52. package/lib/client/components/QaSidebar.js +5 -2
  53. package/lib/client/components/QaSidebar.js.map +1 -1
  54. package/lib/client/components/QaSourcesPanel.js +3 -18
  55. package/lib/client/components/QaSourcesPanel.js.map +1 -1
  56. package/lib/client/components/QaWorkGroup.js +4 -8
  57. package/lib/client/components/QaWorkGroup.js.map +1 -1
  58. package/lib/client/components/source-icon.js +26 -0
  59. package/lib/client/components/source-icon.js.map +1 -0
  60. package/lib/client/components/thinking-phrases.js +2 -11
  61. package/lib/client/components/thinking-phrases.js.map +1 -1
  62. package/lib/client/components/use-now.js +21 -0
  63. package/lib/client/components/use-now.js.map +1 -0
  64. package/lib/client/index.js +11 -3
  65. package/lib/client/index.js.map +1 -1
  66. package/lib/client/lineage.js +18 -0
  67. package/lib/client/lineage.js.map +1 -0
  68. package/lib/client/markdown/CodeBlock.js +28 -0
  69. package/lib/client/markdown/CodeBlock.js.map +1 -0
  70. package/lib/client/markdown/blocks.js +342 -0
  71. package/lib/client/markdown/blocks.js.map +1 -0
  72. package/lib/client/markdown/highlight.js +1089 -0
  73. package/lib/client/markdown/highlight.js.map +1 -0
  74. package/lib/client/markdown/inline.js +377 -0
  75. package/lib/client/markdown/inline.js.map +1 -0
  76. package/lib/client/markdown/render.js +147 -0
  77. package/lib/client/markdown/render.js.map +1 -0
  78. package/lib/client/markdown/source-chip.js +55 -0
  79. package/lib/client/markdown/source-chip.js.map +1 -0
  80. package/lib/client/markdown/use-transient-flag.js +27 -0
  81. package/lib/client/markdown/use-transient-flag.js.map +1 -0
  82. package/lib/client/role/RoleSelector.js +11 -2
  83. package/lib/client/role/RoleSelector.js.map +1 -1
  84. package/lib/client/role/preview.js +123 -0
  85. package/lib/client/role/preview.js.map +1 -0
  86. package/lib/client/styles.js +73 -19
  87. package/lib/client/styles.js.map +1 -1
  88. package/lib/client.js +3129 -761
  89. package/lib/client.js.map +1 -1
  90. package/lib/config-resolvers/accounts.js +15 -0
  91. package/lib/config-resolvers/accounts.js.map +1 -1
  92. package/lib/config-resolvers/defaults.js +8 -0
  93. package/lib/config-resolvers/defaults.js.map +1 -1
  94. package/lib/config-resolvers/sources.js +16 -0
  95. package/lib/config-resolvers/sources.js.map +1 -1
  96. package/lib/config.js +57 -0
  97. package/lib/config.js.map +1 -1
  98. package/lib/index.js +25 -10
  99. package/lib/index.js.map +1 -1
  100. package/lib/lockdown-policy.js +19 -0
  101. package/lib/lockdown-policy.js.map +1 -1
  102. package/lib/provenance/host-store.js +7 -3
  103. package/lib/provenance/host-store.js.map +1 -1
  104. package/lib/provenance/retention.js +25 -0
  105. package/lib/provenance/retention.js.map +1 -0
  106. package/lib/provenance/snapshot-store.js +290 -35
  107. package/lib/provenance/snapshot-store.js.map +1 -1
  108. package/lib/questions.js +16 -3
  109. package/lib/questions.js.map +1 -1
  110. package/lib/secure-session.js +115 -21
  111. package/lib/secure-session.js.map +1 -1
  112. package/lib/typert.host.js +79 -52
  113. package/lib/typert.remote-client.js +75 -48
  114. package/lib/types/access/role-repository.d.ts +38 -7
  115. package/lib/types/access/service.d.ts +77 -3
  116. package/lib/types/account-remotes.d.ts +8 -4
  117. package/lib/types/accounts/database.d.ts +84 -0
  118. package/lib/types/accounts/file.d.ts +17 -39
  119. package/lib/types/accounts/store.d.ts +98 -19
  120. package/lib/types/admin/quality-store.d.ts +20 -2
  121. package/lib/types/client/admin/{format.d.ts → copy.d.ts} +1 -1
  122. package/lib/types/client/components/Markdown.d.ts +7 -8
  123. package/lib/types/client/components/QaSidebar.d.ts +3 -1
  124. package/lib/types/client/components/QaSourcesPanel.d.ts +1 -3
  125. package/lib/types/client/components/source-icon.d.ts +12 -0
  126. package/lib/types/client/components/use-now.d.ts +8 -0
  127. package/lib/types/client/lineage.d.ts +15 -0
  128. package/lib/types/client/markdown/CodeBlock.d.ts +14 -0
  129. package/lib/types/client/markdown/blocks.d.ts +74 -0
  130. package/lib/types/client/markdown/highlight.d.ts +29 -0
  131. package/lib/types/client/markdown/inline.d.ts +40 -0
  132. package/lib/types/client/markdown/render.d.ts +13 -0
  133. package/lib/types/client/markdown/source-chip.d.ts +32 -0
  134. package/lib/types/client/markdown/use-transient-flag.d.ts +12 -0
  135. package/lib/types/client/role/RoleSelector.d.ts +11 -1
  136. package/lib/types/client/role/preview.d.ts +109 -0
  137. package/lib/types/index.d.ts +5 -1
  138. package/lib/types/lockdown-policy.d.ts +16 -0
  139. package/lib/types/provenance/host-store.d.ts +7 -3
  140. package/lib/types/provenance/retention.d.ts +46 -0
  141. package/lib/types/provenance/snapshot-store.d.ts +63 -7
  142. package/lib/types/questions.d.ts +5 -0
  143. package/lib/types/secure-session.d.ts +27 -1
  144. package/lib/types/types.d.ts +54 -0
  145. package/package.json +4 -4
  146. package/lib/client/admin/format.js.map +0 -1
@@ -0,0 +1,1089 @@
1
+ /**
2
+ * The chat renderer's syntax highlighter: a small tokenizer over per-language
3
+ * keyword/comment/string tables, not a grammar engine. The original UI runs
4
+ * shiki; its grammar modules alone cost ~1.6 MB, which a self-contained plugin
5
+ * bundle cannot carry, so this scanner covers the shapes that carry meaning in
6
+ * an answer — comments, strings, numbers, keywords — and leaves the rest of the
7
+ * line in the foreground color. Colors come from the host theme's
8
+ * `--shiki-token-*` custom properties, so a fenced block here matches a fenced
9
+ * block in the assistant's own transcript in both light and dark themes.
10
+ *
11
+ * An unknown or absent language renders plain: never an error, never a guess.
12
+ */
13
+ /** Double and single quotes that end at the line they start on. */
14
+ const QUOTES = [
15
+ { open: '"', close: '"', escape: true },
16
+ { open: "'", close: "'", escape: true },
17
+ ];
18
+ const SQL_KEYWORDS = [
19
+ "add",
20
+ "all",
21
+ "alter",
22
+ "and",
23
+ "any",
24
+ "as",
25
+ "asc",
26
+ "begin",
27
+ "between",
28
+ "by",
29
+ "case",
30
+ "cast",
31
+ "check",
32
+ "column",
33
+ "commit",
34
+ "constraint",
35
+ "create",
36
+ "cross",
37
+ "default",
38
+ "delete",
39
+ "desc",
40
+ "distinct",
41
+ "drop",
42
+ "else",
43
+ "end",
44
+ "exists",
45
+ "foreign",
46
+ "from",
47
+ "full",
48
+ "group",
49
+ "having",
50
+ "if",
51
+ "in",
52
+ "index",
53
+ "inner",
54
+ "insert",
55
+ "into",
56
+ "is",
57
+ "join",
58
+ "key",
59
+ "left",
60
+ "like",
61
+ "limit",
62
+ "not",
63
+ "null",
64
+ "offset",
65
+ "on",
66
+ "or",
67
+ "order",
68
+ "outer",
69
+ "primary",
70
+ "references",
71
+ "returning",
72
+ "right",
73
+ "rollback",
74
+ "select",
75
+ "set",
76
+ "table",
77
+ "then",
78
+ "transaction",
79
+ "union",
80
+ "unique",
81
+ "update",
82
+ "values",
83
+ "view",
84
+ "when",
85
+ "where",
86
+ "with",
87
+ ];
88
+ const SHELL_KEYWORDS = [
89
+ "case",
90
+ "cd",
91
+ "do",
92
+ "done",
93
+ "elif",
94
+ "else",
95
+ "esac",
96
+ "exit",
97
+ "export",
98
+ "fi",
99
+ "for",
100
+ "function",
101
+ "if",
102
+ "in",
103
+ "local",
104
+ "readonly",
105
+ "return",
106
+ "set",
107
+ "source",
108
+ "then",
109
+ "unset",
110
+ "until",
111
+ "while",
112
+ ];
113
+ const LANGUAGE_SPECS = new Map(Object.entries({
114
+ csharp: {
115
+ keywords: [
116
+ "abstract",
117
+ "as",
118
+ "async",
119
+ "await",
120
+ "base",
121
+ "bool",
122
+ "break",
123
+ "byte",
124
+ "case",
125
+ "catch",
126
+ "char",
127
+ "checked",
128
+ "class",
129
+ "const",
130
+ "continue",
131
+ "decimal",
132
+ "default",
133
+ "delegate",
134
+ "do",
135
+ "double",
136
+ "dynamic",
137
+ "else",
138
+ "enum",
139
+ "event",
140
+ "explicit",
141
+ "extern",
142
+ "finally",
143
+ "fixed",
144
+ "float",
145
+ "for",
146
+ "foreach",
147
+ "get",
148
+ "goto",
149
+ "if",
150
+ "implicit",
151
+ "in",
152
+ "init",
153
+ "int",
154
+ "interface",
155
+ "internal",
156
+ "is",
157
+ "lock",
158
+ "long",
159
+ "namespace",
160
+ "new",
161
+ "object",
162
+ "operator",
163
+ "out",
164
+ "override",
165
+ "params",
166
+ "private",
167
+ "protected",
168
+ "public",
169
+ "readonly",
170
+ "record",
171
+ "ref",
172
+ "return",
173
+ "sbyte",
174
+ "sealed",
175
+ "set",
176
+ "short",
177
+ "sizeof",
178
+ "stackalloc",
179
+ "static",
180
+ "string",
181
+ "struct",
182
+ "switch",
183
+ "this",
184
+ "throw",
185
+ "try",
186
+ "typeof",
187
+ "uint",
188
+ "ulong",
189
+ "unchecked",
190
+ "unsafe",
191
+ "ushort",
192
+ "using",
193
+ "value",
194
+ "var",
195
+ "virtual",
196
+ "void",
197
+ "volatile",
198
+ "when",
199
+ "where",
200
+ "while",
201
+ "yield",
202
+ ],
203
+ lineComments: ["//"],
204
+ blockComment: ["/*", "*/"],
205
+ strings: [
206
+ { open: '@"', close: '"', doubled: true, multiline: true },
207
+ { open: '$"', close: '"', escape: true },
208
+ ...QUOTES,
209
+ ],
210
+ annotations: true,
211
+ directives: true,
212
+ },
213
+ javascript: {
214
+ keywords: [
215
+ "as",
216
+ "async",
217
+ "await",
218
+ "break",
219
+ "case",
220
+ "catch",
221
+ "class",
222
+ "const",
223
+ "continue",
224
+ "debugger",
225
+ "default",
226
+ "delete",
227
+ "do",
228
+ "else",
229
+ "export",
230
+ "extends",
231
+ "finally",
232
+ "for",
233
+ "from",
234
+ "function",
235
+ "get",
236
+ "if",
237
+ "import",
238
+ "in",
239
+ "instanceof",
240
+ "let",
241
+ "new",
242
+ "of",
243
+ "return",
244
+ "set",
245
+ "static",
246
+ "super",
247
+ "switch",
248
+ "this",
249
+ "throw",
250
+ "try",
251
+ "typeof",
252
+ "var",
253
+ "void",
254
+ "while",
255
+ "with",
256
+ "yield",
257
+ ],
258
+ lineComments: ["//"],
259
+ blockComment: ["/*", "*/"],
260
+ strings: [
261
+ ...QUOTES,
262
+ { open: "`", close: "`", escape: true, multiline: true },
263
+ ],
264
+ annotations: true,
265
+ },
266
+ json: {
267
+ lineComments: ["//"],
268
+ strings: QUOTES,
269
+ keys: true,
270
+ },
271
+ java: {
272
+ keywords: [
273
+ "abstract",
274
+ "assert",
275
+ "boolean",
276
+ "break",
277
+ "byte",
278
+ "case",
279
+ "catch",
280
+ "char",
281
+ "class",
282
+ "const",
283
+ "continue",
284
+ "default",
285
+ "do",
286
+ "double",
287
+ "else",
288
+ "enum",
289
+ "extends",
290
+ "final",
291
+ "finally",
292
+ "float",
293
+ "for",
294
+ "goto",
295
+ "if",
296
+ "implements",
297
+ "import",
298
+ "instanceof",
299
+ "int",
300
+ "interface",
301
+ "long",
302
+ "native",
303
+ "new",
304
+ "package",
305
+ "private",
306
+ "protected",
307
+ "public",
308
+ "record",
309
+ "return",
310
+ "sealed",
311
+ "short",
312
+ "static",
313
+ "strictfp",
314
+ "super",
315
+ "switch",
316
+ "synchronized",
317
+ "this",
318
+ "throw",
319
+ "throws",
320
+ "transient",
321
+ "try",
322
+ "var",
323
+ "void",
324
+ "volatile",
325
+ "while",
326
+ ],
327
+ lineComments: ["//"],
328
+ blockComment: ["/*", "*/"],
329
+ strings: QUOTES,
330
+ annotations: true,
331
+ },
332
+ kotlin: {
333
+ keywords: [
334
+ "as",
335
+ "break",
336
+ "class",
337
+ "companion",
338
+ "const",
339
+ "constructor",
340
+ "continue",
341
+ "data",
342
+ "do",
343
+ "else",
344
+ "enum",
345
+ "expect",
346
+ "external",
347
+ "final",
348
+ "for",
349
+ "fun",
350
+ "get",
351
+ "if",
352
+ "in",
353
+ "init",
354
+ "interface",
355
+ "internal",
356
+ "is",
357
+ "lateinit",
358
+ "object",
359
+ "open",
360
+ "operator",
361
+ "out",
362
+ "override",
363
+ "package",
364
+ "private",
365
+ "protected",
366
+ "public",
367
+ "return",
368
+ "sealed",
369
+ "set",
370
+ "super",
371
+ "suspend",
372
+ "tailrec",
373
+ "this",
374
+ "throw",
375
+ "try",
376
+ "typealias",
377
+ "val",
378
+ "var",
379
+ "vararg",
380
+ "when",
381
+ "where",
382
+ "while",
383
+ ],
384
+ lineComments: ["//"],
385
+ blockComment: ["/*", "*/"],
386
+ strings: [{ open: '"""', close: '"""', multiline: true }, ...QUOTES],
387
+ annotations: true,
388
+ },
389
+ go: {
390
+ keywords: [
391
+ "break",
392
+ "case",
393
+ "chan",
394
+ "const",
395
+ "continue",
396
+ "default",
397
+ "defer",
398
+ "else",
399
+ "fallthrough",
400
+ "for",
401
+ "func",
402
+ "go",
403
+ "goto",
404
+ "if",
405
+ "import",
406
+ "interface",
407
+ "map",
408
+ "package",
409
+ "range",
410
+ "return",
411
+ "select",
412
+ "struct",
413
+ "switch",
414
+ "type",
415
+ "var",
416
+ ],
417
+ lineComments: ["//"],
418
+ blockComment: ["/*", "*/"],
419
+ strings: [{ open: "`", close: "`", multiline: true }, ...QUOTES],
420
+ },
421
+ rust: {
422
+ keywords: [
423
+ "as",
424
+ "async",
425
+ "await",
426
+ "break",
427
+ "const",
428
+ "continue",
429
+ "crate",
430
+ "dyn",
431
+ "else",
432
+ "enum",
433
+ "extern",
434
+ "fn",
435
+ "for",
436
+ "if",
437
+ "impl",
438
+ "in",
439
+ "let",
440
+ "loop",
441
+ "match",
442
+ "mod",
443
+ "move",
444
+ "mut",
445
+ "pub",
446
+ "ref",
447
+ "return",
448
+ "self",
449
+ "static",
450
+ "struct",
451
+ "super",
452
+ "trait",
453
+ "type",
454
+ "unsafe",
455
+ "use",
456
+ "where",
457
+ "while",
458
+ ],
459
+ lineComments: ["//"],
460
+ blockComment: ["/*", "*/"],
461
+ strings: QUOTES,
462
+ annotations: true,
463
+ },
464
+ c: {
465
+ keywords: [
466
+ "auto",
467
+ "break",
468
+ "case",
469
+ "char",
470
+ "const",
471
+ "continue",
472
+ "default",
473
+ "do",
474
+ "double",
475
+ "else",
476
+ "enum",
477
+ "extern",
478
+ "float",
479
+ "for",
480
+ "goto",
481
+ "if",
482
+ "inline",
483
+ "int",
484
+ "long",
485
+ "register",
486
+ "restrict",
487
+ "return",
488
+ "short",
489
+ "signed",
490
+ "sizeof",
491
+ "static",
492
+ "struct",
493
+ "switch",
494
+ "typedef",
495
+ "union",
496
+ "unsigned",
497
+ "void",
498
+ "volatile",
499
+ "while",
500
+ ],
501
+ lineComments: ["//"],
502
+ blockComment: ["/*", "*/"],
503
+ strings: QUOTES,
504
+ directives: true,
505
+ },
506
+ cpp: {
507
+ keywords: [
508
+ "alignas",
509
+ "auto",
510
+ "bool",
511
+ "break",
512
+ "case",
513
+ "catch",
514
+ "char",
515
+ "class",
516
+ "const",
517
+ "constexpr",
518
+ "continue",
519
+ "decltype",
520
+ "default",
521
+ "delete",
522
+ "do",
523
+ "double",
524
+ "else",
525
+ "enum",
526
+ "explicit",
527
+ "extern",
528
+ "false",
529
+ "float",
530
+ "for",
531
+ "friend",
532
+ "goto",
533
+ "if",
534
+ "inline",
535
+ "int",
536
+ "long",
537
+ "mutable",
538
+ "namespace",
539
+ "new",
540
+ "noexcept",
541
+ "nullptr",
542
+ "operator",
543
+ "override",
544
+ "private",
545
+ "protected",
546
+ "public",
547
+ "register",
548
+ "return",
549
+ "short",
550
+ "signed",
551
+ "sizeof",
552
+ "static",
553
+ "struct",
554
+ "switch",
555
+ "template",
556
+ "this",
557
+ "throw",
558
+ "try",
559
+ "typedef",
560
+ "typename",
561
+ "union",
562
+ "unsigned",
563
+ "using",
564
+ "virtual",
565
+ "void",
566
+ "volatile",
567
+ "while",
568
+ ],
569
+ lineComments: ["//"],
570
+ blockComment: ["/*", "*/"],
571
+ strings: QUOTES,
572
+ directives: true,
573
+ },
574
+ python: {
575
+ keywords: [
576
+ "and",
577
+ "as",
578
+ "assert",
579
+ "async",
580
+ "await",
581
+ "break",
582
+ "class",
583
+ "continue",
584
+ "def",
585
+ "del",
586
+ "elif",
587
+ "else",
588
+ "except",
589
+ "finally",
590
+ "for",
591
+ "from",
592
+ "global",
593
+ "if",
594
+ "import",
595
+ "in",
596
+ "is",
597
+ "lambda",
598
+ "nonlocal",
599
+ "not",
600
+ "or",
601
+ "pass",
602
+ "raise",
603
+ "return",
604
+ "try",
605
+ "while",
606
+ "with",
607
+ "yield",
608
+ ],
609
+ lineComments: ["#"],
610
+ strings: [
611
+ { open: '"""', close: '"""', escape: true, multiline: true },
612
+ { open: "'''", close: "'''", escape: true, multiline: true },
613
+ { open: 'f"', close: '"', escape: true },
614
+ { open: "f'", close: "'", escape: true },
615
+ ...QUOTES,
616
+ ],
617
+ annotations: true,
618
+ },
619
+ ruby: {
620
+ keywords: [
621
+ "alias",
622
+ "and",
623
+ "begin",
624
+ "break",
625
+ "case",
626
+ "class",
627
+ "def",
628
+ "defined",
629
+ "do",
630
+ "else",
631
+ "elsif",
632
+ "end",
633
+ "ensure",
634
+ "for",
635
+ "if",
636
+ "in",
637
+ "module",
638
+ "next",
639
+ "not",
640
+ "or",
641
+ "redo",
642
+ "require",
643
+ "rescue",
644
+ "retry",
645
+ "return",
646
+ "self",
647
+ "super",
648
+ "then",
649
+ "undef",
650
+ "unless",
651
+ "until",
652
+ "when",
653
+ "while",
654
+ "yield",
655
+ ],
656
+ lineComments: ["#"],
657
+ strings: QUOTES,
658
+ annotations: true,
659
+ },
660
+ php: {
661
+ keywords: [
662
+ "abstract",
663
+ "array",
664
+ "as",
665
+ "break",
666
+ "case",
667
+ "catch",
668
+ "class",
669
+ "clone",
670
+ "const",
671
+ "continue",
672
+ "declare",
673
+ "default",
674
+ "do",
675
+ "echo",
676
+ "else",
677
+ "elseif",
678
+ "enum",
679
+ "extends",
680
+ "final",
681
+ "finally",
682
+ "fn",
683
+ "for",
684
+ "foreach",
685
+ "function",
686
+ "global",
687
+ "if",
688
+ "implements",
689
+ "include",
690
+ "instanceof",
691
+ "interface",
692
+ "isset",
693
+ "namespace",
694
+ "new",
695
+ "print",
696
+ "private",
697
+ "protected",
698
+ "public",
699
+ "readonly",
700
+ "require",
701
+ "return",
702
+ "static",
703
+ "switch",
704
+ "throw",
705
+ "trait",
706
+ "try",
707
+ "unset",
708
+ "use",
709
+ "while",
710
+ "yield",
711
+ ],
712
+ lineComments: ["//", "#"],
713
+ blockComment: ["/*", "*/"],
714
+ strings: QUOTES,
715
+ },
716
+ swift: {
717
+ keywords: [
718
+ "associatedtype",
719
+ "case",
720
+ "catch",
721
+ "class",
722
+ "defer",
723
+ "deinit",
724
+ "do",
725
+ "else",
726
+ "enum",
727
+ "extension",
728
+ "fileprivate",
729
+ "for",
730
+ "func",
731
+ "guard",
732
+ "if",
733
+ "import",
734
+ "in",
735
+ "init",
736
+ "internal",
737
+ "let",
738
+ "open",
739
+ "operator",
740
+ "private",
741
+ "protocol",
742
+ "public",
743
+ "repeat",
744
+ "return",
745
+ "self",
746
+ "static",
747
+ "struct",
748
+ "subscript",
749
+ "switch",
750
+ "throw",
751
+ "throws",
752
+ "try",
753
+ "typealias",
754
+ "var",
755
+ "where",
756
+ "while",
757
+ ],
758
+ lineComments: ["//"],
759
+ blockComment: ["/*", "*/"],
760
+ strings: [{ open: '"""', close: '"""', multiline: true }, ...QUOTES],
761
+ annotations: true,
762
+ },
763
+ sql: {
764
+ keywords: SQL_KEYWORDS,
765
+ caseInsensitive: true,
766
+ lineComments: ["--"],
767
+ blockComment: ["/*", "*/"],
768
+ strings: [{ open: "'", close: "'", doubled: true, multiline: true }],
769
+ },
770
+ shell: {
771
+ keywords: SHELL_KEYWORDS,
772
+ lineComments: ["#"],
773
+ strings: [
774
+ { open: '"', close: '"', escape: true, multiline: true },
775
+ { open: "'", close: "'", multiline: true },
776
+ ],
777
+ },
778
+ yaml: { lineComments: ["#"], strings: QUOTES, keys: true },
779
+ toml: { lineComments: ["#"], strings: QUOTES, keys: true },
780
+ ini: { lineComments: [";", "#"], strings: QUOTES, keys: true },
781
+ css: { blockComment: ["/*", "*/"], strings: QUOTES },
782
+ markup: { blockComment: ["<!--", "-->"], markup: true },
783
+ diff: { diff: true },
784
+ markdown: {
785
+ lineComments: [],
786
+ strings: [...QUOTES, { open: "`", close: "`", multiline: true }],
787
+ },
788
+ }));
789
+ /** Alias table: fence info strings and file-extension hints to a spec key. */
790
+ const LANGUAGE_ALIASES = new Map([
791
+ ["c#", "csharp"],
792
+ ["cs", "csharp"],
793
+ ["dotnet", "csharp"],
794
+ ["js", "javascript"],
795
+ ["jsx", "javascript"],
796
+ ["mjs", "javascript"],
797
+ ["cjs", "javascript"],
798
+ ["node", "javascript"],
799
+ ["ts", "javascript"],
800
+ ["tsx", "javascript"],
801
+ ["typescript", "javascript"],
802
+ ["py", "python"],
803
+ ["python3", "python"],
804
+ ["sh", "shell"],
805
+ ["bash", "shell"],
806
+ ["zsh", "shell"],
807
+ ["console", "shell"],
808
+ ["shell-session", "shell"],
809
+ ["powershell", "shell"],
810
+ ["ps1", "shell"],
811
+ ["golang", "go"],
812
+ ["rs", "rust"],
813
+ ["c++", "cpp"],
814
+ ["yml", "yaml"],
815
+ ["html", "markup"],
816
+ ["xml", "markup"],
817
+ ["svg", "markup"],
818
+ ["vue", "markup"],
819
+ ["scss", "css"],
820
+ ["less", "css"],
821
+ ["patch", "diff"],
822
+ ["md", "markdown"],
823
+ ["text", "plain"],
824
+ ["txt", "plain"],
825
+ ["plain", "plain"],
826
+ ]);
827
+ const NUMBER = /^(?:0[xXbBoO][0-9a-fA-F_]+|\d[\d_]*(?:\.\d+)?(?:[eE][+-]?\d+)?)/u;
828
+ const IDENTIFIER = /^[A-Za-z_$][\w$]*/u;
829
+ const IDENTIFIER_START = /[A-Za-z_$]/u;
830
+ /** Source longer than this renders plain: highlighting is not worth the walk. */
831
+ const MAX_HIGHLIGHT_LENGTH = 50_000;
832
+ const CONSTANTS = new Set([
833
+ "true",
834
+ "false",
835
+ "null",
836
+ "undefined",
837
+ "none",
838
+ "nil",
839
+ "nan",
840
+ "infinity",
841
+ "this",
842
+ "self",
843
+ ]);
844
+ /**
845
+ * Highlight one fenced block.
846
+ * @param code - The fence's source text.
847
+ * @param lang - The fence's info string.
848
+ * @returns One {@link HighlightLine} per source line.
849
+ */
850
+ export function highlightLines(code, lang) {
851
+ const spec = languageSpec(lang);
852
+ if (spec === undefined || code.length > MAX_HIGHLIGHT_LENGTH) {
853
+ return code.split("\n").map((line) => [{ text: line }]);
854
+ }
855
+ const spans = spec.diff === true ? highlightDiff(code) : scan(code, spec);
856
+ const lines = [[]];
857
+ for (const span of spans) {
858
+ span.text.split("\n").forEach((part, index) => {
859
+ if (index > 0)
860
+ lines.push([]);
861
+ if (part === "")
862
+ return;
863
+ lines[lines.length - 1]?.push(span.cls === undefined ? { text: part } : { text: part, cls: span.cls });
864
+ });
865
+ }
866
+ return lines;
867
+ }
868
+ /** Resolve a fence info string to a language spec, or undefined for plain. */
869
+ function languageSpec(lang) {
870
+ if (lang === undefined)
871
+ return undefined;
872
+ const key = lang.trim().toLowerCase();
873
+ if (key === "")
874
+ return undefined;
875
+ const alias = LANGUAGE_ALIASES.get(key) ?? key;
876
+ if (alias === "plain")
877
+ return undefined;
878
+ return LANGUAGE_SPECS.get(alias);
879
+ }
880
+ /** Unified-diff lines carry their role, not a lexical class. */
881
+ function highlightDiff(code) {
882
+ const spans = [];
883
+ code.split("\n").forEach((line, index) => {
884
+ if (index > 0)
885
+ spans.push({ text: "\n" });
886
+ const head = line.slice(0, 3);
887
+ const cls = head.startsWith("@@")
888
+ ? "hunk"
889
+ : head.startsWith("+++") ||
890
+ head.startsWith("---") ||
891
+ head.startsWith("diff") ||
892
+ head.startsWith("index")
893
+ ? "meta"
894
+ : line.startsWith("+")
895
+ ? "insert"
896
+ : line.startsWith("-")
897
+ ? "delete"
898
+ : undefined;
899
+ spans.push(cls === undefined ? { text: line } : { text: line, cls });
900
+ });
901
+ return spans;
902
+ }
903
+ /**
904
+ * The generic scanner: comments, strings, numbers, keywords, and the
905
+ * positional conventions (value keys, decorators, preprocessor directives).
906
+ * @param code - Source text.
907
+ * @param spec - The language's tables.
908
+ * @returns Colored runs, in source order.
909
+ */
910
+ function scan(code, spec) {
911
+ const spans = [];
912
+ const keywords = new Set(spec.keywords ?? []);
913
+ const strings = [...(spec.strings ?? [])].sort((left, right) => right.open.length - left.open.length);
914
+ const lineComments = spec.lineComments ?? [];
915
+ const blockComment = spec.blockComment;
916
+ let plain = "";
917
+ const text = (value) => {
918
+ plain += value;
919
+ };
920
+ const push = (value, cls) => {
921
+ if (plain !== "") {
922
+ spans.push({ text: plain });
923
+ plain = "";
924
+ }
925
+ spans.push({ text: value, cls });
926
+ };
927
+ let index = 0;
928
+ while (index < code.length) {
929
+ const marker = lineComments.find((candidate) => code.startsWith(candidate, index));
930
+ if (marker !== undefined) {
931
+ const end = code.indexOf("\n", index);
932
+ const stop = end < 0 ? code.length : end;
933
+ push(code.slice(index, stop), "comment");
934
+ index = stop;
935
+ continue;
936
+ }
937
+ if (blockComment !== undefined && code.startsWith(blockComment[0], index)) {
938
+ const close = code.indexOf(blockComment[1], index + blockComment[0].length);
939
+ const stop = close < 0 ? code.length : close + blockComment[1].length;
940
+ push(code.slice(index, stop), "comment");
941
+ index = stop;
942
+ continue;
943
+ }
944
+ const current = code[index] ?? "";
945
+ if (spec.directives === true &&
946
+ current === "#" &&
947
+ /(^|\n)[ \t]*$/u.test(code.slice(0, index))) {
948
+ const end = code.indexOf("\n", index);
949
+ const stop = end < 0 ? code.length : end;
950
+ push(code.slice(index, stop), "meta");
951
+ index = stop;
952
+ continue;
953
+ }
954
+ if (spec.annotations === true &&
955
+ current === "@" &&
956
+ IDENTIFIER.test(code.slice(index + 1))) {
957
+ const name = IDENTIFIER.exec(code.slice(index + 1))?.[0] ?? "";
958
+ push(`@${name}`, "meta");
959
+ index += name.length + 1;
960
+ continue;
961
+ }
962
+ const rule = strings.find((candidate) => code.startsWith(candidate.open, index));
963
+ if (rule !== undefined) {
964
+ const end = readStringEnd(code, index + rule.open.length, rule);
965
+ const value = code.slice(index, end);
966
+ push(value, spec.keys === true && isKeyAfter(code, end) ? "key" : "string");
967
+ index = end;
968
+ continue;
969
+ }
970
+ if (spec.markup === true && current === "<") {
971
+ const end = scanMarkup(code, index, push, text);
972
+ if (end !== undefined) {
973
+ index = end;
974
+ continue;
975
+ }
976
+ }
977
+ if (/\d/u.test(current) && !/[\w$]/u.test(code[index - 1] ?? "")) {
978
+ const value = NUMBER.exec(code.slice(index))?.[0] ?? "";
979
+ push(value, "number");
980
+ index += value.length;
981
+ continue;
982
+ }
983
+ if (IDENTIFIER_START.test(current)) {
984
+ const word = IDENTIFIER.exec(code.slice(index))?.[0] ?? "";
985
+ const folded = spec.caseInsensitive === true ? word.toLowerCase() : word;
986
+ const cls = keywords.has(folded)
987
+ ? "keyword"
988
+ : CONSTANTS.has(folded)
989
+ ? "constant"
990
+ : spec.keys === true && isKeyAfter(code, index + word.length)
991
+ ? "key"
992
+ : undefined;
993
+ if (cls === undefined)
994
+ text(word);
995
+ else
996
+ push(word, cls);
997
+ index += word.length;
998
+ continue;
999
+ }
1000
+ text(current);
1001
+ index += 1;
1002
+ }
1003
+ if (plain !== "")
1004
+ spans.push({ text: plain });
1005
+ return spans;
1006
+ }
1007
+ /** True when the token ending at `end` names a `key:`/`key=` entry. */
1008
+ function isKeyAfter(code, end) {
1009
+ let index = end;
1010
+ while (code[index] === " " || code[index] === "\t")
1011
+ index += 1;
1012
+ return code[index] === ":" || code[index] === "=";
1013
+ }
1014
+ /**
1015
+ * The index just past a string that starts at `index`, or `code.length` when
1016
+ * it never closes. A single-line rule stops at the newline it cannot cross.
1017
+ */
1018
+ function readStringEnd(code, index, rule) {
1019
+ let cursor = index;
1020
+ while (cursor < code.length) {
1021
+ const current = code[cursor] ?? "";
1022
+ if (rule.escape === true && current === "\\") {
1023
+ cursor += 2;
1024
+ continue;
1025
+ }
1026
+ if (code.startsWith(rule.close, cursor)) {
1027
+ if (rule.doubled === true &&
1028
+ code.startsWith(rule.close, cursor + rule.close.length)) {
1029
+ cursor += rule.close.length * 2;
1030
+ continue;
1031
+ }
1032
+ return cursor + rule.close.length;
1033
+ }
1034
+ if (current === "\n" && rule.multiline !== true)
1035
+ return cursor;
1036
+ cursor += 1;
1037
+ }
1038
+ return code.length;
1039
+ }
1040
+ /**
1041
+ * A markup token at `index`: comment, doctype, or a tag with its attributes.
1042
+ * @returns The index just past the token, or undefined when `<` starts none.
1043
+ */
1044
+ function scanMarkup(code, index, push, text) {
1045
+ if (code.startsWith("<!--", index)) {
1046
+ const close = code.indexOf("-->", index);
1047
+ const stop = close < 0 ? code.length : close + 3;
1048
+ push(code.slice(index, stop), "comment");
1049
+ return stop;
1050
+ }
1051
+ if (code.startsWith("<!", index)) {
1052
+ const close = code.indexOf(">", index);
1053
+ const stop = close < 0 ? code.length : close + 1;
1054
+ push(code.slice(index, stop), "meta");
1055
+ return stop;
1056
+ }
1057
+ const name = /^<\/?([A-Za-z][\w:.-]*)/u.exec(code.slice(index));
1058
+ if (name === null)
1059
+ return undefined;
1060
+ push(name[0], "tag");
1061
+ let cursor = index + name[0].length;
1062
+ while (cursor < code.length && code[cursor] !== ">" && code[cursor] !== "<") {
1063
+ const current = code[cursor] ?? "";
1064
+ if (current === "/" && code[cursor + 1] === ">")
1065
+ break;
1066
+ if (/\s/u.test(current)) {
1067
+ text(current);
1068
+ cursor += 1;
1069
+ continue;
1070
+ }
1071
+ const attribute = /^[^\s=/>]+/u.exec(code.slice(cursor))?.[0] ?? current;
1072
+ push(attribute, "attr");
1073
+ cursor += attribute.length;
1074
+ const equals = /^\s*=\s*/u.exec(code.slice(cursor))?.[0] ?? "";
1075
+ if (equals === "")
1076
+ continue;
1077
+ text(equals);
1078
+ cursor += equals.length;
1079
+ const quote = code[cursor];
1080
+ if (quote === '"' || quote === "'") {
1081
+ const close = code.indexOf(quote, cursor + 1);
1082
+ const stop = close < 0 ? code.length : close + 1;
1083
+ push(code.slice(cursor, stop), "string");
1084
+ cursor = stop;
1085
+ }
1086
+ }
1087
+ return cursor;
1088
+ }
1089
+ //# sourceMappingURL=highlight.js.map