ardo 2.0.0 → 2.1.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.
- package/dist/{Features-C_06EvGb.d.ts → Features-DEndhnwl.d.ts} +10 -4
- package/dist/{chunk-OTUACKCQ.js → chunk-4IRLOOXV.js} +20 -9
- package/dist/chunk-4IRLOOXV.js.map +1 -0
- package/dist/{chunk-N5CEHG2F.js → chunk-CGFRUWNJ.js} +2 -1
- package/dist/chunk-CGFRUWNJ.js.map +1 -0
- package/dist/{chunk-UWAVET45.js → chunk-LSNTX2BA.js} +8 -6
- package/dist/chunk-LSNTX2BA.js.map +1 -0
- package/dist/{chunk-G5L4ZUTS.js → chunk-O64PX2AK.js} +2 -2
- package/dist/{chunk-ZXPAEM3M.js → chunk-QC2JA663.js} +14 -6
- package/dist/{chunk-ZXPAEM3M.js.map → chunk-QC2JA663.js.map} +1 -1
- package/dist/{chunk-LUOUBO3L.js → chunk-SWER4H2H.js} +540 -394
- package/dist/chunk-SWER4H2H.js.map +1 -0
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +6 -6
- package/dist/mdx/provider.js +14 -6
- package/dist/mdx/provider.js.map +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/typedoc/index.d.ts +6 -0
- package/dist/typedoc/index.js +2 -2
- package/dist/{types-DchPWkJl.d.ts → types-tjxB5eh7.d.ts} +22 -2
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.js +2 -2
- package/dist/ui/styles.css +232 -66
- package/dist/vite/index.d.ts +1 -1
- package/dist/vite/index.js +3 -3
- package/package.json +9 -9
- package/dist/chunk-LUOUBO3L.js.map +0 -1
- package/dist/chunk-N5CEHG2F.js.map +0 -1
- package/dist/chunk-OTUACKCQ.js.map +0 -1
- package/dist/chunk-UWAVET45.js.map +0 -1
- /package/dist/{chunk-G5L4ZUTS.js.map → chunk-O64PX2AK.js.map} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveConfig
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-CGFRUWNJ.js";
|
|
4
4
|
import {
|
|
5
5
|
generateApiDocs
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4IRLOOXV.js";
|
|
7
7
|
|
|
8
8
|
// src/vite/plugin.ts
|
|
9
9
|
import { reactRouter } from "@react-router/dev/vite";
|
|
@@ -13,10 +13,406 @@ import remarkMdxFrontmatter from "remark-mdx-frontmatter";
|
|
|
13
13
|
import remarkGfm from "remark-gfm";
|
|
14
14
|
import remarkDirective from "remark-directive";
|
|
15
15
|
import rehypeShiki from "@shikijs/rehype";
|
|
16
|
+
|
|
17
|
+
// src/markdown/shiki.ts
|
|
18
|
+
import {
|
|
19
|
+
createHighlighter
|
|
20
|
+
} from "shiki";
|
|
21
|
+
import { visit } from "unist-util-visit";
|
|
22
|
+
async function createShikiHighlighter(config) {
|
|
23
|
+
const themeConfig = config.theme ?? {
|
|
24
|
+
light: "github-light",
|
|
25
|
+
dark: "github-dark"
|
|
26
|
+
};
|
|
27
|
+
const themes = typeof themeConfig === "string" ? [themeConfig] : [themeConfig.light, themeConfig.dark];
|
|
28
|
+
const highlighter = await createHighlighter({
|
|
29
|
+
themes,
|
|
30
|
+
langs: [
|
|
31
|
+
"javascript",
|
|
32
|
+
"typescript",
|
|
33
|
+
"jsx",
|
|
34
|
+
"tsx",
|
|
35
|
+
"json",
|
|
36
|
+
"html",
|
|
37
|
+
"css",
|
|
38
|
+
"markdown",
|
|
39
|
+
"bash",
|
|
40
|
+
"shell",
|
|
41
|
+
"yaml",
|
|
42
|
+
"python",
|
|
43
|
+
"rust",
|
|
44
|
+
"go",
|
|
45
|
+
"sql",
|
|
46
|
+
"diff"
|
|
47
|
+
]
|
|
48
|
+
});
|
|
49
|
+
return highlighter;
|
|
50
|
+
}
|
|
51
|
+
function rehypeShikiFromHighlighter(options) {
|
|
52
|
+
const { highlighter, config } = options;
|
|
53
|
+
const themeConfig = config.theme ?? {
|
|
54
|
+
light: "github-light",
|
|
55
|
+
dark: "github-dark"
|
|
56
|
+
};
|
|
57
|
+
return function(tree) {
|
|
58
|
+
visit(tree, "element", (node, index, parent) => {
|
|
59
|
+
if (node.tagName !== "pre" || !node.children[0] || node.children[0].tagName !== "code") {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const codeNode = node.children[0];
|
|
63
|
+
const className = codeNode.properties?.className || [];
|
|
64
|
+
const langClass = className.find((c) => c.startsWith("language-"));
|
|
65
|
+
const lang = langClass ? langClass.replace("language-", "") : "text";
|
|
66
|
+
const codeContent = getTextContent(codeNode);
|
|
67
|
+
if (!codeContent.trim()) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
let html;
|
|
72
|
+
if (typeof themeConfig === "string") {
|
|
73
|
+
html = highlighter.codeToHtml(codeContent, {
|
|
74
|
+
lang,
|
|
75
|
+
theme: themeConfig
|
|
76
|
+
});
|
|
77
|
+
} else {
|
|
78
|
+
html = highlighter.codeToHtml(codeContent, {
|
|
79
|
+
lang,
|
|
80
|
+
themes: {
|
|
81
|
+
light: themeConfig.light,
|
|
82
|
+
dark: themeConfig.dark
|
|
83
|
+
},
|
|
84
|
+
defaultColor: false
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const metaString = codeNode.properties?.metastring || "";
|
|
88
|
+
const lineNumbers = config.lineNumbers || metaString.includes("showLineNumbers");
|
|
89
|
+
const highlightLines = parseHighlightLines(metaString);
|
|
90
|
+
const title = parseTitle(metaString);
|
|
91
|
+
const wrapperHtml = buildCodeBlockHtml(html, {
|
|
92
|
+
lang,
|
|
93
|
+
lineNumbers,
|
|
94
|
+
highlightLines,
|
|
95
|
+
title
|
|
96
|
+
});
|
|
97
|
+
if (parent && typeof index === "number") {
|
|
98
|
+
const newNode = {
|
|
99
|
+
type: "element",
|
|
100
|
+
tagName: "div",
|
|
101
|
+
properties: {
|
|
102
|
+
className: ["ardo-code-block"],
|
|
103
|
+
"data-lang": lang
|
|
104
|
+
},
|
|
105
|
+
children: [
|
|
106
|
+
{
|
|
107
|
+
type: "raw",
|
|
108
|
+
value: wrapperHtml
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
};
|
|
112
|
+
parent.children[index] = newNode;
|
|
113
|
+
}
|
|
114
|
+
} catch {
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function getTextContent(node) {
|
|
120
|
+
if (node.type === "text") {
|
|
121
|
+
return node.value;
|
|
122
|
+
}
|
|
123
|
+
if ("children" in node) {
|
|
124
|
+
return node.children.map((child) => getTextContent(child)).join("");
|
|
125
|
+
}
|
|
126
|
+
return "";
|
|
127
|
+
}
|
|
128
|
+
function parseHighlightLines(meta) {
|
|
129
|
+
const match = meta.match(/\{([\d,-]+)\}/);
|
|
130
|
+
if (!match) return [];
|
|
131
|
+
const ranges = match[1].split(",");
|
|
132
|
+
const lines = [];
|
|
133
|
+
for (const range of ranges) {
|
|
134
|
+
if (range.includes("-")) {
|
|
135
|
+
const [start, end] = range.split("-").map(Number);
|
|
136
|
+
for (let i = start; i <= end; i++) {
|
|
137
|
+
lines.push(i);
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
lines.push(Number(range));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return lines;
|
|
144
|
+
}
|
|
145
|
+
function parseTitle(meta) {
|
|
146
|
+
const match = meta.match(/title="([^"]+)"/);
|
|
147
|
+
return match ? match[1] : void 0;
|
|
148
|
+
}
|
|
149
|
+
function buildCodeBlockHtml(shikiHtml, options) {
|
|
150
|
+
const { lang, lineNumbers, highlightLines, title } = options;
|
|
151
|
+
let html = "";
|
|
152
|
+
if (title) {
|
|
153
|
+
html += `<div class="ardo-code-title">${escapeHtml(title)}</div>`;
|
|
154
|
+
}
|
|
155
|
+
html += `<div class="ardo-code-wrapper" data-lang="${lang}">`;
|
|
156
|
+
if (lineNumbers || highlightLines.length > 0) {
|
|
157
|
+
const lines = shikiHtml.split("\n");
|
|
158
|
+
const processedHtml = lines.map((line, i) => {
|
|
159
|
+
const lineNum = i + 1;
|
|
160
|
+
const isHighlighted = highlightLines.includes(lineNum);
|
|
161
|
+
const classes = ["ardo-code-line"];
|
|
162
|
+
if (isHighlighted) classes.push("highlighted");
|
|
163
|
+
let prefix = "";
|
|
164
|
+
if (lineNumbers) {
|
|
165
|
+
prefix = `<span class="ardo-line-number">${lineNum}</span>`;
|
|
166
|
+
}
|
|
167
|
+
return `<span class="${classes.join(" ")}">${prefix}${line}</span>`;
|
|
168
|
+
}).join("\n");
|
|
169
|
+
html += processedHtml;
|
|
170
|
+
} else {
|
|
171
|
+
html += shikiHtml;
|
|
172
|
+
}
|
|
173
|
+
html += `<button class="ardo-copy-button" data-code="${encodeURIComponent(extractCodeFromHtml(shikiHtml))}">
|
|
174
|
+
<span class="ardo-copy-icon">Copy</span>
|
|
175
|
+
<span class="ardo-copied-icon" style="display:none">Copied!</span>
|
|
176
|
+
</button>`;
|
|
177
|
+
html += "</div>";
|
|
178
|
+
return html;
|
|
179
|
+
}
|
|
180
|
+
function extractCodeFromHtml(html) {
|
|
181
|
+
return html.replace(/<[^>]+>/g, "").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&").replace(/"/g, '"').replace(/'/g, "'");
|
|
182
|
+
}
|
|
183
|
+
function escapeHtml(text) {
|
|
184
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
185
|
+
}
|
|
186
|
+
function remarkCodeMeta() {
|
|
187
|
+
return function(tree) {
|
|
188
|
+
visit(tree, "code", (node) => {
|
|
189
|
+
if (!node.meta) return;
|
|
190
|
+
const meta = node.meta;
|
|
191
|
+
const data = node.data || (node.data = {});
|
|
192
|
+
const hProperties = data.hProperties || {};
|
|
193
|
+
hProperties.metastring = meta;
|
|
194
|
+
data.hProperties = hProperties;
|
|
195
|
+
node.meta = null;
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function ardoLineTransformer(options = {}) {
|
|
200
|
+
let highlightLines = [];
|
|
201
|
+
let showLineNumbers = false;
|
|
202
|
+
let metaRaw = "";
|
|
203
|
+
return {
|
|
204
|
+
name: "ardo:lines",
|
|
205
|
+
// preprocess runs BEFORE line() hooks, so state is ready for line()
|
|
206
|
+
preprocess(_code, shikiOptions) {
|
|
207
|
+
metaRaw = shikiOptions.meta?.__raw || "";
|
|
208
|
+
highlightLines = parseHighlightLines(metaRaw);
|
|
209
|
+
showLineNumbers = options.globalLineNumbers || metaRaw.includes("showLineNumbers");
|
|
210
|
+
},
|
|
211
|
+
// pre runs AFTER line() — used only for node property modifications
|
|
212
|
+
pre(node) {
|
|
213
|
+
node.properties = node.properties || {};
|
|
214
|
+
const title = parseTitle(metaRaw);
|
|
215
|
+
if (title) {
|
|
216
|
+
node.properties["data-title"] = title;
|
|
217
|
+
}
|
|
218
|
+
const labelMatch = metaRaw.match(/\[([^\]]+)\]/);
|
|
219
|
+
if (labelMatch) {
|
|
220
|
+
node.properties["data-label"] = labelMatch[1];
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
line(node, line) {
|
|
224
|
+
const currentClass = node.properties?.class || "";
|
|
225
|
+
const classes = currentClass ? currentClass.split(" ") : [];
|
|
226
|
+
classes.push("ardo-code-line");
|
|
227
|
+
if (highlightLines.includes(line)) {
|
|
228
|
+
classes.push("highlighted");
|
|
229
|
+
}
|
|
230
|
+
node.properties = node.properties || {};
|
|
231
|
+
node.properties.class = classes.join(" ");
|
|
232
|
+
if (showLineNumbers) {
|
|
233
|
+
node.children.unshift({
|
|
234
|
+
type: "element",
|
|
235
|
+
tagName: "span",
|
|
236
|
+
properties: { class: "ardo-line-number" },
|
|
237
|
+
children: [{ type: "text", value: String(line) }]
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// src/markdown/containers.ts
|
|
245
|
+
import { visit as visit2 } from "unist-util-visit";
|
|
246
|
+
var containerTypes = [
|
|
247
|
+
"tip",
|
|
248
|
+
"warning",
|
|
249
|
+
"danger",
|
|
250
|
+
"info",
|
|
251
|
+
"note",
|
|
252
|
+
"details",
|
|
253
|
+
"code-group"
|
|
254
|
+
];
|
|
255
|
+
var defaultTitles = {
|
|
256
|
+
tip: "TIP",
|
|
257
|
+
warning: "WARNING",
|
|
258
|
+
danger: "DANGER",
|
|
259
|
+
info: "INFO",
|
|
260
|
+
note: "NOTE",
|
|
261
|
+
details: "Details",
|
|
262
|
+
"code-group": ""
|
|
263
|
+
};
|
|
264
|
+
function remarkContainers() {
|
|
265
|
+
return function(tree) {
|
|
266
|
+
visit2(tree, "containerDirective", (node) => {
|
|
267
|
+
const type = node.name;
|
|
268
|
+
if (!containerTypes.includes(type)) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const data = node.data || (node.data = {});
|
|
272
|
+
const titleNode = node.children[0];
|
|
273
|
+
let customTitle;
|
|
274
|
+
if (titleNode && titleNode.type === "paragraph" && titleNode.children[0]?.type === "text" && titleNode.data?.directiveLabel) {
|
|
275
|
+
customTitle = titleNode.children[0].value;
|
|
276
|
+
node.children.shift();
|
|
277
|
+
}
|
|
278
|
+
const title = customTitle || defaultTitles[type];
|
|
279
|
+
if (type === "code-group") {
|
|
280
|
+
data.hName = "div";
|
|
281
|
+
data.hProperties = {
|
|
282
|
+
className: ["ardo-code-group"]
|
|
283
|
+
};
|
|
284
|
+
const tabs = [];
|
|
285
|
+
for (const child of node.children) {
|
|
286
|
+
if (child.type === "code") {
|
|
287
|
+
const codeNode = child;
|
|
288
|
+
const meta = codeNode.meta || "";
|
|
289
|
+
const labelMatch = meta.match(/\[([^\]]+)\]/);
|
|
290
|
+
const label = labelMatch ? labelMatch[1] : codeNode.lang || "Code";
|
|
291
|
+
tabs.push({ label, content: child });
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const tabsHtml = tabs.map(
|
|
295
|
+
(tab, i) => `<button class="ardo-code-group-tab${i === 0 ? " active" : ""}" data-index="${i}">${escapeHtml2(tab.label)}</button>`
|
|
296
|
+
).join("");
|
|
297
|
+
node.children = [
|
|
298
|
+
{
|
|
299
|
+
type: "html",
|
|
300
|
+
value: `<div class="ardo-code-group-tabs">${tabsHtml}</div>`
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
type: "html",
|
|
304
|
+
value: '<div class="ardo-code-group-panels">'
|
|
305
|
+
},
|
|
306
|
+
...tabs.map(
|
|
307
|
+
(tab, i) => ({
|
|
308
|
+
type: "html",
|
|
309
|
+
value: `<div class="ardo-code-group-panel${i === 0 ? " active" : ""}" data-index="${i}">`
|
|
310
|
+
})
|
|
311
|
+
),
|
|
312
|
+
...node.children.flatMap((child, _i) => [
|
|
313
|
+
child,
|
|
314
|
+
{
|
|
315
|
+
type: "html",
|
|
316
|
+
value: "</div>"
|
|
317
|
+
}
|
|
318
|
+
]),
|
|
319
|
+
{
|
|
320
|
+
type: "html",
|
|
321
|
+
value: "</div>"
|
|
322
|
+
}
|
|
323
|
+
];
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
if (type === "details") {
|
|
327
|
+
data.hName = "details";
|
|
328
|
+
data.hProperties = {
|
|
329
|
+
className: ["ardo-details"]
|
|
330
|
+
};
|
|
331
|
+
node.children.unshift({
|
|
332
|
+
type: "html",
|
|
333
|
+
value: `<summary class="ardo-details-summary">${escapeHtml2(title)}</summary>`
|
|
334
|
+
});
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
data.hName = "div";
|
|
338
|
+
data.hProperties = {
|
|
339
|
+
className: ["ardo-container", `ardo-container-${type}`]
|
|
340
|
+
};
|
|
341
|
+
node.children.unshift({
|
|
342
|
+
type: "html",
|
|
343
|
+
value: `<p class="ardo-container-title">${escapeHtml2(title)}</p>`
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
function escapeHtml2(text) {
|
|
349
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
350
|
+
}
|
|
351
|
+
var containerToComponent = {
|
|
352
|
+
tip: "Tip",
|
|
353
|
+
warning: "Warning",
|
|
354
|
+
danger: "Danger",
|
|
355
|
+
info: "Info",
|
|
356
|
+
note: "Note"
|
|
357
|
+
};
|
|
358
|
+
function remarkContainersMdx() {
|
|
359
|
+
return function(tree) {
|
|
360
|
+
visit2(tree, "containerDirective", (node, index, parent) => {
|
|
361
|
+
if (!parent || typeof index !== "number") return;
|
|
362
|
+
if (node.name === "code-group") {
|
|
363
|
+
const labels = node.children.filter((child) => child.type === "code").map((child) => {
|
|
364
|
+
const meta = child.meta || "";
|
|
365
|
+
const match = meta.match(/\[([^\]]+)\]/);
|
|
366
|
+
return match ? match[1] : child.lang || "Code";
|
|
367
|
+
});
|
|
368
|
+
const jsxNode2 = {
|
|
369
|
+
type: "mdxJsxFlowElement",
|
|
370
|
+
name: "CodeGroup",
|
|
371
|
+
attributes: [
|
|
372
|
+
{
|
|
373
|
+
type: "mdxJsxAttribute",
|
|
374
|
+
name: "labels",
|
|
375
|
+
value: labels.join(",")
|
|
376
|
+
}
|
|
377
|
+
],
|
|
378
|
+
children: node.children
|
|
379
|
+
};
|
|
380
|
+
parent.children[index] = jsxNode2;
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
const componentName = containerToComponent[node.name];
|
|
384
|
+
if (!componentName) return;
|
|
385
|
+
const titleNode = node.children[0];
|
|
386
|
+
let customTitle;
|
|
387
|
+
if (titleNode && titleNode.type === "paragraph" && titleNode.children[0]?.type === "text" && titleNode.data?.directiveLabel) {
|
|
388
|
+
customTitle = titleNode.children[0].value;
|
|
389
|
+
node.children.shift();
|
|
390
|
+
}
|
|
391
|
+
const attributes = [];
|
|
392
|
+
if (customTitle) {
|
|
393
|
+
attributes.push({
|
|
394
|
+
type: "mdxJsxAttribute",
|
|
395
|
+
name: "title",
|
|
396
|
+
value: customTitle
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
const jsxNode = {
|
|
400
|
+
type: "mdxJsxFlowElement",
|
|
401
|
+
name: componentName,
|
|
402
|
+
attributes,
|
|
403
|
+
children: node.children
|
|
404
|
+
};
|
|
405
|
+
parent.children[index] = jsxNode;
|
|
406
|
+
});
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// src/vite/plugin.ts
|
|
16
411
|
import fs2 from "fs/promises";
|
|
17
412
|
import fsSync2 from "fs";
|
|
18
413
|
import path2 from "path";
|
|
19
414
|
import { execSync } from "child_process";
|
|
415
|
+
import matter from "gray-matter";
|
|
20
416
|
|
|
21
417
|
// src/vite/routes-plugin.ts
|
|
22
418
|
import fs from "fs/promises";
|
|
@@ -182,6 +578,35 @@ function detectGitHubRepoName(cwd) {
|
|
|
182
578
|
return void 0;
|
|
183
579
|
}
|
|
184
580
|
}
|
|
581
|
+
function readProjectMeta(root) {
|
|
582
|
+
const pkgPath = path2.join(root, "package.json");
|
|
583
|
+
try {
|
|
584
|
+
const raw = fsSync2.readFileSync(pkgPath, "utf-8");
|
|
585
|
+
const pkg = JSON.parse(raw);
|
|
586
|
+
let repository;
|
|
587
|
+
if (typeof pkg.repository === "string") {
|
|
588
|
+
repository = pkg.repository;
|
|
589
|
+
} else if (pkg.repository?.url) {
|
|
590
|
+
repository = pkg.repository.url.replace(/^git\+/, "").replace(/^git:\/\//, "https://").replace(/\.git$/, "");
|
|
591
|
+
}
|
|
592
|
+
let author;
|
|
593
|
+
if (typeof pkg.author === "string") {
|
|
594
|
+
author = pkg.author;
|
|
595
|
+
} else if (pkg.author?.name) {
|
|
596
|
+
author = pkg.author.name;
|
|
597
|
+
}
|
|
598
|
+
return {
|
|
599
|
+
name: pkg.name,
|
|
600
|
+
homepage: pkg.homepage,
|
|
601
|
+
repository,
|
|
602
|
+
version: pkg.version,
|
|
603
|
+
author,
|
|
604
|
+
license: pkg.license
|
|
605
|
+
};
|
|
606
|
+
} catch {
|
|
607
|
+
return {};
|
|
608
|
+
}
|
|
609
|
+
}
|
|
185
610
|
var VIRTUAL_MODULE_ID = "virtual:ardo/config";
|
|
186
611
|
var RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
|
|
187
612
|
var VIRTUAL_SIDEBAR_ID = "virtual:ardo/sidebar";
|
|
@@ -225,6 +650,8 @@ function ardoPlugin(options = {}) {
|
|
|
225
650
|
async configResolved(config) {
|
|
226
651
|
const root = config.root;
|
|
227
652
|
routesDir = routesDirOption || path2.join(root, "app", "routes");
|
|
653
|
+
const detectedProject = readProjectMeta(root);
|
|
654
|
+
const project = { ...detectedProject, ...pressConfig.project };
|
|
228
655
|
const defaultConfig = {
|
|
229
656
|
title: pressConfig.title ?? "Ardo",
|
|
230
657
|
description: pressConfig.description ?? "Documentation powered by Ardo"
|
|
@@ -232,6 +659,7 @@ function ardoPlugin(options = {}) {
|
|
|
232
659
|
const configWithRoutes = {
|
|
233
660
|
...defaultConfig,
|
|
234
661
|
...pressConfig,
|
|
662
|
+
project,
|
|
235
663
|
srcDir: routesDir
|
|
236
664
|
};
|
|
237
665
|
resolvedConfig = resolveConfig(configWithRoutes, root);
|
|
@@ -254,7 +682,8 @@ function ardoPlugin(options = {}) {
|
|
|
254
682
|
description: resolvedConfig.description,
|
|
255
683
|
base: resolvedConfig.base,
|
|
256
684
|
lang: resolvedConfig.lang,
|
|
257
|
-
themeConfig: resolvedConfig.themeConfig
|
|
685
|
+
themeConfig: resolvedConfig.themeConfig,
|
|
686
|
+
project: resolvedConfig.project
|
|
258
687
|
};
|
|
259
688
|
return `export default ${JSON.stringify(clientConfig)}`;
|
|
260
689
|
}
|
|
@@ -317,14 +746,17 @@ function ardoPlugin(options = {}) {
|
|
|
317
746
|
}
|
|
318
747
|
const themeConfig = pressConfig.markdown?.theme;
|
|
319
748
|
const hasThemeObject = themeConfig && typeof themeConfig === "object" && "light" in themeConfig;
|
|
749
|
+
const lineNumbers = pressConfig.markdown?.lineNumbers || false;
|
|
320
750
|
const shikiOptions = hasThemeObject ? {
|
|
321
751
|
themes: {
|
|
322
752
|
light: themeConfig.light || "github-light",
|
|
323
753
|
dark: themeConfig.dark || "github-dark"
|
|
324
754
|
},
|
|
325
|
-
defaultColor: false
|
|
755
|
+
defaultColor: false,
|
|
756
|
+
transformers: [ardoLineTransformer({ globalLineNumbers: lineNumbers })]
|
|
326
757
|
} : {
|
|
327
|
-
theme: themeConfig || "github-dark"
|
|
758
|
+
theme: themeConfig || "github-dark",
|
|
759
|
+
transformers: [ardoLineTransformer({ globalLineNumbers: lineNumbers })]
|
|
328
760
|
};
|
|
329
761
|
const mdxPlugin = mdx({
|
|
330
762
|
include: /\.(md|mdx)$/,
|
|
@@ -332,7 +764,9 @@ function ardoPlugin(options = {}) {
|
|
|
332
764
|
remarkFrontmatter,
|
|
333
765
|
[remarkMdxFrontmatter, { name: "frontmatter" }],
|
|
334
766
|
remarkGfm,
|
|
335
|
-
remarkDirective
|
|
767
|
+
remarkDirective,
|
|
768
|
+
remarkContainersMdx,
|
|
769
|
+
remarkCodeMeta
|
|
336
770
|
],
|
|
337
771
|
rehypePlugins: [[rehypeShiki, shikiOptions]],
|
|
338
772
|
providerImportSource: "ardo/mdx-provider"
|
|
@@ -352,251 +786,131 @@ async function generateSidebar(config, routesDir) {
|
|
|
352
786
|
return themeConfig.sidebar;
|
|
353
787
|
}
|
|
354
788
|
try {
|
|
355
|
-
const sidebar = await scanDirectory(routesDir, routesDir
|
|
789
|
+
const sidebar = await scanDirectory(routesDir, routesDir);
|
|
356
790
|
return sidebar;
|
|
357
791
|
} catch {
|
|
358
792
|
return [];
|
|
359
793
|
}
|
|
360
794
|
}
|
|
361
|
-
async function scanDirectory(dir, rootDir
|
|
795
|
+
async function scanDirectory(dir, rootDir) {
|
|
362
796
|
const entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
363
797
|
const items = [];
|
|
364
798
|
for (const entry of entries) {
|
|
365
799
|
const fullPath = path2.join(dir, entry.name);
|
|
366
800
|
const relativePath = path2.relative(rootDir, fullPath);
|
|
367
801
|
if (entry.isDirectory()) {
|
|
368
|
-
const children = await scanDirectory(fullPath, rootDir
|
|
802
|
+
const children = await scanDirectory(fullPath, rootDir);
|
|
369
803
|
if (children.length > 0) {
|
|
370
804
|
const indexPath = path2.join(fullPath, "index.mdx");
|
|
371
805
|
let link;
|
|
372
806
|
try {
|
|
373
|
-
await fs2.access(indexPath);
|
|
374
|
-
link = "/" + relativePath.replace(/\\/g, "/");
|
|
375
|
-
} catch {
|
|
376
|
-
}
|
|
377
|
-
items.push({
|
|
378
|
-
text: formatTitle(entry.name),
|
|
379
|
-
link,
|
|
380
|
-
items: children
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
} else if ((entry.name.endsWith(".mdx") || entry.name.endsWith(".md")) && entry.name !== "index.mdx" && entry.name !== "index.md") {
|
|
384
|
-
const fileContent = await fs2.readFile(fullPath, "utf-8");
|
|
385
|
-
const frontmatterMatch = fileContent.match(/^---\n([\s\S]*?)\n---/);
|
|
386
|
-
const ext = entry.name.endsWith(".mdx") ? ".mdx" : ".md";
|
|
387
|
-
let title = formatTitle(entry.name.replace(ext, ""));
|
|
388
|
-
let order;
|
|
389
|
-
if (frontmatterMatch) {
|
|
390
|
-
const frontmatterText = frontmatterMatch[1];
|
|
391
|
-
const titleMatch = frontmatterText.match(/title:\s*["']?([^"'\n]+)["']?/);
|
|
392
|
-
const orderMatch = frontmatterText.match(/order:\s*(\d+)/);
|
|
393
|
-
if (titleMatch) {
|
|
394
|
-
title = titleMatch[1].trim();
|
|
395
|
-
}
|
|
396
|
-
if (orderMatch) {
|
|
397
|
-
order = parseInt(orderMatch[1], 10);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
const link = "/" + relativePath.replace(ext, "").replace(/\\/g, "/");
|
|
401
|
-
items.push({
|
|
402
|
-
text: title,
|
|
403
|
-
link,
|
|
404
|
-
order
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
items.sort((a, b) => {
|
|
409
|
-
if (a.order !== void 0 && b.order !== void 0) {
|
|
410
|
-
return a.order - b.order;
|
|
411
|
-
}
|
|
412
|
-
if (a.order !== void 0) return -1;
|
|
413
|
-
if (b.order !== void 0) return 1;
|
|
414
|
-
return a.text.localeCompare(b.text);
|
|
415
|
-
});
|
|
416
|
-
return items.map(({ order: _order, ...item }) => item);
|
|
417
|
-
}
|
|
418
|
-
function formatTitle(name) {
|
|
419
|
-
return name.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
420
|
-
}
|
|
421
|
-
async function generateSearchIndex(routesDir) {
|
|
422
|
-
const docs = [];
|
|
423
|
-
async function scanForSearch(dir, section) {
|
|
424
|
-
try {
|
|
425
|
-
const entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
426
|
-
for (const entry of entries) {
|
|
427
|
-
const fullPath = path2.join(dir, entry.name);
|
|
428
|
-
if (entry.isDirectory()) {
|
|
429
|
-
const newSection = section ? `${section} > ${formatTitle(entry.name)}` : formatTitle(entry.name);
|
|
430
|
-
await scanForSearch(fullPath, newSection);
|
|
431
|
-
} else if (entry.name.endsWith(".mdx") || entry.name.endsWith(".md")) {
|
|
432
|
-
const relativePath = path2.relative(routesDir, fullPath);
|
|
433
|
-
const fileContent = await fs2.readFile(fullPath, "utf-8");
|
|
434
|
-
const frontmatterMatch = fileContent.match(/^---\n([\s\S]*?)\n---/);
|
|
435
|
-
const ext = entry.name.endsWith(".mdx") ? ".mdx" : ".md";
|
|
436
|
-
let title = formatTitle(entry.name.replace(ext, ""));
|
|
437
|
-
let content = fileContent;
|
|
438
|
-
if (frontmatterMatch) {
|
|
439
|
-
const frontmatterText = frontmatterMatch[1];
|
|
440
|
-
const titleMatch = frontmatterText.match(/title:\s*["']?([^"'\n]+)["']?/);
|
|
441
|
-
if (titleMatch) {
|
|
442
|
-
title = titleMatch[1].trim();
|
|
443
|
-
}
|
|
444
|
-
content = fileContent.slice(frontmatterMatch[0].length);
|
|
445
|
-
}
|
|
446
|
-
content = content.replace(/```[\s\S]*?```/g, "").replace(/`[^`]+`/g, "").replace(/import\s+.*?from\s+['"].*?['"]/g, "").replace(/<[^>]+>/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/[#*_~>]/g, "").replace(/\n+/g, " ").replace(/\s+/g, " ").trim().slice(0, 2e3);
|
|
447
|
-
const routePath = entry.name === "index.mdx" || entry.name === "index.md" ? "/" + path2.dirname(relativePath).replace(/\\/g, "/") : "/" + relativePath.replace(ext, "").replace(/\\/g, "/");
|
|
448
|
-
const finalPath = routePath === "/." ? "/" : routePath;
|
|
449
|
-
docs.push({
|
|
450
|
-
id: relativePath,
|
|
451
|
-
title,
|
|
452
|
-
content,
|
|
453
|
-
path: finalPath,
|
|
454
|
-
section
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
} catch {
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
await scanForSearch(routesDir);
|
|
462
|
-
return docs;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// src/runtime/loader.ts
|
|
466
|
-
import fs3 from "fs/promises";
|
|
467
|
-
import path3 from "path";
|
|
468
|
-
|
|
469
|
-
// src/markdown/pipeline.ts
|
|
470
|
-
import { unified } from "unified";
|
|
471
|
-
import remarkParse from "remark-parse";
|
|
472
|
-
import remarkGfm2 from "remark-gfm";
|
|
473
|
-
import remarkFrontmatter2 from "remark-frontmatter";
|
|
474
|
-
import remarkDirective2 from "remark-directive";
|
|
475
|
-
import remarkRehype from "remark-rehype";
|
|
476
|
-
import rehypeStringify from "rehype-stringify";
|
|
477
|
-
import matter from "gray-matter";
|
|
478
|
-
|
|
479
|
-
// src/markdown/containers.ts
|
|
480
|
-
import { visit } from "unist-util-visit";
|
|
481
|
-
var containerTypes = [
|
|
482
|
-
"tip",
|
|
483
|
-
"warning",
|
|
484
|
-
"danger",
|
|
485
|
-
"info",
|
|
486
|
-
"note",
|
|
487
|
-
"details",
|
|
488
|
-
"code-group"
|
|
489
|
-
];
|
|
490
|
-
var defaultTitles = {
|
|
491
|
-
tip: "TIP",
|
|
492
|
-
warning: "WARNING",
|
|
493
|
-
danger: "DANGER",
|
|
494
|
-
info: "INFO",
|
|
495
|
-
note: "NOTE",
|
|
496
|
-
details: "Details",
|
|
497
|
-
"code-group": ""
|
|
498
|
-
};
|
|
499
|
-
function remarkContainers() {
|
|
500
|
-
return function(tree) {
|
|
501
|
-
visit(tree, "containerDirective", (node) => {
|
|
502
|
-
const type = node.name;
|
|
503
|
-
if (!containerTypes.includes(type)) {
|
|
504
|
-
return;
|
|
505
|
-
}
|
|
506
|
-
const data = node.data || (node.data = {});
|
|
507
|
-
const titleNode = node.children[0];
|
|
508
|
-
let customTitle;
|
|
509
|
-
if (titleNode && titleNode.type === "paragraph" && titleNode.children[0]?.type === "text" && titleNode.data?.directiveLabel) {
|
|
510
|
-
customTitle = titleNode.children[0].value;
|
|
511
|
-
node.children.shift();
|
|
512
|
-
}
|
|
513
|
-
const title = customTitle || defaultTitles[type];
|
|
514
|
-
if (type === "code-group") {
|
|
515
|
-
data.hName = "div";
|
|
516
|
-
data.hProperties = {
|
|
517
|
-
className: ["ardo-code-group"]
|
|
518
|
-
};
|
|
519
|
-
const tabs = [];
|
|
520
|
-
for (const child of node.children) {
|
|
521
|
-
if (child.type === "code") {
|
|
522
|
-
const codeNode = child;
|
|
523
|
-
const meta = codeNode.meta || "";
|
|
524
|
-
const labelMatch = meta.match(/\[([^\]]+)\]/);
|
|
525
|
-
const label = labelMatch ? labelMatch[1] : codeNode.lang || "Code";
|
|
526
|
-
tabs.push({ label, content: child });
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
const tabsHtml = tabs.map(
|
|
530
|
-
(tab, i) => `<button class="ardo-code-group-tab${i === 0 ? " active" : ""}" data-index="${i}">${escapeHtml(tab.label)}</button>`
|
|
531
|
-
).join("");
|
|
532
|
-
node.children = [
|
|
533
|
-
{
|
|
534
|
-
type: "html",
|
|
535
|
-
value: `<div class="ardo-code-group-tabs">${tabsHtml}</div>`
|
|
536
|
-
},
|
|
537
|
-
{
|
|
538
|
-
type: "html",
|
|
539
|
-
value: '<div class="ardo-code-group-panels">'
|
|
540
|
-
},
|
|
541
|
-
...tabs.map(
|
|
542
|
-
(tab, i) => ({
|
|
543
|
-
type: "html",
|
|
544
|
-
value: `<div class="ardo-code-group-panel${i === 0 ? " active" : ""}" data-index="${i}">`
|
|
545
|
-
})
|
|
546
|
-
),
|
|
547
|
-
...node.children.flatMap((child, _i) => [
|
|
548
|
-
child,
|
|
549
|
-
{
|
|
550
|
-
type: "html",
|
|
551
|
-
value: "</div>"
|
|
552
|
-
}
|
|
553
|
-
]),
|
|
554
|
-
{
|
|
555
|
-
type: "html",
|
|
556
|
-
value: "</div>"
|
|
557
|
-
}
|
|
558
|
-
];
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
|
-
if (type === "details") {
|
|
562
|
-
data.hName = "details";
|
|
563
|
-
data.hProperties = {
|
|
564
|
-
className: ["ardo-details"]
|
|
565
|
-
};
|
|
566
|
-
node.children.unshift({
|
|
567
|
-
type: "html",
|
|
568
|
-
value: `<summary class="ardo-details-summary">${escapeHtml(title)}</summary>`
|
|
807
|
+
await fs2.access(indexPath);
|
|
808
|
+
link = "/" + relativePath.replace(/\\/g, "/");
|
|
809
|
+
} catch {
|
|
810
|
+
}
|
|
811
|
+
items.push({
|
|
812
|
+
text: formatTitle(entry.name),
|
|
813
|
+
link,
|
|
814
|
+
items: children
|
|
569
815
|
});
|
|
570
|
-
return;
|
|
571
816
|
}
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
817
|
+
} else if ((entry.name.endsWith(".mdx") || entry.name.endsWith(".md")) && entry.name !== "index.mdx" && entry.name !== "index.md") {
|
|
818
|
+
const fileContent = await fs2.readFile(fullPath, "utf-8");
|
|
819
|
+
const { data: frontmatter } = matter(fileContent);
|
|
820
|
+
const ext = entry.name.endsWith(".mdx") ? ".mdx" : ".md";
|
|
821
|
+
const title = frontmatter.title || formatTitle(entry.name.replace(ext, ""));
|
|
822
|
+
const order = typeof frontmatter.order === "number" ? frontmatter.order : void 0;
|
|
823
|
+
const link = "/" + relativePath.replace(ext, "").replace(/\\/g, "/");
|
|
824
|
+
items.push({
|
|
825
|
+
text: title,
|
|
826
|
+
link,
|
|
827
|
+
order
|
|
579
828
|
});
|
|
580
|
-
}
|
|
581
|
-
}
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
items.sort((a, b) => {
|
|
832
|
+
if (a.order !== void 0 && b.order !== void 0) {
|
|
833
|
+
return a.order - b.order;
|
|
834
|
+
}
|
|
835
|
+
if (a.order !== void 0) return -1;
|
|
836
|
+
if (b.order !== void 0) return 1;
|
|
837
|
+
return a.text.localeCompare(b.text);
|
|
838
|
+
});
|
|
839
|
+
return items.map(({ order: _order, ...item }) => item);
|
|
582
840
|
}
|
|
583
|
-
function
|
|
584
|
-
return
|
|
841
|
+
function formatTitle(name) {
|
|
842
|
+
return name.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
843
|
+
}
|
|
844
|
+
async function generateSearchIndex(routesDir) {
|
|
845
|
+
const docs = [];
|
|
846
|
+
async function scanForSearch(dir, section) {
|
|
847
|
+
try {
|
|
848
|
+
const entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
849
|
+
for (const entry of entries) {
|
|
850
|
+
const fullPath = path2.join(dir, entry.name);
|
|
851
|
+
if (entry.isDirectory()) {
|
|
852
|
+
const newSection = section ? `${section} > ${formatTitle(entry.name)}` : formatTitle(entry.name);
|
|
853
|
+
await scanForSearch(fullPath, newSection);
|
|
854
|
+
} else if (entry.name.endsWith(".mdx") || entry.name.endsWith(".md")) {
|
|
855
|
+
const relativePath = path2.relative(routesDir, fullPath);
|
|
856
|
+
const fileContent = await fs2.readFile(fullPath, "utf-8");
|
|
857
|
+
const { data: frontmatter, content: rawContent } = matter(fileContent);
|
|
858
|
+
const ext = entry.name.endsWith(".mdx") ? ".mdx" : ".md";
|
|
859
|
+
const title = frontmatter.title || formatTitle(entry.name.replace(ext, ""));
|
|
860
|
+
let content = rawContent;
|
|
861
|
+
content = content.replace(/```[\s\S]*?```/g, "").replace(/`[^`]+`/g, "").replace(/import\s+.*?from\s+['"].*?['"]/g, "").replace(/<[^>]+>/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/[#*_~>]/g, "").replace(/\n+/g, " ").replace(/\s+/g, " ").trim().slice(0, 2e3);
|
|
862
|
+
const routePath = entry.name === "index.mdx" || entry.name === "index.md" ? "/" + path2.dirname(relativePath).replace(/\\/g, "/") : "/" + relativePath.replace(ext, "").replace(/\\/g, "/");
|
|
863
|
+
const finalPath = routePath === "/." ? "/" : routePath;
|
|
864
|
+
docs.push({
|
|
865
|
+
id: relativePath,
|
|
866
|
+
title,
|
|
867
|
+
content,
|
|
868
|
+
path: finalPath,
|
|
869
|
+
section
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
} catch (error) {
|
|
874
|
+
console.warn(
|
|
875
|
+
"[ardo] Failed to scan for search index:",
|
|
876
|
+
error instanceof Error ? error.message : error
|
|
877
|
+
);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
await scanForSearch(routesDir);
|
|
881
|
+
return docs;
|
|
585
882
|
}
|
|
586
883
|
|
|
884
|
+
// src/runtime/loader.ts
|
|
885
|
+
import fs3 from "fs/promises";
|
|
886
|
+
import path3 from "path";
|
|
887
|
+
|
|
888
|
+
// src/markdown/pipeline.ts
|
|
889
|
+
import { unified } from "unified";
|
|
890
|
+
import remarkParse from "remark-parse";
|
|
891
|
+
import remarkGfm2 from "remark-gfm";
|
|
892
|
+
import remarkFrontmatter2 from "remark-frontmatter";
|
|
893
|
+
import remarkDirective2 from "remark-directive";
|
|
894
|
+
import remarkRehype from "remark-rehype";
|
|
895
|
+
import rehypeStringify from "rehype-stringify";
|
|
896
|
+
import matter2 from "gray-matter";
|
|
897
|
+
|
|
587
898
|
// src/markdown/toc.ts
|
|
588
|
-
import { visit as
|
|
899
|
+
import { visit as visit3 } from "unist-util-visit";
|
|
589
900
|
function remarkExtractToc(options) {
|
|
590
901
|
const { tocExtraction, levels } = options;
|
|
591
902
|
const [minLevel, maxLevel] = levels;
|
|
592
903
|
return function(tree) {
|
|
593
904
|
const headings = [];
|
|
594
|
-
|
|
905
|
+
let headingIndex = 0;
|
|
906
|
+
visit3(tree, "heading", (node) => {
|
|
595
907
|
if (node.depth < minLevel || node.depth > maxLevel) {
|
|
596
908
|
return;
|
|
597
909
|
}
|
|
598
910
|
const text = getHeadingText(node);
|
|
599
|
-
const
|
|
911
|
+
const slug = slugify(text);
|
|
912
|
+
const id = slug || `heading-${headingIndex}`;
|
|
913
|
+
headingIndex++;
|
|
600
914
|
headings.push({
|
|
601
915
|
text,
|
|
602
916
|
level: node.depth,
|
|
@@ -654,174 +968,6 @@ function buildTocTree(headings, _minLevel) {
|
|
|
654
968
|
return result;
|
|
655
969
|
}
|
|
656
970
|
|
|
657
|
-
// src/markdown/shiki.ts
|
|
658
|
-
import { createHighlighter } from "shiki";
|
|
659
|
-
import { visit as visit3 } from "unist-util-visit";
|
|
660
|
-
async function createShikiHighlighter(config) {
|
|
661
|
-
const themeConfig = config.theme ?? {
|
|
662
|
-
light: "github-light",
|
|
663
|
-
dark: "github-dark"
|
|
664
|
-
};
|
|
665
|
-
const themes = typeof themeConfig === "string" ? [themeConfig] : [themeConfig.light, themeConfig.dark];
|
|
666
|
-
const highlighter = await createHighlighter({
|
|
667
|
-
themes,
|
|
668
|
-
langs: [
|
|
669
|
-
"javascript",
|
|
670
|
-
"typescript",
|
|
671
|
-
"jsx",
|
|
672
|
-
"tsx",
|
|
673
|
-
"json",
|
|
674
|
-
"html",
|
|
675
|
-
"css",
|
|
676
|
-
"markdown",
|
|
677
|
-
"bash",
|
|
678
|
-
"shell",
|
|
679
|
-
"yaml",
|
|
680
|
-
"python",
|
|
681
|
-
"rust",
|
|
682
|
-
"go",
|
|
683
|
-
"sql",
|
|
684
|
-
"diff"
|
|
685
|
-
]
|
|
686
|
-
});
|
|
687
|
-
return highlighter;
|
|
688
|
-
}
|
|
689
|
-
function rehypeShikiFromHighlighter(options) {
|
|
690
|
-
const { highlighter, config } = options;
|
|
691
|
-
const themeConfig = config.theme ?? {
|
|
692
|
-
light: "github-light",
|
|
693
|
-
dark: "github-dark"
|
|
694
|
-
};
|
|
695
|
-
return function(tree) {
|
|
696
|
-
visit3(tree, "element", (node, index, parent) => {
|
|
697
|
-
if (node.tagName !== "pre" || !node.children[0] || node.children[0].tagName !== "code") {
|
|
698
|
-
return;
|
|
699
|
-
}
|
|
700
|
-
const codeNode = node.children[0];
|
|
701
|
-
const className = codeNode.properties?.className || [];
|
|
702
|
-
const langClass = className.find((c) => c.startsWith("language-"));
|
|
703
|
-
const lang = langClass ? langClass.replace("language-", "") : "text";
|
|
704
|
-
const codeContent = getTextContent(codeNode);
|
|
705
|
-
if (!codeContent.trim()) {
|
|
706
|
-
return;
|
|
707
|
-
}
|
|
708
|
-
try {
|
|
709
|
-
let html;
|
|
710
|
-
if (typeof themeConfig === "string") {
|
|
711
|
-
html = highlighter.codeToHtml(codeContent, {
|
|
712
|
-
lang,
|
|
713
|
-
theme: themeConfig
|
|
714
|
-
});
|
|
715
|
-
} else {
|
|
716
|
-
html = highlighter.codeToHtml(codeContent, {
|
|
717
|
-
lang,
|
|
718
|
-
themes: {
|
|
719
|
-
light: themeConfig.light,
|
|
720
|
-
dark: themeConfig.dark
|
|
721
|
-
},
|
|
722
|
-
defaultColor: false
|
|
723
|
-
});
|
|
724
|
-
}
|
|
725
|
-
const metaString = codeNode.properties?.metastring || "";
|
|
726
|
-
const lineNumbers = config.lineNumbers || metaString.includes("showLineNumbers");
|
|
727
|
-
const highlightLines = parseHighlightLines(metaString);
|
|
728
|
-
const title = parseTitle(metaString);
|
|
729
|
-
const wrapperHtml = buildCodeBlockHtml(html, {
|
|
730
|
-
lang,
|
|
731
|
-
lineNumbers,
|
|
732
|
-
highlightLines,
|
|
733
|
-
title
|
|
734
|
-
});
|
|
735
|
-
if (parent && typeof index === "number") {
|
|
736
|
-
const newNode = {
|
|
737
|
-
type: "element",
|
|
738
|
-
tagName: "div",
|
|
739
|
-
properties: {
|
|
740
|
-
className: ["ardo-code-block"],
|
|
741
|
-
"data-lang": lang
|
|
742
|
-
},
|
|
743
|
-
children: [
|
|
744
|
-
{
|
|
745
|
-
type: "raw",
|
|
746
|
-
value: wrapperHtml
|
|
747
|
-
}
|
|
748
|
-
]
|
|
749
|
-
};
|
|
750
|
-
parent.children[index] = newNode;
|
|
751
|
-
}
|
|
752
|
-
} catch {
|
|
753
|
-
}
|
|
754
|
-
});
|
|
755
|
-
};
|
|
756
|
-
}
|
|
757
|
-
function getTextContent(node) {
|
|
758
|
-
if (node.type === "text") {
|
|
759
|
-
return node.value;
|
|
760
|
-
}
|
|
761
|
-
if ("children" in node) {
|
|
762
|
-
return node.children.map((child) => getTextContent(child)).join("");
|
|
763
|
-
}
|
|
764
|
-
return "";
|
|
765
|
-
}
|
|
766
|
-
function parseHighlightLines(meta) {
|
|
767
|
-
const match = meta.match(/\{([\d,-]+)\}/);
|
|
768
|
-
if (!match) return [];
|
|
769
|
-
const ranges = match[1].split(",");
|
|
770
|
-
const lines = [];
|
|
771
|
-
for (const range of ranges) {
|
|
772
|
-
if (range.includes("-")) {
|
|
773
|
-
const [start, end] = range.split("-").map(Number);
|
|
774
|
-
for (let i = start; i <= end; i++) {
|
|
775
|
-
lines.push(i);
|
|
776
|
-
}
|
|
777
|
-
} else {
|
|
778
|
-
lines.push(Number(range));
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
return lines;
|
|
782
|
-
}
|
|
783
|
-
function parseTitle(meta) {
|
|
784
|
-
const match = meta.match(/title="([^"]+)"/);
|
|
785
|
-
return match ? match[1] : void 0;
|
|
786
|
-
}
|
|
787
|
-
function buildCodeBlockHtml(shikiHtml, options) {
|
|
788
|
-
const { lang, lineNumbers, highlightLines, title } = options;
|
|
789
|
-
let html = "";
|
|
790
|
-
if (title) {
|
|
791
|
-
html += `<div class="ardo-code-title">${escapeHtml2(title)}</div>`;
|
|
792
|
-
}
|
|
793
|
-
html += `<div class="ardo-code-wrapper" data-lang="${lang}">`;
|
|
794
|
-
if (lineNumbers || highlightLines.length > 0) {
|
|
795
|
-
const lines = shikiHtml.split("\n");
|
|
796
|
-
const processedHtml = lines.map((line, i) => {
|
|
797
|
-
const lineNum = i + 1;
|
|
798
|
-
const isHighlighted = highlightLines.includes(lineNum);
|
|
799
|
-
const classes = ["ardo-code-line"];
|
|
800
|
-
if (isHighlighted) classes.push("highlighted");
|
|
801
|
-
let prefix = "";
|
|
802
|
-
if (lineNumbers) {
|
|
803
|
-
prefix = `<span class="ardo-line-number">${lineNum}</span>`;
|
|
804
|
-
}
|
|
805
|
-
return `<span class="${classes.join(" ")}">${prefix}${line}</span>`;
|
|
806
|
-
}).join("\n");
|
|
807
|
-
html += processedHtml;
|
|
808
|
-
} else {
|
|
809
|
-
html += shikiHtml;
|
|
810
|
-
}
|
|
811
|
-
html += `<button class="ardo-copy-button" data-code="${encodeURIComponent(extractCodeFromHtml(shikiHtml))}">
|
|
812
|
-
<span class="ardo-copy-icon">Copy</span>
|
|
813
|
-
<span class="ardo-copied-icon" style="display:none">Copied!</span>
|
|
814
|
-
</button>`;
|
|
815
|
-
html += "</div>";
|
|
816
|
-
return html;
|
|
817
|
-
}
|
|
818
|
-
function extractCodeFromHtml(html) {
|
|
819
|
-
return html.replace(/<[^>]+>/g, "").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&").replace(/"/g, '"').replace(/'/g, "'");
|
|
820
|
-
}
|
|
821
|
-
function escapeHtml2(text) {
|
|
822
|
-
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
823
|
-
}
|
|
824
|
-
|
|
825
971
|
// src/markdown/links.ts
|
|
826
972
|
import { visit as visit4 } from "unist-util-visit";
|
|
827
973
|
function rehypeLinks(options) {
|
|
@@ -847,7 +993,7 @@ function rehypeLinks(options) {
|
|
|
847
993
|
|
|
848
994
|
// src/markdown/pipeline.ts
|
|
849
995
|
async function transformMarkdown(content, config, options = {}) {
|
|
850
|
-
const { data: frontmatter, content: markdownContent } =
|
|
996
|
+
const { data: frontmatter, content: markdownContent } = matter2(content);
|
|
851
997
|
const { basePath = "/", highlighter: providedHighlighter } = options;
|
|
852
998
|
const tocExtraction = { toc: [] };
|
|
853
999
|
const highlighter = providedHighlighter ?? await createShikiHighlighter(config);
|
|
@@ -961,7 +1107,7 @@ function getPageDataForRoute(docs, slug) {
|
|
|
961
1107
|
// src/runtime/sidebar.ts
|
|
962
1108
|
import fs4 from "fs/promises";
|
|
963
1109
|
import path4 from "path";
|
|
964
|
-
import
|
|
1110
|
+
import matter3 from "gray-matter";
|
|
965
1111
|
async function generateSidebar2(options) {
|
|
966
1112
|
const { contentDir, basePath, config } = options;
|
|
967
1113
|
const configSidebar = config.themeConfig.sidebar;
|
|
@@ -998,7 +1144,7 @@ async function scanDirectoryForSidebar(dir, rootDir, _basePath) {
|
|
|
998
1144
|
let order;
|
|
999
1145
|
try {
|
|
1000
1146
|
const indexContent = await fs4.readFile(indexPath, "utf-8");
|
|
1001
|
-
const { data: frontmatter } =
|
|
1147
|
+
const { data: frontmatter } = matter3(indexContent);
|
|
1002
1148
|
if (frontmatter.title) {
|
|
1003
1149
|
title = frontmatter.title;
|
|
1004
1150
|
}
|
|
@@ -1018,7 +1164,7 @@ async function scanDirectoryForSidebar(dir, rootDir, _basePath) {
|
|
|
1018
1164
|
}
|
|
1019
1165
|
} else if (entry.name.endsWith(".md") && entry.name !== "index.md") {
|
|
1020
1166
|
const fileContent = await fs4.readFile(fullPath, "utf-8");
|
|
1021
|
-
const { data: frontmatter } =
|
|
1167
|
+
const { data: frontmatter } = matter3(fileContent);
|
|
1022
1168
|
if (frontmatter.sidebar === false) {
|
|
1023
1169
|
continue;
|
|
1024
1170
|
}
|
|
@@ -1050,9 +1196,9 @@ function normalizePath(p) {
|
|
|
1050
1196
|
}
|
|
1051
1197
|
|
|
1052
1198
|
export {
|
|
1199
|
+
createShikiHighlighter,
|
|
1053
1200
|
ardoRoutesPlugin,
|
|
1054
1201
|
ardoPlugin,
|
|
1055
|
-
createShikiHighlighter,
|
|
1056
1202
|
transformMarkdown,
|
|
1057
1203
|
transformMarkdownToReact,
|
|
1058
1204
|
loadDoc,
|
|
@@ -1061,4 +1207,4 @@ export {
|
|
|
1061
1207
|
getPageDataForRoute,
|
|
1062
1208
|
generateSidebar2 as generateSidebar
|
|
1063
1209
|
};
|
|
1064
|
-
//# sourceMappingURL=chunk-
|
|
1210
|
+
//# sourceMappingURL=chunk-SWER4H2H.js.map
|