@scalar/code-highlight 0.3.3 → 0.3.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @scalar/code-highlight
2
2
 
3
+ ## 0.3.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#8964](https://github.com/scalar/scalar/pull/8964): fix markdown inside HTML text tags like `<p>` so inline formatting is rendered.
8
+
3
9
  ## 0.3.3
4
10
 
5
11
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/markdown/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAqB,MAAM,OAAO,CAAA;AAsB9E,YAAY,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAEjC;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,IAAI,KAAG,IAAI,IAAI,OAE9C,CAAA;AAqBD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IAChC,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,UAuDF;AASD;;GAEG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAU,GAChB;IACD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,EAAE,CAiBF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,GAAG,MAAM,CAUpE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,YAgC5C"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/markdown/markdown.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAsD,IAAI,EAAE,eAAe,EAAE,MAAM,OAAO,CAAA;AAuB/G,YAAY,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAEjC;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,IAAI,KAAG,IAAI,IAAI,OAE9C,CAAA;AAiGD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IAChC,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,UAyDF;AASD;;GAEG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAU,GAChB;IACD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,EAAE,CAiBF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,GAAG,MAAM,CAUpE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,YAgC5C"}
@@ -1,5 +1,6 @@
1
1
  import rehypeExternalLinks from 'rehype-external-links';
2
2
  import rehypeFormat from 'rehype-format';
3
+ import rehypeParse from 'rehype-parse';
3
4
  import rehypeRaw from 'rehype-raw';
4
5
  import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
5
6
  import rehypeStringify from 'rehype-stringify';
@@ -31,6 +32,69 @@ const transformNodes = (options, ..._ignored) => (tree) => {
31
32
  });
32
33
  return;
33
34
  };
35
+ const TAGS_WITH_INLINE_MARKDOWN = new Set(['dd', 'dt', 'li', 'p', 'summary', 'td', 'th']);
36
+ const MAY_CONTAIN_INLINE_MARKDOWN = /[`*_\[~]/;
37
+ /**
38
+ * Preserve HTML-like text in inline markdown by turning mdast `html` nodes into text nodes.
39
+ */
40
+ const preserveHtmlLikeText = () => (tree) => {
41
+ visit(tree, 'html', (node, index, parent) => {
42
+ if (typeof index !== 'number' || !parent || !('children' in parent) || !Array.isArray(parent.children)) {
43
+ return;
44
+ }
45
+ parent.children[index] = {
46
+ type: 'text',
47
+ value: node.value ?? '',
48
+ };
49
+ });
50
+ };
51
+ const inlineMarkdownProcessor = unified().use(remarkParse).use(remarkGfm).use(preserveHtmlLikeText).use(remarkRehype);
52
+ const htmlFragmentParser = unified().use(rehypeParse, { fragment: true });
53
+ const htmlFragmentStringifier = unified().use(rehypeStringify);
54
+ /**
55
+ * Parse inline markdown and return children from the generated paragraph.
56
+ */
57
+ const extractInlineChildrenFromMarkdown = (value) => {
58
+ const tree = inlineMarkdownProcessor.runSync(inlineMarkdownProcessor.parse(value));
59
+ if (tree.children.length !== 1) {
60
+ return [];
61
+ }
62
+ const paragraph = tree.children.at(0);
63
+ if (!paragraph || paragraph.type !== 'element' || paragraph.tagName !== 'p') {
64
+ return [];
65
+ }
66
+ return paragraph.children;
67
+ };
68
+ /**
69
+ * Re-parses text nodes in selected HTML tags so inline markdown works in tags like <p>.
70
+ */
71
+ const transformInlineMarkdownInHtml = () => (tree) => {
72
+ visit(tree, 'element', (node) => {
73
+ if (!TAGS_WITH_INLINE_MARKDOWN.has(node.tagName)) {
74
+ return;
75
+ }
76
+ node.children = node.children.flatMap((child) => {
77
+ if (child.type !== 'text' || !MAY_CONTAIN_INLINE_MARKDOWN.test(child.value)) {
78
+ return [child];
79
+ }
80
+ const markdownChildren = extractInlineChildrenFromMarkdown(child.value);
81
+ return markdownChildren.length ? markdownChildren : [child];
82
+ });
83
+ });
84
+ };
85
+ /**
86
+ * Rewrites raw HTML strings so inline markdown parsing is only applied to raw HTML input.
87
+ */
88
+ const transformInlineMarkdownInRawHtml = () => (tree) => {
89
+ visit(tree, 'raw', (node) => {
90
+ if (typeof node.value !== 'string' || !MAY_CONTAIN_INLINE_MARKDOWN.test(node.value)) {
91
+ return;
92
+ }
93
+ const htmlFragmentTree = htmlFragmentParser.parse(node.value);
94
+ transformInlineMarkdownInHtml()(htmlFragmentTree);
95
+ node.value = htmlFragmentStringifier.stringify(htmlFragmentTree);
96
+ });
97
+ };
34
98
  /**
35
99
  * Take a Markdown string and generate HTML from it
36
100
  */
@@ -51,7 +115,9 @@ export function htmlFromMarkdown(markdown, options) {
51
115
  .use(remarkRehype, { allowDangerousHtml: true })
52
116
  // Adds GitHub alerts
53
117
  .use(rehypeAlert)
54
- // Creates a HTML AST
118
+ // Parse inline markdown only inside raw HTML fragments, not normal markdown output
119
+ .use(transformInlineMarkdownInRawHtml)
120
+ // Creates an HTML AST
55
121
  .use(rehypeRaw)
56
122
  // Removes disallowed tags
57
123
  .use(rehypeSanitize, {
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "lowlight",
17
17
  "highlightjs"
18
18
  ],
19
- "version": "0.3.3",
19
+ "version": "0.3.4",
20
20
  "engines": {
21
21
  "node": ">=22"
22
22
  },