@xyd-js/content 0.0.0-build
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 +14 -0
- package/ISSUES.md +1 -0
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/TODO.md +2 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +1625 -0
- package/dist/index.js.map +1 -0
- package/dist/md.d.ts +72 -0
- package/dist/md.js +23508 -0
- package/dist/md.js.map +1 -0
- package/dist/mdToc-NBBxMJ4l.d.ts +12 -0
- package/dist/vite.d.ts +1066 -0
- package/dist/vite.js +20156 -0
- package/dist/vite.js.map +1 -0
- package/package.json +67 -0
- package/packages/md/index.ts +25 -0
- package/packages/md/plugins/component-directives/index.ts +3 -0
- package/packages/md/plugins/component-directives/mdComponentDirective.ts +577 -0
- package/packages/md/plugins/component-directives/types.ts +1 -0
- package/packages/md/plugins/component-directives/utils.ts +27 -0
- package/packages/md/plugins/composer/__fixtures__/1.single-example/input.md +7 -0
- package/packages/md/plugins/composer/__fixtures__/1.single-example/output.json +63 -0
- package/packages/md/plugins/composer/__fixtures__/2.single-example-with-name/input.md +7 -0
- package/packages/md/plugins/composer/__fixtures__/2.single-example-with-name/output.json +63 -0
- package/packages/md/plugins/composer/__fixtures__/3.multiple-examples/input.md +15 -0
- package/packages/md/plugins/composer/__fixtures__/3.multiple-examples/output.json +122 -0
- package/packages/md/plugins/composer/__fixtures__/4.example-groups/input.md +23 -0
- package/packages/md/plugins/composer/__fixtures__/4.example-groups/output.json +184 -0
- package/packages/md/plugins/composer/__tests__/mdComposer.test.ts +41 -0
- package/packages/md/plugins/composer/__tests__/testHelpers.ts +48 -0
- package/packages/md/plugins/composer/index.ts +1 -0
- package/packages/md/plugins/composer/mdComposer.ts +146 -0
- package/packages/md/plugins/developer-writing/index.ts +3 -0
- package/packages/md/plugins/developer-writing/mdCodeRehype.ts +81 -0
- package/packages/md/plugins/functions/__fixtures__/external.ts +4 -0
- package/packages/md/plugins/functions/__fixtures__/test-include.md +31 -0
- package/packages/md/plugins/functions/__fixtures__/test.js +11 -0
- package/packages/md/plugins/functions/__fixtures__/test.py +9 -0
- package/packages/md/plugins/functions/__fixtures__/test.ts +18 -0
- package/packages/md/plugins/functions/__tests__/mdFunctionImportCode.test.ts +314 -0
- package/packages/md/plugins/functions/__tests__/mdFunctionInclude.test.ts +44 -0
- package/packages/md/plugins/functions/__tests__/parseFunctionCall.test.ts +70 -0
- package/packages/md/plugins/functions/__tests__/testHelpers.ts +95 -0
- package/packages/md/plugins/functions/index.ts +15 -0
- package/packages/md/plugins/functions/mdFunctionChangelog.ts +135 -0
- package/packages/md/plugins/functions/mdFunctionImportCode.ts +92 -0
- package/packages/md/plugins/functions/mdFunctionInclude.ts +119 -0
- package/packages/md/plugins/functions/mdFunctionUniform.ts +79 -0
- package/packages/md/plugins/functions/types.ts +9 -0
- package/packages/md/plugins/functions/uniformProcessor.ts +349 -0
- package/packages/md/plugins/functions/utils.ts +457 -0
- package/packages/md/plugins/index.ts +125 -0
- package/packages/md/plugins/mdCode.ts +16 -0
- package/packages/md/plugins/mdHeadingId.ts +47 -0
- package/packages/md/plugins/mdImage.test.ts +59 -0
- package/packages/md/plugins/mdImage.ts +55 -0
- package/packages/md/plugins/mdImageRehype.ts +13 -0
- package/packages/md/plugins/mdPage.ts +35 -0
- package/packages/md/plugins/mdThemeSettings.ts +34 -0
- package/packages/md/plugins/mdToc.ts +229 -0
- package/packages/md/plugins/meta/index.ts +1 -0
- package/packages/md/plugins/meta/mdMeta.ts +198 -0
- package/packages/md/plugins/output-variables/__fixtures__/1.simple/input.md +22 -0
- package/packages/md/plugins/output-variables/__fixtures__/1.simple/output.json +191 -0
- package/packages/md/plugins/output-variables/__fixtures__/2.multiple-vars/input.md +21 -0
- package/packages/md/plugins/output-variables/__fixtures__/2.multiple-vars/output.json +127 -0
- package/packages/md/plugins/output-variables/__tests__/index.test.ts +28 -0
- package/packages/md/plugins/output-variables/__tests__/testHelpers.ts +36 -0
- package/packages/md/plugins/output-variables/index.ts +1 -0
- package/packages/md/plugins/output-variables/lib/const.ts +4 -0
- package/packages/md/plugins/output-variables/lib/factoryAttributes.ts +350 -0
- package/packages/md/plugins/output-variables/lib/factoryLabel.ts +135 -0
- package/packages/md/plugins/output-variables/lib/factoryName.ts +59 -0
- package/packages/md/plugins/output-variables/lib/index.ts +21 -0
- package/packages/md/plugins/output-variables/lib/outputVarsContainer.ts +328 -0
- package/packages/md/plugins/output-variables/lib/util.ts +494 -0
- package/packages/md/plugins/output-variables/remarkOutputVars.ts +22 -0
- package/packages/md/plugins/recmaOverrideComponents.ts +74 -0
- package/packages/md/plugins/rehypeHeading.ts +58 -0
- package/packages/md/plugins/types.ts +15 -0
- package/packages/md/plugins/utils/componentLike.ts +76 -0
- package/packages/md/plugins/utils/index.ts +2 -0
- package/packages/md/plugins/utils/injectCodeMeta.ts +59 -0
- package/packages/md/plugins/utils/mdParameters.test.ts +114 -0
- package/packages/md/plugins/utils/mdParameters.ts +249 -0
- package/packages/md/plugins/utils/mdastTypes.ts +42 -0
- package/packages/md/search/index.ts +257 -0
- package/packages/md/search/types.ts +36 -0
- package/packages/vite/index.ts +20 -0
- package/src/fs.ts +81 -0
- package/src/index.ts +7 -0
- package/src/navigation.ts +147 -0
- package/src/types.ts +8 -0
- package/tsconfig.json +49 -0
- package/tsup.config.ts +32 -0
- package/vitest.config.ts +17 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { visit } from "unist-util-visit";
|
|
2
|
+
import { mdParameters } from "./utils/mdParameters";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* remark plugin to inject image meta/attributes (e.g. caption) into image nodes
|
|
6
|
+
* Supports both attributes in alt/title and trailing {caption="..."} blocks after the image.
|
|
7
|
+
*/
|
|
8
|
+
export function mdImage() {
|
|
9
|
+
return (tree: any) => {
|
|
10
|
+
// helper: extract MD parameters and merge into hProperties
|
|
11
|
+
function mergeProps(target: Record<string, any>, raw: string) {
|
|
12
|
+
const { props, attributes } = mdParameters(raw, { htmlMd: true });
|
|
13
|
+
// mdParameters returns props for text blocks, attributes for alt/title; unify
|
|
14
|
+
Object.assign(target, props ?? attributes);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Option 1: support trailing attribute blocks after images
|
|
18
|
+
visit(tree, 'paragraph', (node: any) => {
|
|
19
|
+
for (let idx = 0; idx < node.children.length - 1; idx++) {
|
|
20
|
+
const curr = node.children[idx];
|
|
21
|
+
const next = node.children[idx + 1];
|
|
22
|
+
|
|
23
|
+
if (curr.type === 'image' && next.type === 'text') {
|
|
24
|
+
const raw = next.value.trim();
|
|
25
|
+
if (/^\{.*\}$/.test(raw)) {
|
|
26
|
+
curr.data = curr.data || {};
|
|
27
|
+
curr.data.hProperties = curr.data.hProperties || {};
|
|
28
|
+
mergeProps(curr.data.hProperties, raw);
|
|
29
|
+
// remove the attribute block text node
|
|
30
|
+
node.children.splice(idx + 1, 1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Option 2: process inline attributes in alt and title
|
|
37
|
+
visit(tree, 'image', (node: any) => {
|
|
38
|
+
const hProps = (node.data = node.data || {}).hProperties = node.data.hProperties || {};
|
|
39
|
+
|
|
40
|
+
// alt: look for { ... } suffix
|
|
41
|
+
if (typeof node.alt === 'string') {
|
|
42
|
+
const altMatch = node.alt.match(/^(.*?)\s*(\{.*\})$/);
|
|
43
|
+
if (altMatch) {
|
|
44
|
+
node.alt = altMatch[1].trim();
|
|
45
|
+
mergeProps(hProps, altMatch[2]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// title: process any attributes
|
|
50
|
+
if (node.title) {
|
|
51
|
+
mergeProps(hProps, node.title);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { visit } from "unist-util-visit";
|
|
2
|
+
|
|
3
|
+
export function mdImageRehype() {
|
|
4
|
+
return (tree: any) => {
|
|
5
|
+
visit(tree, 'element', (node) => {
|
|
6
|
+
if (node.tagName === 'img' && node.properties) {
|
|
7
|
+
// If caption or other custom props are present, keep them
|
|
8
|
+
// (hProperties from remark should already be on properties)
|
|
9
|
+
// No-op, but could add logic here if needed in future
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {Plugin} from 'unified';
|
|
2
|
+
import {Node as UnistNode} from 'unist';
|
|
3
|
+
import {visit} from 'unist-util-visit';
|
|
4
|
+
|
|
5
|
+
declare global {
|
|
6
|
+
var page: boolean | null | undefined
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// TODO: to delete
|
|
10
|
+
/**
|
|
11
|
+
* This plugin extracts the `page` variable from the markdown file.
|
|
12
|
+
* This variable(`page`) is used to determine if theme should be dropped out.
|
|
13
|
+
*
|
|
14
|
+
* It means that if page=true, theme is not used, and we can use the markdown file as a standalone page.
|
|
15
|
+
*/
|
|
16
|
+
export const extractPage: Plugin = () => {
|
|
17
|
+
return (tree: UnistNode) => {
|
|
18
|
+
console.time('plugin:extractPage');
|
|
19
|
+
visit(tree, 'exportNamedDeclaration', (node: any) => {
|
|
20
|
+
const declaration = node.declaration;
|
|
21
|
+
|
|
22
|
+
if (!declaration || !declaration.declarations || !declaration.declarations.length) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// seek declarations like export const page = true in md files
|
|
27
|
+
declaration.declarations.forEach((decl: any) => {
|
|
28
|
+
if (decl.id.name === 'page') {
|
|
29
|
+
global.page = decl.init as boolean;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
console.timeEnd('plugin:extractPage');
|
|
34
|
+
};
|
|
35
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {Plugin} from 'unified';
|
|
2
|
+
import {Node as UnistNode} from 'unist';
|
|
3
|
+
import {visit} from 'unist-util-visit';
|
|
4
|
+
|
|
5
|
+
interface ThemeSettings {
|
|
6
|
+
bigArticle: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
declare global {
|
|
10
|
+
var themeSettings: ThemeSettings | undefined;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// TODO: to delete
|
|
14
|
+
/**
|
|
15
|
+
* This plugin adds the `themeSettings` variable to the global scope.
|
|
16
|
+
* This variable is used to determine the theme settings for the current page.
|
|
17
|
+
*/
|
|
18
|
+
export const extractThemeSettings: Plugin = () => {
|
|
19
|
+
return (tree: UnistNode) => {
|
|
20
|
+
visit(tree, 'exportNamedDeclaration', (node: any) => {
|
|
21
|
+
console.time('plugin:extractThemeSettings');
|
|
22
|
+
|
|
23
|
+
const declaration = node.declaration;
|
|
24
|
+
if (declaration && declaration.declarations) {
|
|
25
|
+
declaration.declarations.forEach((decl: any) => {
|
|
26
|
+
if (decl.id.name === 'themeSettings') {
|
|
27
|
+
global.themeSettings = decl.init as ThemeSettings;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
console.timeEnd('plugin:extractThemeSettings');
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
};
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { Root, Heading } from "mdast";
|
|
2
|
+
import { MdxjsEsm } from "mdast-util-mdx";
|
|
3
|
+
import { Plugin } from "unified";
|
|
4
|
+
import { MdxJsxFlowElement, MdxJsxAttribute } from "mdast-util-mdx-jsx";
|
|
5
|
+
|
|
6
|
+
import { mdParameters } from './utils/mdParameters';
|
|
7
|
+
|
|
8
|
+
export type TocEntry = {
|
|
9
|
+
depth: number,
|
|
10
|
+
id: string,
|
|
11
|
+
value: string,
|
|
12
|
+
attributes: { [key: string]: string },
|
|
13
|
+
children: TocEntry[],
|
|
14
|
+
maxTocDepth?: number
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type CustomTag = {
|
|
18
|
+
name: RegExp,
|
|
19
|
+
depth: (name: string) => number
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export interface RemarkMdxTocOptions {
|
|
23
|
+
name?: string,
|
|
24
|
+
customTags?: CustomTag[],
|
|
25
|
+
maxDepth?: number,
|
|
26
|
+
minDepth?: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// TODO: fix any
|
|
30
|
+
export function remarkMdxToc(options: RemarkMdxTocOptions): Plugin {
|
|
31
|
+
return function remarkMdxToc() {
|
|
32
|
+
return async function remarkMdxToc(ast: any) {
|
|
33
|
+
if (!options?.minDepth) {
|
|
34
|
+
options.minDepth = 2
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.time('plugin:remarkMdxToc');
|
|
38
|
+
const { visit } = await import("unist-util-visit");
|
|
39
|
+
const { toString } = await import("mdast-util-to-string");
|
|
40
|
+
const { valueToEstree } = await import('estree-util-value-to-estree')
|
|
41
|
+
const { name: isIdentifierName } = await import('estree-util-is-identifier-name');
|
|
42
|
+
|
|
43
|
+
const mdast = ast as Root;
|
|
44
|
+
const name = options.name ?? "toc"
|
|
45
|
+
if (!isIdentifierName(name)) {
|
|
46
|
+
throw new Error(`Invalid name for an identifier: ${name}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const toc: TocEntry[] = [];
|
|
50
|
+
const flatToc: TocEntry[] = [];
|
|
51
|
+
const nodesToRemove: number[] = [];
|
|
52
|
+
|
|
53
|
+
const createEntry = (node: Heading | MdxJsxFlowElement, depth: number, index: number): TocEntry | null => {
|
|
54
|
+
let attributes = (node.data || {}) as TocEntry['attributes'];
|
|
55
|
+
if (node.type === "mdxJsxFlowElement") {
|
|
56
|
+
attributes = Object.fromEntries(
|
|
57
|
+
node.attributes
|
|
58
|
+
.filter(attribute => attribute.type === 'mdxJsxAttribute' && typeof attribute.value === 'string')
|
|
59
|
+
.map(attribute => [(attribute as MdxJsxAttribute).name, attribute.value])
|
|
60
|
+
) as TocEntry['attributes'];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let value = toString(node, { includeImageAlt: false });
|
|
64
|
+
const { attributes: parsedAttributes, sanitizedText } = mdParameters(value);
|
|
65
|
+
|
|
66
|
+
// Merge parsed attributes with existing ones
|
|
67
|
+
attributes = { ...attributes, ...parsedAttributes };
|
|
68
|
+
|
|
69
|
+
// Handle toc attribute
|
|
70
|
+
if (attributes.toc === 'false') {
|
|
71
|
+
return null; // Skip this entry
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// If toc attribute is present, update the node's content to remove the [toc] part
|
|
75
|
+
if (attributes.toc === 'true' && node.type === "heading") {
|
|
76
|
+
// Keep the heading but remove the [toc] text and hide it
|
|
77
|
+
(node as any).data = {
|
|
78
|
+
...(node as any).data,
|
|
79
|
+
hProperties: {
|
|
80
|
+
...(node as any).data?.hProperties,
|
|
81
|
+
hideHeading: "true",
|
|
82
|
+
removeHeading: attributes.content === "false" ? "true" : ""
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
node.children = node.children.map(child => {
|
|
86
|
+
if (child.type === "text") {
|
|
87
|
+
return {
|
|
88
|
+
...child,
|
|
89
|
+
value: ""
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return child;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Use toc value if provided, otherwise use clean text
|
|
97
|
+
const tocValue = attributes.toc === 'true' ? sanitizedText : (attributes.toc || sanitizedText);
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
depth,
|
|
101
|
+
id: (node.data as any)?.hProperties?.id,
|
|
102
|
+
value: tocValue,
|
|
103
|
+
attributes,
|
|
104
|
+
children: [],
|
|
105
|
+
maxTocDepth: attributes.maxTocDepth ? parseInt(attributes.maxTocDepth) : undefined
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
visit(mdast, ["heading", "mdxJsxFlowElement"], (node, index) => {
|
|
110
|
+
// @ts-ignore
|
|
111
|
+
let depth = 0;
|
|
112
|
+
if (node.type === "mdxJsxFlowElement") {
|
|
113
|
+
let valid = false;
|
|
114
|
+
if (/^h[1-6]$/.test(node.name || "")) {
|
|
115
|
+
valid = true;
|
|
116
|
+
depth = parseInt(node.name!.substring(1));
|
|
117
|
+
} else if (options.customTags) {
|
|
118
|
+
for (const tag of options.customTags) {
|
|
119
|
+
if (tag.name.test(node.name || "")) {
|
|
120
|
+
valid = true;
|
|
121
|
+
depth = tag.depth(node.name || "");
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!valid) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
} else if (node.type === "heading") {
|
|
131
|
+
depth = node.depth;
|
|
132
|
+
} else {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const entry = createEntry(node, depth, index as number);
|
|
137
|
+
if (!entry) return;
|
|
138
|
+
|
|
139
|
+
// If toc attribute is explicitly set to true or +toc is present, include it regardless of depth
|
|
140
|
+
if (entry.attributes.toc === 'true' || entry.attributes["+toc"] === 'true') {
|
|
141
|
+
flatToc.push(entry);
|
|
142
|
+
let parent: TocEntry[] = toc;
|
|
143
|
+
for (let i = flatToc.length - 1; i >= 0; --i) {
|
|
144
|
+
const current = flatToc[i];
|
|
145
|
+
if (current.depth < entry.depth) {
|
|
146
|
+
parent = current.children;
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
parent.push(entry);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// First check if this entry should be included based on parent's maxTocDepth
|
|
155
|
+
let parentMaxDepth = options.maxDepth;
|
|
156
|
+
for (let i = flatToc.length - 1; i >= 0; --i) {
|
|
157
|
+
const parent = flatToc[i];
|
|
158
|
+
if (parent.depth < entry.depth) {
|
|
159
|
+
if (parent.maxTocDepth !== undefined) {
|
|
160
|
+
parentMaxDepth = parent.maxTocDepth;
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Now check against the effective max depth (either global or parent's maxTocDepth)
|
|
167
|
+
if (depth && parentMaxDepth && depth > parentMaxDepth) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (depth && (options?.minDepth && depth < options.minDepth)) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
flatToc.push(entry);
|
|
176
|
+
|
|
177
|
+
let parent: TocEntry[] = toc;
|
|
178
|
+
for (let i = flatToc.length - 1; i >= 0; --i) {
|
|
179
|
+
const current = flatToc[i];
|
|
180
|
+
if (current.depth < entry.depth) {
|
|
181
|
+
parent = current.children;
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
parent.push(entry);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Remove nodes marked for removal
|
|
189
|
+
nodesToRemove.sort((a, b) => b - a).forEach(index => {
|
|
190
|
+
mdast.children.splice(index, 1);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
const tocExport: MdxjsEsm = {
|
|
194
|
+
type: "mdxjsEsm",
|
|
195
|
+
value: "",
|
|
196
|
+
data: {
|
|
197
|
+
estree: {
|
|
198
|
+
type: "Program",
|
|
199
|
+
sourceType: "module",
|
|
200
|
+
body: [
|
|
201
|
+
{
|
|
202
|
+
type: "ExportNamedDeclaration",
|
|
203
|
+
specifiers: [],
|
|
204
|
+
attributes: [],
|
|
205
|
+
source: null,
|
|
206
|
+
declaration: {
|
|
207
|
+
type: "VariableDeclaration",
|
|
208
|
+
kind: "const",
|
|
209
|
+
declarations: [
|
|
210
|
+
{
|
|
211
|
+
type: "VariableDeclarator",
|
|
212
|
+
id: {
|
|
213
|
+
type: "Identifier",
|
|
214
|
+
name
|
|
215
|
+
},
|
|
216
|
+
init: valueToEstree(toc)
|
|
217
|
+
}
|
|
218
|
+
],
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
]
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
mdast.children.unshift(tocExport);
|
|
226
|
+
console.timeEnd('plugin:remarkMdxToc');
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { mdMeta } from "./mdMeta";
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { Root } from 'mdast';
|
|
2
|
+
import { matter } from 'vfile-matter';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
import { Metadata, Settings, Theme } from '@xyd-js/core';
|
|
6
|
+
import { getMetaComponent } from '@xyd-js/context';
|
|
7
|
+
import { Reference, TypeDocReferenceContext } from '@xyd-js/uniform';
|
|
8
|
+
import { uniformToMiniUniform } from '@xyd-js/sources/ts';
|
|
9
|
+
|
|
10
|
+
import { FunctionName } from '../functions/types';
|
|
11
|
+
import { parseFunctionCall, parseImportPath } from '../functions/utils';
|
|
12
|
+
import { processUniformFunctionCall } from '../functions/uniformProcessor';
|
|
13
|
+
import { componentLike } from '../utils';
|
|
14
|
+
import { SymbolxVfile } from '../types';
|
|
15
|
+
|
|
16
|
+
export interface MdMetaOptions {
|
|
17
|
+
resolveFrom?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// TODO: IT SHOULD BE PART OF COMPOSER
|
|
21
|
+
|
|
22
|
+
export function mdMeta(settings?: Settings, options?: MdMetaOptions) {
|
|
23
|
+
return function() {
|
|
24
|
+
return async (tree: Root, file: SymbolxVfile<any>) => {
|
|
25
|
+
console.time('plugin:mdMeta:total');
|
|
26
|
+
console.time('plugin:mdMeta:frontmatter');
|
|
27
|
+
// Parse frontmatter and expose it at file.data.matter
|
|
28
|
+
matter(file as any);
|
|
29
|
+
console.timeEnd('plugin:mdMeta:frontmatter');
|
|
30
|
+
|
|
31
|
+
if (!file.data.matter) {
|
|
32
|
+
console.timeEnd('plugin:mdMeta:total');
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
console.time('plugin:mdMeta:metaProcessing');
|
|
37
|
+
const meta = file.data.matter as Metadata<Record<string, any>>
|
|
38
|
+
if (!meta) {
|
|
39
|
+
console.timeEnd('plugin:mdMeta:metaProcessing');
|
|
40
|
+
console.timeEnd('plugin:mdMeta:total');
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let uniformMeta = false
|
|
45
|
+
if (meta?.uniform || meta?.openapi || meta?.graphql) {
|
|
46
|
+
uniformMeta = true
|
|
47
|
+
if (meta.graphql) {
|
|
48
|
+
meta.uniform = meta.graphql
|
|
49
|
+
} else if (meta.openapi) {
|
|
50
|
+
meta.uniform = meta.openapi
|
|
51
|
+
}
|
|
52
|
+
meta.component = "atlas"
|
|
53
|
+
|
|
54
|
+
if (typeof meta.uniform === "string") {
|
|
55
|
+
meta.componentProps = {
|
|
56
|
+
references: `@uniform('${meta.uniform}')`
|
|
57
|
+
}
|
|
58
|
+
} else if (typeof meta.uniform === "object") {
|
|
59
|
+
const uniformArgs = {}
|
|
60
|
+
|
|
61
|
+
if (meta.uniform.eager) {
|
|
62
|
+
// TODO: support eager line ranges?
|
|
63
|
+
const { filePath, regions } = parseImportPath(meta.uniform.path)
|
|
64
|
+
|
|
65
|
+
if (regions.length > 1) {
|
|
66
|
+
console.warn("Eager uniform with multiple regions is not supported")
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (regions.length) {
|
|
70
|
+
uniformArgs["eager"] = regions[0].name
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
meta.uniform.path = filePath
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
meta.componentProps = {
|
|
77
|
+
references: `@uniform('${meta.uniform.path}', ${JSON.stringify(uniformArgs)})`
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!meta || !meta.component) {
|
|
83
|
+
console.timeEnd('plugin:mdMeta:metaProcessing');
|
|
84
|
+
console.timeEnd('plugin:mdMeta:total');
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const metaComponent = getMetaComponent(meta.component)
|
|
89
|
+
|
|
90
|
+
if (!metaComponent) {
|
|
91
|
+
console.timeEnd('plugin:mdMeta:metaProcessing');
|
|
92
|
+
console.timeEnd('plugin:mdMeta:total');
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
console.timeEnd('plugin:mdMeta:metaProcessing');
|
|
96
|
+
|
|
97
|
+
console.time('plugin:mdMeta:propsProcessing');
|
|
98
|
+
const promises: Promise<void>[] = []
|
|
99
|
+
|
|
100
|
+
let resolvedProps: Record<string, any> = {}
|
|
101
|
+
|
|
102
|
+
if (uniformMeta && meta.componentProps && typeof meta.componentProps === "object") {
|
|
103
|
+
// TODO: ??? TO DELETE ???
|
|
104
|
+
for (const key in meta.componentProps) { // TODO: support nested props
|
|
105
|
+
const value = meta.componentProps[key]
|
|
106
|
+
|
|
107
|
+
const result = parseFunctionCall({
|
|
108
|
+
children: [
|
|
109
|
+
{
|
|
110
|
+
type: "text",
|
|
111
|
+
value: value
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
}, FunctionName.Uniform);
|
|
115
|
+
|
|
116
|
+
if (!result) {
|
|
117
|
+
resolvedProps[key] = value
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const importPath = result[0]
|
|
122
|
+
const importArgs = result[1];
|
|
123
|
+
|
|
124
|
+
if (!importPath) {
|
|
125
|
+
continue
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const promise = (async () => {
|
|
129
|
+
let references = await processUniformFunctionCall(
|
|
130
|
+
importPath,
|
|
131
|
+
file,
|
|
132
|
+
options?.resolveFrom,
|
|
133
|
+
settings,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
if (importArgs?.eager && references) { // TODO: move to `processUniformFunctionCall`
|
|
138
|
+
// TODO: rename uniformToMiniUniform eager
|
|
139
|
+
// TODO: support multile regions
|
|
140
|
+
references = uniformToMiniUniform(importArgs.eager, references as Reference<TypeDocReferenceContext>[]);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
resolvedProps[key] = references
|
|
144
|
+
})()
|
|
145
|
+
|
|
146
|
+
promises.push(promise)
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
resolvedProps = meta.componentProps || {}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
await Promise.all(promises)
|
|
153
|
+
console.timeEnd('plugin:mdMeta:propsProcessing');
|
|
154
|
+
|
|
155
|
+
console.time('plugin:mdMeta:transform');
|
|
156
|
+
const resolvedComponentProps = await metaComponent.transform(
|
|
157
|
+
(settings?.theme || {}) as Theme,
|
|
158
|
+
resolvedProps,
|
|
159
|
+
file.data.outputVars,
|
|
160
|
+
Object.freeze(tree.children) as any,
|
|
161
|
+
meta,
|
|
162
|
+
// @ts-ignore
|
|
163
|
+
settings
|
|
164
|
+
)
|
|
165
|
+
console.timeEnd('plugin:mdMeta:transform');
|
|
166
|
+
|
|
167
|
+
console.time('plugin:mdMeta:componentCreation');
|
|
168
|
+
const exportNode = componentLike(
|
|
169
|
+
metaComponent.componentName,
|
|
170
|
+
resolvedComponentProps,
|
|
171
|
+
[]
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
tree.children = [
|
|
175
|
+
...treeSanitize(tree),
|
|
176
|
+
...exportNode.children
|
|
177
|
+
]
|
|
178
|
+
console.timeEnd('plugin:mdMeta:componentCreation');
|
|
179
|
+
console.timeEnd('plugin:mdMeta:total');
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// TODO: add more / BETTER SOLUTION FOR CLEARIN
|
|
185
|
+
const allowedNodes = [
|
|
186
|
+
"mdxjsEsm",
|
|
187
|
+
// "outputVars", // TODO: !!! cuz some issues with outputvars + containerDirective !!!
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
function treeSanitize(tree: Root) {
|
|
191
|
+
return tree.children.filter((child) => {
|
|
192
|
+
if (allowedNodes.includes(child.type)) {
|
|
193
|
+
return true
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return false
|
|
197
|
+
})
|
|
198
|
+
}
|