@forsakringskassan/docs-generator 3.9.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.
@@ -2,7 +2,7 @@ import { createRequire as $createRequire } from "node:module";
2
2
 
3
3
  const require = $createRequire(import.meta.url);
4
4
 
5
- import { r as runAsWorker, f as format2, a as resolveConfig } from './vendor-DqIMfP3a.mjs';
5
+ import { r as runAsWorker, f as format2, a as resolveConfig } from './vendor-DPuGyhL4.mjs';
6
6
  import 'node:url';
7
7
  import 'node:path';
8
8
  import 'fs';
@@ -54,4 +54,4 @@ async function formatCode(source, filepath) {
54
54
  runAsWorker(formatCode);
55
55
 
56
56
  export { formatCode };
57
- //# sourceMappingURL=format-code.worker-CB5zyf9p.mjs.map
57
+ //# sourceMappingURL=format-code.worker-BsG38cNK.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"format-code.worker-CB5zyf9p.mjs","sources":["../src/utils/format-code.worker.ts"],"sourcesContent":["import { type Options, format as prettier, resolveConfig } from \"prettier\";\nimport { runAsWorker } from \"synckit\";\n\nconst configCache = new Map<string, Options | null>();\n\nasync function getConfig(filepath: string): Promise<Options | null> {\n const cached = configCache.get(filepath);\n if (cached !== undefined) {\n return cached;\n }\n const options = await resolveConfig(filepath);\n configCache.set(filepath, options);\n return options;\n}\n\n/**\n * @internal\n */\nexport async function formatCode(\n source: string,\n filepath: string,\n): Promise<string> {\n const options = await getConfig(filepath);\n const formatted = await prettier(source, { ...options, filepath });\n return formatted.trim();\n}\n\n/* eslint-disable-next-line unicorn/no-top-level-side-effects -- required for worker to function */\nrunAsWorker(formatCode);\n"],"names":["prettier"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,MAAM,WAAA,uBAAkB,GAAA,EAA4B;AAEpD,eAAe,UAAU,QAAA,EAA2C;AAChE,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,GAAA,CAAI,QAAQ,CAAA;AACvC,EAAA,IAAI,WAAW,MAAA,EAAW;AACtB,IAAA,OAAO,MAAA;AAAA,EACX;AACA,EAAA,MAAM,OAAA,GAAU,MAAM,aAAA,CAAc,QAAQ,CAAA;AAC5C,EAAA,WAAA,CAAY,GAAA,CAAI,UAAU,OAAO,CAAA;AACjC,EAAA,OAAO,OAAA;AACX;AAKA,eAAsB,UAAA,CAClB,QACA,QAAA,EACe;AACf,EAAA,MAAM,OAAA,GAAU,MAAM,SAAA,CAAU,QAAQ,CAAA;AACxC,EAAA,MAAM,SAAA,GAAY,MAAMA,OAAA,CAAS,MAAA,EAAQ,EAAE,GAAG,OAAA,EAAS,UAAU,CAAA;AACjE,EAAA,OAAO,UAAU,IAAA,EAAK;AAC1B;AAGA,WAAA,CAAY,UAAU,CAAA;;"}
1
+ {"version":3,"file":"format-code.worker-BsG38cNK.mjs","sources":["../src/utils/format-code.worker.ts"],"sourcesContent":["import { type Options, format as prettier, resolveConfig } from \"prettier\";\nimport { runAsWorker } from \"synckit\";\n\nconst configCache = new Map<string, Options | null>();\n\nasync function getConfig(filepath: string): Promise<Options | null> {\n const cached = configCache.get(filepath);\n if (cached !== undefined) {\n return cached;\n }\n const options = await resolveConfig(filepath);\n configCache.set(filepath, options);\n return options;\n}\n\n/**\n * @internal\n */\nexport async function formatCode(\n source: string,\n filepath: string,\n): Promise<string> {\n const options = await getConfig(filepath);\n const formatted = await prettier(source, { ...options, filepath });\n return formatted.trim();\n}\n\n/* eslint-disable-next-line unicorn/no-top-level-side-effects -- required for worker to function */\nrunAsWorker(formatCode);\n"],"names":["prettier"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,MAAM,WAAA,uBAAkB,GAAA,EAA4B;AAEpD,eAAe,UAAU,QAAA,EAA2C;AAChE,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,GAAA,CAAI,QAAQ,CAAA;AACvC,EAAA,IAAI,WAAW,MAAA,EAAW;AACtB,IAAA,OAAO,MAAA;AAAA,EACX;AACA,EAAA,MAAM,OAAA,GAAU,MAAM,aAAA,CAAc,QAAQ,CAAA;AAC5C,EAAA,WAAA,CAAY,GAAA,CAAI,UAAU,OAAO,CAAA;AACjC,EAAA,OAAO,OAAA;AACX;AAKA,eAAsB,UAAA,CAClB,QACA,QAAA,EACe;AACf,EAAA,MAAM,OAAA,GAAU,MAAM,SAAA,CAAU,QAAQ,CAAA;AACxC,EAAA,MAAM,SAAA,GAAY,MAAMA,OAAA,CAAS,MAAA,EAAQ,EAAE,GAAG,OAAA,EAAS,UAAU,CAAA;AACjE,EAAA,OAAO,UAAU,IAAA,EAAK;AAC1B;AAGA,WAAA,CAAY,UAAU,CAAA;;"}
package/dist/index.d.mts CHANGED
@@ -213,6 +213,25 @@ export declare interface ExtractExamplesOptions extends ProcessorOptions {
213
213
  */
214
214
  export declare function extractExamplesProcessor(options: ExtractExamplesOptions): Processor;
215
215
 
216
+ /**
217
+ * Options for `extractMarkdownProcessor`.
218
+ *
219
+ * @public
220
+ */
221
+ export declare interface ExtractMarkdownOptions extends ProcessorOptions {
222
+ /**
223
+ * Folder to write docs to.
224
+ */
225
+ outputFolder: string;
226
+ }
227
+
228
+ /**
229
+ * Processor to extract and write examples to separate files.
230
+ *
231
+ * @public
232
+ */
233
+ export declare function extractMarkdownProcessor(options: ExtractMarkdownOptions): Processor;
234
+
216
235
  /**
217
236
  * @public
218
237
  */
@@ -720,6 +739,8 @@ export declare interface ProcessorContext {
720
739
  readonly sidenav: NavigationSection;
721
740
  readonly resources: ResourceTask[];
722
741
  readonly outputFolder: string;
742
+ setState<K extends keyof StateMap>(key: K, value: StateMap[K]): void;
743
+ getState<K extends keyof StateMap>(key: K): StateMap[K] | null;
723
744
  addDocument(document: Document_2 | Document_2[]): void;
724
745
  addVendorAsset(asset: VendorAsset | VendorAsset[]): void;
725
746
  /**
@@ -926,6 +947,12 @@ export declare interface SourceUrlProcessorOptions extends ProcessorOptions {
926
947
  readonly componentFileExtension?: string;
927
948
  }
928
949
 
950
+ /**
951
+ * @public
952
+ */
953
+ export declare interface StateMap {
954
+ }
955
+
929
956
  /* Excluded from this release type: TemplateBlockData */
930
957
 
931
958
  /**
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: [],
@@ -3790,6 +4008,7 @@ function createContext(options) {
3790
4008
  visible: true
3791
4009
  };
3792
4010
  const templateData = /* @__PURE__ */ new Map();
4011
+ const stateData = /* @__PURE__ */ new Map();
3793
4012
  return {
3794
4013
  get docs() {
3795
4014
  return docs;
@@ -3856,6 +4075,15 @@ function createContext(options) {
3856
4075
  },
3857
4076
  setTemplateData(key, value) {
3858
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);
3859
4087
  }
3860
4088
  };
3861
4089
  }
@@ -4135,5 +4363,5 @@ class Generator {
4135
4363
  }
4136
4364
  }
4137
4365
 
4138
- export { Generator, apiExtractorProcessor, availableProcessors, cookieProcessor, defineSources, extractExamplesProcessor, frontMatterFileReader, htmlRedirectProcessor, isRelease, livereloadProcessor, manifestProcessor, matomoProcessor, motdProcessor, navigationFileReader, partialFileReader, 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 };
4139
4367
  //# sourceMappingURL=index.mjs.map