@doc-kit/core 1.2.0 → 1.3.0

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +1 -1
  3. package/package.json +6 -7
  4. package/src/generators/ast/generate.mjs +7 -3
  5. package/src/generators/ast/index.mjs +9 -0
  6. package/src/generators/index.mjs +1 -0
  7. package/src/generators/json/README.md +1 -1
  8. package/src/generators/json/generated/schema.d.ts +1 -1
  9. package/src/generators/json/index.mjs +9 -0
  10. package/src/generators/json/utils/markdown.mjs +2 -2
  11. package/src/generators/json-all/README.md +1 -1
  12. package/src/generators/json-simple/README.md +1 -1
  13. package/src/generators/loader.mjs +14 -0
  14. package/src/generators/metadata/generate.mjs +4 -2
  15. package/src/generators/metadata/index.mjs +9 -0
  16. package/src/generators/metadata/maps/mdn.json +3 -0
  17. package/src/generators/metadata/types.d.ts +1 -1
  18. package/src/generators/metadata/utils/parse.mjs +2 -4
  19. package/src/generators/metadata/utils/transformers.mjs +1 -1
  20. package/src/generators/metadata/utils/visitors.mjs +2 -2
  21. package/src/generators/types.d.ts +8 -0
  22. package/src/generators.mjs +4 -0
  23. package/src/logger/constants.mjs +35 -0
  24. package/src/logger/transports/github.mjs +48 -15
  25. package/src/plugins/shiki/highlighter.mjs +373 -0
  26. package/src/plugins/shiki/rehype.mjs +38 -0
  27. package/src/{utils/type-annotations/highlighted.mjs → plugins/type-annotations/highlighter.mjs} +14 -19
  28. package/src/{utils → plugins}/type-annotations/remark.mjs +6 -2
  29. package/src/threading/chunk-worker.mjs +4 -0
  30. package/src/threading/constants.mjs +10 -0
  31. package/src/threading/index.mjs +6 -1
  32. package/src/utils/configuration/constants.mjs +3 -3
  33. package/src/utils/configuration/index.mjs +86 -20
  34. package/src/utils/configuration/types.d.ts +27 -0
  35. package/src/utils/loaders.mjs +23 -1
  36. package/src/utils/markdown/constants.mjs +7 -0
  37. package/src/utils/markdown/plugins.mjs +232 -0
  38. package/src/utils/markdown/processor.mjs +60 -0
  39. package/src/utils/highlighter.mjs +0 -198
  40. package/src/utils/remark-shiki.mjs +0 -29
  41. package/src/utils/remark.mjs +0 -90
  42. /package/src/{utils → plugins}/type-annotations/hast.mjs +0 -0
  43. /package/src/{utils → plugins}/type-annotations/mdast.mjs +0 -0
  44. /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
- );
@@ -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
- );