@doc-kit/core 1.2.1 → 1.3.1
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 +26 -0
- package/README.md +1 -1
- package/package.json +8 -11
- package/src/generators/ast/generate.mjs +11 -9
- package/src/generators/ast/index.mjs +9 -0
- package/src/generators/ast-js/generate.mjs +4 -4
- package/src/generators/index.mjs +1 -0
- package/src/generators/json/README.md +1 -1
- package/src/generators/json/generated/schema.d.ts +1 -1
- package/src/generators/json/index.mjs +9 -0
- package/src/generators/json/utils/markdown.mjs +2 -2
- package/src/generators/json-all/README.md +1 -1
- package/src/generators/json-simple/README.md +1 -1
- package/src/generators/json-simple/generate.mjs +13 -5
- package/src/generators/loader.mjs +14 -0
- package/src/generators/metadata/generate.mjs +4 -2
- package/src/generators/metadata/index.mjs +9 -0
- package/src/generators/metadata/maps/mdn.json +2 -0
- package/src/generators/metadata/types.d.ts +1 -1
- package/src/generators/metadata/utils/parse.mjs +2 -4
- package/src/generators/metadata/utils/visitors.mjs +2 -2
- package/src/generators/types.d.ts +8 -0
- package/src/generators.mjs +9 -3
- package/src/logger/constants.mjs +35 -0
- package/src/logger/transports/github.mjs +48 -15
- package/src/plugins/shiki/highlighter.mjs +373 -0
- package/src/plugins/shiki/rehype.mjs +38 -0
- package/src/{utils/type-annotations/highlighted.mjs → plugins/type-annotations/highlighter.mjs} +14 -19
- package/src/{utils → plugins}/type-annotations/remark.mjs +6 -2
- package/src/threading/chunk-worker.mjs +4 -0
- package/src/threading/constants.mjs +24 -0
- package/src/threading/index.mjs +10 -1
- package/src/threading/parallel.mjs +28 -31
- package/src/utils/configuration/constants.mjs +4 -6
- package/src/utils/configuration/index.mjs +89 -21
- package/src/utils/configuration/types.d.ts +27 -0
- package/src/utils/glob.mjs +42 -0
- package/src/utils/loaders.mjs +23 -1
- package/src/utils/markdown/constants.mjs +7 -0
- package/src/utils/markdown/plugins.mjs +232 -0
- package/src/utils/markdown/processor.mjs +60 -0
- package/src/utils/highlighter.mjs +0 -198
- package/src/utils/remark-shiki.mjs +0 -29
- package/src/utils/remark.mjs +0 -90
- /package/src/{utils → plugins}/type-annotations/hast.mjs +0 -0
- /package/src/{utils → plugins}/type-annotations/mdast.mjs +0 -0
- /package/src/{utils → plugins}/type-annotations/syntax.mjs +0 -0
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
import { endianness } from 'node:os';
|
|
4
|
-
|
|
5
|
-
import createHighlighter from '@node-core/rehype-shiki';
|
|
6
|
-
import { h as createElement } from 'hastscript';
|
|
7
|
-
import { SKIP, visit } from 'unist-util-visit';
|
|
8
|
-
|
|
9
|
-
import shikiConfig from '../../shiki.config.mjs';
|
|
10
|
-
|
|
11
|
-
// This is what Remark will use as prefix within a <pre> className
|
|
12
|
-
// to attribute the current language of the <pre> element
|
|
13
|
-
const languagePrefix = 'language-';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Creates a toolbar element with a language label and copy button.
|
|
17
|
-
*
|
|
18
|
-
* @param {string} languageId - The language identifier for the code block.
|
|
19
|
-
* @returns {import('hast').Element} The toolbar element.
|
|
20
|
-
*/
|
|
21
|
-
function createToolbarElement(languageId) {
|
|
22
|
-
return createElement('div', { class: 'code-toolbar' }, [
|
|
23
|
-
createElement('span', { class: 'code-language' }, languageId),
|
|
24
|
-
createElement('button', { class: 'copy-button' }, 'copy'),
|
|
25
|
-
]);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Checks if the given node is a valid code element.
|
|
30
|
-
*
|
|
31
|
-
* @param {import('unist').Node} node - The node to be verified.
|
|
32
|
-
*
|
|
33
|
-
* @return {boolean} - True when it is a valid code element, false otherwise.
|
|
34
|
-
*/
|
|
35
|
-
function isCodeBlock(node) {
|
|
36
|
-
return Boolean(
|
|
37
|
-
node?.tagName === 'pre' && node?.children[0].tagName === 'code'
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const highlighter = await createHighlighter({
|
|
42
|
-
// riscv64 with sv39 has limited virtual memory space, where creating
|
|
43
|
-
// too many (>20) wasm memory instances fails.
|
|
44
|
-
// https://github.com/nodejs/node/pull/60591
|
|
45
|
-
//
|
|
46
|
-
// The wasm highlighter is currently not compatible with big endian.
|
|
47
|
-
// https://github.com/nodejs/node/pull/62512#issuecomment-4243469950
|
|
48
|
-
wasm: process.arch !== 'riscv64' && endianness() === 'LE',
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Creates a HAST transformer for Shiki which is used for transforming our codeboxes
|
|
53
|
-
*
|
|
54
|
-
* @deprecated This is used only for the legacy-html generator, please use `@node-core/rehype-shiki` directly instead.
|
|
55
|
-
*
|
|
56
|
-
* @type {import('unified').Plugin}
|
|
57
|
-
*/
|
|
58
|
-
export default function rehypeShikiji() {
|
|
59
|
-
/**
|
|
60
|
-
* @param {import('hast').Root} tree - The HAST tree to be transformed.
|
|
61
|
-
*/
|
|
62
|
-
return function (tree) {
|
|
63
|
-
visit(tree, 'element', (node, index, parent) => {
|
|
64
|
-
// We only want to process <pre>...</pre> elements
|
|
65
|
-
if (!parent || index == null || node.tagName !== 'pre') {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// We want the contents of the <pre> element, hence we attempt to get the first child
|
|
70
|
-
const preElement = node.children[0];
|
|
71
|
-
|
|
72
|
-
// If thereÄs nothing inside the <pre> element... What are we doing here?
|
|
73
|
-
if (!preElement || !preElement.properties) {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Ensure that we're not visiting a <code> element but it's inner contents
|
|
78
|
-
// (keep iterating further down until we reach where we want)
|
|
79
|
-
if (preElement.type !== 'element' || preElement.tagName !== 'code') {
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Get the <pre> element class names
|
|
84
|
-
const preClassNames = preElement.properties.className;
|
|
85
|
-
|
|
86
|
-
// The current classnames should be an array and it should have a length
|
|
87
|
-
if (typeof preClassNames !== 'object' || preClassNames.length === 0) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// We want to retrieve the language class name from the class names
|
|
92
|
-
const codeLanguage = preClassNames.find(
|
|
93
|
-
c => typeof c === 'string' && c.startsWith(languagePrefix)
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
// If we didn't find any `language-` classname then we shouldn't highlight
|
|
97
|
-
if (typeof codeLanguage !== 'string') {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Grabs the relevant alias/name of the language
|
|
102
|
-
const languageId = codeLanguage.slice(languagePrefix.length);
|
|
103
|
-
|
|
104
|
-
// Parses the <pre> contents and returns a HAST tree with the highlighted code
|
|
105
|
-
const { children } = highlighter.shiki.codeToHast(
|
|
106
|
-
preElement.children[0].value,
|
|
107
|
-
{
|
|
108
|
-
lang: languageId,
|
|
109
|
-
// Allows support for dual themes (light, dark) for Shiki
|
|
110
|
-
themes: { light: shikiConfig.themes[0], dark: shikiConfig.themes[1] },
|
|
111
|
-
}
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
// Adds the original language back to the <pre> element
|
|
115
|
-
children[0].properties.class = `${children[0].properties.class} ${codeLanguage}`;
|
|
116
|
-
|
|
117
|
-
// Adds the toolbar (language label + copy button) to the <pre> element
|
|
118
|
-
children[0].children.push(createToolbarElement(languageId));
|
|
119
|
-
|
|
120
|
-
// Replaces the <pre> element with the updated one
|
|
121
|
-
parent.children.splice(index, 1, ...children);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
visit(tree, 'element', (_, index, parent) => {
|
|
125
|
-
const codeElements = [];
|
|
126
|
-
|
|
127
|
-
let currentIndex = index;
|
|
128
|
-
|
|
129
|
-
while (isCodeBlock(parent?.children[currentIndex])) {
|
|
130
|
-
const preElement = parent?.children[currentIndex];
|
|
131
|
-
const codeElement = preElement.children[0];
|
|
132
|
-
|
|
133
|
-
// We should get the language name from the class name
|
|
134
|
-
if (preElement.properties.class?.length) {
|
|
135
|
-
const className = preElement.properties.class;
|
|
136
|
-
const matches = className.match(/language-(?<language>.*)/);
|
|
137
|
-
const language = matches?.groups.language ?? 'text';
|
|
138
|
-
|
|
139
|
-
// For this iteration of our code, we only support multi-code tab for
|
|
140
|
-
// JavaScript languages for Node.js (CJS / MJS)
|
|
141
|
-
if (language === 'cjs' || language === 'mjs') {
|
|
142
|
-
// We patch up Shiki's `pre` element properties into the `code` element
|
|
143
|
-
// since we want to keep the original properties
|
|
144
|
-
codeElement.properties.class = `${className} ${language}`;
|
|
145
|
-
codeElement.properties.style = preElement.properties.style;
|
|
146
|
-
codeElement.properties.language = language;
|
|
147
|
-
|
|
148
|
-
// Add the code element to the pre children
|
|
149
|
-
codeElements.push(codeElement);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
currentIndex += 1;
|
|
154
|
-
|
|
155
|
-
// Since we only support CJS/MJS switch, we should have exactly 2 elements
|
|
156
|
-
// with different languages in order to create a switchable code tab
|
|
157
|
-
if (
|
|
158
|
-
codeElements.length === 2 &&
|
|
159
|
-
codeElements[0].properties?.language !==
|
|
160
|
-
codeElements[1].properties?.language
|
|
161
|
-
) {
|
|
162
|
-
const switchablePreElement = createElement(
|
|
163
|
-
'pre',
|
|
164
|
-
{
|
|
165
|
-
// We grab Shiki's styling from the code tag
|
|
166
|
-
// back to the pre element tag to ensure consistency
|
|
167
|
-
style: codeElements[0].properties.style,
|
|
168
|
-
class: 'shiki',
|
|
169
|
-
},
|
|
170
|
-
[
|
|
171
|
-
createElement('input', {
|
|
172
|
-
class: 'js-flavor-toggle',
|
|
173
|
-
type: 'checkbox',
|
|
174
|
-
// If the CJS code block is the first one, then we should keep
|
|
175
|
-
// the checkbox checked so that it highglit the CJS by default
|
|
176
|
-
checked: codeElements[0].properties.language === 'cjs',
|
|
177
|
-
}),
|
|
178
|
-
...codeElements,
|
|
179
|
-
createToolbarElement('javascript'),
|
|
180
|
-
]
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
// This removes all the original code Elements and adds a new CodeTab Element
|
|
184
|
-
// at the original start of the first Code Element
|
|
185
|
-
parent.children.splice(
|
|
186
|
-
index,
|
|
187
|
-
currentIndex - index,
|
|
188
|
-
switchablePreElement
|
|
189
|
-
);
|
|
190
|
-
|
|
191
|
-
// Prevent visiting the code block children and for the next N Elements
|
|
192
|
-
// since all of them belong to this CodeTabs Element
|
|
193
|
-
return [SKIP];
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
};
|
|
198
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
import rehypeStringify from 'rehype-stringify';
|
|
4
|
-
import remarkParse from 'remark-parse';
|
|
5
|
-
import remarkRehype from 'remark-rehype';
|
|
6
|
-
import { unified } from 'unified';
|
|
7
|
-
|
|
8
|
-
import syntaxHighlighter from './highlighter.mjs';
|
|
9
|
-
import { lazy } from './misc.mjs';
|
|
10
|
-
import { rehypeOptions } from './remark.mjs';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Retrieves an instance of Remark configured to output stringified HTML code
|
|
14
|
-
* including parsing Code Boxes with syntax highlighting.
|
|
15
|
-
*
|
|
16
|
-
* This lives apart from `./remark.mjs` because importing it loads Shiki (every
|
|
17
|
-
* grammar plus the regex engine, ~250MB per process). Only the generators that
|
|
18
|
-
* highlight code — `legacy-html` here — should pay for that.
|
|
19
|
-
*/
|
|
20
|
-
export const getRemarkRehypeWithShiki = lazy(() =>
|
|
21
|
-
unified()
|
|
22
|
-
.use(remarkParse)
|
|
23
|
-
// legacy-html gets the minimal (unhighlighted) type rendering
|
|
24
|
-
.use(remarkRehype, rehypeOptions)
|
|
25
|
-
// This is a custom ad-hoc within the Shiki Rehype plugin, used to highlight code
|
|
26
|
-
// and transform them into HAST nodes
|
|
27
|
-
.use(syntaxHighlighter)
|
|
28
|
-
.use(rehypeStringify, { allowDangerousHtml: true })
|
|
29
|
-
);
|
package/src/utils/remark.mjs
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
import rehypeStringify from 'rehype-stringify';
|
|
4
|
-
import remarkGfm from 'remark-gfm';
|
|
5
|
-
import remarkMdx from 'remark-mdx';
|
|
6
|
-
import remarkParse from 'remark-parse';
|
|
7
|
-
import remarkRehype from 'remark-rehype';
|
|
8
|
-
import remarkStringify from 'remark-stringify';
|
|
9
|
-
import { unified } from 'unified';
|
|
10
|
-
|
|
11
|
-
import { lazy } from './misc.mjs';
|
|
12
|
-
import { typeAnnotationToHast } from './type-annotations/hast.mjs';
|
|
13
|
-
import remarkTypeAnnotations from './type-annotations/remark.mjs';
|
|
14
|
-
|
|
15
|
-
// Nothing in this module loads Shiki: the `ast` and `metadata` stages (and
|
|
16
|
-
// every worker that runs them) import it, and none of them highlight code.
|
|
17
|
-
// The highlighting pipeline lives in `./remark-shiki.mjs`.
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Renders an MDX JSX element as just its children, so the surrounding prose
|
|
21
|
-
* still renders in HTML-string output.
|
|
22
|
-
*
|
|
23
|
-
* @param {import('mdast-util-to-hast').State} state
|
|
24
|
-
* @param {import('unist').Parent} node
|
|
25
|
-
*/
|
|
26
|
-
const mdxElementToChildren = (state, node) => state.all(node);
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Drops a node from HTML-string output.
|
|
30
|
-
*/
|
|
31
|
-
const dropNode = () => undefined;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* The `remark-rehype` options shared by the HTML-string pipelines.
|
|
35
|
-
*
|
|
36
|
-
* Existing HTML nodes pass through untouched (they were created during the
|
|
37
|
-
* rehype process), and dangerous HTML is allowed since the Markdown sources
|
|
38
|
-
* are trusted. The MDX node types cannot be rendered to an HTML string (that
|
|
39
|
-
* is the React generators' job): JSX elements degrade to their children so the
|
|
40
|
-
* surrounding prose still renders, and expressions/ESM are dropped.
|
|
41
|
-
*
|
|
42
|
-
* @type {import('remark-rehype').Options}
|
|
43
|
-
*/
|
|
44
|
-
export const rehypeOptions = {
|
|
45
|
-
allowDangerousHtml: true,
|
|
46
|
-
passThrough: ['element'],
|
|
47
|
-
handlers: {
|
|
48
|
-
typeAnnotation: typeAnnotationToHast,
|
|
49
|
-
mdxJsxTextElement: mdxElementToChildren,
|
|
50
|
-
mdxJsxFlowElement: mdxElementToChildren,
|
|
51
|
-
mdxFlowExpression: dropNode,
|
|
52
|
-
mdxTextExpression: dropNode,
|
|
53
|
-
mdxjsEsm: dropNode,
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Retrieves an instance of Remark configured to parse GFM (GitHub Flavored Markdown)
|
|
59
|
-
* plus `{...}` type annotations (see `./type-annotations`), which only exist
|
|
60
|
-
* in non-MDX files — the MDX pipeline below never registers them.
|
|
61
|
-
*/
|
|
62
|
-
export const getRemark = lazy(() =>
|
|
63
|
-
unified()
|
|
64
|
-
.use(remarkParse)
|
|
65
|
-
.use(remarkTypeAnnotations)
|
|
66
|
-
.use(remarkGfm)
|
|
67
|
-
.use(remarkStringify)
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Retrieves an instance of Remark configured to parse MDX (JSX-in-Markdown).
|
|
72
|
-
*
|
|
73
|
-
* Unlike {@link getRemark}, this understands `<Component />` and `{expression}`
|
|
74
|
-
* syntax as real JSX/expression nodes. It is only used for `.mdx` (or
|
|
75
|
-
* explicitly opted-in) files, since Node.js core `.md` files use bare `<` and
|
|
76
|
-
* `{` for type annotations that MDX would otherwise try to parse.
|
|
77
|
-
*/
|
|
78
|
-
export const getRemarkMdx = lazy(() =>
|
|
79
|
-
unified().use(remarkParse).use(remarkMdx).use(remarkGfm).use(remarkStringify)
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Retrieves an instance of Remark configured to output stringified HTML code
|
|
84
|
-
*/
|
|
85
|
-
export const getRemarkRehype = lazy(() =>
|
|
86
|
-
unified()
|
|
87
|
-
.use(remarkParse)
|
|
88
|
-
.use(remarkRehype, rehypeOptions)
|
|
89
|
-
.use(rehypeStringify, { allowDangerousHtml: true })
|
|
90
|
-
);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|