@md-plugins/md-plugin-codeblocks 0.1.0-beta.18 → 0.1.0-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,6 +5,7 @@ A **Markdown-It** plugin that enhances code block rendering by providing syntax
5
5
  ## Features
6
6
 
7
7
  - **Syntax Highlighting**: Automatically highlights code blocks using **Shiki**.
8
+ - **TwoSlash Hovers**: Opt in to TypeScript-powered hover and query output for richer examples.
8
9
  - **Line Numbering**: Optionally adds line numbers to code blocks.
9
10
  - **Magic Comments**: Supports special comments like `[[! highlight]]`, `[[! add]]`, and `[[! rem]]` for inline code annotations.
10
11
  - **Tabbed Code Blocks**: Enables the creation of tabbed code blocks for multi-language or multi-file examples.
@@ -101,6 +102,17 @@ console.log('Line 3')
101
102
  ```
102
103
  ````
103
104
 
105
+ ### TwoSlash Type Hovers
106
+
107
+ Add the `twoslash` attribute to TypeScript or JavaScript examples when you want inferred type information, compiler diagnostics, or `^?` query output.
108
+
109
+ ````markup
110
+ ```ts [twoslash]
111
+ const count = 1
112
+ // ^?
113
+ ```
114
+ ````
115
+
104
116
  ### Line Highlighting and Annotations
105
117
 
106
118
  ````markup
package/dist/index.mjs CHANGED
@@ -37,6 +37,14 @@ const highlighter = await createHighlighter({
37
37
  langs: shikiLangs,
38
38
  langAlias: shikiLangAlias
39
39
  });
40
+ const debugEnvValue = process.env.DEBUG;
41
+ delete process.env.DEBUG;
42
+ const twoslashModule = await import('@shikijs/twoslash').finally(() => {
43
+ if (debugEnvValue !== void 0) {
44
+ process.env.DEBUG = debugEnvValue;
45
+ }
46
+ });
47
+ const { rendererRich, transformerTwoslash } = twoslashModule;
40
48
  const supportedLangSet = new Set(highlighter.getLoadedLanguages());
41
49
  const themeOptions = {
42
50
  themes: {
@@ -52,11 +60,13 @@ function buildCodeBlockTransformers({
52
60
  codeClass,
53
61
  lineList,
54
62
  maxheight,
55
- preClass
63
+ preClass,
64
+ twoslash
56
65
  }) {
57
66
  return [
58
67
  preClassTransformer(preClass, maxheight),
59
68
  codeClassTransformer(codeClass),
69
+ ...twoslash === true ? [twoslashTransformer] : [],
60
70
  transformerNotationHighlight(),
61
71
  transformerNotationDiff(),
62
72
  transformerNotationFocus(),
@@ -65,6 +75,14 @@ function buildCodeBlockTransformers({
65
75
  lineDecorTransformer(lineList)
66
76
  ];
67
77
  }
78
+ const twoslashTransformer = transformerTwoslash({
79
+ renderer: rendererRich(),
80
+ twoslashOptions: {
81
+ compilerOptions: {
82
+ traceResolution: false
83
+ }
84
+ }
85
+ });
68
86
  function preClassTransformer(preClass, maxheight) {
69
87
  return {
70
88
  name: "md-plugins:pre-class",
@@ -216,11 +234,13 @@ const codeblocksPlugin = (md, options) => {
216
234
  const tabsMatch = line.match(tabsLineRE);
217
235
  if (tabsMatch !== null) {
218
236
  const { lang, attrs, title } = tabsMatch.groups || {};
219
- currentTabName = title?.trim() || `Tab ${list.length + 1}`;
237
+ const bareAttrs = extractBareAttrs(title?.trim() || null);
238
+ currentTabName = bareAttrs.title ?? `Tab ${list.length + 1}`;
220
239
  list.push(currentTabName);
221
240
  tabMap[currentTabName] = {
222
241
  attrs: {
223
242
  ...parseAttrs(attrs?.trim() || null),
243
+ ...bareAttrs.attrs,
224
244
  lang
225
245
  },
226
246
  content: []
@@ -239,6 +259,7 @@ const codeblocksPlugin = (md, options) => {
239
259
  };
240
260
  }
241
261
  const magicCommentList = ["highlight", "rem", "add"];
262
+ const bareAttrList = ["twoslash"];
242
263
  const magicCommentRE = new RegExp(` *\\[\\[! (?<type>(${magicCommentList.join("|")}))\\]\\] *`);
243
264
  const magicCommentGlobalRE = new RegExp(magicCommentRE, "g");
244
265
  function extractCodeLineProps(lines, attrs) {
@@ -298,7 +319,7 @@ const codeblocksPlugin = (md, options) => {
298
319
  return acc;
299
320
  }
300
321
  function getHighlightedContent(rawContent, attrs) {
301
- const { lang, maxheight } = attrs;
322
+ const { lang, maxheight, twoslash } = attrs;
302
323
  let content = rawContent.trim();
303
324
  const lineList = parseCodeLine(content, attrs);
304
325
  if (lang !== "markup") {
@@ -312,7 +333,8 @@ const codeblocksPlugin = (md, options) => {
312
333
  codeClass,
313
334
  lineList,
314
335
  maxheight,
315
- preClass: preClass ?? "markdown-code"
336
+ preClass: preClass ?? "markdown-code",
337
+ twoslash: twoslash === true || twoslash === "true"
316
338
  })
317
339
  }).replace("<pre ", "<pre v-pre ") + `<${copyButtonComponent}${langProp} />`;
318
340
  }
@@ -326,6 +348,27 @@ const codeblocksPlugin = (md, options) => {
326
348
  }
327
349
  return acc;
328
350
  }
351
+ function extractBareAttrs(title) {
352
+ if (title === null) {
353
+ return {
354
+ attrs: {},
355
+ title: null
356
+ };
357
+ }
358
+ const attrs = {};
359
+ const remainingTitle = [];
360
+ for (const chunk of title.split(/\s+/)) {
361
+ if (remainingTitle.length === 0 && bareAttrList.includes(chunk)) {
362
+ attrs[chunk] = true;
363
+ continue;
364
+ }
365
+ remainingTitle.push(chunk);
366
+ }
367
+ return {
368
+ attrs,
369
+ title: remainingTitle.length > 0 ? remainingTitle.join(" ") : null
370
+ };
371
+ }
329
372
  function parseDefinitionLine(token) {
330
373
  const match = token.info.trim().match(definitionLineRE);
331
374
  if (match === null) {
@@ -335,10 +378,12 @@ const codeblocksPlugin = (md, options) => {
335
378
  };
336
379
  }
337
380
  const { lang, attrs, title } = match.groups || {};
381
+ const bareAttrs = extractBareAttrs(title?.trim() || null);
338
382
  const acc = {
339
383
  ...parseAttrs(attrs?.trim() || null),
384
+ ...bareAttrs.attrs,
340
385
  lang,
341
- title: title?.trim() || null
386
+ title: bareAttrs.title
342
387
  };
343
388
  if (acc.lang === "tabs") {
344
389
  acc.tabs = extractTabs(token.content);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@md-plugins/md-plugin-codeblocks",
3
- "version": "0.1.0-beta.18",
3
+ "version": "0.1.0-beta.19",
4
4
  "description": "A markdown-it plugin for code blocks.",
5
5
  "keywords": [
6
6
  "markdown-it",
@@ -37,12 +37,13 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@shikijs/transformers": "^4.1.0",
40
+ "@shikijs/twoslash": "^4.1.0",
40
41
  "shiki": "^4.1.0"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@types/markdown-it": "^14.1.2",
44
45
  "markdown-it": "^14.2.0",
45
- "@md-plugins/shared": "0.1.0-beta.18"
46
+ "@md-plugins/shared": "0.1.0-beta.19"
46
47
  },
47
48
  "peerDependencies": {
48
49
  "markdown-it": "^14.2.0"