@forsakringskassan/docs-generator 3.8.0 → 3.10.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/index.mjs CHANGED
@@ -3,12 +3,12 @@ import { createRequire as $createRequire } from "node:module";
3
3
  const require = $createRequire(import.meta.url);
4
4
 
5
5
  import { ApiItemKind, ApiModel } from '@microsoft/api-extractor-model';
6
- import { t as ts, Z as Ze, M as MarkdownItCallable, s as strToU8, z as zlibSync, g as strFromU8, d as dedent, h as closest, i as distance, j as fm, k as isCI, m as moduleImporter, l as cliProgress, n as tinylr, w as watch, o as createInstance, p as fse, q as inter } from './vendor-DqIMfP3a.mjs';
6
+ import { t as ts, Z as Ze, M as MarkdownItCallable, g as fm, s as strToU8, z as zlibSync, h as strFromU8, d as dedent, i as closest, j as distance, k as isCI, m as moduleImporter, l as cliProgress, n as tinylr, w as watch, o as createInstance, p as fse, q as inter } from './vendor-DPuGyhL4.mjs';
7
7
  import path__default from 'node:path';
8
8
  import crypto from 'node:crypto';
9
9
  import path from 'node:path/posix';
10
10
  import { exec, execSync } from 'node:child_process';
11
- import { g as generateId, f as formatCode, p as parseInfostring, i as isDocumentPage, n as normalizePath, a as getFingerprint, h as hasTag, b as parseImport, d as findTag, e as getOutputFilePath, j as htmlencode, k as filePath, c as createMarkdownRenderer, l as generateExample } from './create-markdown-renderer-D5BdKyep.mjs';
11
+ import { g as generateId, f as formatCode, p as parseInfostring, a as getFingerprint, h as hasTag, b as parseImport, d as findTag, e as getOutputFilePath, i as isDocumentPage, j as findDocument, k as getDocumentBody, n as normalizePath, l as htmlencode, m as filePath, c as createMarkdownRenderer, o as generateExample } from './create-markdown-renderer-CXtEyRCU.mjs';
12
12
  import { DocExcerpt } from '@microsoft/tsdoc';
13
13
  import fs from 'node:fs/promises';
14
14
  import util, { promisify, styleText } from 'node:util';
@@ -288,6 +288,15 @@ function slugify(value) {
288
288
  return value.toLowerCase().replaceAll("/", "--").replaceAll(/[^a-z]+/g, "-").replace(/^-+|-+$/, "");
289
289
  }
290
290
 
291
+ function* takeWhile(it, predicate) {
292
+ for (const value of it) {
293
+ if (!predicate(value)) {
294
+ return;
295
+ }
296
+ yield value;
297
+ }
298
+ }
299
+
291
300
  function isRelease() {
292
301
  try {
293
302
  const cmd = `git log -n1 --format=format:%s`;
@@ -299,6 +308,19 @@ function isRelease() {
299
308
  }
300
309
  }
301
310
 
311
+ function* zip(a, b) {
312
+ const ia = Array.isArray(a) ? a.values() : a;
313
+ const ib = Array.isArray(b) ? b.values() : b;
314
+ for (; ; ) {
315
+ const va = ia.next();
316
+ const vb = ib.next();
317
+ if (va.done || vb.done) {
318
+ return;
319
+ }
320
+ yield [va.value, vb.value];
321
+ }
322
+ }
323
+
302
324
  const available = {
303
325
  interface: ["default", "interface", "properties"]
304
326
  };
@@ -570,6 +592,23 @@ function apiExtractorProcessor(options = {}) {
570
592
  };
571
593
  }
572
594
 
595
+ function cookieProcessor(options = {}) {
596
+ const { enabled = true } = options;
597
+ return {
598
+ after: "generate-docs",
599
+ name: "cookie-processor",
600
+ runtime: [{ src: "src/runtime/cookie.ts" }],
601
+ handler(context) {
602
+ if (!enabled) {
603
+ return;
604
+ }
605
+ context.addTemplateBlock("body:begin", "cookie-warning", {
606
+ filename: "partials/cookie-warning.html"
607
+ });
608
+ }
609
+ };
610
+ }
611
+
573
612
  const documentAttributeKeys = [
574
613
  "title",
575
614
  "short-title",
@@ -586,97 +625,12 @@ const documentAttributeKeys = [
586
625
  "redirect_from"
587
626
  ];
588
627
 
589
- const md$6 = MarkdownItCallable();
590
- md$6.renderer.rules.fence = (tokens, idx, _options, rawEnv) => {
591
- const { collected } = rawEnv;
592
- const { content, info } = tokens[idx];
593
- const { language, tags } = parseInfostring(info);
594
- if (language === "import") {
595
- return "";
596
- }
597
- const nameTag = tags.find((it) => it.startsWith("name="));
598
- const name = nameTag ? slugify(nameTag.slice("name=".length)) : void 0;
599
- collected.push({
600
- name,
601
- content,
602
- language,
603
- tags
604
- });
605
- return "";
606
- };
607
- function findExamples$1(doc) {
608
- if (doc.format !== "markdown") {
609
- return [];
610
- }
611
- const collected = [];
612
- md$6.render(doc.body, { collected });
613
- return collected;
614
- }
615
- function getSuffix(tags) {
616
- const relevant = tags.filter((it) => ["nocompile", "nolint"].includes(it));
617
- if (relevant.length > 0) {
618
- return `-${relevant.join("-")}`;
619
- }
620
- return "";
621
- }
622
- function getExtension(lang) {
623
- switch (lang) {
624
- case "typescript":
625
- return "ts";
626
- case "javascript":
627
- return "js";
628
- default:
629
- return lang;
630
- }
631
- }
632
- function extractExamplesProcessor(options) {
633
- const {
634
- enabled = true,
635
- outputFolder,
636
- languages = ["javascript", "typescript", "css", "scss"]
637
- } = options;
638
- function isRelevant(example) {
639
- return languages.includes(example.language);
640
- }
641
- return {
642
- stage: "render",
643
- name: "extract-examples-processor",
644
- async handler(context) {
645
- if (!enabled) {
646
- return;
647
- }
648
- if (!outputFolder) {
649
- throw new Error(
650
- `"outputFolder" not set in "extractExamplesProcessor(..)"`
651
- );
652
- }
653
- await fs.rm(outputFolder, { recursive: true, force: true });
654
- const docs = context.docs.filter(isDocumentPage).filter(haveOutput);
655
- let total = 0;
656
- for (const doc of docs) {
657
- const examples = findExamples$1(doc).filter(isRelevant);
658
- if (examples.length === 0) {
659
- continue;
660
- }
661
- const dir = normalizePath(outputFolder, doc.fileInfo.fullPath);
662
- await fs.mkdir(dir, { recursive: true });
663
- let n = 1;
664
- for (const example of examples) {
665
- const suffix = getSuffix(example.tags);
666
- const extension = getExtension(example.language);
667
- const filename = `example-${example.name ?? String(n++)}${suffix}.${extension}`;
668
- const filePath = path.join(dir, filename);
669
- await fs.writeFile(filePath, example.content, "utf8");
670
- total++;
671
- }
672
- }
673
- context.log(total, "examples extracted");
674
- }
675
- };
628
+ function isDocumentPartial(doc) {
629
+ return doc.kind === "partial";
676
630
  }
677
631
 
678
- const md$5 = MarkdownItCallable();
679
- md$5.renderer.rules.fence = (tokens, idx, _options, env) => {
632
+ const md$6 = MarkdownItCallable();
633
+ md$6.renderer.rules.fence = (tokens, idx, _options, env) => {
680
634
  const { collected, exampleFileMatcher } = env;
681
635
  const { content, info, map } = tokens[idx];
682
636
  const { language: rawLanguage, tags } = parseInfostring(info);
@@ -714,13 +668,13 @@ function flattenOutline(outline) {
714
668
  ];
715
669
  });
716
670
  }
717
- function findExamples(context, doc) {
671
+ function findExamples$1(context, doc) {
718
672
  const { exampleFileMatcher } = context;
719
673
  if (doc.format !== "markdown") {
720
674
  return [];
721
675
  }
722
676
  const collected = [];
723
- md$5.render(doc.body, {
677
+ md$6.render(doc.body, {
724
678
  exampleFileMatcher,
725
679
  collected
726
680
  });
@@ -734,10 +688,11 @@ function manifestPageFromDocument(context, doc) {
734
688
  title: doc.attributes.title ?? doc.name,
735
689
  redirect: format === "redirect" ? body : null,
736
690
  outline: flattenOutline(doc.outline),
737
- examples: findExamples(context, doc)
691
+ examples: findExamples$1(context, doc)
738
692
  };
739
693
  }
740
694
 
695
+ const manifestState = /* @__PURE__ */ Symbol("manifest");
741
696
  function line(page) {
742
697
  if (page.redirect) {
743
698
  return `${page.path} -> ${page.redirect}`;
@@ -792,6 +747,7 @@ function manifestProcessor(options = {}) {
792
747
  return a.path.localeCompare(b.path);
793
748
  });
794
749
  const manifest = { pages };
750
+ context.setState(manifestState, manifest);
795
751
  if (markdown) {
796
752
  const content = normalize(renderMarkdown(manifest));
797
753
  await fs.mkdir(path__default.dirname(markdown), { recursive: true });
@@ -815,6 +771,285 @@ function manifestProcessor(options = {}) {
815
771
  };
816
772
  }
817
773
 
774
+ async function copyFile(src, dst) {
775
+ await fs.mkdir(path__default.dirname(dst), { recursive: true });
776
+ await fs.cp(src, dst);
777
+ }
778
+ function equal(values) {
779
+ return values[0] === values[1];
780
+ }
781
+ function commonPath(a, b) {
782
+ const it = zip(a.split(path__default.sep), b.split(path__default.sep));
783
+ const common = Array.from(takeWhile(it, equal), (it2) => it2[0]);
784
+ return common.join(path__default.sep);
785
+ }
786
+ async function extractExamples(page, options) {
787
+ const { outputFolder } = options;
788
+ for (const example of page.examples) {
789
+ if (!example.src) {
790
+ continue;
791
+ }
792
+ const common = commonPath(
793
+ path__default.resolve(outputFolder),
794
+ path__default.resolve(example.src)
795
+ );
796
+ const subpath = path__default.relative(common, path__default.resolve(example.src));
797
+ await copyFile(example.src, path__default.join(outputFolder, "files", subpath));
798
+ }
799
+ }
800
+ function isMarkdown(doc) {
801
+ return doc.format === "markdown";
802
+ }
803
+ async function getFrontMatter(filePath) {
804
+ const content = await fs.readFile(filePath, "utf8");
805
+ const { attributes } = fm(content);
806
+ delete attributes.redirect_from;
807
+ if (Object.keys(attributes).length === 0) {
808
+ return "";
809
+ }
810
+ return `---
811
+ ${JSON.stringify(attributes)}
812
+ ---
813
+
814
+ `;
815
+ }
816
+ function cmp(a, b) {
817
+ return a[0].localeCompare(b[0]);
818
+ }
819
+ async function extractDocument(doc, docs, partials, options) {
820
+ const { outputFolder } = options;
821
+ const markdown = doc.body.replaceAll(
822
+ /^:::\s*api(.*)\n([\s\S]+?):::/gm,
823
+ (match, info, content2) => {
824
+ const needle = content2.trim();
825
+ const trimmedInfo = info.trim();
826
+ const tags = trimmedInfo ? trimmedInfo.split(/\s+/) : [];
827
+ const result = findDocument(docs, needle);
828
+ if (!result.document) {
829
+ return match;
830
+ }
831
+ const { document, kind, reference } = result;
832
+ if (!isDocumentPartial(document)) {
833
+ return match;
834
+ }
835
+ const body = getDocumentBody(document, tags, {
836
+ kind,
837
+ reference
838
+ });
839
+ const fingerprint = getFingerprint(body);
840
+ const id = `partial:${document.format}:${fingerprint}`;
841
+ partials.set(id, {
842
+ id,
843
+ format: document.format,
844
+ body
845
+ });
846
+ return `:::api
847
+ ${id}
848
+ :::
849
+ `;
850
+ }
851
+ );
852
+ const src = doc.fileInfo.fullPath;
853
+ const dst = path__default.join(outputFolder, "files", doc.fileInfo.fullPath);
854
+ const fm2 = await getFrontMatter(src);
855
+ const content = `${fm2}${markdown}`;
856
+ await fs.mkdir(path__default.dirname(dst), { recursive: true });
857
+ await fs.writeFile(dst, content, "utf8");
858
+ }
859
+ async function extractDocuments(docs, partials, options) {
860
+ const files = docs.filter(isDocumentPage).filter(isMarkdown).filter(haveOutput).map((doc) => extractDocument(doc, docs, partials, options));
861
+ await Promise.all(files);
862
+ }
863
+ async function extractPartials(partials, options) {
864
+ const { outputFolder } = options;
865
+ const dst = path__default.join(outputFolder, "partials.json");
866
+ const content = JSON.stringify(Array.from(partials.values()), null, 2);
867
+ await fs.mkdir(path__default.dirname(dst), { recursive: true });
868
+ await fs.writeFile(dst, content, "utf8");
869
+ }
870
+ async function extractLinks(docs, options) {
871
+ const { outputFolder } = options;
872
+ const links = /* @__PURE__ */ new Map();
873
+ const pages = docs.filter(isDocumentPage).filter(haveOutput);
874
+ for (const page of pages) {
875
+ const path2 = getOutputFilePath("", page.fileInfo);
876
+ links.set(page.id, path2);
877
+ if (!links.has(page.name)) {
878
+ links.set(page.name, path2);
879
+ }
880
+ for (const alias of page.alias) {
881
+ if (!links.has(alias)) {
882
+ links.set(alias, path2);
883
+ }
884
+ }
885
+ }
886
+ const sorted = Array.from(links).toSorted(cmp);
887
+ const entries = Object.fromEntries(sorted);
888
+ const content = JSON.stringify(entries, null, 2);
889
+ const dst = path__default.join(outputFolder, "links.json");
890
+ await fs.mkdir(path__default.dirname(dst), { recursive: true });
891
+ await fs.writeFile(dst, content, "utf8");
892
+ }
893
+ async function writeIndex(options) {
894
+ const { outputFolder } = options;
895
+ const dst = path__default.join(outputFolder, "index.mjs");
896
+ const lines = [
897
+ `import path from "node:path";`,
898
+ `import { frontMatterFileReader, partialFileReader } from "@forsakringskassan/docs-generator";`,
899
+ ``,
900
+ `export const basename = import.meta.dirname;`,
901
+ `export const sourceFiles = [`,
902
+ ` { `,
903
+ ` include: path.join(basename, "files/**/*.md"),`,
904
+ ` basename,`,
905
+ ` fileReader: frontMatterFileReader,`,
906
+ ` }`,
907
+ ` { `,
908
+ ` include: path.join(basename, "partials.json"),`,
909
+ ` basename,`,
910
+ ` fileReader: partialFileReader,`,
911
+ ` }`,
912
+ `];`
913
+ ];
914
+ await fs.writeFile(dst, lines.join("\n"), "utf8");
915
+ }
916
+ async function writeDts(options) {
917
+ const { outputFolder } = options;
918
+ const dst = path__default.join(outputFolder, "index.d.mts");
919
+ const lines = [
920
+ `import { SourceFiles } from "@forsakringskassan/docs-generator";`,
921
+ ``,
922
+ `export declare const basename: string;`,
923
+ `export declare const sourceFiles: SourceFiles[];`
924
+ ];
925
+ await fs.writeFile(dst, lines.join("\n"), "utf8");
926
+ }
927
+ function extractMarkdownProcessor(options) {
928
+ const { enabled = true, outputFolder } = options;
929
+ return {
930
+ after: "render",
931
+ name: "extract-markdown-processor",
932
+ async handler(context) {
933
+ if (!enabled) {
934
+ return;
935
+ }
936
+ if (!outputFolder) {
937
+ throw new Error(
938
+ `"outputFolder" not set in "extractMarkdownProcessor(..)"`
939
+ );
940
+ }
941
+ const manifest = context.getState(manifestState);
942
+ if (!manifest) {
943
+ throw new Error(
944
+ `"extractMarkdownProcessor()" requires "manifestProcess()"`
945
+ );
946
+ }
947
+ await fs.rm(outputFolder, { recursive: true, force: true });
948
+ await fs.mkdir(outputFolder, { recursive: true });
949
+ const partials = /* @__PURE__ */ new Map();
950
+ await extractDocuments(context.docs, partials, { outputFolder });
951
+ await extractPartials(partials, { outputFolder });
952
+ await extractLinks(context.docs, { outputFolder });
953
+ const { pages } = manifest;
954
+ const resources = pages.map((page) => {
955
+ return extractExamples(page, { outputFolder });
956
+ });
957
+ await Promise.all(resources);
958
+ await writeIndex({ outputFolder });
959
+ await writeDts({ outputFolder });
960
+ }
961
+ };
962
+ }
963
+
964
+ const md$5 = MarkdownItCallable();
965
+ md$5.renderer.rules.fence = (tokens, idx, _options, rawEnv) => {
966
+ const { collected } = rawEnv;
967
+ const { content, info } = tokens[idx];
968
+ const { language, tags } = parseInfostring(info);
969
+ if (language === "import") {
970
+ return "";
971
+ }
972
+ const nameTag = tags.find((it) => it.startsWith("name="));
973
+ const name = nameTag ? slugify(nameTag.slice("name=".length)) : void 0;
974
+ collected.push({
975
+ name,
976
+ content,
977
+ language,
978
+ tags
979
+ });
980
+ return "";
981
+ };
982
+ function findExamples(doc) {
983
+ if (doc.format !== "markdown") {
984
+ return [];
985
+ }
986
+ const collected = [];
987
+ md$5.render(doc.body, { collected });
988
+ return collected;
989
+ }
990
+ function getSuffix(tags) {
991
+ const relevant = tags.filter((it) => ["nocompile", "nolint"].includes(it));
992
+ if (relevant.length > 0) {
993
+ return `-${relevant.join("-")}`;
994
+ }
995
+ return "";
996
+ }
997
+ function getExtension(lang) {
998
+ switch (lang) {
999
+ case "typescript":
1000
+ return "ts";
1001
+ case "javascript":
1002
+ return "js";
1003
+ default:
1004
+ return lang;
1005
+ }
1006
+ }
1007
+ function extractExamplesProcessor(options) {
1008
+ const {
1009
+ enabled = true,
1010
+ outputFolder,
1011
+ languages = ["javascript", "typescript", "css", "scss"]
1012
+ } = options;
1013
+ function isRelevant(example) {
1014
+ return languages.includes(example.language);
1015
+ }
1016
+ return {
1017
+ stage: "render",
1018
+ name: "extract-examples-processor",
1019
+ async handler(context) {
1020
+ if (!enabled) {
1021
+ return;
1022
+ }
1023
+ if (!outputFolder) {
1024
+ throw new Error(
1025
+ `"outputFolder" not set in "extractExamplesProcessor(..)"`
1026
+ );
1027
+ }
1028
+ await fs.rm(outputFolder, { recursive: true, force: true });
1029
+ const docs = context.docs.filter(isDocumentPage).filter(haveOutput);
1030
+ let total = 0;
1031
+ for (const doc of docs) {
1032
+ const examples = findExamples(doc).filter(isRelevant);
1033
+ if (examples.length === 0) {
1034
+ continue;
1035
+ }
1036
+ const dir = normalizePath(outputFolder, doc.fileInfo.fullPath);
1037
+ await fs.mkdir(dir, { recursive: true });
1038
+ let n = 1;
1039
+ for (const example of examples) {
1040
+ const suffix = getSuffix(example.tags);
1041
+ const extension = getExtension(example.language);
1042
+ const filename = `example-${example.name ?? String(n++)}${suffix}.${extension}`;
1043
+ const filePath = path.join(dir, filename);
1044
+ await fs.writeFile(filePath, example.content, "utf8");
1045
+ total++;
1046
+ }
1047
+ }
1048
+ context.log(total, "examples extracted");
1049
+ }
1050
+ };
1051
+ }
1052
+
818
1053
  function normalizeOptions(options) {
819
1054
  const defaults = {
820
1055
  enabled: true,
@@ -1141,6 +1376,42 @@ function selectableVersionProcessor(pkg, container, options) {
1141
1376
  };
1142
1377
  }
1143
1378
 
1379
+ function sourceUrlProcessor(...args) {
1380
+ const pkg = args.length === 2 ? args[0] : {};
1381
+ const options = args.length === 2 ? args[1] : args[0];
1382
+ const {
1383
+ enabled = true,
1384
+ sourceFiles = ["**/*"],
1385
+ urlFormat,
1386
+ componentFileExtension = "vue"
1387
+ } = options;
1388
+ const repository = getRepositoryUrl(pkg) ?? "";
1389
+ const matcher = fileMatcher(sourceFiles);
1390
+ return {
1391
+ after: "generate-docs",
1392
+ name: "source-url-processor",
1393
+ async handler(context) {
1394
+ if (!enabled) {
1395
+ return;
1396
+ }
1397
+ const hash = await gitCommitHash("full") ?? "";
1398
+ const short = await gitCommitHash("short") ?? "";
1399
+ function componentSourceUrl(component) {
1400
+ const { source, name } = component;
1401
+ const filename = source ?? `${name}.${componentFileExtension}`;
1402
+ const path = matcher(filename, "when generating source url");
1403
+ return interpolate(urlFormat, {
1404
+ path,
1405
+ hash,
1406
+ short,
1407
+ repository
1408
+ });
1409
+ }
1410
+ context.setTemplateData("componentSourceUrl", componentSourceUrl);
1411
+ }
1412
+ };
1413
+ }
1414
+
1144
1415
  function isNavigationSection(node) {
1145
1416
  return "key" in node;
1146
1417
  }
@@ -1469,59 +1740,6 @@ function versionProcessor(pkg, container, options) {
1469
1740
  };
1470
1741
  }
1471
1742
 
1472
- function sourceUrlProcessor(...args) {
1473
- const pkg = args.length === 2 ? args[0] : {};
1474
- const options = args.length === 2 ? args[1] : args[0];
1475
- const {
1476
- enabled = true,
1477
- sourceFiles = ["**/*"],
1478
- urlFormat,
1479
- componentFileExtension = "vue"
1480
- } = options;
1481
- const repository = getRepositoryUrl(pkg) ?? "";
1482
- const matcher = fileMatcher(sourceFiles);
1483
- return {
1484
- after: "generate-docs",
1485
- name: "source-url-processor",
1486
- async handler(context) {
1487
- if (!enabled) {
1488
- return;
1489
- }
1490
- const hash = await gitCommitHash("full") ?? "";
1491
- const short = await gitCommitHash("short") ?? "";
1492
- function componentSourceUrl(component) {
1493
- const { source, name } = component;
1494
- const filename = source ?? `${name}.${componentFileExtension}`;
1495
- const path = matcher(filename, "when generating source url");
1496
- return interpolate(urlFormat, {
1497
- path,
1498
- hash,
1499
- short,
1500
- repository
1501
- });
1502
- }
1503
- context.setTemplateData("componentSourceUrl", componentSourceUrl);
1504
- }
1505
- };
1506
- }
1507
-
1508
- function cookieProcessor(options = {}) {
1509
- const { enabled = true } = options;
1510
- return {
1511
- after: "generate-docs",
1512
- name: "cookie-processor",
1513
- runtime: [{ src: "src/runtime/cookie.ts" }],
1514
- handler(context) {
1515
- if (!enabled) {
1516
- return;
1517
- }
1518
- context.addTemplateBlock("body:begin", "cookie-warning", {
1519
- filename: "partials/cookie-warning.html"
1520
- });
1521
- }
1522
- };
1523
- }
1524
-
1525
1743
  function generateIndex(entries) {
1526
1744
  const index = {
1527
1745
  terms: [],
@@ -1776,7 +1994,7 @@ function getComponent(attrs) {
1776
1994
  }
1777
1995
  return toArray$1(attrs.component).map(normalizeComponent);
1778
1996
  }
1779
- function parseFile$1(filePath, basePath, content) {
1997
+ function parseFile$2(filePath, basePath, content) {
1780
1998
  const relative = basePath ? path__default.relative(basePath, normalizePath(filePath)) : normalizePath(filePath);
1781
1999
  const parsed = path__default.parse(relative);
1782
2000
  const blocks = fm(content);
@@ -1822,7 +2040,7 @@ function parseFile$1(filePath, basePath, content) {
1822
2040
  }
1823
2041
  async function frontMatterFileReader(filePath, basePath) {
1824
2042
  const content = await fs.readFile(filePath, "utf8");
1825
- const doc = parseFile$1(filePath, basePath, content);
2043
+ const doc = parseFile$2(filePath, basePath, content);
1826
2044
  return [doc];
1827
2045
  }
1828
2046
 
@@ -2589,7 +2807,7 @@ function fileReaderProcessor(sourceFiles) {
2589
2807
  };
2590
2808
  }
2591
2809
 
2592
- function parseFile(filePath, basePath, content) {
2810
+ function parseFile$1(filePath, basePath, content) {
2593
2811
  const attributes = JSON.parse(content);
2594
2812
  const { title, href } = attributes;
2595
2813
  if (!title) {
@@ -2628,10 +2846,31 @@ function parseFile(filePath, basePath, content) {
2628
2846
  }
2629
2847
  async function navigationFileReader(filePath, basePath) {
2630
2848
  const content = await fs.readFile(filePath, "utf8");
2631
- const doc = parseFile(filePath, basePath, content);
2849
+ const doc = parseFile$1(filePath, basePath, content);
2632
2850
  return [doc];
2633
2851
  }
2634
2852
 
2853
+ function parseFile(filePath, content) {
2854
+ const parsed = JSON.parse(content);
2855
+ return parsed.map((it) => {
2856
+ return {
2857
+ kind: "partial",
2858
+ id: it.id,
2859
+ name: it.id,
2860
+ alias: [],
2861
+ body: it.body,
2862
+ format: it.format,
2863
+ fileInfo: {
2864
+ fullPath: filePath
2865
+ }
2866
+ };
2867
+ });
2868
+ }
2869
+ async function partialFileReader(filePath) {
2870
+ const content = await fs.readFile(filePath, "utf8");
2871
+ return parseFile(filePath, content);
2872
+ }
2873
+
2635
2874
  async function compileSassString(dst, style) {
2636
2875
  const result = await compileStringAsync(style, {
2637
2876
  style: "expanded",
@@ -2716,9 +2955,11 @@ function toExternalVendor(vendor) {
2716
2955
  }
2717
2956
  async function compileScript(options) {
2718
2957
  const {
2719
- assetFolder,
2720
2958
  name,
2721
2959
  src,
2960
+ rootDir,
2961
+ outputFolder,
2962
+ outputName,
2722
2963
  assets,
2723
2964
  vendor,
2724
2965
  buildOptions,
@@ -2747,15 +2988,19 @@ async function compileScript(options) {
2747
2988
  const content = await fs$1.readFile(outfile, "utf8");
2748
2989
  const fingerprint = getFingerprint(content);
2749
2990
  const integrity = getIntegrity(content);
2750
- const filename = `${name}-${fingerprint}.js`;
2751
- const dst = path__default.join(assetFolder, filename);
2991
+ const filename = `${outputName}.js`.replaceAll("[name]", () => name).replaceAll("[hash]", () => fingerprint);
2992
+ const dst = path__default.join(outputFolder, filename);
2993
+ const publicPath = path__default.posix.join(
2994
+ path__default.posix.relative(rootDir, outputFolder),
2995
+ filename
2996
+ );
2752
2997
  await fs$1.mkdir(path__default.dirname(dst), { recursive: true });
2753
2998
  await fs$1.rename(outfile, dst);
2754
2999
  const stat = await fs$1.stat(dst);
2755
3000
  return {
2756
3001
  name,
2757
3002
  filename,
2758
- publicPath: `./assets/${filename}`,
3003
+ publicPath: `./${publicPath}`,
2759
3004
  integrity,
2760
3005
  format,
2761
3006
  size: stat.size,
@@ -2775,7 +3020,7 @@ function byPriority({ options: a }, { options: b }) {
2775
3020
  function isExternal(asset) {
2776
3021
  return asset.options.appendTo === "none";
2777
3022
  }
2778
- function jsAssetProcessor(assetFolder, assets, vendor) {
3023
+ function jsAssetProcessor(rootDir, assets, vendor) {
2779
3024
  const externalAssets = assets.filter(isExternal).map((it) => it.name);
2780
3025
  return {
2781
3026
  name: "js-asset-processor",
@@ -2786,9 +3031,11 @@ function jsAssetProcessor(assetFolder, assets, vendor) {
2786
3031
  const body = context.getTemplateData("injectBody", []);
2787
3032
  for (const asset of assets.toSorted(byPriority)) {
2788
3033
  const info = await compileScript({
2789
- assetFolder,
2790
3034
  name: asset.name,
2791
3035
  src: asset.src,
3036
+ rootDir,
3037
+ outputFolder: asset.outputFolder,
3038
+ outputName: asset.outputName,
2792
3039
  assets: externalAssets,
2793
3040
  vendor,
2794
3041
  buildOptions: asset.buildOptions
@@ -3761,6 +4008,7 @@ function createContext(options) {
3761
4008
  visible: true
3762
4009
  };
3763
4010
  const templateData = /* @__PURE__ */ new Map();
4011
+ const stateData = /* @__PURE__ */ new Map();
3764
4012
  return {
3765
4013
  get docs() {
3766
4014
  return docs;
@@ -3827,6 +4075,15 @@ function createContext(options) {
3827
4075
  },
3828
4076
  setTemplateData(key, value) {
3829
4077
  templateData.set(key, value);
4078
+ },
4079
+ setState(key, value) {
4080
+ stateData.set(key, value);
4081
+ },
4082
+ getState(key) {
4083
+ if (!stateData.has(key)) {
4084
+ return null;
4085
+ }
4086
+ return stateData.get(key);
3830
4087
  }
3831
4088
  };
3832
4089
  }
@@ -3900,9 +4157,12 @@ class Generator {
3900
4157
  });
3901
4158
  }
3902
4159
  compileScript(name, src, options, buildOptions) {
4160
+ const { assetFolder } = this;
3903
4161
  this.scripts.push({
3904
4162
  name,
3905
4163
  src,
4164
+ outputFolder: assetFolder,
4165
+ outputName: "[name]-[hash]",
3906
4166
  options: {
3907
4167
  appendTo: "none",
3908
4168
  attributes: {},
@@ -3914,6 +4174,37 @@ class Generator {
3914
4174
  }
3915
4175
  });
3916
4176
  }
4177
+ /**
4178
+ * Compile a worker script.
4179
+ *
4180
+ * This is mostly the same as {@link Generator.compileScript} with some differences:
4181
+ *
4182
+ * - The script is written directly to `outputFolder` instead of `assetFolder` (i.e. to the web root).
4183
+ * - The output filename does not include a hash.
4184
+ *
4185
+ * @public
4186
+ * @since %version%
4187
+ * @param name - Asset name.
4188
+ * @param src - Asset entrypoint.
4189
+ * @param buildOptions - Options passed to `esbuild`.
4190
+ */
4191
+ compileWorker(name, src, buildOptions) {
4192
+ const { outputFolder } = this;
4193
+ this.scripts.push({
4194
+ name,
4195
+ src,
4196
+ outputFolder,
4197
+ outputName: "[name]",
4198
+ options: {
4199
+ appendTo: "none",
4200
+ attributes: {},
4201
+ priority: 0
4202
+ },
4203
+ buildOptions: {
4204
+ ...buildOptions
4205
+ }
4206
+ });
4207
+ }
3917
4208
  compileStyle(name, src, options) {
3918
4209
  this.styles.push({
3919
4210
  name,
@@ -3996,7 +4287,7 @@ class Generator {
3996
4287
  redirectProcessor(),
3997
4288
  vendorProcessor(assetFolder, this.vendor),
3998
4289
  cssAssetProcessor(assetFolder, this.styles),
3999
- jsAssetProcessor(assetFolder, this.scripts, this.vendor),
4290
+ jsAssetProcessor(outputFolder, this.scripts, this.vendor),
4000
4291
  staticResourcesProcessor(assetFolder, this.resources),
4001
4292
  navigationProcessor(),
4002
4293
  nunjucksProcessor({
@@ -4072,5 +4363,5 @@ class Generator {
4072
4363
  }
4073
4364
  }
4074
4365
 
4075
- export { Generator, apiExtractorProcessor, availableProcessors, cookieProcessor, defineSources, extractExamplesProcessor, frontMatterFileReader, htmlRedirectProcessor, isRelease, livereloadProcessor, manifestProcessor, matomoProcessor, motdProcessor, navigationFileReader, playgroundProcessor, processorRuntimeName, redirectFileProcessor, searchProcessor, selectableVersionProcessor, sourceUrlProcessor, topnavProcessor, versionBannerProcessor, versionProcessor, vueFileReader };
4366
+ export { Generator, apiExtractorProcessor, availableProcessors, cookieProcessor, defineSources, extractExamplesProcessor, extractMarkdownProcessor, frontMatterFileReader, htmlRedirectProcessor, isRelease, livereloadProcessor, manifestProcessor, matomoProcessor, motdProcessor, navigationFileReader, partialFileReader, playgroundProcessor, processorRuntimeName, redirectFileProcessor, searchProcessor, selectableVersionProcessor, sourceUrlProcessor, topnavProcessor, versionBannerProcessor, versionProcessor, vueFileReader };
4076
4367
  //# sourceMappingURL=index.mjs.map