@shikijs/twoslash 3.22.0 → 4.0.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/core.mjs CHANGED
@@ -1,1338 +1,214 @@
1
- import { splitTokens } from '@shikijs/core';
2
-
3
- class ShikiTwoslashError extends Error {
4
- constructor(message) {
5
- super(message);
6
- this.name = "ShikiTwoslashError";
7
- }
8
- }
9
-
10
- class TwoslashIncludesManager {
11
- constructor(map = /* @__PURE__ */ new Map()) {
12
- this.map = map;
13
- }
14
- add(name, code) {
15
- const lines = [];
16
- code.split("\n").forEach((l, _i) => {
17
- const trimmed = l.trim();
18
- if (trimmed.startsWith("// - ")) {
19
- const key = trimmed.split("// - ")[1].split(" ")[0];
20
- this.map.set(`${name}-${key}`, lines.join("\n"));
21
- } else {
22
- lines.push(l);
23
- }
24
- });
25
- this.map.set(name, lines.join("\n"));
26
- }
27
- applyInclude(code) {
28
- const reMarker = /\/\/ @include: (.*)$/gm;
29
- const toReplace = [];
30
- for (const match of code.matchAll(reMarker)) {
31
- const key = match[1];
32
- const replaceWith = this.map.get(key);
33
- if (!replaceWith) {
34
- const msg = `Could not find an include with the key: '${key}'.
35
- There is: ${Array.from(this.map.keys())}.`;
36
- throw new Error(msg);
37
- } else {
38
- toReplace.push([match.index, match[0].length, replaceWith]);
39
- }
40
- }
41
- let newCode = code.toString();
42
- toReplace.reverse().forEach(([index, length, replacementCode]) => {
43
- newCode = newCode.slice(0, index) + replacementCode + newCode.slice(index + length);
44
- });
45
- return newCode;
46
- }
47
- }
48
- const INCLUDE_META_REGEX = /include\s+([\w-]+)\b.*/;
49
- function parseIncludeMeta(meta) {
50
- if (!meta)
51
- return null;
52
- const match = meta.match(INCLUDE_META_REGEX);
53
- return match?.[1] ?? null;
54
- }
55
-
56
- const module$1 = {
57
- type: "element",
58
- tagName: "svg",
59
- properties: {
60
- viewBox: "0 0 32 32"
61
- },
62
- children: [
63
- {
64
- type: "element",
65
- tagName: "path",
66
- properties: {
67
- d: "M11 2H2v9h2V4h7V2z",
68
- fill: "currentColor"
69
- },
70
- children: [
71
- ]
72
- },
73
- {
74
- type: "element",
75
- tagName: "path",
76
- properties: {
77
- d: "M2 21v9h9v-2H4v-7H2z",
78
- fill: "currentColor"
79
- },
80
- children: [
81
- ]
82
- },
83
- {
84
- type: "element",
85
- tagName: "path",
86
- properties: {
87
- d: "M30 11V2h-9v2h7v7h2z",
88
- fill: "currentColor"
89
- },
90
- children: [
91
- ]
92
- },
93
- {
94
- type: "element",
95
- tagName: "path",
96
- properties: {
97
- d: "M21 30h9v-9h-2v7h-7v2z",
98
- fill: "currentColor"
99
- },
100
- children: [
101
- ]
102
- },
103
- {
104
- type: "element",
105
- tagName: "path",
106
- properties: {
107
- d: "M25.49 10.13l-9-5a1 1 0 0 0-1 0l-9 5A1 1 0 0 0 6 11v10a1 1 0 0 0 .51.87l9 5a1 1 0 0 0 1 0l9-5A1 1 0 0 0 26 21V11a1 1 0 0 0-.51-.87zM16 7.14L22.94 11L16 14.86L9.06 11zM8 12.7l7 3.89v7.71l-7-3.89zm9 11.6v-7.71l7-3.89v7.71z",
108
- fill: "currentColor"
109
- },
110
- children: [
111
- ]
112
- }
113
- ]
114
- };
115
- const method = {
116
- type: "element",
117
- tagName: "svg",
118
- properties: {
119
- viewBox: "0 0 32 32"
120
- },
121
- children: [
122
- {
123
- type: "element",
124
- tagName: "path",
125
- properties: {
126
- fill: "currentColor",
127
- d: "m19.626 29.526l-.516-1.933a12.004 12.004 0 0 0 6.121-19.26l1.538-1.28a14.003 14.003 0 0 1-7.143 22.473"
128
- },
129
- children: [
130
- ]
131
- },
132
- {
133
- type: "element",
134
- tagName: "path",
135
- properties: {
136
- fill: "currentColor",
137
- d: "M10 29H8v-3.82l.804-.16C10.262 24.727 12 23.62 12 20v-1.382l-4-2v-2.236l4-2V12c0-5.467 3.925-9 10-9h2v3.82l-.804.16C21.738 7.273 20 8.38 20 12v.382l4 2v2.236l-4 2V20c0 5.467-3.925 9-10 9m0-2c4.935 0 8-2.682 8-7v-2.618l3.764-1.882L18 13.618V12c0-4.578 2.385-6.192 4-6.76V5c-4.935 0-8 2.682-8 7v1.618L10.236 15.5L14 17.382V20c0 4.578-2.385 6.192-4 6.76Z"
138
- },
139
- children: [
140
- ]
141
- },
142
- {
143
- type: "element",
144
- tagName: "path",
145
- properties: {
146
- fill: "currentColor",
147
- d: "M5.231 24.947a14.003 14.003 0 0 1 7.147-22.474l.516 1.932a12.004 12.004 0 0 0-6.125 19.263Z"
148
- },
149
- children: [
150
- ]
151
- }
152
- ]
153
- };
154
- const property = {
155
- type: "element",
156
- tagName: "svg",
157
- properties: {
158
- viewBox: "0 0 32 32"
159
- },
160
- children: [
161
- {
162
- type: "element",
163
- tagName: "path",
164
- properties: {
165
- fill: "currentColor",
166
- d: "M12.1 2a9.8 9.8 0 0 0-5.4 1.6l6.4 6.4a2.1 2.1 0 0 1 .2 3a2.1 2.1 0 0 1-3-.2L3.7 6.4A9.84 9.84 0 0 0 2 12.1a10.14 10.14 0 0 0 10.1 10.1a10.9 10.9 0 0 0 2.6-.3l6.7 6.7a5 5 0 0 0 7.1-7.1l-6.7-6.7a10.9 10.9 0 0 0 .3-2.6A10 10 0 0 0 12.1 2m8 10.1a7.61 7.61 0 0 1-.3 2.1l-.3 1.1l.8.8l6.7 6.7a2.88 2.88 0 0 1 .9 2.1A2.72 2.72 0 0 1 27 27a2.9 2.9 0 0 1-4.2 0l-6.7-6.7l-.8-.8l-1.1.3a7.61 7.61 0 0 1-2.1.3a8.27 8.27 0 0 1-5.7-2.3A7.63 7.63 0 0 1 4 12.1a8.33 8.33 0 0 1 .3-2.2l4.4 4.4a4.14 4.14 0 0 0 5.9.2a4.14 4.14 0 0 0-.2-5.9L10 4.2a6.45 6.45 0 0 1 2-.3a8.27 8.27 0 0 1 5.7 2.3a8.49 8.49 0 0 1 2.4 5.9"
167
- },
168
- children: [
169
- ]
170
- }
171
- ]
172
- };
173
- const constructor = {
174
- type: "element",
175
- tagName: "svg",
176
- properties: {
177
- viewBox: "0 0 32 32"
178
- },
179
- children: [
180
- {
181
- type: "element",
182
- tagName: "path",
183
- properties: {
184
- d: "M21.49 13.115l-9-5a1 1 0 0 0-1 0l-9 5A1.008 1.008 0 0 0 2 14v9.995a1 1 0 0 0 .52.87l9 5A1.004 1.004 0 0 0 12 30a1.056 1.056 0 0 0 .49-.135l9-5A.992.992 0 0 0 22 24V14a1.008 1.008 0 0 0-.51-.885zM11 27.295l-7-3.89v-7.72l7 3.89zm1-9.45L5.06 14L12 10.135l6.94 3.86zm8 5.56l-7 3.89v-7.72l7-3.89z",
185
- fill: "currentColor"
186
- },
187
- children: [
188
- ]
189
- },
190
- {
191
- type: "element",
192
- tagName: "path",
193
- properties: {
194
- d: "M30 6h-4V2h-2v4h-4v2h4v4h2V8h4V6z",
195
- fill: "currentColor"
196
- },
197
- children: [
198
- ]
199
- }
200
- ]
201
- };
202
- const string = {
203
- type: "element",
204
- tagName: "svg",
205
- properties: {
206
- viewBox: "0 0 32 32"
207
- },
208
- children: [
209
- {
210
- type: "element",
211
- tagName: "path",
212
- properties: {
213
- fill: "currentColor",
214
- d: "M29 22h-5a2.003 2.003 0 0 1-2-2v-6a2.002 2.002 0 0 1 2-2h5v2h-5v6h5zM18 12h-4V8h-2v14h6a2.003 2.003 0 0 0 2-2v-6a2.002 2.002 0 0 0-2-2m-4 8v-6h4v6zm-6-8H3v2h5v2H4a2 2 0 0 0-2 2v2a2 2 0 0 0 2 2h6v-8a2.002 2.002 0 0 0-2-2m0 8H4v-2h4z"
215
- },
216
- children: [
217
- ]
218
- }
219
- ]
220
- };
221
- const completionIcons = {
222
- module: module$1,
223
- "class": {
224
- type: "element",
225
- tagName: "svg",
226
- properties: {
227
- viewBox: "0 0 32 32"
228
- },
229
- children: [
230
- {
231
- type: "element",
232
- tagName: "path",
233
- properties: {
234
- fill: "currentColor",
235
- d: "M26 16a3.961 3.961 0 0 0-2.02.566l-2.859-2.859l2.293-2.293a2 2 0 0 0 0-2.828l-6-6a2 2 0 0 0-2.828 0l-6 6a2 2 0 0 0 0 2.828l2.293 2.293l-2.859 2.859a4.043 4.043 0 1 0 1.414 1.414l2.859-2.859l2.293 2.293a1.977 1.977 0 0 0 .414.31V22h-3v8h8v-8h-3v-4.277a1.977 1.977 0 0 0 .414-.309l2.293-2.293l2.859 2.859A3.989 3.989 0 1 0 26 16M8 20a2 2 0 1 1-2-2a2.002 2.002 0 0 1 2 2m10 4v4h-4v-4zm-2-8l-6-6l6-6l6 6Zm10 6a2 2 0 1 1 2-2a2.002 2.002 0 0 1-2 2"
236
- },
237
- children: [
238
- ]
239
- }
240
- ]
241
- },
242
- method: method,
243
- property: property,
244
- constructor: constructor,
245
- "interface": {
246
- type: "element",
247
- tagName: "svg",
248
- properties: {
249
- viewBox: "0 0 32 32"
250
- },
251
- children: [
252
- {
253
- type: "element",
254
- tagName: "path",
255
- properties: {
256
- fill: "currentColor",
257
- d: "M23 16.01a7 7 0 0 0-4.18 1.39l-4.22-4.22A6.86 6.86 0 0 0 16 9.01a7 7 0 1 0-2.81 5.59l4.21 4.22a7 7 0 1 0 5.6-2.81m-19-7a5 5 0 1 1 5 5a5 5 0 0 1-5-5"
258
- },
259
- children: [
260
- ]
261
- }
262
- ]
263
- },
264
- "function": {
265
- type: "element",
266
- tagName: "svg",
267
- properties: {
268
- viewBox: "0 0 32 32"
269
- },
270
- children: [
271
- {
272
- type: "element",
273
- tagName: "path",
274
- properties: {
275
- fill: "currentColor",
276
- d: "m19.626 29.526l-.516-1.933a12.004 12.004 0 0 0 6.121-19.26l1.538-1.28a14.003 14.003 0 0 1-7.143 22.473"
277
- },
278
- children: [
279
- ]
280
- },
281
- {
282
- type: "element",
283
- tagName: "path",
284
- properties: {
285
- fill: "currentColor",
286
- d: "M10 29H8v-3.82l.804-.16C10.262 24.727 12 23.62 12 20v-1.382l-4-2v-2.236l4-2V12c0-5.467 3.925-9 10-9h2v3.82l-.804.16C21.738 7.273 20 8.38 20 12v.382l4 2v2.236l-4 2V20c0 5.467-3.925 9-10 9m0-2c4.935 0 8-2.682 8-7v-2.618l3.764-1.882L18 13.618V12c0-4.578 2.385-6.192 4-6.76V5c-4.935 0-8 2.682-8 7v1.618L10.236 15.5L14 17.382V20c0 4.578-2.385 6.192-4 6.76Z"
287
- },
288
- children: [
289
- ]
290
- },
291
- {
292
- type: "element",
293
- tagName: "path",
294
- properties: {
295
- fill: "currentColor",
296
- d: "M5.231 24.947a14.003 14.003 0 0 1 7.147-22.474l.516 1.932a12.004 12.004 0 0 0-6.125 19.263Z"
297
- },
298
- children: [
299
- ]
300
- }
301
- ]
302
- },
303
- string: string
304
- };
305
-
306
- const log = {
307
- type: "element",
308
- tagName: "svg",
309
- properties: {
310
- viewBox: "0 0 32 32"
311
- },
312
- children: [
313
- {
314
- type: "element",
315
- tagName: "path",
316
- properties: {
317
- fill: "currentColor",
318
- d: "M17 22v-8h-4v2h2v6h-3v2h8v-2zM16 8a1.5 1.5 0 1 0 1.5 1.5A1.5 1.5 0 0 0 16 8"
319
- },
320
- children: [
321
- ]
322
- },
323
- {
324
- type: "element",
325
- tagName: "path",
326
- properties: {
327
- fill: "currentColor",
328
- d: "M26 28H6a2.002 2.002 0 0 1-2-2V6a2.002 2.002 0 0 1 2-2h20a2.002 2.002 0 0 1 2 2v20a2.002 2.002 0 0 1-2 2M6 6v20h20V6Z"
329
- },
330
- children: [
331
- ]
332
- }
333
- ]
334
- };
335
- const error = {
336
- type: "element",
337
- tagName: "svg",
338
- properties: {
339
- viewBox: "0 0 32 32"
340
- },
341
- children: [
342
- {
343
- type: "element",
344
- tagName: "path",
345
- properties: {
346
- fill: "currentColor",
347
- d: "M16 2a14 14 0 1 0 14 14A14 14 0 0 0 16 2m0 26a12 12 0 1 1 12-12a12 12 0 0 1-12 12"
348
- },
349
- children: [
350
- ]
351
- },
352
- {
353
- type: "element",
354
- tagName: "path",
355
- properties: {
356
- fill: "currentColor",
357
- d: "M15 8h2v11h-2zm1 14a1.5 1.5 0 1 0 1.5 1.5A1.5 1.5 0 0 0 16 22"
358
- },
359
- children: [
360
- ]
361
- }
362
- ]
363
- };
364
- const warn = {
365
- type: "element",
366
- tagName: "svg",
367
- properties: {
368
- viewBox: "0 0 32 32"
369
- },
370
- children: [
371
- {
372
- type: "element",
373
- tagName: "path",
374
- properties: {
375
- fill: "currentColor",
376
- d: "M16 23a1.5 1.5 0 1 0 1.5 1.5A1.5 1.5 0 0 0 16 23m-1-11h2v9h-2z"
377
- },
378
- children: [
379
- ]
380
- },
381
- {
382
- type: "element",
383
- tagName: "path",
384
- properties: {
385
- fill: "currentColor",
386
- d: "M29 30H3a1 1 0 0 1-.887-1.461l13-25a1 1 0 0 1 1.774 0l13 25A1 1 0 0 1 29 30M4.65 28h22.7l.001-.003L16.002 6.17h-.004L4.648 27.997Z"
387
- },
388
- children: [
389
- ]
390
- }
391
- ]
392
- };
393
- const annotate = {
394
- type: "element",
395
- tagName: "svg",
396
- properties: {
397
- viewBox: "0 0 32 32"
398
- },
399
- children: [
400
- {
401
- type: "element",
402
- tagName: "path",
403
- properties: {
404
- fill: "currentColor",
405
- d: "M11 24h10v2H11zm2 4h6v2h-6zm3-26A10 10 0 0 0 6 12a9.19 9.19 0 0 0 3.46 7.62c1 .93 1.54 1.46 1.54 2.38h2c0-1.84-1.11-2.87-2.19-3.86A7.2 7.2 0 0 1 8 12a8 8 0 0 1 16 0a7.2 7.2 0 0 1-2.82 6.14c-1.07 1-2.18 2-2.18 3.86h2c0-.92.53-1.45 1.54-2.39A9.18 9.18 0 0 0 26 12A10 10 0 0 0 16 2"
406
- },
407
- children: [
408
- ]
409
- }
410
- ]
411
- };
412
- const tagIcons = {
413
- log: log,
414
- error: error,
415
- warn: warn,
416
- annotate: annotate
417
- };
418
-
419
- const defaultCompletionIcons = completionIcons;
420
- const defaultCustomTagIcons = tagIcons;
421
-
422
- function rendererClassic() {
423
- return {
424
- nodeStaticInfo(info, node) {
425
- return {
426
- type: "element",
427
- tagName: "data-lsp",
428
- properties: {
429
- lsp: info.text
430
- },
431
- children: [node]
432
- };
433
- },
434
- nodeError(_, node) {
435
- return {
436
- type: "element",
437
- tagName: "data-err",
438
- properties: {},
439
- children: [node]
440
- };
441
- },
442
- lineError(error) {
443
- return [
444
- {
445
- type: "element",
446
- tagName: "div",
447
- properties: {
448
- class: "error"
449
- },
450
- children: [
451
- {
452
- type: "element",
453
- tagName: "span",
454
- properties: {},
455
- children: [
456
- {
457
- type: "text",
458
- value: error.text
459
- }
460
- ]
461
- },
462
- {
463
- type: "element",
464
- tagName: "span",
465
- properties: {
466
- class: "code"
467
- },
468
- children: [
469
- {
470
- type: "text",
471
- value: String(error.code)
472
- }
473
- ]
474
- }
475
- ]
476
- },
477
- {
478
- type: "element",
479
- tagName: "span",
480
- properties: {
481
- class: "error-behind"
482
- },
483
- children: [
484
- {
485
- type: "text",
486
- value: error.text
487
- }
488
- ]
489
- }
490
- ];
491
- },
492
- lineCompletion(query) {
493
- return [
494
- {
495
- type: "element",
496
- tagName: "div",
497
- properties: { class: "meta-line" },
498
- children: [
499
- { type: "text", value: " ".repeat(query.character) },
500
- {
501
- type: "element",
502
- tagName: "span",
503
- properties: { class: "inline-completions" },
504
- children: [{
505
- type: "element",
506
- tagName: "ul",
507
- properties: { class: "dropdown" },
508
- children: query.completions.filter((i) => i.name.startsWith(query.completionsPrefix || "____")).map((i) => ({
509
- type: "element",
510
- tagName: "li",
511
- properties: {
512
- class: "kindModifiers" in i && typeof i.kindModifiers === "string" && i.kindModifiers?.split(",").includes("deprecated") ? "deprecated" : void 0
513
- },
514
- children: [{
515
- type: "element",
516
- tagName: "span",
517
- properties: {},
518
- children: [
519
- {
520
- type: "element",
521
- tagName: "span",
522
- properties: { class: "result-found" },
523
- children: [
524
- {
525
- type: "text",
526
- value: query.completionsPrefix || ""
527
- }
528
- ]
529
- },
530
- {
531
- type: "text",
532
- value: i.name.slice(query.completionsPrefix?.length || 0)
533
- }
534
- ]
535
- }]
536
- }))
537
- }]
538
- }
539
- ]
540
- }
541
- ];
542
- },
543
- lineQuery(query, targetNode) {
544
- const targetText = targetNode?.type === "text" ? targetNode.value : "";
545
- const offset = Math.max(0, (query.character || 0) + Math.floor(targetText.length / 2) - 1);
546
- return [
547
- {
548
- type: "element",
549
- tagName: "div",
550
- properties: { class: "meta-line" },
551
- children: [
552
- { type: "text", value: " ".repeat(offset) },
553
- {
554
- type: "element",
555
- tagName: "span",
556
- properties: { class: "popover" },
557
- children: [
558
- {
559
- type: "element",
560
- tagName: "div",
561
- properties: { class: "arrow" },
562
- children: []
563
- },
564
- {
565
- type: "text",
566
- value: query.text || ""
567
- }
568
- ]
569
- }
570
- ]
571
- }
572
- ];
573
- },
574
- lineCustomTag(tag) {
575
- return [
576
- {
577
- type: "element",
578
- tagName: "div",
579
- properties: { class: `meta-line logger ${tag.name}-log` },
580
- children: [
581
- {
582
- type: "element",
583
- tagName: "span",
584
- properties: { class: "message" },
585
- children: [
586
- {
587
- type: "text",
588
- value: tag.text || ""
589
- }
590
- ]
591
- }
592
- ]
593
- }
594
- ];
595
- }
596
- };
597
- }
598
-
599
- function extend(extension, node) {
600
- if (!extension)
601
- return node;
602
- return {
603
- ...node,
604
- tagName: extension.tagName ?? node.tagName,
605
- properties: {
606
- ...node.properties,
607
- class: extension.class || node.properties?.class,
608
- ...extension.properties
609
- },
610
- children: extension.children?.(node.children) ?? node.children
611
- };
612
- }
613
- function renderMarkdownPassThrough(markdown) {
614
- return [
615
- {
616
- type: "text",
617
- value: markdown
618
- }
619
- ];
620
- }
621
- function rendererRich(options = {}) {
622
- const {
623
- completionIcons = defaultCompletionIcons,
624
- customTagIcons = defaultCustomTagIcons,
625
- processHoverInfo = defaultHoverInfoProcessor,
626
- processHoverDocs = (docs) => docs,
627
- classExtra = "",
628
- jsdoc = true,
629
- errorRendering = "line",
630
- queryRendering = "popup",
631
- renderMarkdown = renderMarkdownPassThrough,
632
- renderMarkdownInline = renderMarkdownPassThrough,
633
- hast
634
- } = options;
635
- function highlightPopupContent(info) {
636
- if (!info.text)
637
- return [];
638
- const content = processHoverInfo(info.text);
639
- if (!content || content === "any")
640
- return [];
641
- const popupContents = [];
642
- let lang = this.options.lang;
643
- if (lang === "jsx")
644
- lang = "tsx";
645
- else if (lang === "js" || lang === "javascript")
646
- lang = "ts";
647
- const typeCode = {
648
- type: "element",
649
- tagName: "code",
650
- properties: {},
651
- children: this.codeToHast(
652
- content,
653
- {
654
- ...this.options,
655
- meta: {},
656
- transformers: [],
657
- lang,
658
- structure: content.trim().includes("\n") ? "classic" : "inline"
659
- }
660
- ).children
661
- };
662
- typeCode.properties.class = "twoslash-popup-code";
663
- popupContents.push(
664
- extend(
665
- hast?.popupTypes,
666
- typeCode
667
- )
668
- );
669
- if (jsdoc && info.docs) {
670
- const docs = processHoverDocs(info.docs) ?? info.docs;
671
- if (docs) {
672
- const children = renderMarkdown.call(this, docs);
673
- popupContents.push(extend(
674
- hast?.popupDocs,
675
- {
676
- type: "element",
677
- tagName: "div",
678
- properties: { class: "twoslash-popup-docs" },
679
- children
680
- }
681
- ));
682
- }
683
- }
684
- if (jsdoc && info.tags?.length) {
685
- popupContents.push(extend(
686
- hast?.popupDocsTags,
687
- {
688
- type: "element",
689
- tagName: "div",
690
- properties: {
691
- class: "twoslash-popup-docs twoslash-popup-docs-tags"
692
- },
693
- children: info.tags.map((tag) => ({
694
- type: "element",
695
- tagName: "span",
696
- properties: {
697
- class: `twoslash-popup-docs-tag`
698
- },
699
- children: [
700
- {
701
- type: "element",
702
- tagName: "span",
703
- properties: {
704
- class: "twoslash-popup-docs-tag-name"
705
- },
706
- children: [
707
- {
708
- type: "text",
709
- value: `@${tag[0]}`
710
- }
711
- ]
712
- },
713
- ...tag[1] ? [
714
- {
715
- type: "element",
716
- tagName: "span",
717
- properties: {
718
- class: "twoslash-popup-docs-tag-value"
719
- },
720
- children: renderMarkdownInline.call(this, tag[1], `tag:${tag[0]}`)
721
- }
722
- ] : []
723
- ]
724
- }))
725
- }
726
- ));
727
- }
728
- return popupContents;
729
- }
730
- return {
731
- nodeStaticInfo(info, node) {
732
- const themedContent = highlightPopupContent.call(this, info);
733
- if (!themedContent.length)
734
- return node;
735
- const popup = extend(
736
- hast?.hoverPopup,
737
- {
738
- type: "element",
739
- tagName: "span",
740
- properties: {
741
- class: ["twoslash-popup-container", classExtra].filter(Boolean).join(" ")
742
- },
743
- children: themedContent
744
- }
745
- );
746
- return extend(
747
- hast?.hoverToken,
748
- {
749
- type: "element",
750
- tagName: "span",
751
- properties: {
752
- class: "twoslash-hover"
753
- },
754
- children: hast?.hoverCompose ? hast?.hoverCompose({ popup, token: node }) : [popup, node]
755
- }
756
- );
757
- },
758
- nodeQuery(query, node) {
759
- if (!query.text)
760
- return {};
761
- const themedContent = highlightPopupContent.call(this, query);
762
- if (queryRendering !== "popup") {
763
- return extend(
764
- hast?.queryToken,
765
- {
766
- type: "element",
767
- tagName: "span",
768
- properties: {
769
- class: "twoslash-hover"
770
- },
771
- children: [
772
- node
773
- ]
774
- }
775
- );
776
- }
777
- const popup = extend(
778
- hast?.queryPopup,
779
- {
780
- type: "element",
781
- tagName: "span",
782
- properties: {
783
- class: ["twoslash-popup-container", classExtra].filter(Boolean).join(" ")
784
- },
785
- children: [
786
- {
787
- type: "element",
788
- tagName: "div",
789
- properties: { class: "twoslash-popup-arrow" },
790
- children: []
791
- },
792
- ...themedContent
793
- ]
794
- }
795
- );
796
- return extend(
797
- hast?.queryToken,
798
- {
799
- type: "element",
800
- tagName: "span",
801
- properties: {
802
- // TODO: `twoslash-query-presisted` was a typo before v3.17. We keep it for backward compatibility.
803
- // We should remove it in the next major version.
804
- class: "twoslash-hover twoslash-query-persisted twoslash-query-presisted"
805
- },
806
- children: hast?.queryCompose ? hast?.queryCompose({ popup, token: node }) : [popup, node]
807
- }
808
- );
809
- },
810
- nodeCompletion(query, node) {
811
- if (node.type !== "text")
812
- throw new ShikiTwoslashError(`Renderer hook nodeCompletion only works on text nodes, got ${node.type}`);
813
- const items = query.completions.map((i) => {
814
- const kind = i.kind || "default";
815
- const isDeprecated = "kindModifiers" in i && typeof i.kindModifiers === "string" && i.kindModifiers?.split(",").includes("deprecated");
816
- return {
817
- type: "element",
818
- tagName: "li",
819
- properties: {},
820
- children: [
821
- ...completionIcons ? [{
822
- type: "element",
823
- tagName: "span",
824
- properties: { class: `twoslash-completions-icon completions-${kind.replace(/\s/g, "-")}` },
825
- children: [
826
- completionIcons[kind] || completionIcons.property
827
- ].filter(Boolean)
828
- }] : [],
829
- {
830
- type: "element",
831
- tagName: "span",
832
- properties: {
833
- class: isDeprecated ? "deprecated" : void 0
834
- },
835
- children: [
836
- {
837
- type: "element",
838
- tagName: "span",
839
- properties: { class: "twoslash-completions-matched" },
840
- children: [
841
- {
842
- type: "text",
843
- value: i.name.startsWith(query.completionsPrefix) ? query.completionsPrefix : ""
844
- }
845
- ]
846
- },
847
- {
848
- type: "element",
849
- tagName: "span",
850
- properties: { class: "twoslash-completions-unmatched" },
851
- children: [
852
- {
853
- type: "text",
854
- value: i.name.startsWith(query.completionsPrefix) ? i.name.slice(query.completionsPrefix.length || 0) : i.name
855
- }
856
- ]
857
- }
858
- ]
859
- }
860
- ]
861
- };
862
- });
863
- const cursor = extend(
864
- hast?.completionCursor,
865
- {
866
- type: "element",
867
- tagName: "span",
868
- properties: {
869
- class: ["twoslash-completion-cursor", classExtra].filter(Boolean).join(" ")
870
- },
871
- children: []
872
- }
873
- );
874
- const popup = extend(
875
- hast?.completionPopup,
876
- {
877
- type: "element",
878
- tagName: "ul",
879
- properties: {
880
- class: ["twoslash-completion-list", classExtra].filter(Boolean).join(" ")
881
- },
882
- children: items
883
- }
884
- );
885
- const children = [];
886
- if (node.value)
887
- children.push({ type: "text", value: node.value });
888
- if (hast?.completionCompose) {
889
- children.push(...hast.completionCompose({ popup, cursor }));
890
- } else {
891
- children.push({
892
- ...cursor,
893
- children: [popup]
894
- });
895
- }
896
- return extend(
897
- hast?.completionToken,
898
- {
899
- type: "element",
900
- tagName: "span",
901
- properties: {},
902
- children
903
- }
904
- );
905
- },
906
- nodesError(error, children) {
907
- if (errorRendering !== "hover") {
908
- return [
909
- extend(
910
- hast?.errorToken,
911
- {
912
- type: "element",
913
- tagName: "span",
914
- properties: {
915
- class: [`twoslash-error`, getErrorLevelClass(error)].filter(Boolean).join(" ")
916
- },
917
- children
918
- }
919
- )
920
- ];
921
- }
922
- const popup = extend(
923
- hast?.errorPopup,
924
- {
925
- type: "element",
926
- tagName: "span",
927
- properties: {
928
- class: ["twoslash-popup-container", classExtra].filter(Boolean).join(" ")
929
- },
930
- children: [
931
- extend(
932
- hast?.popupError,
933
- {
934
- type: "element",
935
- tagName: "div",
936
- properties: {
937
- class: "twoslash-popup-error"
938
- },
939
- children: renderMarkdown.call(this, error.text)
940
- }
941
- )
942
- ]
943
- }
944
- );
945
- const token = {
946
- type: "element",
947
- tagName: "span",
948
- children,
949
- properties: {}
950
- };
951
- return [
952
- extend(
953
- hast?.errorToken,
954
- {
955
- type: "element",
956
- tagName: "span",
957
- properties: {
958
- class: `twoslash-error twoslash-error-hover ${getErrorLevelClass(error)}`
959
- },
960
- children: hast?.errorCompose ? hast?.errorCompose({ popup, token }) : [popup, token]
961
- }
962
- )
963
- ];
964
- },
965
- lineQuery(query, node) {
966
- if (queryRendering !== "line")
967
- return [];
968
- const themedContent = highlightPopupContent.call(this, query);
969
- const targetNode = node?.type === "element" ? node.children[0] : void 0;
970
- const targetText = targetNode?.type === "text" ? targetNode.value : "";
971
- const offset = Math.max(0, (query.character || 0) + Math.floor(targetText.length / 2) - 2);
972
- return [
973
- {
974
- type: "element",
975
- tagName: "div",
976
- properties: {
977
- class: ["twoslash-meta-line twoslash-query-line", classExtra].filter(Boolean).join(" ")
978
- },
979
- children: [
980
- { type: "text", value: " ".repeat(offset) },
981
- {
982
- type: "element",
983
- tagName: "span",
984
- properties: {
985
- class: ["twoslash-popup-container", classExtra].filter(Boolean).join(" ")
986
- },
987
- children: [
988
- {
989
- type: "element",
990
- tagName: "div",
991
- properties: { class: "twoslash-popup-arrow" },
992
- children: []
993
- },
994
- ...themedContent
995
- ]
996
- }
997
- ]
998
- }
999
- ];
1000
- },
1001
- lineError(error) {
1002
- if (errorRendering !== "line")
1003
- return [];
1004
- return [
1005
- {
1006
- type: "element",
1007
- tagName: "div",
1008
- properties: {
1009
- class: ["twoslash-meta-line twoslash-error-line", getErrorLevelClass(error), classExtra].filter(Boolean).join(" ")
1010
- },
1011
- children: [
1012
- {
1013
- type: "text",
1014
- value: error.text
1015
- }
1016
- ]
1017
- }
1018
- ];
1019
- },
1020
- lineCustomTag(tag) {
1021
- return [
1022
- {
1023
- type: "element",
1024
- tagName: "div",
1025
- properties: {
1026
- class: [`twoslash-tag-line twoslash-tag-${tag.name}-line`, classExtra].filter(Boolean).join(" ")
1027
- },
1028
- children: [
1029
- ...customTagIcons ? [{
1030
- type: "element",
1031
- tagName: "span",
1032
- properties: { class: `twoslash-tag-icon tag-${tag.name}-icon` },
1033
- children: [
1034
- customTagIcons[tag.name]
1035
- ].filter(Boolean)
1036
- }] : [],
1037
- {
1038
- type: "text",
1039
- value: tag.text || ""
1040
- }
1041
- ]
1042
- }
1043
- ];
1044
- },
1045
- nodesHighlight(highlight, nodes) {
1046
- return [
1047
- extend(
1048
- hast?.nodesHighlight,
1049
- {
1050
- type: "element",
1051
- tagName: "span",
1052
- properties: {
1053
- class: "twoslash-highlighted"
1054
- },
1055
- children: nodes
1056
- }
1057
- )
1058
- ];
1059
- }
1060
- };
1061
- }
1062
- const regexType = /^[A-Z]\w*(<[^>]*>)?:/;
1063
- const regexFunction = /^\w*\(/;
1064
- function defaultHoverInfoProcessor(type) {
1065
- let content = type.replace(/^\(([\w-]+)\)\s+/gm, "").replace(/\nimport .*$/, "").replace(/^(interface|namespace) \w+$/gm, "").trim();
1066
- if (content.match(regexType))
1067
- content = `type ${content}`;
1068
- else if (content.match(regexFunction))
1069
- content = `function ${content}`;
1070
- return content;
1071
- }
1072
- function getErrorLevelClass(error) {
1073
- switch (error.level) {
1074
- case "warning":
1075
- return "twoslash-error-level-warning";
1076
- case "suggestion":
1077
- return "twoslash-error-level-suggestion";
1078
- case "message":
1079
- return "twoslash-error-level-message";
1080
- default:
1081
- return "";
1082
- }
1083
- }
1
+ import { a as defaultCustomTagIcons, c as ShikiTwoslashError, i as defaultCompletionIcons, n as rendererRich, o as TwoslashIncludesManager, r as rendererClassic, s as parseIncludeMeta, t as defaultHoverInfoProcessor } from "./renderer-rich-DEkszi0Z.mjs";
2
+ import { splitTokens } from "@shikijs/core";
1084
3
 
4
+ //#region src/core.ts
1085
5
  function defaultTwoslashOptions() {
1086
- return {
1087
- customTags: ["annotate", "log", "warn", "error"],
1088
- compilerOptions: {
1089
- moduleResolution: 100
1090
- }
1091
- };
6
+ return {
7
+ customTags: [
8
+ "annotate",
9
+ "log",
10
+ "warn",
11
+ "error"
12
+ ],
13
+ compilerOptions: { moduleResolution: 100 }
14
+ };
1092
15
  }
1093
16
  function createTransformerFactory(defaultTwoslasher, defaultRenderer) {
1094
- return function transformerTwoslash(options = {}) {
1095
- const {
1096
- langs = ["ts", "tsx"],
1097
- twoslashOptions = defaultTwoslashOptions(),
1098
- langAlias = {
1099
- typescript: "ts",
1100
- json5: "json",
1101
- yml: "yaml"
1102
- },
1103
- twoslasher = defaultTwoslasher,
1104
- explicitTrigger = false,
1105
- disableTriggers = ["notwoslash", "no-twoslash"],
1106
- renderer = defaultRenderer,
1107
- throws = true,
1108
- includesMap = /* @__PURE__ */ new Map(),
1109
- typesCache
1110
- } = options;
1111
- const onTwoslashError = options.onTwoslashError || (throws ? (error) => {
1112
- throw error;
1113
- } : () => false);
1114
- const onShikiError = options.onShikiError || (throws ? (error) => {
1115
- throw error;
1116
- } : () => false);
1117
- const trigger = explicitTrigger instanceof RegExp ? explicitTrigger : /\btwoslash\b/;
1118
- if (!renderer)
1119
- throw new ShikiTwoslashError("Missing renderer");
1120
- const map = /* @__PURE__ */ new WeakMap();
1121
- const {
1122
- filter = (lang, _, options2) => {
1123
- return langs.includes(lang) && (!explicitTrigger || trigger.test(options2.meta?.__raw || "")) && !disableTriggers.some((i) => typeof i === "string" ? options2.meta?.__raw?.includes(i) : i.test(options2.meta?.__raw || ""));
1124
- }
1125
- } = options;
1126
- const includes = new TwoslashIncludesManager(includesMap);
1127
- let _twoslasher = twoslasher;
1128
- if (typesCache) {
1129
- _twoslasher = ((code, lang, options2, meta) => {
1130
- const preprocessed = typesCache?.preprocess?.(code, lang, options2, meta);
1131
- if (preprocessed !== void 0)
1132
- code = preprocessed;
1133
- let twoslash = typesCache?.read(code, lang, options2, meta);
1134
- if (!twoslash) {
1135
- twoslash = twoslasher(code, lang, options2);
1136
- typesCache?.write(code, twoslash, lang, options2, meta);
1137
- }
1138
- return twoslash;
1139
- });
1140
- typesCache.init?.();
1141
- }
1142
- return {
1143
- preprocess(code) {
1144
- let lang = this.options.lang;
1145
- if (lang in langAlias)
1146
- lang = langAlias[this.options.lang];
1147
- if (filter(lang, code, this.options, this)) {
1148
- try {
1149
- const codeWithIncludes = includes.applyInclude(code);
1150
- const include = parseIncludeMeta(this.options.meta?.__raw);
1151
- if (include)
1152
- includes.add(include, codeWithIncludes);
1153
- const twoslash = _twoslasher(codeWithIncludes, lang, twoslashOptions, this.meta);
1154
- map.set(this.meta, twoslash);
1155
- this.meta.twoslash = twoslash;
1156
- this.options.lang = twoslash.meta?.extension || lang;
1157
- return twoslash.code;
1158
- } catch (error) {
1159
- const result = onTwoslashError(error, code, lang, this.options);
1160
- if (typeof result === "string")
1161
- return result;
1162
- }
1163
- }
1164
- },
1165
- tokens(tokens) {
1166
- const twoslash = map.get(this.meta);
1167
- if (!twoslash)
1168
- return;
1169
- return splitTokens(
1170
- tokens,
1171
- twoslash.nodes.flatMap(
1172
- (i) => ["hover", "error", "query", "highlight", "completion"].includes(i.type) ? [i.start, i.start + i.length] : []
1173
- )
1174
- );
1175
- },
1176
- pre(pre) {
1177
- const twoslash = map.get(this.meta);
1178
- if (!twoslash)
1179
- return;
1180
- this.addClassToHast(pre, "twoslash lsp");
1181
- },
1182
- code(codeEl) {
1183
- const twoslash = map.get(this.meta);
1184
- if (!twoslash)
1185
- return;
1186
- const insertAfterLine = (line, nodes) => {
1187
- if (!nodes.length)
1188
- return;
1189
- let index;
1190
- if (line >= this.lines.length) {
1191
- index = codeEl.children.length;
1192
- } else {
1193
- const lineEl = this.lines[line];
1194
- index = codeEl.children.indexOf(lineEl);
1195
- if (index === -1) {
1196
- onShikiError(new ShikiTwoslashError(`Cannot find line ${line} in code element`), this.source, this.options.lang);
1197
- return;
1198
- }
1199
- }
1200
- const nodeAfter = codeEl.children[index + 1];
1201
- if (nodeAfter && nodeAfter.type === "text" && nodeAfter.value === "\n")
1202
- codeEl.children.splice(index + 1, 1);
1203
- codeEl.children.splice(index + 1, 0, ...nodes);
1204
- };
1205
- const tokensMap = [];
1206
- this.lines.forEach((lineEl, line) => {
1207
- let index = 0;
1208
- for (const token of lineEl.children.flatMap((i) => i.type === "element" ? i.children || [] : [])) {
1209
- if ("value" in token && typeof token.value === "string") {
1210
- tokensMap.push([line, index, index + token.value.length, token]);
1211
- index += token.value.length;
1212
- }
1213
- }
1214
- });
1215
- const locateTextTokens = (line, character, length) => {
1216
- const start = character;
1217
- const end = character + length;
1218
- if (length === 0) {
1219
- return tokensMap.filter(([l, s, e]) => l === line && s < start && start <= e).map((i) => i[3]);
1220
- }
1221
- return tokensMap.filter(([l, s, e]) => l === line && (start <= s && s < end) && (start < e && e <= end)).map((i) => i[3]);
1222
- };
1223
- const tokensSkipHover = /* @__PURE__ */ new Set();
1224
- const actionsHovers = [];
1225
- const actionsHighlights = [];
1226
- for (const node of twoslash.nodes) {
1227
- if (node.type === "tag") {
1228
- if (renderer.lineCustomTag)
1229
- insertAfterLine(node.line, renderer.lineCustomTag.call(this, node));
1230
- continue;
1231
- }
1232
- const tokens = locateTextTokens(node.line, node.character, node.length);
1233
- if (!tokens.length && !(node.type === "error" && renderer.nodesError)) {
1234
- onShikiError(new ShikiTwoslashError(`Cannot find tokens for node: ${JSON.stringify(node)}`), this.source, this.options.lang);
1235
- continue;
1236
- }
1237
- const wrapTokens = (fn) => {
1238
- const line = this.lines[node.line];
1239
- let charIndex = 0;
1240
- let itemStart = line.children.length;
1241
- let itemEnd = 0;
1242
- line.children.forEach((token, index) => {
1243
- if (charIndex >= node.character && index < itemStart)
1244
- itemStart = index;
1245
- if (charIndex <= node.character + node.length && index > itemEnd)
1246
- itemEnd = index;
1247
- charIndex += getTokenString(token).length;
1248
- });
1249
- if (charIndex <= node.character + node.length)
1250
- itemEnd = line.children.length;
1251
- const targets = line.children.slice(itemStart, itemEnd);
1252
- const length = targets.length;
1253
- line.children.splice(itemStart, length, ...fn(targets));
1254
- };
1255
- switch (node.type) {
1256
- case "error": {
1257
- if (renderer.nodeError) {
1258
- tokens.forEach((token) => {
1259
- tokensSkipHover.add(token);
1260
- const clone = { ...token };
1261
- Object.assign(token, renderer.nodeError.call(this, node, clone));
1262
- });
1263
- }
1264
- if (renderer.nodesError) {
1265
- tokens.forEach((token) => {
1266
- tokensSkipHover.add(token);
1267
- });
1268
- actionsHighlights.push(() => {
1269
- wrapTokens((targets) => renderer.nodesError?.call(this, node, targets) || targets);
1270
- });
1271
- }
1272
- if (renderer.lineError)
1273
- insertAfterLine(node.line, renderer.lineError.call(this, node));
1274
- break;
1275
- }
1276
- case "query": {
1277
- const token = tokens[0];
1278
- if (token && renderer.nodeQuery) {
1279
- tokensSkipHover.add(token);
1280
- const clone = { ...token };
1281
- Object.assign(token, renderer.nodeQuery.call(this, node, clone));
1282
- }
1283
- if (renderer.lineQuery)
1284
- insertAfterLine(node.line, renderer.lineQuery.call(this, node, token));
1285
- break;
1286
- }
1287
- case "completion": {
1288
- if (renderer.nodeCompletion) {
1289
- tokens.forEach((token) => {
1290
- tokensSkipHover.add(token);
1291
- const clone = { ...token };
1292
- Object.assign(token, renderer.nodeCompletion.call(this, node, clone));
1293
- });
1294
- }
1295
- if (renderer.lineCompletion)
1296
- insertAfterLine(node.line, renderer.lineCompletion.call(this, node));
1297
- break;
1298
- }
1299
- case "highlight": {
1300
- if (renderer.nodesHighlight) {
1301
- actionsHighlights.push(() => {
1302
- wrapTokens((targets) => renderer.nodesHighlight?.call(this, node, targets) || targets);
1303
- });
1304
- }
1305
- break;
1306
- }
1307
- case "hover": {
1308
- if (renderer.nodeStaticInfo) {
1309
- actionsHovers.push(() => {
1310
- tokens.forEach((token) => {
1311
- if (tokensSkipHover.has(token))
1312
- return;
1313
- tokensSkipHover.add(token);
1314
- const clone = { ...token };
1315
- Object.assign(token, renderer.nodeStaticInfo.call(this, node, clone));
1316
- });
1317
- });
1318
- }
1319
- break;
1320
- }
1321
- default: {
1322
- onShikiError(new ShikiTwoslashError(`Unknown node type: ${node?.type}`), this.source, this.options.lang);
1323
- }
1324
- }
1325
- }
1326
- actionsHovers.forEach((i) => i());
1327
- actionsHighlights.forEach((i) => i());
1328
- }
1329
- };
1330
- };
17
+ return function transformerTwoslash(options = {}) {
18
+ const { langs = ["ts", "tsx"], twoslashOptions = defaultTwoslashOptions(), langAlias = {
19
+ typescript: "ts",
20
+ json5: "json",
21
+ yml: "yaml"
22
+ }, twoslasher = defaultTwoslasher, explicitTrigger = false, disableTriggers = ["notwoslash", "no-twoslash"], renderer = defaultRenderer, throws = true, includesMap = /* @__PURE__ */ new Map(), typesCache } = options;
23
+ const onTwoslashError = options.onTwoslashError || (throws ? (error) => {
24
+ throw error;
25
+ } : () => false);
26
+ const onShikiError = options.onShikiError || (throws ? (error) => {
27
+ throw error;
28
+ } : () => false);
29
+ const trigger = explicitTrigger instanceof RegExp ? explicitTrigger : /\btwoslash\b/;
30
+ if (!renderer) throw new ShikiTwoslashError("Missing renderer");
31
+ const map = /* @__PURE__ */ new WeakMap();
32
+ const { filter = (lang, _, options) => {
33
+ return langs.includes(lang) && (!explicitTrigger || trigger.test(options.meta?.__raw || "")) && !disableTriggers.some((i) => typeof i === "string" ? options.meta?.__raw?.includes(i) : i.test(options.meta?.__raw || ""));
34
+ } } = options;
35
+ const includes = new TwoslashIncludesManager(includesMap);
36
+ let _twoslasher = twoslasher;
37
+ if (typesCache) {
38
+ _twoslasher = ((code, lang, options, meta) => {
39
+ const preprocessed = typesCache?.preprocess?.(code, lang, options, meta);
40
+ if (preprocessed !== void 0) code = preprocessed;
41
+ let twoslash = typesCache?.read(code, lang, options, meta);
42
+ if (!twoslash) {
43
+ twoslash = twoslasher(code, lang, options);
44
+ typesCache?.write(code, twoslash, lang, options, meta);
45
+ }
46
+ return twoslash;
47
+ });
48
+ typesCache.init?.();
49
+ }
50
+ return {
51
+ preprocess(code) {
52
+ let lang = this.options.lang;
53
+ if (lang in langAlias) lang = langAlias[this.options.lang];
54
+ if (filter(lang, code, this.options, this)) try {
55
+ const codeWithIncludes = includes.applyInclude(code);
56
+ const include = parseIncludeMeta(this.options.meta?.__raw);
57
+ if (include) includes.add(include, codeWithIncludes);
58
+ const twoslash = _twoslasher(codeWithIncludes, lang, twoslashOptions, this.meta);
59
+ map.set(this.meta, twoslash);
60
+ this.meta.twoslash = twoslash;
61
+ this.options.lang = twoslash.meta?.extension || lang;
62
+ return twoslash.code;
63
+ } catch (error) {
64
+ const result = onTwoslashError(error, code, lang, this.options);
65
+ if (typeof result === "string") return result;
66
+ }
67
+ },
68
+ tokens(tokens) {
69
+ const twoslash = map.get(this.meta);
70
+ if (!twoslash) return;
71
+ return splitTokens(tokens, twoslash.nodes.flatMap((i) => [
72
+ "hover",
73
+ "error",
74
+ "query",
75
+ "highlight",
76
+ "completion"
77
+ ].includes(i.type) ? [i.start, i.start + i.length] : []));
78
+ },
79
+ pre(pre) {
80
+ if (!map.get(this.meta)) return;
81
+ this.addClassToHast(pre, "twoslash lsp");
82
+ },
83
+ code(codeEl) {
84
+ const twoslash = map.get(this.meta);
85
+ if (!twoslash) return;
86
+ const insertAfterLine = (line, nodes) => {
87
+ if (!nodes.length) return;
88
+ let index;
89
+ if (line >= this.lines.length) index = codeEl.children.length;
90
+ else {
91
+ const lineEl = this.lines[line];
92
+ index = codeEl.children.indexOf(lineEl);
93
+ if (index === -1) {
94
+ onShikiError(new ShikiTwoslashError(`Cannot find line ${line} in code element`), this.source, this.options.lang);
95
+ return;
96
+ }
97
+ }
98
+ const nodeAfter = codeEl.children[index + 1];
99
+ if (nodeAfter && nodeAfter.type === "text" && nodeAfter.value === "\n") codeEl.children.splice(index + 1, 1);
100
+ codeEl.children.splice(index + 1, 0, ...nodes);
101
+ };
102
+ const tokensMap = [];
103
+ this.lines.forEach((lineEl, line) => {
104
+ let index = 0;
105
+ for (const token of lineEl.children.flatMap((i) => i.type === "element" ? i.children || [] : [])) if ("value" in token && typeof token.value === "string") {
106
+ tokensMap.push([
107
+ line,
108
+ index,
109
+ index + token.value.length,
110
+ token
111
+ ]);
112
+ index += token.value.length;
113
+ }
114
+ });
115
+ const locateTextTokens = (line, character, length) => {
116
+ const start = character;
117
+ const end = character + length;
118
+ if (length === 0) return tokensMap.filter(([l, s, e]) => l === line && s < start && start <= e).map((i) => i[3]);
119
+ return tokensMap.filter(([l, s, e]) => l === line && start <= s && s < end && start < e && e <= end).map((i) => i[3]);
120
+ };
121
+ const tokensSkipHover = /* @__PURE__ */ new Set();
122
+ const actionsHovers = [];
123
+ const actionsHighlights = [];
124
+ for (const node of twoslash.nodes) {
125
+ if (node.type === "tag") {
126
+ if (renderer.lineCustomTag) insertAfterLine(node.line, renderer.lineCustomTag.call(this, node));
127
+ continue;
128
+ }
129
+ const tokens = locateTextTokens(node.line, node.character, node.length);
130
+ if (!tokens.length && !(node.type === "error" && renderer.nodesError)) {
131
+ onShikiError(new ShikiTwoslashError(`Cannot find tokens for node: ${JSON.stringify(node)}`), this.source, this.options.lang);
132
+ continue;
133
+ }
134
+ const wrapTokens = (fn) => {
135
+ const line = this.lines[node.line];
136
+ let charIndex = 0;
137
+ let itemStart = line.children.length;
138
+ let itemEnd = 0;
139
+ line.children.forEach((token, index) => {
140
+ if (charIndex >= node.character && index < itemStart) itemStart = index;
141
+ if (charIndex <= node.character + node.length && index > itemEnd) itemEnd = index;
142
+ charIndex += getTokenString(token).length;
143
+ });
144
+ if (charIndex <= node.character + node.length) itemEnd = line.children.length;
145
+ const targets = line.children.slice(itemStart, itemEnd);
146
+ const length = targets.length;
147
+ line.children.splice(itemStart, length, ...fn(targets));
148
+ };
149
+ switch (node.type) {
150
+ case "error":
151
+ if (renderer.nodeError) tokens.forEach((token) => {
152
+ tokensSkipHover.add(token);
153
+ const clone = { ...token };
154
+ Object.assign(token, renderer.nodeError.call(this, node, clone));
155
+ });
156
+ if (renderer.nodesError) {
157
+ tokens.forEach((token) => {
158
+ tokensSkipHover.add(token);
159
+ });
160
+ actionsHighlights.push(() => {
161
+ wrapTokens((targets) => renderer.nodesError?.call(this, node, targets) || targets);
162
+ });
163
+ }
164
+ if (renderer.lineError) insertAfterLine(node.line, renderer.lineError.call(this, node));
165
+ break;
166
+ case "query": {
167
+ const token = tokens[0];
168
+ if (token && renderer.nodeQuery) {
169
+ tokensSkipHover.add(token);
170
+ const clone = { ...token };
171
+ Object.assign(token, renderer.nodeQuery.call(this, node, clone));
172
+ }
173
+ if (renderer.lineQuery) insertAfterLine(node.line, renderer.lineQuery.call(this, node, token));
174
+ break;
175
+ }
176
+ case "completion":
177
+ if (renderer.nodeCompletion) tokens.forEach((token) => {
178
+ tokensSkipHover.add(token);
179
+ const clone = { ...token };
180
+ Object.assign(token, renderer.nodeCompletion.call(this, node, clone));
181
+ });
182
+ if (renderer.lineCompletion) insertAfterLine(node.line, renderer.lineCompletion.call(this, node));
183
+ break;
184
+ case "highlight":
185
+ if (renderer.nodesHighlight) actionsHighlights.push(() => {
186
+ wrapTokens((targets) => renderer.nodesHighlight?.call(this, node, targets) || targets);
187
+ });
188
+ break;
189
+ case "hover":
190
+ if (renderer.nodeStaticInfo) actionsHovers.push(() => {
191
+ tokens.forEach((token) => {
192
+ if (tokensSkipHover.has(token)) return;
193
+ tokensSkipHover.add(token);
194
+ const clone = { ...token };
195
+ Object.assign(token, renderer.nodeStaticInfo.call(this, node, clone));
196
+ });
197
+ });
198
+ break;
199
+ default: onShikiError(new ShikiTwoslashError(`Unknown node type: ${node?.type}`), this.source, this.options.lang);
200
+ }
201
+ }
202
+ actionsHovers.forEach((i) => i());
203
+ actionsHighlights.forEach((i) => i());
204
+ }
205
+ };
206
+ };
1331
207
  }
1332
208
  function getTokenString(token) {
1333
- if ("value" in token)
1334
- return token.value;
1335
- return token.children?.map(getTokenString).join("") || "";
209
+ if ("value" in token) return token.value;
210
+ return token.children?.map(getTokenString).join("") || "";
1336
211
  }
1337
212
 
1338
- export { ShikiTwoslashError, createTransformerFactory, defaultCompletionIcons, defaultCustomTagIcons, defaultHoverInfoProcessor, defaultTwoslashOptions, rendererClassic, rendererRich };
213
+ //#endregion
214
+ export { ShikiTwoslashError, createTransformerFactory, defaultCompletionIcons, defaultCustomTagIcons, defaultHoverInfoProcessor, defaultTwoslashOptions, rendererClassic, rendererRich };