@scalar/code-highlight 0.0.7 → 0.0.8
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 +6 -0
- package/dist/markdown/index.d.ts +1 -1
- package/dist/markdown/index.d.ts.map +1 -1
- package/dist/markdown/index.js +1 -1
- package/dist/markdown/markdown.d.ts +17 -2
- package/dist/markdown/markdown.d.ts.map +1 -1
- package/dist/markdown/markdown.js +109 -4
- package/package.json +7 -5
package/CHANGELOG.md
CHANGED
package/dist/markdown/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './markdown.js';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/markdown/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/markdown/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
|
package/dist/markdown/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { htmlFromMarkdown } from './markdown.js';
|
|
1
|
+
export { getHeadings, htmlFromMarkdown, splitContent } from './markdown.js';
|
|
@@ -1,6 +1,21 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Take a Markdown string and generate HTML from it
|
|
3
|
+
*/
|
|
4
|
+
export declare function htmlFromMarkdown(markdown: string, options?: {
|
|
3
5
|
removeTags?: string[];
|
|
4
6
|
allowTags?: string[];
|
|
7
|
+
transform?: (node: Record<string, any>) => Record<string, any>;
|
|
8
|
+
transformType?: string;
|
|
5
9
|
}): string;
|
|
10
|
+
/**
|
|
11
|
+
* Find all headings of a specific type in a Markdown AST.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getHeadings(markdown: string, depth?: number): {
|
|
14
|
+
depth: number;
|
|
15
|
+
value: string;
|
|
16
|
+
}[];
|
|
17
|
+
/**
|
|
18
|
+
* Return multiple Markdown documents. Every heading should be its own document.
|
|
19
|
+
*/
|
|
20
|
+
export declare function splitContent(markdown: string): string[];
|
|
6
21
|
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -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":"AA4CA;;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,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,UAkDF;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;AAuBD;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,YAgC5C"}
|
|
@@ -6,12 +6,33 @@ import rehypeStringify from 'rehype-stringify';
|
|
|
6
6
|
import remarkGfm from 'remark-gfm';
|
|
7
7
|
import remarkParse from 'remark-parse';
|
|
8
8
|
import remarkRehype from 'remark-rehype';
|
|
9
|
+
import remarkStringify from 'remark-stringify';
|
|
9
10
|
import { unified } from 'unified';
|
|
11
|
+
import { visit, SKIP } from 'unist-util-visit';
|
|
10
12
|
import { rehypeHighlight } from '../rehype-highlight/rehype-highlight.js';
|
|
11
13
|
import { standardLanguages } from '../languages/standard.js';
|
|
12
14
|
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Plugin to transform nodes in a Markdown AST
|
|
17
|
+
*/
|
|
18
|
+
const transformNodes = function (options,
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
20
|
+
..._ignored) {
|
|
21
|
+
return (tree) => {
|
|
22
|
+
if (!options?.transform || !options?.type) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
visit(tree, options?.type, (node) => {
|
|
26
|
+
options?.transform ? options?.transform(node) : node;
|
|
27
|
+
return SKIP;
|
|
28
|
+
});
|
|
29
|
+
return;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Take a Markdown string and generate HTML from it
|
|
34
|
+
*/
|
|
35
|
+
function htmlFromMarkdown(markdown, options) {
|
|
15
36
|
// Add permitted tags and remove stripped ones
|
|
16
37
|
const removeTags = options?.removeTags ?? [];
|
|
17
38
|
const tagNames = [
|
|
@@ -23,6 +44,10 @@ function htmlFromMarkdown(markdownString, options) {
|
|
|
23
44
|
.use(remarkParse)
|
|
24
45
|
// Support autolink literals, footnotes, strikethrough, tables and tasklists
|
|
25
46
|
.use(remarkGfm)
|
|
47
|
+
.use(transformNodes, {
|
|
48
|
+
transform: options?.transform,
|
|
49
|
+
type: options?.transformType,
|
|
50
|
+
})
|
|
26
51
|
// Allows any HTML tags
|
|
27
52
|
.use(remarkRehype, { allowDangerousHtml: true })
|
|
28
53
|
// Creates a HTML AST
|
|
@@ -30,6 +55,8 @@ function htmlFromMarkdown(markdownString, options) {
|
|
|
30
55
|
// Removes disallowed tags
|
|
31
56
|
.use(rehypeSanitize, {
|
|
32
57
|
...defaultSchema,
|
|
58
|
+
// Don’t prefix the heading ids
|
|
59
|
+
clobberPrefix: '',
|
|
33
60
|
// Makes it even more strict
|
|
34
61
|
tagNames,
|
|
35
62
|
attributes: {
|
|
@@ -50,8 +77,86 @@ function htmlFromMarkdown(markdownString, options) {
|
|
|
50
77
|
// Converts the HTML AST to a string
|
|
51
78
|
.use(rehypeStringify)
|
|
52
79
|
// Run the pipeline
|
|
53
|
-
.processSync(
|
|
80
|
+
.processSync(markdown);
|
|
54
81
|
return html.toString();
|
|
55
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Create a Markdown AST from a string.
|
|
85
|
+
*/
|
|
86
|
+
function getMarkdownAst(markdown) {
|
|
87
|
+
return unified().use(remarkParse).use(remarkGfm).parse(markdown);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Find all headings of a specific type in a Markdown AST.
|
|
91
|
+
*/
|
|
92
|
+
function getHeadings(markdown, depth = 1) {
|
|
93
|
+
const tree = getMarkdownAst(markdown);
|
|
94
|
+
const nodes = [];
|
|
95
|
+
visit(tree, 'heading', (node) => {
|
|
96
|
+
const text = findTextInHeading(node);
|
|
97
|
+
if (text) {
|
|
98
|
+
nodes.push({ depth: node.depth ?? depth, value: text.value });
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
return nodes;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Find the text in a Markdown node (recursively).
|
|
105
|
+
*/
|
|
106
|
+
function findTextInHeading(node) {
|
|
107
|
+
if (node.type === 'text') {
|
|
108
|
+
return node;
|
|
109
|
+
}
|
|
110
|
+
if ('children' in node && node.children) {
|
|
111
|
+
for (const child of node.children) {
|
|
112
|
+
const text = findTextInHeading(child);
|
|
113
|
+
if (text) {
|
|
114
|
+
return text;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Return multiple Markdown documents. Every heading should be its own document.
|
|
122
|
+
*/
|
|
123
|
+
function splitContent(markdown) {
|
|
124
|
+
const tree = getMarkdownAst(markdown);
|
|
125
|
+
/** Sections */
|
|
126
|
+
const sections = [];
|
|
127
|
+
/** Nodes inside a section */
|
|
128
|
+
let nodes = [];
|
|
129
|
+
tree.children?.forEach((node) => {
|
|
130
|
+
// If the node is a heading, start a new section
|
|
131
|
+
if (node.type === 'heading') {
|
|
132
|
+
if (nodes.length) {
|
|
133
|
+
sections.push(nodes);
|
|
134
|
+
}
|
|
135
|
+
sections.push([node]);
|
|
136
|
+
nodes = [];
|
|
137
|
+
}
|
|
138
|
+
// Otherwise, add the node to the current section
|
|
139
|
+
else {
|
|
140
|
+
nodes.push(node);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
// Add any remaining nodes
|
|
144
|
+
if (nodes.length) {
|
|
145
|
+
sections.push(nodes);
|
|
146
|
+
}
|
|
147
|
+
return sections.map((section) => createDocument(section));
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Use remark to create a Markdown document from a list of nodes.
|
|
151
|
+
*/
|
|
152
|
+
function createDocument(nodes) {
|
|
153
|
+
// Create the Markdown string
|
|
154
|
+
const markdown = unified().use(remarkStringify).use(remarkGfm).stringify({
|
|
155
|
+
type: 'root',
|
|
156
|
+
children: nodes,
|
|
157
|
+
});
|
|
158
|
+
// Remove the whitespace
|
|
159
|
+
return markdown.trim();
|
|
160
|
+
}
|
|
56
161
|
|
|
57
|
-
export { htmlFromMarkdown };
|
|
162
|
+
export { getHeadings, htmlFromMarkdown, splitContent };
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"lowlight",
|
|
17
17
|
"highlightjs"
|
|
18
18
|
],
|
|
19
|
-
"version": "0.0.
|
|
19
|
+
"version": "0.0.8",
|
|
20
20
|
"engines": {
|
|
21
21
|
"node": ">=18"
|
|
22
22
|
},
|
|
@@ -73,19 +73,21 @@
|
|
|
73
73
|
"remark-gfm": "^4.0.0",
|
|
74
74
|
"remark-parse": "^11.0.0",
|
|
75
75
|
"remark-rehype": "^11.1.0",
|
|
76
|
+
"remark-stringify": "^11.0.0",
|
|
76
77
|
"unified": "^11.0.4",
|
|
77
78
|
"unist-util-visit": "^5.0.0"
|
|
78
79
|
},
|
|
79
80
|
"devDependencies": {
|
|
80
81
|
"@rollup/plugin-typescript": "^11.1.6",
|
|
81
82
|
"@types/hast": "^3.0.4",
|
|
83
|
+
"@types/mdast": "^4.0.4",
|
|
84
|
+
"@types/unist": "^3.0.2",
|
|
82
85
|
"rollup": "^4.16.4",
|
|
83
|
-
"tsc-alias": "^1.8.8",
|
|
84
86
|
"vfile": "^6.0.1",
|
|
85
87
|
"vite": "^5.2.10",
|
|
86
|
-
"vue": "^3.4.
|
|
87
|
-
"@scalar/build-tooling": "0.1.
|
|
88
|
-
"@scalar/themes": "0.9.
|
|
88
|
+
"vue": "^3.4.29",
|
|
89
|
+
"@scalar/build-tooling": "0.1.10",
|
|
90
|
+
"@scalar/themes": "0.9.22"
|
|
89
91
|
},
|
|
90
92
|
"scripts": {
|
|
91
93
|
"build": "scalar-build-rollup",
|