ardo 2.8.0 → 3.0.1

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.
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-NBRHGTR2.js";
5
5
  import {
6
6
  generateApiDocs
7
- } from "./chunk-CYZLI4AU.js";
7
+ } from "./chunk-PGHUPTGL.js";
8
8
 
9
9
  // src/vite/plugin.ts
10
10
  import { reactRouter } from "@react-router/dev/vite";
@@ -12,7 +12,6 @@ import mdx from "@mdx-js/rollup";
12
12
  import remarkFrontmatter from "remark-frontmatter";
13
13
  import remarkMdxFrontmatter from "remark-mdx-frontmatter";
14
14
  import remarkGfm from "remark-gfm";
15
- import remarkDirective from "remark-directive";
16
15
  import rehypeShiki from "@shikijs/rehype";
17
16
 
18
17
  // src/markdown/shiki.ts
@@ -50,17 +49,29 @@ async function createShikiHighlighter(config) {
50
49
  const highlighter = await createHighlighter({
51
50
  themes,
52
51
  langs: [
52
+ // Web fundamentals
53
53
  "javascript",
54
54
  "typescript",
55
55
  "jsx",
56
56
  "tsx",
57
- "json",
58
57
  "html",
59
58
  "css",
59
+ "scss",
60
+ // Data & config formats
61
+ "json",
62
+ "jsonc",
63
+ "yaml",
64
+ "toml",
65
+ "xml",
66
+ "graphql",
67
+ // Markdown & docs
60
68
  "markdown",
69
+ "mdx",
70
+ // Shell & DevOps
61
71
  "bash",
62
72
  "shell",
63
- "yaml",
73
+ "dockerfile",
74
+ // General purpose
64
75
  "python",
65
76
  "rust",
66
77
  "go",
@@ -260,172 +271,6 @@ function ardoLineTransformer(options = {}) {
260
271
  };
261
272
  }
262
273
 
263
- // src/markdown/containers.ts
264
- import { visit as visit2 } from "unist-util-visit";
265
- var containerTypes = [
266
- "tip",
267
- "warning",
268
- "danger",
269
- "info",
270
- "note",
271
- "details",
272
- "code-group"
273
- ];
274
- var defaultTitles = {
275
- tip: "TIP",
276
- warning: "WARNING",
277
- danger: "DANGER",
278
- info: "INFO",
279
- note: "NOTE",
280
- details: "Details",
281
- "code-group": ""
282
- };
283
- function remarkContainers() {
284
- return function(tree) {
285
- visit2(tree, "containerDirective", (node) => {
286
- const type = node.name;
287
- if (!containerTypes.includes(type)) {
288
- return;
289
- }
290
- const data = node.data || (node.data = {});
291
- const titleNode = node.children[0];
292
- let customTitle;
293
- if (titleNode && titleNode.type === "paragraph" && titleNode.children[0]?.type === "text" && titleNode.data?.directiveLabel) {
294
- customTitle = titleNode.children[0].value;
295
- node.children.shift();
296
- }
297
- const title = customTitle || defaultTitles[type];
298
- if (type === "code-group") {
299
- data.hName = "div";
300
- data.hProperties = {
301
- className: ["ardo-code-group"]
302
- };
303
- const tabs = [];
304
- for (const child of node.children) {
305
- if (child.type === "code") {
306
- const codeNode = child;
307
- const meta = codeNode.meta || "";
308
- const labelMatch = meta.match(/\[([^\]]+)\]/);
309
- const label = labelMatch ? labelMatch[1] : codeNode.lang || "Code";
310
- tabs.push({ label, content: child });
311
- }
312
- }
313
- const tabsHtml = tabs.map(
314
- (tab, i) => `<button class="ardo-code-group-tab${i === 0 ? " active" : ""}" data-index="${i}">${escapeHtml2(tab.label)}</button>`
315
- ).join("");
316
- node.children = [
317
- {
318
- type: "html",
319
- value: `<div class="ardo-code-group-tabs">${tabsHtml}</div>`
320
- },
321
- {
322
- type: "html",
323
- value: '<div class="ardo-code-group-panels">'
324
- },
325
- ...tabs.map(
326
- (tab, i) => ({
327
- type: "html",
328
- value: `<div class="ardo-code-group-panel${i === 0 ? " active" : ""}" data-index="${i}">`
329
- })
330
- ),
331
- ...node.children.flatMap((child, _i) => [
332
- child,
333
- {
334
- type: "html",
335
- value: "</div>"
336
- }
337
- ]),
338
- {
339
- type: "html",
340
- value: "</div>"
341
- }
342
- ];
343
- return;
344
- }
345
- if (type === "details") {
346
- data.hName = "details";
347
- data.hProperties = {
348
- className: ["ardo-details"]
349
- };
350
- node.children.unshift({
351
- type: "html",
352
- value: `<summary class="ardo-details-summary">${escapeHtml2(title)}</summary>`
353
- });
354
- return;
355
- }
356
- data.hName = "div";
357
- data.hProperties = {
358
- className: ["ardo-container", `ardo-container-${type}`]
359
- };
360
- node.children.unshift({
361
- type: "html",
362
- value: `<p class="ardo-container-title">${escapeHtml2(title)}</p>`
363
- });
364
- });
365
- };
366
- }
367
- function escapeHtml2(text) {
368
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
369
- }
370
- var containerToComponent = {
371
- tip: "Tip",
372
- warning: "Warning",
373
- danger: "Danger",
374
- info: "Info",
375
- note: "Note"
376
- };
377
- function remarkContainersMdx() {
378
- return function(tree) {
379
- visit2(tree, "containerDirective", (node, index, parent) => {
380
- if (!parent || typeof index !== "number") return;
381
- if (node.name === "code-group") {
382
- const labels = node.children.filter((child) => child.type === "code").map((child) => {
383
- const meta = child.meta || "";
384
- const match = meta.match(/\[([^\]]+)\]/);
385
- return match ? match[1] : child.lang || "Code";
386
- });
387
- const jsxNode2 = {
388
- type: "mdxJsxFlowElement",
389
- name: "CodeGroup",
390
- attributes: [
391
- {
392
- type: "mdxJsxAttribute",
393
- name: "labels",
394
- value: labels.join(",")
395
- }
396
- ],
397
- children: node.children
398
- };
399
- parent.children[index] = jsxNode2;
400
- return;
401
- }
402
- const componentName = containerToComponent[node.name];
403
- if (!componentName) return;
404
- const titleNode = node.children[0];
405
- let customTitle;
406
- if (titleNode && titleNode.type === "paragraph" && titleNode.children[0]?.type === "text" && titleNode.data?.directiveLabel) {
407
- customTitle = titleNode.children[0].value;
408
- node.children.shift();
409
- }
410
- const attributes = [];
411
- if (customTitle) {
412
- attributes.push({
413
- type: "mdxJsxAttribute",
414
- name: "title",
415
- value: customTitle
416
- });
417
- }
418
- const jsxNode = {
419
- type: "mdxJsxFlowElement",
420
- name: componentName,
421
- attributes,
422
- children: node.children
423
- };
424
- parent.children[index] = jsxNode;
425
- });
426
- };
427
- }
428
-
429
274
  // src/vite/plugin.ts
430
275
  import fs2 from "fs/promises";
431
276
  import fsSync2 from "fs";
@@ -582,6 +427,89 @@ function outdent(text) {
582
427
  if (indent === 0 || indent === Infinity) return trimmed;
583
428
  return lines.map((line) => line.slice(indent)).join("\n");
584
429
  }
430
+ function findSelfClosingCodeBlocks(source) {
431
+ const results = [];
432
+ const tag = "<CodeBlock";
433
+ let searchFrom = 0;
434
+ while (true) {
435
+ const start = source.indexOf(tag, searchFrom);
436
+ if (start === -1) break;
437
+ const afterTag = start + tag.length;
438
+ if (afterTag >= source.length || !/\s/.test(source[afterTag])) {
439
+ searchFrom = afterTag;
440
+ continue;
441
+ }
442
+ let i = afterTag;
443
+ let depth = 0;
444
+ let inSingle = false;
445
+ let inDouble = false;
446
+ let inTemplate = false;
447
+ let found = false;
448
+ while (i < source.length) {
449
+ const ch = source[i];
450
+ if ((inSingle || inDouble || inTemplate) && ch === "\\") {
451
+ i += 2;
452
+ continue;
453
+ }
454
+ if (inSingle) {
455
+ if (ch === "'") inSingle = false;
456
+ i++;
457
+ continue;
458
+ }
459
+ if (inDouble) {
460
+ if (ch === '"') inDouble = false;
461
+ i++;
462
+ continue;
463
+ }
464
+ if (inTemplate) {
465
+ if (ch === "`") inTemplate = false;
466
+ i++;
467
+ continue;
468
+ }
469
+ if (ch === "'") {
470
+ inSingle = true;
471
+ i++;
472
+ continue;
473
+ }
474
+ if (ch === '"') {
475
+ inDouble = true;
476
+ i++;
477
+ continue;
478
+ }
479
+ if (ch === "`") {
480
+ inTemplate = true;
481
+ i++;
482
+ continue;
483
+ }
484
+ if (ch === "{") {
485
+ depth++;
486
+ i++;
487
+ continue;
488
+ }
489
+ if (ch === "}") {
490
+ depth--;
491
+ i++;
492
+ continue;
493
+ }
494
+ if (depth === 0 && ch === "/" && i + 1 < source.length && source[i + 1] === ">") {
495
+ const fullMatch = source.substring(start, i + 2);
496
+ const propsStr = source.substring(afterTag, i).trim();
497
+ results.push({ fullMatch, propsStr, index: start });
498
+ found = true;
499
+ searchFrom = i + 2;
500
+ break;
501
+ }
502
+ if (depth === 0 && ch === ">") {
503
+ searchFrom = i + 1;
504
+ found = true;
505
+ break;
506
+ }
507
+ i++;
508
+ }
509
+ if (!found) break;
510
+ }
511
+ return results;
512
+ }
585
513
  function ardoCodeBlockPlugin(markdownConfig) {
586
514
  return {
587
515
  name: "ardo:codeblock-highlight",
@@ -592,14 +520,12 @@ function ardoCodeBlockPlugin(markdownConfig) {
592
520
  if (id.includes("node_modules")) return;
593
521
  let result = code;
594
522
  let offset = 0;
595
- const propRegex = /<CodeBlock\s+([^>]*?)\/>/g;
596
- let match;
597
- while ((match = propRegex.exec(code)) !== null) {
598
- const fullMatch = match[0];
599
- const propsStr = match[1];
600
- const codeMatch = propsStr.match(/\bcode="((?:[^"\\]|\\.)*)"/s) || propsStr.match(/\bcode=\{"((?:[^"\\]|\\.)*)"\}/s);
523
+ const propMatches = findSelfClosingCodeBlocks(code);
524
+ for (const match of propMatches) {
525
+ const { fullMatch, propsStr } = match;
526
+ const codeMatch = propsStr.match(/\bcode="((?:[^"\\]|\\.)*)"/s) || propsStr.match(/\bcode=\{\s*"((?:[^"\\]|\\.)*)"\s*\}/s) || propsStr.match(/\bcode=\{\s*'((?:[^'\\]|\\.)*)'\s*\}/s);
601
527
  if (!codeMatch) continue;
602
- const langMatch = propsStr.match(/\blanguage="([^"]*)"/) || propsStr.match(/\blanguage=\{"([^"]*)"\}/);
528
+ const langMatch = propsStr.match(/\blanguage="([^"]*)"/) || propsStr.match(/\blanguage=\{"([^"]*)"\}/) || propsStr.match(/\blanguage=\{'([^']*)'\}/);
603
529
  if (!langMatch) continue;
604
530
  if (propsStr.includes("__html")) continue;
605
531
  const codeContent = codeMatch[1].replace(/\\n/g, "\n").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
@@ -618,11 +544,12 @@ function ardoCodeBlockPlugin(markdownConfig) {
618
544
  }
619
545
  const childrenRegex = /<CodeBlock\s+([^>]*?)>([\s\S]*?)<\/CodeBlock>/g;
620
546
  offset = result.length - code.length;
621
- while ((match = childrenRegex.exec(code)) !== null) {
622
- const fullMatch = match[0];
623
- const propsStr = match[1];
624
- let rawChildren = match[2];
625
- const langMatch = propsStr.match(/\blanguage="([^"]*)"/) || propsStr.match(/\blanguage=\{"([^"]*)"\}/);
547
+ let regexMatch;
548
+ while ((regexMatch = childrenRegex.exec(code)) !== null) {
549
+ const fullMatch = regexMatch[0];
550
+ const propsStr = regexMatch[1];
551
+ let rawChildren = regexMatch[2];
552
+ const langMatch = propsStr.match(/\blanguage="([^"]*)"/) || propsStr.match(/\blanguage=\{"([^"]*)"\}/) || propsStr.match(/\blanguage=\{'([^']*)'\}/);
626
553
  if (!langMatch) continue;
627
554
  if (propsStr.includes("__html")) continue;
628
555
  const templateMatch = rawChildren.match(/^\s*\{`([\s\S]*)`\}\s*$/);
@@ -638,7 +565,7 @@ function ardoCodeBlockPlugin(markdownConfig) {
638
565
  const escapedHtml = JSON.stringify(html);
639
566
  const escapedCode = JSON.stringify(codeContent);
640
567
  const newTag = `<CodeBlock __html={${escapedHtml}} code={${escapedCode}} ${propsStr} />`;
641
- result = result.slice(0, match.index + offset) + newTag + result.slice(match.index + offset + fullMatch.length);
568
+ result = result.slice(0, regexMatch.index + offset) + newTag + result.slice(regexMatch.index + offset + fullMatch.length);
642
569
  offset += newTag.length - fullMatch.length;
643
570
  } catch {
644
571
  }
@@ -770,6 +697,16 @@ function ardoPlugin(options = {}) {
770
697
  },
771
698
  ssr: {
772
699
  noExternal: ["ardo"]
700
+ },
701
+ build: {
702
+ rollupOptions: {
703
+ // Workaround: Rolldown (Vite 8) treats all files as UTF-8 text and
704
+ // fails on native .node binaries like fsevents with "stream did not
705
+ // contain valid UTF-8". This is a known Rolldown limitation:
706
+ // https://github.com/rolldown/rolldown/issues/5662
707
+ // Remove once Rolldown handles native modules natively.
708
+ external: ["fsevents"]
709
+ }
773
710
  }
774
711
  };
775
712
  if (githubPages && env.command === "build" && !userConfig.base) {
@@ -928,8 +865,6 @@ export const meta = () => [${metaEntries.join(", ")}];
928
865
  remarkFrontmatter,
929
866
  [remarkMdxFrontmatter, { name: "frontmatter" }],
930
867
  remarkGfm,
931
- remarkDirective,
932
- remarkContainersMdx,
933
868
  remarkCodeMeta
934
869
  ],
935
870
  rehypePlugins: [[rehypeShiki, shikiOptions]],
@@ -1084,20 +1019,19 @@ import { unified } from "unified";
1084
1019
  import remarkParse from "remark-parse";
1085
1020
  import remarkGfm2 from "remark-gfm";
1086
1021
  import remarkFrontmatter2 from "remark-frontmatter";
1087
- import remarkDirective2 from "remark-directive";
1088
1022
  import remarkRehype from "remark-rehype";
1089
1023
  import rehypeStringify from "rehype-stringify";
1090
1024
  import matter2 from "gray-matter";
1091
1025
 
1092
1026
  // src/markdown/toc.ts
1093
- import { visit as visit3 } from "unist-util-visit";
1027
+ import { visit as visit2 } from "unist-util-visit";
1094
1028
  function remarkExtractToc(options) {
1095
1029
  const { tocExtraction, levels } = options;
1096
1030
  const [minLevel, maxLevel] = levels;
1097
1031
  return function(tree) {
1098
1032
  const headings = [];
1099
1033
  let headingIndex = 0;
1100
- visit3(tree, "heading", (node) => {
1034
+ visit2(tree, "heading", (node) => {
1101
1035
  if (node.depth < minLevel || node.depth > maxLevel) {
1102
1036
  return;
1103
1037
  }
@@ -1163,7 +1097,7 @@ function buildTocTree(headings, _minLevel) {
1163
1097
  }
1164
1098
 
1165
1099
  // src/markdown/links.ts
1166
- import { visit as visit4 } from "unist-util-visit";
1100
+ import { visit as visit3 } from "unist-util-visit";
1167
1101
  function rehypeLinks(options) {
1168
1102
  const { basePath } = options;
1169
1103
  const normalizedBase = basePath === "/" ? "" : basePath.replace(/\/$/, "");
@@ -1171,7 +1105,7 @@ function rehypeLinks(options) {
1171
1105
  if (!normalizedBase) {
1172
1106
  return;
1173
1107
  }
1174
- visit4(tree, "element", (node) => {
1108
+ visit3(tree, "element", (node) => {
1175
1109
  if (node.tagName === "a") {
1176
1110
  const href = node.properties?.href;
1177
1111
  if (typeof href === "string") {
@@ -1191,7 +1125,7 @@ async function transformMarkdown(content, config, options = {}) {
1191
1125
  const { basePath = "/", highlighter: providedHighlighter } = options;
1192
1126
  const tocExtraction = { toc: [] };
1193
1127
  const highlighter = providedHighlighter ?? await createShikiHighlighter(config);
1194
- const processor = unified().use(remarkParse).use(remarkFrontmatter2, ["yaml"]).use(remarkGfm2).use(remarkDirective2).use(remarkContainers).use(remarkExtractToc, { tocExtraction, levels: config.toc?.level ?? [2, 3] }).use(remarkRehype, { allowDangerousHtml: true }).use(rehypeShikiFromHighlighter, { highlighter, config }).use(rehypeLinks, { basePath }).use(rehypeStringify, { allowDangerousHtml: true });
1128
+ const processor = unified().use(remarkParse).use(remarkFrontmatter2, ["yaml"]).use(remarkGfm2).use(remarkExtractToc, { tocExtraction, levels: config.toc?.level ?? [2, 3] }).use(remarkRehype, { allowDangerousHtml: true }).use(rehypeShikiFromHighlighter, { highlighter, config }).use(rehypeLinks, { basePath }).use(rehypeStringify, { allowDangerousHtml: true });
1195
1129
  if (config.remarkPlugins) {
1196
1130
  for (const plugin of config.remarkPlugins) {
1197
1131
  processor.use(plugin);
@@ -1403,4 +1337,4 @@ export {
1403
1337
  getPageDataForRoute,
1404
1338
  generateSidebar2 as generateSidebar
1405
1339
  };
1406
- //# sourceMappingURL=chunk-YUGJQYEK.js.map
1340
+ //# sourceMappingURL=chunk-XJO5ROKA.js.map