@scalar/code-highlight 0.3.2 → 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 +12 -0
- package/dist/languages/curl.d.ts +7 -0
- package/dist/languages/curl.d.ts.map +1 -0
- package/dist/languages/curl.js +86 -0
- package/dist/languages/standard.d.ts +1 -1
- package/dist/languages/standard.d.ts.map +1 -1
- package/dist/languages/standard.js +1 -2
- package/dist/markdown/markdown.d.ts.map +1 -1
- package/dist/markdown/markdown.js +67 -1
- package/package.json +4 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
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
|
+
|
|
9
|
+
## 0.3.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#8735](https://github.com/scalar/scalar/pull/8735): fix: replace direct cjs mime and curl dependencies with local implementations
|
|
14
|
+
|
|
3
15
|
## 0.3.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curl.d.ts","sourceRoot":"","sources":["../../src/languages/curl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAE9C;;GAEG;AACH,QAAA,MAAM,YAAY,EAAE,UAyFnB,CAAA;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cURL grammar adapted from highlightjs-curl to avoid a CJS dependency.
|
|
3
|
+
*/
|
|
4
|
+
const curlLanguage = (hljs) => {
|
|
5
|
+
const quoteString = {
|
|
6
|
+
className: 'string',
|
|
7
|
+
begin: /"/,
|
|
8
|
+
end: /"/,
|
|
9
|
+
contains: [
|
|
10
|
+
hljs.BACKSLASH_ESCAPE,
|
|
11
|
+
{
|
|
12
|
+
className: 'variable',
|
|
13
|
+
begin: /\$\(/,
|
|
14
|
+
end: /\)/,
|
|
15
|
+
contains: [hljs.BACKSLASH_ESCAPE],
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
relevance: 0,
|
|
19
|
+
};
|
|
20
|
+
const optionRequest = {
|
|
21
|
+
className: 'literal',
|
|
22
|
+
begin: /(--request|-X)\s/,
|
|
23
|
+
contains: [
|
|
24
|
+
{
|
|
25
|
+
className: 'symbol',
|
|
26
|
+
begin: /(get|post|delete|options|head|put|patch|trace|connect)/,
|
|
27
|
+
end: /\s/,
|
|
28
|
+
returnEnd: true,
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
returnEnd: true,
|
|
32
|
+
relevance: 10,
|
|
33
|
+
};
|
|
34
|
+
const option = {
|
|
35
|
+
className: 'literal',
|
|
36
|
+
begin: /--/,
|
|
37
|
+
end: /[\s"]/,
|
|
38
|
+
returnEnd: true,
|
|
39
|
+
relevance: 0,
|
|
40
|
+
};
|
|
41
|
+
const optionSingle = {
|
|
42
|
+
className: 'literal',
|
|
43
|
+
begin: /-\w/,
|
|
44
|
+
end: /[\s"]/,
|
|
45
|
+
returnEnd: true,
|
|
46
|
+
relevance: 0,
|
|
47
|
+
};
|
|
48
|
+
const escapedQuote = {
|
|
49
|
+
className: 'string',
|
|
50
|
+
begin: /\\"/,
|
|
51
|
+
relevance: 0,
|
|
52
|
+
};
|
|
53
|
+
const aposString = {
|
|
54
|
+
className: 'string',
|
|
55
|
+
begin: /'/,
|
|
56
|
+
end: /'/,
|
|
57
|
+
relevance: 0,
|
|
58
|
+
};
|
|
59
|
+
const number = {
|
|
60
|
+
className: 'number',
|
|
61
|
+
variants: [{ begin: hljs.C_NUMBER_RE }],
|
|
62
|
+
relevance: 0,
|
|
63
|
+
};
|
|
64
|
+
const pathMode = {
|
|
65
|
+
match: /(\/[a-z._-]+)+/,
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
name: 'curl',
|
|
69
|
+
aliases: ['curl'],
|
|
70
|
+
keywords: 'curl',
|
|
71
|
+
case_insensitive: true,
|
|
72
|
+
contains: [
|
|
73
|
+
optionRequest,
|
|
74
|
+
option,
|
|
75
|
+
optionSingle,
|
|
76
|
+
quoteString,
|
|
77
|
+
escapedQuote,
|
|
78
|
+
aposString,
|
|
79
|
+
hljs.APOS_STRING_MODE,
|
|
80
|
+
hljs.QUOTE_STRING_MODE,
|
|
81
|
+
number,
|
|
82
|
+
pathMode,
|
|
83
|
+
],
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
export default curlLanguage;
|
|
@@ -24,7 +24,7 @@ export declare const standardLanguages: {
|
|
|
24
24
|
readonly cpp: LanguageFn;
|
|
25
25
|
readonly csharp: LanguageFn;
|
|
26
26
|
readonly css: LanguageFn;
|
|
27
|
-
readonly curl:
|
|
27
|
+
readonly curl: LanguageFn;
|
|
28
28
|
readonly dart: LanguageFn;
|
|
29
29
|
readonly diff: LanguageFn;
|
|
30
30
|
readonly docker: LanguageFn;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standard.d.ts","sourceRoot":"","sources":["../../src/languages/standard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"standard.d.ts","sourceRoot":"","sources":["../../src/languages/standard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAgD9C;;;;;;;;;;;;;;GAcG;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkDiB,CAAA"}
|
|
@@ -43,8 +43,7 @@ import swift from 'highlight.js/lib/languages/swift';
|
|
|
43
43
|
import typescript from 'highlight.js/lib/languages/typescript';
|
|
44
44
|
import xml from 'highlight.js/lib/languages/xml';
|
|
45
45
|
import yaml from 'highlight.js/lib/languages/yaml';
|
|
46
|
-
|
|
47
|
-
import curl from 'highlightjs-curl';
|
|
46
|
+
import curl from './curl.js';
|
|
48
47
|
/**
|
|
49
48
|
* We group languages into three categories based on their popularity and usage.
|
|
50
49
|
* This helps in optimizing the bundle size by allowing users to include only
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/markdown/markdown.ts"],"names":[],"mappings":"
|
|
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
|
-
//
|
|
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.
|
|
19
|
+
"version": "0.3.4",
|
|
20
20
|
"engines": {
|
|
21
21
|
"node": ">=22"
|
|
22
22
|
},
|
|
@@ -73,7 +73,6 @@
|
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"hast-util-to-text": "^4.0.2",
|
|
75
75
|
"highlight.js": "^11.11.1",
|
|
76
|
-
"highlightjs-curl": "^1.3.0",
|
|
77
76
|
"lowlight": "^3.3.0",
|
|
78
77
|
"rehype-external-links": "^3.0.0",
|
|
79
78
|
"rehype-format": "^5.0.1",
|
|
@@ -93,12 +92,12 @@
|
|
|
93
92
|
"@types/mdast": "^4.0.4",
|
|
94
93
|
"vfile": "^6.0.3",
|
|
95
94
|
"vite": "8.0.0",
|
|
96
|
-
"@scalar/themes": "0.15.
|
|
95
|
+
"@scalar/themes": "0.15.3"
|
|
97
96
|
},
|
|
98
97
|
"scripts": {
|
|
99
|
-
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && cp -r src/css dist/css",
|
|
98
|
+
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && shx cp -r src/css dist/css",
|
|
100
99
|
"dev": "vite",
|
|
101
|
-
"test": "vitest",
|
|
100
|
+
"test": "vitest --run",
|
|
102
101
|
"types:check": "tsc --noEmit"
|
|
103
102
|
}
|
|
104
103
|
}
|