@terrafirmagreg-team/mdx 1.2.4 → 1.2.5
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/package.json +5 -3
- package/src/components/mdx-components.tsx +4 -4
- package/src/components/story-panel.tsx +1 -1
- package/src/lib/md-plugins.ts +11 -23
- package/src/lib/mdx/accordions.ts +14 -3
- package/src/lib/mdx/banner.ts +0 -1
- package/src/lib/mdx/callouts.ts +153 -0
- package/src/lib/mdx/directive-fallback.ts +87 -0
- package/src/lib/mdx/directive-utils.ts +1 -1
- package/src/lib/mdx/directives.ts +59 -118
- package/src/lib/mdx/entries/block.ts +6 -0
- package/src/lib/mdx/entries/entity.ts +6 -0
- package/src/lib/mdx/entries/factory.ts +102 -0
- package/src/lib/mdx/entries/fluid.ts +6 -0
- package/src/lib/mdx/entries/guide.ts +6 -0
- package/src/lib/mdx/entries/image.ts +9 -0
- package/src/lib/mdx/entries/index.ts +45 -0
- package/src/lib/mdx/entries/item.ts +6 -0
- package/src/lib/mdx/entries/multiblock.ts +16 -0
- package/src/lib/mdx/entries/quest.ts +6 -0
- package/src/lib/mdx/entries/recipe.ts +6 -0
- package/src/lib/mdx/entries/story.ts +6 -0
- package/src/lib/mdx/entries/tag.ts +6 -0
- package/src/lib/mdx/files.ts +129 -0
- package/src/lib/mdx/{references.ts → github-autolinks.ts} +7 -5
- package/src/lib/mdx/tabs.ts +0 -1
- package/src/lib/story-remark.ts +97 -31
- package/src/lib/mdx/game-export.ts +0 -110
- package/src/lib/mdx/html-style.ts +0 -136
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@terrafirmagreg-team/mdx",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "MDX/markdown pipeline",
|
|
6
6
|
"license": "LGPL-3.0-only",
|
|
@@ -21,14 +21,16 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@fumadocs/story": "^1.5.3",
|
|
23
23
|
"@fumari/stf": "^1.1.2",
|
|
24
|
-
"@terrafirmagreg-team/translate": "^1.2.
|
|
25
|
-
"@terrafirmagreg-team/ui": "^1.2.
|
|
24
|
+
"@terrafirmagreg-team/translate": "^1.2.6",
|
|
25
|
+
"@terrafirmagreg-team/ui": "^1.2.7",
|
|
26
26
|
"@types/turndown": "^5.0.6",
|
|
27
27
|
"fumadocs-core": "16.17.10",
|
|
28
28
|
"fumadocs-docgen": "^3.2.0",
|
|
29
29
|
"fumadocs-twoslash": "^4.0.4",
|
|
30
30
|
"fumadocs-typescript": "5.6.0",
|
|
31
|
+
"gemoji": "^8.1.0",
|
|
31
32
|
"lucide-react": "^1.63.0",
|
|
33
|
+
"mdast-util-to-string": "^4.0.0",
|
|
32
34
|
"rehype-katex": "^7.0.1",
|
|
33
35
|
"rehype-raw": "^7.0.0",
|
|
34
36
|
"remark-directive": "^4.0.0",
|
|
@@ -39,9 +39,9 @@ import { Callout, CalloutContainer } from '@terrafirmagreg-team/ui/components/md
|
|
|
39
39
|
import { Input, Output, Preview } from '@terrafirmagreg-team/ui/components/mdx/preview';
|
|
40
40
|
import { DocsImage } from './docs-image';
|
|
41
41
|
import { Multiblock } from '@terrafirmagreg-team/ui/components/mdx/multiblock';
|
|
42
|
-
import { GradientText } from '@terrafirmagreg-team/ui/components/mdx/gradient-text';
|
|
43
|
-
import { GlowHeader } from '@terrafirmagreg-team/ui/components/mdx/glow-header';
|
|
44
42
|
import { Icon } from '@terrafirmagreg-team/ui/components/mdx/icon';
|
|
43
|
+
import { Video } from '@terrafirmagreg-team/ui/components/mdx/video';
|
|
44
|
+
import { Gradient } from '@terrafirmagreg-team/ui/components/mdx/gradient';
|
|
45
45
|
import { LinkPreview } from '@terrafirmagreg-team/ui/components/blocks/link/link-preview';
|
|
46
46
|
import type { MDXComponents } from 'mdx/types';
|
|
47
47
|
import type { ComponentProps, HTMLAttributes } from 'react';
|
|
@@ -87,9 +87,9 @@ export function getMDXComponents(components?: MDXComponents) {
|
|
|
87
87
|
Output,
|
|
88
88
|
DocsImage,
|
|
89
89
|
Multiblock,
|
|
90
|
-
GradientText,
|
|
91
|
-
GlowHeader,
|
|
92
90
|
Icon,
|
|
91
|
+
Video,
|
|
92
|
+
Gradient,
|
|
93
93
|
a: LinkPreview,
|
|
94
94
|
pre: (props: HTMLAttributes<HTMLPreElement>) => (
|
|
95
95
|
<CodeBlock {...props}>
|
|
@@ -144,7 +144,7 @@ function Content() {
|
|
|
144
144
|
)}
|
|
145
145
|
<div className="bg-fd-background p-4 not-last:border-b">
|
|
146
146
|
<PreviewBoundary resetKey={args}>
|
|
147
|
-
{createElement(Component, args)}
|
|
147
|
+
{createElement(Component, { ...args, key: variant })}
|
|
148
148
|
</PreviewBoundary>
|
|
149
149
|
</div>
|
|
150
150
|
{preset && (
|
package/src/lib/md-plugins.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { rehypeCode } from 'fumadocs-core/mdx-plugins/rehype-code';
|
|
2
2
|
import {
|
|
3
3
|
rehypeCodeDefaultOptions,
|
|
4
|
-
remarkDirectiveAdmonition,
|
|
5
4
|
remarkMdxFiles,
|
|
6
5
|
remarkMdxMermaid,
|
|
7
6
|
remarkSteps,
|
|
@@ -16,11 +15,13 @@ import rehypeKatex from 'rehype-katex';
|
|
|
16
15
|
import rehypeRaw from 'rehype-raw';
|
|
17
16
|
import { remarkAccordions } from './mdx/accordions';
|
|
18
17
|
import { remarkBanner } from './mdx/banner';
|
|
18
|
+
import { remarkCallouts } from './mdx/callouts';
|
|
19
|
+
import { remarkDirectiveFallback } from './mdx/directive-fallback';
|
|
19
20
|
import { remarkDirectives } from './mdx/directives';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
21
|
+
import { filesToMdx, remarkFilesDirective } from './mdx/files';
|
|
22
|
+
import { remarkEntries } from './mdx/entries/index.ts';
|
|
23
|
+
import { remarkGithubAutolinks } from './mdx/github-autolinks';
|
|
22
24
|
import { remarkPreview } from './mdx/preview';
|
|
23
|
-
import { remarkChangelogReferences } from './mdx/references';
|
|
24
25
|
import { remarkTabs } from './mdx/tabs';
|
|
25
26
|
import type { PluggableList } from 'unified';
|
|
26
27
|
|
|
@@ -64,31 +65,18 @@ export const mdOptions = (
|
|
|
64
65
|
remarkAccordions,
|
|
65
66
|
remarkBanner,
|
|
66
67
|
remarkDirectives,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
[remarkChangelogReferences, { datasetConfig }],
|
|
68
|
+
remarkEntries,
|
|
69
|
+
[remarkGithubAutolinks, { datasetConfig }],
|
|
70
70
|
[remarkDocGen, { generators: [fileGenerator()] }],
|
|
71
71
|
remarkShow,
|
|
72
72
|
remarkAutoTypeTable,
|
|
73
|
-
|
|
74
|
-
remarkDirectiveAdmonition,
|
|
75
|
-
{
|
|
76
|
-
types: {
|
|
77
|
-
note: 'note',
|
|
78
|
-
tip: 'tip',
|
|
79
|
-
info: 'info',
|
|
80
|
-
warn: 'warning',
|
|
81
|
-
warning: 'warning',
|
|
82
|
-
danger: 'error',
|
|
83
|
-
success: 'success',
|
|
84
|
-
idea: 'idea',
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
],
|
|
73
|
+
remarkCallouts,
|
|
88
74
|
remarkMath,
|
|
89
75
|
remarkSteps,
|
|
90
|
-
remarkMdxFiles,
|
|
76
|
+
[remarkMdxFiles, { toMdx: filesToMdx }],
|
|
77
|
+
remarkFilesDirective,
|
|
91
78
|
remarkMdxMermaid,
|
|
79
|
+
remarkDirectiveFallback,
|
|
92
80
|
[remarkBlockId, { addDataAttribute: 'feedback' }],
|
|
93
81
|
] as PluggableList,
|
|
94
82
|
remarkRehypeOptions: { allowDangerousHtml: true },
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
contentChildren,
|
|
3
3
|
estreeBoolean,
|
|
4
|
+
estreeStringArray,
|
|
4
5
|
extractDirectiveLabel,
|
|
5
6
|
extractLeafLabel,
|
|
6
7
|
jsxAttr,
|
|
@@ -17,11 +18,9 @@ export function remarkAccordions() {
|
|
|
17
18
|
walkContainers(tree, (directive) => {
|
|
18
19
|
if (directive.name === 'accordion' || directive.name === 'details') {
|
|
19
20
|
wrapSingle(directive);
|
|
20
|
-
return false;
|
|
21
21
|
}
|
|
22
22
|
if (directive.name === 'accordions') {
|
|
23
23
|
toAccordions(directive);
|
|
24
|
-
return false;
|
|
25
24
|
}
|
|
26
25
|
});
|
|
27
26
|
};
|
|
@@ -37,10 +36,22 @@ function toAccordion(node: DirectiveNode): JsxElement {
|
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
function wrapSingle(node: DirectiveNode): void {
|
|
39
|
+
const attrs = node.attributes ?? {};
|
|
40
|
+
const open = 'open' in attrs;
|
|
40
41
|
Object.assign(node, {
|
|
41
42
|
type: 'mdxJsxFlowElement',
|
|
42
43
|
name: 'Accordions',
|
|
43
|
-
attributes:
|
|
44
|
+
attributes: open
|
|
45
|
+
? [
|
|
46
|
+
{
|
|
47
|
+
type: 'mdxJsxAttribute',
|
|
48
|
+
name: 'defaultValue',
|
|
49
|
+
value: jsxExpression(
|
|
50
|
+
estreeStringArray([String(extractDirectiveLabel(node))]),
|
|
51
|
+
),
|
|
52
|
+
} as JsxAttribute,
|
|
53
|
+
]
|
|
54
|
+
: [],
|
|
44
55
|
children: [toAccordion(node)],
|
|
45
56
|
});
|
|
46
57
|
}
|
package/src/lib/mdx/banner.ts
CHANGED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { visit, CONTINUE } from 'unist-util-visit';
|
|
2
|
+
import {
|
|
3
|
+
contentChildren,
|
|
4
|
+
toJsxAttributes,
|
|
5
|
+
type DirectiveNode,
|
|
6
|
+
type MdastNode,
|
|
7
|
+
} from './directive-utils.ts';
|
|
8
|
+
|
|
9
|
+
const CALLOUT_TYPES: Record<string, string> = {
|
|
10
|
+
note: 'note',
|
|
11
|
+
tip: 'tip',
|
|
12
|
+
tips: 'tip',
|
|
13
|
+
hint: 'tip',
|
|
14
|
+
info: 'info',
|
|
15
|
+
important: 'important',
|
|
16
|
+
warn: 'warning',
|
|
17
|
+
warning: 'warning',
|
|
18
|
+
caution: 'caution',
|
|
19
|
+
attention: 'attention',
|
|
20
|
+
danger: 'danger',
|
|
21
|
+
error: 'error',
|
|
22
|
+
success: 'success',
|
|
23
|
+
idea: 'idea',
|
|
24
|
+
question: 'question',
|
|
25
|
+
help: 'question',
|
|
26
|
+
faq: 'question',
|
|
27
|
+
failure: 'failure',
|
|
28
|
+
fail: 'failure',
|
|
29
|
+
missing: 'failure',
|
|
30
|
+
bug: 'bug',
|
|
31
|
+
abstract: 'abstract',
|
|
32
|
+
summary: 'abstract',
|
|
33
|
+
tldr: 'abstract',
|
|
34
|
+
example: 'example',
|
|
35
|
+
quote: 'quote',
|
|
36
|
+
cite: 'quote',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const ALERT_RE = /^\[!([^\]\s]+)\][ \t]*/;
|
|
40
|
+
|
|
41
|
+
function calloutKind(name: string | undefined): string | undefined {
|
|
42
|
+
return name ? CALLOUT_TYPES[name.toLowerCase()] : undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function calloutChildren(
|
|
46
|
+
type: string,
|
|
47
|
+
titleNodes: MdastNode[],
|
|
48
|
+
bodyNodes: MdastNode[],
|
|
49
|
+
): MdastNode[] {
|
|
50
|
+
const children: MdastNode[] = [];
|
|
51
|
+
const title =
|
|
52
|
+
titleNodes.length
|
|
53
|
+
? titleNodes
|
|
54
|
+
: [
|
|
55
|
+
{
|
|
56
|
+
type: 'text',
|
|
57
|
+
value: type[0].toUpperCase() + type.slice(1),
|
|
58
|
+
} as MdastNode,
|
|
59
|
+
];
|
|
60
|
+
children.push({
|
|
61
|
+
type: 'mdxJsxFlowElement',
|
|
62
|
+
name: 'CalloutTitle',
|
|
63
|
+
attributes: [],
|
|
64
|
+
children: title,
|
|
65
|
+
} as MdastNode);
|
|
66
|
+
if (bodyNodes.length) {
|
|
67
|
+
children.push({
|
|
68
|
+
type: 'mdxJsxFlowElement',
|
|
69
|
+
name: 'CalloutDescription',
|
|
70
|
+
attributes: [],
|
|
71
|
+
children: bodyNodes,
|
|
72
|
+
} as MdastNode);
|
|
73
|
+
}
|
|
74
|
+
return children;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function directiveLabelNodes(node: DirectiveNode): MdastNode[] {
|
|
78
|
+
for (const child of node.children ?? []) {
|
|
79
|
+
if (child.type === 'paragraph' && child.data?.directiveLabel) {
|
|
80
|
+
return (child.children ?? []) as MdastNode[];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function convertAlert(container: MdastNode): boolean {
|
|
87
|
+
const first = container.children?.[0];
|
|
88
|
+
if (first?.type !== 'paragraph') return false;
|
|
89
|
+
const text = first.children?.[0];
|
|
90
|
+
if (text?.type !== 'text' || typeof text.value !== 'string') return false;
|
|
91
|
+
const match = ALERT_RE.exec(text.value);
|
|
92
|
+
if (!match) return false;
|
|
93
|
+
const type = calloutKind(match[1]);
|
|
94
|
+
if (!type) return false;
|
|
95
|
+
|
|
96
|
+
text.value = text.value.slice(match[0].length);
|
|
97
|
+
const inline = first.children ?? [];
|
|
98
|
+
if (!text.value) {
|
|
99
|
+
inline.shift();
|
|
100
|
+
if (inline[0]?.type === 'break') inline.shift();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const body: MdastNode[] = [
|
|
104
|
+
...(inline.length
|
|
105
|
+
? [{ type: 'paragraph', children: [...inline] } as MdastNode]
|
|
106
|
+
: []),
|
|
107
|
+
...((container.children ?? []).slice(1) as MdastNode[]),
|
|
108
|
+
];
|
|
109
|
+
const callout = {
|
|
110
|
+
type: 'mdxJsxFlowElement',
|
|
111
|
+
name: 'CalloutContainer',
|
|
112
|
+
attributes: [
|
|
113
|
+
{ type: 'mdxJsxAttribute', name: 'type', value: type },
|
|
114
|
+
],
|
|
115
|
+
children: calloutChildren(type, [], body),
|
|
116
|
+
};
|
|
117
|
+
Object.assign(
|
|
118
|
+
container.type === 'listItem' ? first : container,
|
|
119
|
+
callout,
|
|
120
|
+
);
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function remarkCallouts() {
|
|
125
|
+
return (tree: MdastNode) => {
|
|
126
|
+
visit(
|
|
127
|
+
tree as never,
|
|
128
|
+
['containerDirective', 'blockquote', 'listItem'],
|
|
129
|
+
(node) => {
|
|
130
|
+
const item = node as DirectiveNode;
|
|
131
|
+
if (item.type === 'containerDirective') {
|
|
132
|
+
const type = calloutKind(item.name);
|
|
133
|
+
if (!type) return CONTINUE;
|
|
134
|
+
Object.assign(item, {
|
|
135
|
+
type: 'mdxJsxFlowElement',
|
|
136
|
+
name: 'CalloutContainer',
|
|
137
|
+
attributes: [
|
|
138
|
+
{ type: 'mdxJsxAttribute', name: 'type', value: type },
|
|
139
|
+
...toJsxAttributes(item),
|
|
140
|
+
],
|
|
141
|
+
children: calloutChildren(
|
|
142
|
+
type,
|
|
143
|
+
directiveLabelNodes(item),
|
|
144
|
+
contentChildren(item),
|
|
145
|
+
),
|
|
146
|
+
});
|
|
147
|
+
} else {
|
|
148
|
+
convertAlert(item);
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { nameToEmoji } from 'gemoji';
|
|
2
|
+
import { visit } from 'unist-util-visit';
|
|
3
|
+
import {
|
|
4
|
+
DIRECTIVE_TYPES,
|
|
5
|
+
type DirectiveNode,
|
|
6
|
+
type MdastNode,
|
|
7
|
+
} from './directive-utils.ts';
|
|
8
|
+
|
|
9
|
+
type Pos = { start?: { offset?: number }; end?: { offset?: number } };
|
|
10
|
+
type File = { value?: unknown };
|
|
11
|
+
|
|
12
|
+
function sliceSource(node: MdastNode, file?: File): string | undefined {
|
|
13
|
+
const source = typeof file?.value === 'string' ? file.value : '';
|
|
14
|
+
const pos = node.position as Pos | undefined;
|
|
15
|
+
const start = pos?.start?.offset;
|
|
16
|
+
const end = pos?.end?.offset;
|
|
17
|
+
if (typeof start !== 'number' || typeof end !== 'number' || !source)
|
|
18
|
+
return undefined;
|
|
19
|
+
return source.slice(start, end);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function labelText(nodes: MdastNode[] | undefined): string {
|
|
23
|
+
return (nodes ?? [])
|
|
24
|
+
.map((child) =>
|
|
25
|
+
typeof (child as { value?: unknown }).value === 'string'
|
|
26
|
+
? ((child as { value?: unknown }).value as string)
|
|
27
|
+
: '',
|
|
28
|
+
)
|
|
29
|
+
.join('');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function literalMarker(node: DirectiveNode): string {
|
|
33
|
+
const prefix =
|
|
34
|
+
node.type === 'containerDirective'
|
|
35
|
+
? ':::'
|
|
36
|
+
: node.type === 'leafDirective'
|
|
37
|
+
? '::'
|
|
38
|
+
: ':';
|
|
39
|
+
const label = labelText(node.children);
|
|
40
|
+
const attrs = Object.entries(node.attributes ?? {})
|
|
41
|
+
.map(([key, value]) =>
|
|
42
|
+
value == null || value === true || value === ''
|
|
43
|
+
? key
|
|
44
|
+
: `${key}="${String(value)}"`,
|
|
45
|
+
)
|
|
46
|
+
.join(' ');
|
|
47
|
+
return `${prefix}${node.name ?? ''}${label ? `[${label}]` : ''}${attrs ? `{${attrs}}` : ''}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function toText(node: MdastNode, value: string): void {
|
|
51
|
+
const rest = node as unknown as Record<string, unknown>;
|
|
52
|
+
delete rest.name;
|
|
53
|
+
delete rest.attributes;
|
|
54
|
+
delete rest.children;
|
|
55
|
+
Object.assign(node, { type: 'text', value });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function remarkDirectiveFallback() {
|
|
59
|
+
return (tree: MdastNode, file?: File) => {
|
|
60
|
+
visit(tree as never, DIRECTIVE_TYPES, (node) => {
|
|
61
|
+
const directive = node as DirectiveNode;
|
|
62
|
+
const name = directive.name ?? '';
|
|
63
|
+
if (directive.type === 'textDirective') {
|
|
64
|
+
const emoji = nameToEmoji[name];
|
|
65
|
+
if (emoji) {
|
|
66
|
+
toText(node, emoji);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
toText(node, sliceSource(node, file) ?? literalMarker(directive));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (directive.type === 'leafDirective') {
|
|
73
|
+
toText(node, sliceSource(node, file) ?? literalMarker(directive));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const raw = sliceSource(node, file);
|
|
77
|
+
if (raw !== undefined) {
|
|
78
|
+
Object.assign(node, {
|
|
79
|
+
type: 'paragraph',
|
|
80
|
+
name: undefined,
|
|
81
|
+
attributes: undefined,
|
|
82
|
+
children: [{ type: 'text', value: raw }],
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -3,15 +3,15 @@ import {
|
|
|
3
3
|
extractDirectiveLabel,
|
|
4
4
|
extractLeafLabel,
|
|
5
5
|
jsxAttr,
|
|
6
|
-
jsxExpression,
|
|
7
6
|
toJsxAttributes,
|
|
8
7
|
walkDirectives,
|
|
8
|
+
DIRECTIVE_TYPES,
|
|
9
9
|
type DirectiveNode,
|
|
10
10
|
type MdastNode,
|
|
11
11
|
} from './directive-utils.ts';
|
|
12
|
-
import { gradientImage } from '@terrafirmagreg-team/ui/lib/mdx/gradient';
|
|
13
12
|
import { createRequire } from 'node:module';
|
|
14
13
|
import { join, relative } from 'node:path';
|
|
14
|
+
import { visit } from 'unist-util-visit';
|
|
15
15
|
|
|
16
16
|
const require = createRequire(join(process.cwd(), '_'));
|
|
17
17
|
|
|
@@ -22,6 +22,11 @@ function resolvePkgPath(spec: string) {
|
|
|
22
22
|
|
|
23
23
|
export function remarkDirectives() {
|
|
24
24
|
return (tree: MdastNode, file?: { value?: unknown }) => {
|
|
25
|
+
pairGradients(tree);
|
|
26
|
+
visit(tree as never, 'code', (node: MdastNode) => {
|
|
27
|
+
if (node.lang === 'math')
|
|
28
|
+
Object.assign(node, mathNode(String(node.value ?? ''), true));
|
|
29
|
+
});
|
|
25
30
|
walkDirectives(tree, (node) => {
|
|
26
31
|
const { type, name } = node;
|
|
27
32
|
if (
|
|
@@ -38,35 +43,14 @@ export function remarkDirectives() {
|
|
|
38
43
|
Object.assign(node, mathNode(tex, block));
|
|
39
44
|
return false;
|
|
40
45
|
}
|
|
41
|
-
if (type === '
|
|
46
|
+
if (type === 'leafDirective' && name === 'video') {
|
|
42
47
|
Object.assign(node, {
|
|
43
|
-
type: '
|
|
44
|
-
name: '
|
|
45
|
-
attributes:
|
|
46
|
-
|
|
47
|
-
{ type: 'mdxJsxAttribute', name: 'data-md', value: 'gradient' },
|
|
48
|
-
],
|
|
49
|
-
});
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (
|
|
53
|
-
name === 'glow' &&
|
|
54
|
-
(type === 'textDirective' ||
|
|
55
|
-
type === 'leafDirective' ||
|
|
56
|
-
type === 'containerDirective')
|
|
57
|
-
) {
|
|
58
|
-
Object.assign(node, {
|
|
59
|
-
type:
|
|
60
|
-
type === 'textDirective'
|
|
61
|
-
? 'mdxJsxTextElement'
|
|
62
|
-
: 'mdxJsxFlowElement',
|
|
63
|
-
name: 'span',
|
|
64
|
-
attributes: [
|
|
65
|
-
styleAttr(glowStyle(node)),
|
|
66
|
-
{ type: 'mdxJsxAttribute', name: 'data-md', value: 'glow' },
|
|
67
|
-
],
|
|
48
|
+
type: 'mdxJsxFlowElement',
|
|
49
|
+
name: 'Video',
|
|
50
|
+
attributes: toJsxAttributes(node),
|
|
51
|
+
children: [],
|
|
68
52
|
});
|
|
69
|
-
return
|
|
53
|
+
return false;
|
|
70
54
|
}
|
|
71
55
|
if (type === 'textDirective' && name === 'icon') {
|
|
72
56
|
Object.assign(node, {
|
|
@@ -95,7 +79,6 @@ export function remarkDirectives() {
|
|
|
95
79
|
children:
|
|
96
80
|
type === 'containerDirective' ? contentChildren(node) : [],
|
|
97
81
|
});
|
|
98
|
-
return false;
|
|
99
82
|
}
|
|
100
83
|
if (type === 'containerDirective' && name === 'cards') {
|
|
101
84
|
Object.assign(node, {
|
|
@@ -118,22 +101,6 @@ export function remarkDirectives() {
|
|
|
118
101
|
});
|
|
119
102
|
return false;
|
|
120
103
|
}
|
|
121
|
-
if (type === 'leafDirective' && name === 'recipe') {
|
|
122
|
-
Object.assign(node, {
|
|
123
|
-
type: 'mdxJsxFlowElement',
|
|
124
|
-
name: 'Recipe',
|
|
125
|
-
attributes: [
|
|
126
|
-
{
|
|
127
|
-
type: 'mdxJsxAttribute',
|
|
128
|
-
name: 'id',
|
|
129
|
-
value: extractLeafLabel(node).trim(),
|
|
130
|
-
},
|
|
131
|
-
...toJsxAttributes(node),
|
|
132
|
-
],
|
|
133
|
-
children: [],
|
|
134
|
-
});
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
104
|
return undefined;
|
|
138
105
|
});
|
|
139
106
|
};
|
|
@@ -182,80 +149,54 @@ function containerBody(
|
|
|
182
149
|
.trim();
|
|
183
150
|
}
|
|
184
151
|
|
|
185
|
-
function
|
|
186
|
-
return
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
shorthand: false,
|
|
195
|
-
})),
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function styleAttr(entries: [string, string][]) {
|
|
200
|
-
return {
|
|
201
|
-
type: 'mdxJsxAttribute' as const,
|
|
202
|
-
name: 'style',
|
|
203
|
-
value: jsxExpression(estreeObject(entries)),
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function attr(node: DirectiveNode, name: string) {
|
|
208
|
-
const value = node.attributes?.[name];
|
|
209
|
-
return typeof value === 'string' && value ? value : undefined;
|
|
152
|
+
function stripClose(node: MdastNode): boolean {
|
|
153
|
+
if (node.type !== 'paragraph') return false;
|
|
154
|
+
const children = (node.children ?? []) as { type?: string; value?: string }[];
|
|
155
|
+
const last = children.at(-1);
|
|
156
|
+
if (last?.type !== 'text' || typeof last.value !== 'string') return false;
|
|
157
|
+
if (!/\s*::$/.test(last.value)) return false;
|
|
158
|
+
last.value = last.value.replace(/\s*::$/, '');
|
|
159
|
+
if (!last.value) children.pop();
|
|
160
|
+
return true;
|
|
210
161
|
}
|
|
211
162
|
|
|
212
|
-
function
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
163
|
+
function pairGradients(parent: MdastNode): void {
|
|
164
|
+
const children = parent.children;
|
|
165
|
+
if (!children) return;
|
|
166
|
+
for (let i = 0; i < children.length; i++) {
|
|
167
|
+
const child = children[i];
|
|
168
|
+
if (
|
|
169
|
+
child.type === 'leafDirective' &&
|
|
170
|
+
(child as DirectiveNode).name === 'gradient'
|
|
171
|
+
) {
|
|
172
|
+
const body: MdastNode[] = [];
|
|
173
|
+
let closed = false;
|
|
174
|
+
for (let j = i + 1; j < children.length; j++) {
|
|
175
|
+
const sib = children[j];
|
|
176
|
+
if (DIRECTIVE_TYPES.includes(sib.type)) break;
|
|
177
|
+
body.push(sib);
|
|
178
|
+
if (stripClose(sib)) {
|
|
179
|
+
closed = true;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (closed) {
|
|
184
|
+
while (
|
|
185
|
+
body.length &&
|
|
186
|
+
body.at(-1)!.type === 'paragraph' &&
|
|
187
|
+
!(body.at(-1)!.children as unknown[])?.length
|
|
188
|
+
)
|
|
189
|
+
body.pop();
|
|
190
|
+
Object.assign(child, {
|
|
191
|
+
type: 'mdxJsxFlowElement',
|
|
192
|
+
name: 'Gradient',
|
|
193
|
+
attributes: toJsxAttributes(child as DirectiveNode),
|
|
194
|
+
children: body,
|
|
195
|
+
});
|
|
196
|
+
children.splice(i + 1, body.length);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
pairGradients(child);
|
|
248
200
|
}
|
|
249
|
-
if (hasFlag(node, 'fade')) style.push(['borderImage', `${gradient} 1`]);
|
|
250
|
-
return style;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function attrObject(node: DirectiveNode) {
|
|
254
|
-
return {
|
|
255
|
-
from: attr(node, 'from'),
|
|
256
|
-
to: attr(node, 'to'),
|
|
257
|
-
dir: attr(node, 'dir'),
|
|
258
|
-
image: attr(node, 'image'),
|
|
259
|
-
};
|
|
260
201
|
}
|
|
261
202
|
|