radiant-docs 0.1.16 → 0.1.20
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "radiant-docs",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
4
4
|
"description": "CLI tool for previewing Radiant documentation locally",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"bundle-template": "node scripts/bundle-template.js",
|
|
11
11
|
"build": "tsup src/index.ts --format esm --clean && npm run bundle-template",
|
|
12
12
|
"dev": "tsup src/index.ts --format esm --watch",
|
|
13
|
-
"prepublishOnly": "npm run build
|
|
14
|
-
"
|
|
13
|
+
"prepublishOnly": "npm run build",
|
|
14
|
+
"release": "npm version patch && npm publish"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"chokidar": "^4.0.3",
|
|
@@ -340,61 +340,60 @@ const renderedCodeLinesHtml = normalizedTokenLines
|
|
|
340
340
|
</div>
|
|
341
341
|
</div>
|
|
342
342
|
</div>
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
const script = document.currentScript;
|
|
348
|
-
if (!(script instanceof HTMLScriptElement)) return;
|
|
349
|
-
|
|
350
|
-
const root = script.previousElementSibling;
|
|
351
|
-
if (!(root instanceof HTMLElement)) return;
|
|
352
|
-
|
|
353
|
-
const copyButtons = root.querySelectorAll("[data-rd-copy-trigger='true']");
|
|
354
|
-
if (copyButtons.length === 0) return;
|
|
355
|
-
|
|
356
|
-
const setCopiedState = (button, copied) => {
|
|
357
|
-
const copyIcon = button.querySelector("[data-rd-copy-icon]");
|
|
358
|
-
const checkIcon = button.querySelector("[data-rd-copy-check]");
|
|
343
|
+
<script is:inline>
|
|
344
|
+
(() => {
|
|
345
|
+
const script = document.currentScript;
|
|
346
|
+
if (!(script instanceof HTMLScriptElement)) return;
|
|
359
347
|
|
|
360
|
-
|
|
348
|
+
const root = script.closest("[data-rd-code-block-root='true']");
|
|
349
|
+
if (!(root instanceof HTMLElement)) return;
|
|
361
350
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
copyIcon.classList.remove("scale-100", "opacity-100", "rotate-0");
|
|
351
|
+
const copyButtons = root.querySelectorAll("[data-rd-copy-trigger='true']");
|
|
352
|
+
if (copyButtons.length === 0) return;
|
|
365
353
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
copyIcon.classList.remove("scale-50", "opacity-0", "-rotate-6");
|
|
372
|
-
copyIcon.classList.add("scale-100", "opacity-100", "rotate-0");
|
|
354
|
+
const setCopiedState = (button, copied) => {
|
|
355
|
+
const copyIcon = button.querySelector("[data-rd-copy-icon]");
|
|
356
|
+
const checkIcon = button.querySelector("[data-rd-copy-check]");
|
|
373
357
|
|
|
374
|
-
|
|
375
|
-
checkIcon.classList.add("scale-50", "opacity-0", "rotate-6");
|
|
376
|
-
};
|
|
358
|
+
if (!copyIcon || !checkIcon) return;
|
|
377
359
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
const encodedCopyValue =
|
|
382
|
-
button.getAttribute("data-rd-copy-content") ?? "";
|
|
383
|
-
const copyValue = decodeURIComponent(encodedCopyValue);
|
|
360
|
+
if (copied) {
|
|
361
|
+
copyIcon.classList.add("scale-50", "opacity-0", "-rotate-6");
|
|
362
|
+
copyIcon.classList.remove("scale-100", "opacity-100", "rotate-0");
|
|
384
363
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
364
|
+
checkIcon.classList.remove("scale-50", "opacity-0", "rotate-6");
|
|
365
|
+
checkIcon.classList.add("scale-110", "opacity-100", "rotate-0");
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
388
368
|
|
|
389
|
-
|
|
390
|
-
|
|
369
|
+
copyIcon.classList.remove("scale-50", "opacity-0", "-rotate-6");
|
|
370
|
+
copyIcon.classList.add("scale-100", "opacity-100", "rotate-0");
|
|
371
|
+
|
|
372
|
+
checkIcon.classList.remove("scale-110", "opacity-100", "rotate-0");
|
|
373
|
+
checkIcon.classList.add("scale-50", "opacity-0", "rotate-6");
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
copyButtons.forEach((button) => {
|
|
377
|
+
let timeoutId = null;
|
|
378
|
+
button.addEventListener("click", async () => {
|
|
379
|
+
const encodedCopyValue =
|
|
380
|
+
button.getAttribute("data-rd-copy-content") ?? "";
|
|
381
|
+
const copyValue = decodeURIComponent(encodedCopyValue);
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
await navigator.clipboard.writeText(copyValue);
|
|
385
|
+
setCopiedState(button, true);
|
|
386
|
+
|
|
387
|
+
if (timeoutId) window.clearTimeout(timeoutId);
|
|
388
|
+
timeoutId = window.setTimeout(() => {
|
|
389
|
+
setCopiedState(button, false);
|
|
390
|
+
timeoutId = null;
|
|
391
|
+
}, 1200);
|
|
392
|
+
} catch {
|
|
391
393
|
setCopiedState(button, false);
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
} catch {
|
|
395
|
-
setCopiedState(button, false);
|
|
396
|
-
}
|
|
394
|
+
}
|
|
395
|
+
});
|
|
397
396
|
});
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
</
|
|
397
|
+
})();
|
|
398
|
+
</script>
|
|
399
|
+
</div>
|
|
@@ -100,19 +100,53 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
|
|
|
100
100
|
</div>
|
|
101
101
|
|
|
102
102
|
<style>
|
|
103
|
-
.rd-component-preview :global(
|
|
103
|
+
.rd-component-preview :global([data-rd-preview-heading="true"]) {
|
|
104
|
+
color: var(--tw-prose-headings, currentColor);
|
|
105
|
+
font-weight: 600;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.rd-component-preview :global([data-rd-preview-heading-level="2"]) {
|
|
109
|
+
font-size: 1.5em;
|
|
110
|
+
line-height: 1.3333333;
|
|
111
|
+
margin-top: 2em;
|
|
112
|
+
margin-bottom: 1em;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.rd-component-preview :global([data-rd-preview-heading-level="3"]) {
|
|
116
|
+
font-size: 1.25em;
|
|
117
|
+
line-height: 1.6;
|
|
118
|
+
margin-top: 1.6em;
|
|
119
|
+
margin-bottom: 0.6em;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.rd-component-preview :global([data-rd-preview-heading-level="4"]) {
|
|
123
|
+
font-size: 1em;
|
|
124
|
+
line-height: 1.5;
|
|
125
|
+
margin-top: 1.5em;
|
|
126
|
+
margin-bottom: 0.5em;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.rd-component-preview :global([data-rd-preview-heading-level="5"]),
|
|
130
|
+
.rd-component-preview :global([data-rd-preview-heading-level="6"]) {
|
|
131
|
+
font-size: 0.875em;
|
|
132
|
+
line-height: 1.5714286;
|
|
133
|
+
margin-top: 1.4285714em;
|
|
134
|
+
margin-bottom: 0.5714286em;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.rd-component-preview__code :global(.group\/prose-code) {
|
|
104
138
|
margin-top: 0 !important;
|
|
105
139
|
margin-bottom: 0 !important;
|
|
106
140
|
}
|
|
107
141
|
|
|
108
|
-
.rd-component-
|
|
142
|
+
.rd-component-preview__code :global(.group\/prose-code > div) {
|
|
109
143
|
background-color: var(--color-neutral-50) !important;
|
|
110
144
|
border-top-left-radius: 0 !important;
|
|
111
145
|
border-top-right-radius: 0 !important;
|
|
112
146
|
}
|
|
113
147
|
|
|
114
|
-
.rd-component-
|
|
115
|
-
.rd-component-
|
|
148
|
+
.rd-component-preview__code :global(.group\/prose-code pre),
|
|
149
|
+
.rd-component-preview__code :global(.group\/prose-code code) {
|
|
116
150
|
background-color: var(--color-neutral-50) !important;
|
|
117
151
|
}
|
|
118
152
|
|
|
@@ -56,6 +56,17 @@ type MdxJsxTextElementNode = {
|
|
|
56
56
|
children?: unknown[];
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
+
type HeadingNode = {
|
|
60
|
+
type: "heading";
|
|
61
|
+
depth?: number;
|
|
62
|
+
children?: unknown[];
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
type NodeWithChildren = {
|
|
66
|
+
type?: string;
|
|
67
|
+
children?: unknown[];
|
|
68
|
+
};
|
|
69
|
+
|
|
59
70
|
const COMPONENT_PREVIEW_NAME = "ComponentPreview";
|
|
60
71
|
const COMPONENT_PREVIEW_BLOCK_NAME = "ComponentPreviewBlock";
|
|
61
72
|
const COMPONENT_PREVIEW_LANGUAGES = new Set(["jsx", "tsx", "mdx"]);
|
|
@@ -192,44 +203,83 @@ function readBooleanAttribute(
|
|
|
192
203
|
return parseBooleanAttributeValue(attribute.value);
|
|
193
204
|
}
|
|
194
205
|
|
|
195
|
-
function
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
206
|
+
function normalizePreviewHeadingDepth(depth: number | undefined): number {
|
|
207
|
+
if (depth === 1) return 2;
|
|
208
|
+
if (depth === 2 || depth === 3 || depth === 4 || depth === 5 || depth === 6) {
|
|
209
|
+
return depth;
|
|
210
|
+
}
|
|
211
|
+
return 2;
|
|
212
|
+
}
|
|
200
213
|
|
|
201
|
-
|
|
214
|
+
function transformPreviewChildren(children: unknown[] | undefined): unknown[] {
|
|
215
|
+
if (!Array.isArray(children)) return [];
|
|
216
|
+
return children.map((child) => transformPreviewNode(child));
|
|
217
|
+
}
|
|
202
218
|
|
|
219
|
+
function transformPreviewNode(node: unknown): unknown {
|
|
203
220
|
// Promote a single inline MDX JSX node into flow-level JSX so the preview
|
|
204
221
|
// renders block components (e.g. <Callout />) as expected.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
222
|
+
const headingNode = node as HeadingNode;
|
|
223
|
+
if (headingNode.type === "heading") {
|
|
224
|
+
const depth = normalizePreviewHeadingDepth(headingNode.depth);
|
|
225
|
+
return {
|
|
226
|
+
type: "mdxJsxFlowElement",
|
|
227
|
+
name: "div",
|
|
228
|
+
attributes: [
|
|
229
|
+
createAttribute("data-rd-preview-heading", "true"),
|
|
230
|
+
createAttribute("data-rd-preview-heading-level", String(depth)),
|
|
231
|
+
createAttribute("role", "heading"),
|
|
232
|
+
createAttribute("aria-level", String(depth)),
|
|
233
|
+
],
|
|
234
|
+
children: transformPreviewChildren(headingNode.children),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
214
237
|
|
|
238
|
+
const paragraphNode = node as ParagraphNode;
|
|
239
|
+
if (
|
|
240
|
+
paragraphNode.type === "paragraph" &&
|
|
241
|
+
Array.isArray(paragraphNode.children) &&
|
|
242
|
+
paragraphNode.children.length === 1
|
|
243
|
+
) {
|
|
215
244
|
const onlyChild = paragraphNode.children[0] as MdxJsxTextElementNode;
|
|
216
245
|
if (
|
|
217
|
-
onlyChild.type
|
|
218
|
-
typeof onlyChild.name
|
|
219
|
-
onlyChild.name.trim().length
|
|
246
|
+
onlyChild.type === "mdxJsxTextElement" &&
|
|
247
|
+
typeof onlyChild.name === "string" &&
|
|
248
|
+
onlyChild.name.trim().length > 0
|
|
220
249
|
) {
|
|
221
|
-
return
|
|
250
|
+
return {
|
|
251
|
+
type: "mdxJsxFlowElement",
|
|
252
|
+
name: onlyChild.name,
|
|
253
|
+
attributes: Array.isArray(onlyChild.attributes)
|
|
254
|
+
? onlyChild.attributes
|
|
255
|
+
: [],
|
|
256
|
+
children: transformPreviewChildren(onlyChild.children),
|
|
257
|
+
};
|
|
222
258
|
}
|
|
259
|
+
}
|
|
223
260
|
|
|
261
|
+
const nodeWithChildren = node as NodeWithChildren;
|
|
262
|
+
if (Array.isArray(nodeWithChildren.children)) {
|
|
224
263
|
return {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
attributes: Array.isArray(onlyChild.attributes)
|
|
228
|
-
? onlyChild.attributes
|
|
229
|
-
: [],
|
|
230
|
-
children: Array.isArray(onlyChild.children) ? onlyChild.children : [],
|
|
264
|
+
...nodeWithChildren,
|
|
265
|
+
children: transformPreviewChildren(nodeWithChildren.children),
|
|
231
266
|
};
|
|
232
|
-
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return node;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function parseComponentPreviewChildren(rawCode: string): unknown[] {
|
|
273
|
+
const parsedTree = fromMarkdown(rawCode, {
|
|
274
|
+
extensions: [gfm(), mdxjs()],
|
|
275
|
+
mdastExtensions: [gfmFromMarkdown(), mdxFromMarkdown()],
|
|
276
|
+
}) as Root;
|
|
277
|
+
|
|
278
|
+
transformCodeBlockNodes(parsedTree);
|
|
279
|
+
|
|
280
|
+
return transformPreviewChildren(
|
|
281
|
+
Array.isArray(parsedTree.children) ? parsedTree.children : [],
|
|
282
|
+
);
|
|
233
283
|
}
|
|
234
284
|
|
|
235
285
|
function getNearestMdxJsxFlowElementName(
|
|
@@ -274,135 +324,139 @@ function buildDefaultCodeGroupFileName(
|
|
|
274
324
|
return `file-name-${codeIndexInGroup + 1}.${extension}`;
|
|
275
325
|
}
|
|
276
326
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
327
|
+
function transformCodeBlockNodes(tree: Root): void {
|
|
328
|
+
visitParents(tree, "code", (node, ancestors) => {
|
|
329
|
+
const codeNode = node as CodeNode;
|
|
330
|
+
const parent = ancestors[ancestors.length - 1] as ParentNode | undefined;
|
|
331
|
+
const siblings = parent?.children;
|
|
332
|
+
if (!siblings) return;
|
|
333
|
+
|
|
334
|
+
const currentIndex = siblings.indexOf(node);
|
|
335
|
+
if (currentIndex < 0) return;
|
|
336
|
+
|
|
337
|
+
const nearestMdxFlowElementName = getNearestMdxJsxFlowElementName(
|
|
338
|
+
ancestors,
|
|
339
|
+
);
|
|
340
|
+
const isInsideCodeGroup = nearestMdxFlowElementName === "CodeGroup";
|
|
341
|
+
const isInsideComponentPreview =
|
|
342
|
+
nearestMdxFlowElementName === COMPONENT_PREVIEW_NAME;
|
|
343
|
+
const componentPreviewNode = isInsideComponentPreview
|
|
344
|
+
? getNearestMdxJsxFlowElement(ancestors, COMPONENT_PREVIEW_NAME)
|
|
345
|
+
: null;
|
|
346
|
+
const isInsideInlineMdx = isInsideMdxJsxTextElement(ancestors);
|
|
347
|
+
if (isInsideInlineMdx) return;
|
|
348
|
+
|
|
349
|
+
const meta = readMetaString(codeNode.meta);
|
|
350
|
+
const parsedMeta = parseParsedCodeMeta(meta);
|
|
351
|
+
const language =
|
|
352
|
+
typeof codeNode.lang === "string" && codeNode.lang.trim().length > 0
|
|
353
|
+
? codeNode.lang.trim()
|
|
354
|
+
: "plaintext";
|
|
355
|
+
const normalizedLanguage = language.trim().toLowerCase();
|
|
356
|
+
const rawCode = typeof codeNode.value === "string" ? codeNode.value : "";
|
|
357
|
+
const codeIndexInGroup = isInsideCodeGroup
|
|
358
|
+
? siblings
|
|
359
|
+
.slice(0, currentIndex)
|
|
360
|
+
.filter(
|
|
361
|
+
(sibling) => (sibling as { type?: string }).type === "code",
|
|
362
|
+
).length
|
|
363
|
+
: 0;
|
|
364
|
+
const fileName =
|
|
365
|
+
parsedMeta.filename.length > 0
|
|
366
|
+
? parsedMeta.filename
|
|
367
|
+
: isInsideCodeGroup
|
|
368
|
+
? buildDefaultCodeGroupFileName(language, codeIndexInGroup)
|
|
369
|
+
: "";
|
|
370
|
+
const showFilename = isInsideCodeGroup || fileName.length > 0;
|
|
371
|
+
|
|
372
|
+
const attributes: MdxJsxAttributeNode[] = [
|
|
373
|
+
createAttribute("language", language),
|
|
374
|
+
createAttribute("raw", rawCode),
|
|
375
|
+
createAttribute("showFilename", showFilename ? "true" : "false"),
|
|
376
|
+
createAttribute(
|
|
377
|
+
"showLineNumbers",
|
|
378
|
+
parsedMeta.showLineNumbers ? "true" : "false",
|
|
379
|
+
),
|
|
380
|
+
];
|
|
381
|
+
|
|
382
|
+
if (parsedMeta.hideLanguageIcon) {
|
|
383
|
+
attributes.push(createAttribute("hideLanguageIcon", "true"));
|
|
384
|
+
}
|
|
284
385
|
|
|
285
|
-
|
|
286
|
-
|
|
386
|
+
if (showFilename) {
|
|
387
|
+
attributes.push(createAttribute("filename", fileName));
|
|
388
|
+
}
|
|
287
389
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const isInsideCodeGroup = nearestMdxFlowElementName === "CodeGroup";
|
|
292
|
-
const isInsideComponentPreview =
|
|
293
|
-
nearestMdxFlowElementName === COMPONENT_PREVIEW_NAME;
|
|
294
|
-
const componentPreviewNode = isInsideComponentPreview
|
|
295
|
-
? getNearestMdxJsxFlowElement(ancestors, COMPONENT_PREVIEW_NAME)
|
|
296
|
-
: null;
|
|
297
|
-
const isInsideInlineMdx = isInsideMdxJsxTextElement(ancestors);
|
|
298
|
-
if (isInsideInlineMdx) return;
|
|
299
|
-
|
|
300
|
-
const meta = readMetaString(codeNode.meta);
|
|
301
|
-
const parsedMeta = parseParsedCodeMeta(meta);
|
|
302
|
-
const language =
|
|
303
|
-
typeof codeNode.lang === "string" && codeNode.lang.trim().length > 0
|
|
304
|
-
? codeNode.lang.trim()
|
|
305
|
-
: "plaintext";
|
|
306
|
-
const normalizedLanguage = language.trim().toLowerCase();
|
|
307
|
-
const rawCode = typeof codeNode.value === "string" ? codeNode.value : "";
|
|
308
|
-
const codeIndexInGroup = isInsideCodeGroup
|
|
309
|
-
? siblings
|
|
310
|
-
.slice(0, currentIndex)
|
|
311
|
-
.filter(
|
|
312
|
-
(sibling) => (sibling as { type?: string }).type === "code",
|
|
313
|
-
).length
|
|
314
|
-
: 0;
|
|
315
|
-
const fileName =
|
|
316
|
-
parsedMeta.filename.length > 0
|
|
317
|
-
? parsedMeta.filename
|
|
318
|
-
: isInsideCodeGroup
|
|
319
|
-
? buildDefaultCodeGroupFileName(language, codeIndexInGroup)
|
|
320
|
-
: "";
|
|
321
|
-
const showFilename = isInsideCodeGroup || fileName.length > 0;
|
|
322
|
-
|
|
323
|
-
const attributes: MdxJsxAttributeNode[] = [
|
|
324
|
-
createAttribute("language", language),
|
|
325
|
-
createAttribute("raw", rawCode),
|
|
326
|
-
createAttribute("showFilename", showFilename ? "true" : "false"),
|
|
327
|
-
createAttribute(
|
|
328
|
-
"showLineNumbers",
|
|
329
|
-
parsedMeta.showLineNumbers ? "true" : "false",
|
|
330
|
-
),
|
|
331
|
-
];
|
|
332
|
-
|
|
333
|
-
if (parsedMeta.hideLanguageIcon) {
|
|
334
|
-
attributes.push(createAttribute("hideLanguageIcon", "true"));
|
|
335
|
-
}
|
|
390
|
+
if (isInsideCodeGroup) {
|
|
391
|
+
attributes.push(createAttribute("inCodeGroup", "true"));
|
|
392
|
+
}
|
|
336
393
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
394
|
+
if (parsedMeta.highlightedLines.length > 0) {
|
|
395
|
+
attributes.push(
|
|
396
|
+
createAttribute("highlightedLines", parsedMeta.highlightedLines),
|
|
397
|
+
);
|
|
398
|
+
}
|
|
340
399
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
400
|
+
if (parsedMeta.collapsedLines.length > 0) {
|
|
401
|
+
attributes.push(
|
|
402
|
+
createAttribute("collapsedLines", parsedMeta.collapsedLines),
|
|
403
|
+
);
|
|
404
|
+
}
|
|
344
405
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
406
|
+
if (isInsideComponentPreview) {
|
|
407
|
+
if (!COMPONENT_PREVIEW_LANGUAGES.has(normalizedLanguage)) {
|
|
408
|
+
throw new Error(
|
|
409
|
+
`[USER_ERROR]: <${COMPONENT_PREVIEW_NAME}>: Fenced code blocks must use jsx, tsx, or mdx language (received "${language}")`,
|
|
348
410
|
);
|
|
349
411
|
}
|
|
350
412
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
413
|
+
let previewChildren: unknown[] = [];
|
|
414
|
+
try {
|
|
415
|
+
previewChildren = parseComponentPreviewChildren(rawCode);
|
|
416
|
+
} catch (error) {
|
|
417
|
+
const reason =
|
|
418
|
+
error instanceof Error && error.message.trim().length > 0
|
|
419
|
+
? ` -> ${error.message}`
|
|
420
|
+
: "";
|
|
421
|
+
throw new Error(
|
|
422
|
+
`[USER_ERROR]: <${COMPONENT_PREVIEW_NAME}>: Failed to parse fenced code block as MDX content${reason}`,
|
|
354
423
|
);
|
|
355
424
|
}
|
|
356
425
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
previewChildren = parseComponentPreviewChildren(rawCode);
|
|
367
|
-
} catch (error) {
|
|
368
|
-
const reason =
|
|
369
|
-
error instanceof Error && error.message.trim().length > 0
|
|
370
|
-
? ` -> ${error.message}`
|
|
371
|
-
: "";
|
|
372
|
-
throw new Error(
|
|
373
|
-
`[USER_ERROR]: <${COMPONENT_PREVIEW_NAME}>: Failed to parse fenced code block as MDX content${reason}`,
|
|
374
|
-
);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
const previewAttributes = attributes.filter(
|
|
378
|
-
(attribute) => attribute.name !== "inCodeGroup",
|
|
379
|
-
);
|
|
380
|
-
const showAllCode = readBooleanAttribute(
|
|
381
|
-
componentPreviewNode?.attributes,
|
|
382
|
-
"showAllCode",
|
|
383
|
-
);
|
|
384
|
-
if (showAllCode) {
|
|
385
|
-
previewAttributes.push(createAttribute("showAllCode", "true"));
|
|
386
|
-
}
|
|
387
|
-
const previewNode: MdxJsxFlowElementNode = {
|
|
388
|
-
type: "mdxJsxFlowElement",
|
|
389
|
-
name: COMPONENT_PREVIEW_BLOCK_NAME,
|
|
390
|
-
attributes: previewAttributes,
|
|
391
|
-
children: previewChildren,
|
|
392
|
-
};
|
|
393
|
-
siblings[currentIndex] = previewNode;
|
|
394
|
-
return;
|
|
426
|
+
const previewAttributes = attributes.filter(
|
|
427
|
+
(attribute) => attribute.name !== "inCodeGroup",
|
|
428
|
+
);
|
|
429
|
+
const showAllCode = readBooleanAttribute(
|
|
430
|
+
componentPreviewNode?.attributes,
|
|
431
|
+
"showAllCode",
|
|
432
|
+
);
|
|
433
|
+
if (showAllCode) {
|
|
434
|
+
previewAttributes.push(createAttribute("showAllCode", "true"));
|
|
395
435
|
}
|
|
396
|
-
|
|
397
|
-
const replacementNode: MdxJsxFlowElementNode = {
|
|
436
|
+
const previewNode: MdxJsxFlowElementNode = {
|
|
398
437
|
type: "mdxJsxFlowElement",
|
|
399
|
-
name:
|
|
400
|
-
attributes,
|
|
401
|
-
children:
|
|
438
|
+
name: COMPONENT_PREVIEW_BLOCK_NAME,
|
|
439
|
+
attributes: previewAttributes,
|
|
440
|
+
children: previewChildren,
|
|
402
441
|
};
|
|
442
|
+
siblings[currentIndex] = previewNode;
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
403
445
|
|
|
404
|
-
|
|
405
|
-
|
|
446
|
+
const replacementNode: MdxJsxFlowElementNode = {
|
|
447
|
+
type: "mdxJsxFlowElement",
|
|
448
|
+
name: INTERNAL_CODE_BLOCK_NAME,
|
|
449
|
+
attributes,
|
|
450
|
+
children: [],
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
siblings[currentIndex] = replacementNode;
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export const remarkCodeBlockComponent: Plugin<[], Root> = () => {
|
|
458
|
+
return (tree) => {
|
|
459
|
+
transformCodeBlockNodes(tree);
|
|
406
460
|
};
|
|
407
461
|
};
|
|
408
462
|
|
|
@@ -145,6 +145,15 @@
|
|
|
145
145
|
@apply px-1 py-px bg-neutral-100/90 text-neutral-600 rounded-md font-mono font-medium border border-neutral-200/80 after:hidden before:hidden;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
/* Keep nested blockquote content flush with the quote container edges */
|
|
149
|
+
:is(.prose, .prose-rules) blockquote > :first-child {
|
|
150
|
+
margin-top: 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
:is(.prose, .prose-rules) blockquote > :last-child {
|
|
154
|
+
margin-bottom: 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
148
157
|
/* <ol> numbers */
|
|
149
158
|
.prose :where(ol > li)::marker {
|
|
150
159
|
@apply font-medium;
|