dogsbay 0.2.0-beta.92 → 0.2.0-beta.93

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.
@@ -22,7 +22,7 @@ function getSourceDir() {
22
22
  return monorepo;
23
23
  throw new Error("Could not find component source files.");
24
24
  }
25
- function collectDependencies(names) {
25
+ export function collectDependencies(names) {
26
26
  const visited = new Set();
27
27
  const components = [];
28
28
  const npmDeps = [];
@@ -8,11 +8,13 @@
8
8
  * and runs `dogsbay site build`; the AsciiDoc source can be
9
9
  * deleted.
10
10
  *
11
- * Phase 8b of plans/format-asciidoc-import.md. Plain-corpus loader
12
- * only; topology-aware loaders (AsciiBinder `_topic_map.yml`,
13
- * Antora playbooks, AAP `master.adoc` walks) ship in Phase 9 per
14
- * plans/asciidoc-corpus-loaders.md and will hook in here without
15
- * changing the output shape.
11
+ * Corpus discovery is delegated to the `@dogsbay/format-asciidoc`
12
+ * CorpusLoader registry (see `asciidocPlugin.import` below), so the
13
+ * topology-aware loaders are live: detection auto-picks AsciiBinder
14
+ * (`_topic_maps/_topic_map.yml`), AAP (`master.adoc`), Antora component
15
+ * (`antora.yml`), or the plain `.adoc` walk, and topology files never
16
+ * accidentally become pages. Override with `--loader`.
17
+ * See plans/asciidoc-corpus-loaders.md.
16
18
  *
17
19
  * Output layout — same convention as `migrate-mkdocs`:
18
20
  *
@@ -29,10 +31,11 @@ import { copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readFileSync, r
29
31
  import { basename, dirname, join, relative, resolve } from "node:path";
30
32
  import pc from "picocolors";
31
33
  import { emitSiteScaffold } from "@dogsbay/format-astro";
32
- import { plugin as asciidocPlugin } from "@dogsbay/format-asciidoc/cli";
34
+ import { plugin as asciidocPlugin, pickLoader } from "@dogsbay/format-asciidoc/cli";
33
35
  import { asciidocToMarkdown } from "@dogsbay/adoc2md-modular";
34
36
  import { treeToDogsbayMd } from "@dogsbay/format-dogsbay-md";
35
37
  import { ensureGitignore } from "../utils/gitignore.js";
38
+ import { inlineRemoteIncludes, hasRemoteIncludes } from "../utils/remote-includes.js";
36
39
  function parseAttributePairs(pairs) {
37
40
  const out = {};
38
41
  for (const raw of pairs ?? []) {
@@ -211,6 +214,9 @@ function convertFragmentAdocs(sourceRoot, outputContentDir, scopedRootDirs, page
211
214
  let converted = 0;
212
215
  let failed = 0;
213
216
  let skipped = 0;
217
+ // Fragment .md files that carry a `{% include "https://…" %}` directive —
218
+ // resolved by an async fetch pass after the (sync) walk completes. (#007)
219
+ const remoteIncludePaths = [];
214
220
  function walk(srcDir, dstDir, depth) {
215
221
  let entries;
216
222
  try {
@@ -302,6 +308,8 @@ function convertFragmentAdocs(sourceRoot, outputContentDir, scopedRootDirs, page
302
308
  // pursue option A through a non-frontmatter signal that
303
309
  // can't collide with Jinja whitespace control.
304
310
  writeFileSync(mdPath, md, "utf-8");
311
+ if (hasRemoteIncludes(md))
312
+ remoteIncludePaths.push(mdPath);
305
313
  converted += 1;
306
314
  }
307
315
  catch (err) {
@@ -312,7 +320,7 @@ function convertFragmentAdocs(sourceRoot, outputContentDir, scopedRootDirs, page
312
320
  }
313
321
  }
314
322
  walk(sourceRoot, outputContentDir, 0);
315
- return { converted, failed, skipped };
323
+ return { converted, failed, skipped, remoteIncludePaths };
316
324
  }
317
325
  /**
318
326
  * Serialize a NavItem[] (from a CorpusLoader) to nav.yml syntax.
@@ -400,6 +408,21 @@ function buildDogsbayConfig(opts) {
400
408
  return lines.join("\n");
401
409
  }
402
410
  function buildMigrationNotes(opts) {
411
+ // Report the loader that actually ran rather than assuming a plain
412
+ // walk. The non-plain loaders read a topology source for the nav and
413
+ // route only topology-declared pages; `modules/` / `snippets/` /
414
+ // `_attributes/` are pulled in as include targets, not pages.
415
+ const loaderDesc = {
416
+ asciibinder: "AsciiBinder topology (`_topic_maps/_topic_map.yml`)",
417
+ "master-adoc": "AAP `master.adoc` topology",
418
+ antora: "Antora component (`antora.yml`)",
419
+ plain: "plain AsciiDoc — flat `.adoc` walk",
420
+ };
421
+ const corpusDesc = loaderDesc[opts.loader] ?? `\`${opts.loader}\` loader`;
422
+ const distroNote = opts.distro ? `, distro \`${opts.distro}\`` : "";
423
+ const topologyDidnt = opts.loader === "plain"
424
+ ? "- **Topology**: the plain loader walked every `.adoc` flat and derived the nav from the directory layout. If your source is actually AsciiBinder (`_topic_maps/_topic_map.yml`), Antora (`antora.yml`), or AAP (`master.adoc`), re-run with `--loader <name>` (or rely on auto-detection) to use the curated topology and per-page distro filtering instead.\n"
425
+ : "";
403
426
  const hasAttrs = Object.keys(opts.attributes).length > 0;
404
427
  const attrSummary = hasAttrs
405
428
  ? Object.entries(opts.attributes)
@@ -416,7 +439,7 @@ Generated by \`dogsbay migrate-asciidoc\`.
416
439
  ## Summary
417
440
 
418
441
  - **Site name:** ${opts.siteName}
419
- - **Source corpus:** \`${opts.sourceDir}\` (plain AsciiDoc — \`.adoc\` walk)
442
+ - **Source corpus:** \`${opts.sourceDir}\` (${corpusDesc}${distroNote})
420
443
  - **Output:** \`${opts.outputDir}\`
421
444
  - **Pages migrated:** ${opts.pageCount}
422
445
 
@@ -455,8 +478,7 @@ See \`docs/asciidoc.md\` for the full preprocessor behaviour.
455
478
 
456
479
  ## What didn't (yet)
457
480
 
458
- - **Topology**: this migration walked every \`.adoc\` under \`${opts.sourceDir}\` as a flat plain-AsciiDoc corpus. If your source uses AsciiBinder \`_topic_map.yml\`, Antora \`antora-playbook.yml\`, or AAP \`master.adoc\` discovery, those topologies are not yet understood — the dedicated corpus loaders are planned for a future release (see \`plans/asciidoc-corpus-loaders.md\`).
459
- - **Line-form admonition layout**: \`NOTE: foo\` lines always emit the HTML-shaped \`**📌 NOTE**\\\` prefix regardless of options. Block-form \`[NOTE]\\n====\\n…\\n====\` does respect the configured \`admonitionFormat\`.
481
+ ${topologyDidnt}- **Line-form admonition layout**: \`NOTE: foo\` lines always emit the HTML-shaped \`**📌 NOTE**\\\` prefix regardless of options. Block-form \`[NOTE]\\n====\\n…\\n====\` does respect the configured \`admonitionFormat\`.
460
482
 
461
483
  ## Next steps
462
484
 
@@ -540,6 +562,7 @@ export async function migrateAsciidoc(source, options) {
540
562
  attributes: engineAttributes,
541
563
  loader: options.loader,
542
564
  distro: options.distro,
565
+ topicMap: options.topicMap,
543
566
  });
544
567
  if (importedPages.length === 0) {
545
568
  console.log(pc.red(`Error: no .adoc files found under ${sourceDir}`));
@@ -548,6 +571,13 @@ export async function migrateAsciidoc(source, options) {
548
571
  }
549
572
  console.log(`Pages: ${importedPages.length}`);
550
573
  console.log();
574
+ // Which loader did the import auto-pick? Re-run detection (cheap —
575
+ // filesystem existence checks) so MIGRATION.md reports the topology
576
+ // that actually ran, not a hardcoded "plain walk" string. The import
577
+ // above already succeeded, so this won't throw on a no-match.
578
+ const loaderName = pickLoader(sourceDir, options.loader, {
579
+ topicMap: options.topicMap,
580
+ }).name;
551
581
  // 3. Write each page to disk with title frontmatter.
552
582
  //
553
583
  // When the importer populated `page.bodyMarkdown` (currently only
@@ -620,6 +650,26 @@ export async function migrateAsciidoc(source, options) {
620
650
  (frag.skipped > 0 ? ` (${frag.skipped} already-written page paths skipped)` : "") +
621
651
  (frag.failed > 0 ? ` (${frag.failed} failed)` : ""));
622
652
  }
653
+ // 3c-bis. Resolve remote `include::https://…[]` directives: fetch each URL
654
+ // once and bake it into the fragment as a fenced code block, so the build
655
+ // has no runtime network dependency and the content isn't dropped. (#007)
656
+ if (frag.remoteIncludePaths.length > 0) {
657
+ const cache = new Map();
658
+ let inlined = 0;
659
+ for (const mdPath of frag.remoteIncludePaths) {
660
+ const before = readFileSync(mdPath, "utf-8");
661
+ const after = await inlineRemoteIncludes(before, { cache });
662
+ if (after !== before) {
663
+ writeFileSync(mdPath, after, "utf-8");
664
+ inlined += 1;
665
+ }
666
+ }
667
+ const failures = [...cache.values()].filter((v) => v === null).length;
668
+ console.log(pc.green(`Inlined`) +
669
+ ` remote includes in ${inlined} fragment(s) (${cache.size} URL(s)` +
670
+ (failures > 0 ? `, ${failures} unreachable` : "") +
671
+ `)`);
672
+ }
623
673
  // 3d. Mirror non-`.adoc` filesystem entries within the scoped
624
674
  // set: symlinks (critical for AsciiBinder include resolution
625
675
  // where per-section dirs symlink back to root `_attributes/`,
@@ -695,6 +745,8 @@ export async function migrateAsciidoc(source, options) {
695
745
  pageCount: importedPages.length,
696
746
  attributes,
697
747
  rerunCmd,
748
+ loader: loaderName,
749
+ distro: options.distro,
698
750
  }));
699
751
  console.log(pc.green(`Wrote`) + ` MIGRATION.md`);
700
752
  if (!options.quiet) {
@@ -45,6 +45,17 @@ export async function migrateFluidtopicsRest(source, options) {
45
45
  portalBase: source,
46
46
  maps: options.map,
47
47
  titleFilter: options.titleFilter,
48
+ groupBy: options.groupBy,
49
+ singlePageBooks: options.singlePageBooks,
50
+ keepDuplicateMaps: options.keepDuplicateMaps,
51
+ metadataAllow: options.metadata?.split(",").map((s) => s.trim()).filter(Boolean),
52
+ fullTopicMetadata: options.fullTopicMetadata,
53
+ // Custom facets: editorialType (book/article), version, and subject (the
54
+ // DITA subjectScheme "Subject matter" / PBS facet, now lifted per-topic).
55
+ // category & audience are built-in. parseMeta lifts these into
56
+ // page.meta.taxonomies → DocsLayout emits data-pagefind-filter → Pagefind
57
+ // facets. (#search-facets)
58
+ taxonomyNames: ["editorialType", "version", "subject"],
48
59
  lang: options.lang,
49
60
  hrefPrefix,
50
61
  throttleMs: options.throttle ? Number(options.throttle) : undefined,
@@ -74,6 +85,18 @@ export async function migrateFluidtopicsRest(source, options) {
74
85
  schemaVersion: 1,
75
86
  site: { name: siteName, url: options.siteUrl, basePath },
76
87
  content: { sources: [{ path: "./content", from: "dogsbay-md" }] },
88
+ // FT faceted metadata → search filters. `category` / `audience` are
89
+ // built-in facets (no declaration needed); `editorialType` (book/article),
90
+ // `version`, and `subject` (the DITA subjectScheme "Subject matter" / PBS
91
+ // facet) are declared here so the build extracts them into each page's
92
+ // taxonomies, DocsLayout emits the data-pagefind-filter divs, and Pagefind
93
+ // surfaces them as facet columns. Also gives browseable term index pages
94
+ // (/format, /version, /subject). See docs-dev/fluidtopics-rest-importer.md.
95
+ taxonomies: {
96
+ editorialType: { indexPath: "/format", order: 2 },
97
+ version: { indexPath: "/version", order: 3 },
98
+ subject: { indexPath: "/subject", order: 4 },
99
+ },
77
100
  agent: { llmsTxt: true, mdMirror: true },
78
101
  };
79
102
  writeFileSync(join(outputDir, "dogsbay.config.yml"), serializeConfig(config, "yaml"));
@@ -90,7 +113,20 @@ export async function migrateFluidtopicsRest(source, options) {
90
113
  function navItemsToSingleKey(items, basePath) {
91
114
  const out = [];
92
115
  for (const item of items) {
93
- if (item.children && item.children.length > 0) {
116
+ // A node carrying a single-page annotation uses the EXPLICIT nav form
117
+ // (`{ title, single-page, items }`) so the annotation survives into nav.yml;
118
+ // unannotated nodes keep the compact single-key form.
119
+ if (item.singlePage) {
120
+ const entry = { title: item.label, "single-page": item.singlePage };
121
+ if (item.children && item.children.length > 0) {
122
+ entry.items = navItemsToSingleKey(item.children, basePath);
123
+ }
124
+ else if (item.href) {
125
+ entry.file = hrefToNavPath(item.href, basePath);
126
+ }
127
+ out.push(entry);
128
+ }
129
+ else if (item.children && item.children.length > 0) {
94
130
  out.push({ [item.label]: navItemsToSingleKey(item.children, basePath) });
95
131
  }
96
132
  else if (item.href) {
@@ -104,6 +104,15 @@ function validate(parsed, sourcePath) {
104
104
  const propSchema = validatePropSchema(obj.propSchema, sourcePath);
105
105
  const plugins = validatePlugins(obj.plugins, sourcePath);
106
106
  const attributes = validateAttributes(obj.attributes, "attributes", sourcePath);
107
+ if (obj.granularity !== undefined) {
108
+ if (typeof obj.granularity !== "object" || obj.granularity === null) {
109
+ throw new Error(`granularity must be an object in ${sourcePath}`);
110
+ }
111
+ const g = obj.granularity;
112
+ if (g.book !== undefined && typeof g.book !== "boolean") {
113
+ throw new Error(`granularity.book must be a boolean in ${sourcePath}`);
114
+ }
115
+ }
107
116
  // Pass through validated structure — applyDefaults handles missing
108
117
  // optionals and contentSignal sub-fields.
109
118
  return {
@@ -121,6 +130,7 @@ function validate(parsed, sourcePath) {
121
130
  propSchema,
122
131
  plugins,
123
132
  attributes,
133
+ granularity: obj.granularity,
124
134
  };
125
135
  }
126
136
  /**
@@ -29,6 +29,7 @@ export function configToAstroOptions(config) {
29
29
  navMode: config.build?.navMode,
30
30
  llmsTxt: config.agent?.llmsTxt,
31
31
  mdMirror: config.agent?.mdMirror,
32
+ granularity: config.granularity,
32
33
  aiTrain: config.agent?.contentSignal?.aiTrain,
33
34
  aiInput: config.agent?.contentSignal?.aiInput,
34
35
  aiSearch: config.agent?.contentSignal?.search,
package/dist/index.js CHANGED
@@ -213,10 +213,11 @@ program
213
213
  .action((source, options) => migrateMkdocs(source, options));
214
214
  program
215
215
  .command("migrate-asciidoc")
216
- .description("One-way migrate a plain AsciiDoc corpus to a scaffolded Dogsbay-MD " +
216
+ .description("One-way migrate an AsciiDoc corpus to a scaffolded Dogsbay-MD " +
217
217
  "project. Source-of-truth becomes ./content/*.md; the AsciiDoc source " +
218
- "can be deleted. Plain .adoc directory walk only — AsciiBinder, " +
219
- "Antora, and AAP master.adoc loaders are planned for a later release.")
218
+ "can be deleted. Topology is auto-detected — AsciiBinder " +
219
+ "(_topic_maps/_topic_map.yml), AAP (master.adoc), Antora (antora.yml), " +
220
+ "or a plain .adoc directory walk; override with --loader.")
220
221
  .argument("<source>", "Path to a directory containing .adoc files")
221
222
  .option("-o, --output <dir>", "Output directory (default: {source}-dogsbay)")
222
223
  .option("--force", "Overwrite an existing Dogsbay site. Clean re-import: clears the " +
@@ -228,10 +229,14 @@ program
228
229
  .option("-a, --attribute <name=value>", "AsciiDoc attribute (repeatable). Resolved refs/conditionals get " +
229
230
  "baked into the migrated Dogsbay-MD; unresolved ones survive as " +
230
231
  "{{ var }} / {% if %} for a downstream Minja pass.", (val, prev = []) => [...prev, val])
231
- .option("--loader <name>", "Force a corpus loader (plain, master-adoc). Auto-detected when omitted.")
232
+ .option("--loader <name>", "Force a corpus loader (plain, master-adoc, asciibinder, antora). " +
233
+ "Auto-detected when omitted.")
232
234
  .option("--distro <name>", "AsciiBinder distro filter (e.g. 'openshift-enterprise'). Topic-map " +
233
235
  "entries whose Distros: list excludes this value are dropped from " +
234
236
  "the page set and nav. Entries without Distros: are kept as universal.")
237
+ .option("--topic-map <path>", "AsciiBinder topic-map path, relative to the source root " +
238
+ "(default: _topic_maps/_topic_map.yml). Drives loader detection and " +
239
+ "loading for corpora that name their topic map differently.")
235
240
  .option("--local", "Use file: references to local monorepo packages (for development)")
236
241
  .option("--quiet", "Suppress the 'Next steps' trailer")
237
242
  .action((source, options) => migrateAsciidoc(source, options));
@@ -269,6 +274,11 @@ program
269
274
  .option("--lang <locale>", "Locale to request from the portal (e.g. en-US)")
270
275
  .option("--throttle <ms>", "Delay between khub requests (default 150)")
271
276
  .option("--single-page", "Roll each map into ONE page (whole book) instead of one page per topic; xrefs become in-page anchors")
277
+ .option("--group-by <facets>", "Group the nav by map metadata facet(s), comma-separated (e.g. Category or Product,Category). Default: auto (Category). Use 'none' to keep it flat")
278
+ .option("--single-page-books", "Mark book-type maps (editorialType=book) with single-page: yes — an additive 'Read as single page' rollup per guide; articles stay per-topic (size cap applies)")
279
+ .option("--keep-duplicate-maps", "Keep stale duplicate publications (same title+version). Default: keep only the freshest ft:lastEdition per guide, removing duplicate nav entries")
280
+ .option("--metadata <keys>", "Extra FT topic-metadata keys to lift into page frontmatter, comma-separated (beyond the curated subject/product/author/category/audience/version set)")
281
+ .option("--full-topic-metadata", "Fetch full per-topic metadata (one request per topic) for accurate per-topic ft:wordCount/ft:outputSize + 'updated' date. Roughly doubles requests; off by default (technical numerics emit at book level only)")
272
282
  .option("--local", "Use file: references to local monorepo packages (for development)")
273
283
  .option("--quiet", "Suppress the trailer")
274
284
  .action((source, options) => migrateFluidtopicsRest(source, options));
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Remote AsciiDoc include resolution (migrate time).
3
+ *
4
+ * AsciiDoc `include::https://…[]` inlines remote content at build time
5
+ * (AsciiBinder runs with `--allow-uri-read`). The adoc2md engine — which is
6
+ * pure and does no network I/O — emits the URL form as a Minja directive
7
+ * `{% include "./https://…" %}`. The build-time Minja loader is filesystem-only,
8
+ * so the directive would leak verbatim into a `<pre>` block, dropping the
9
+ * content (e.g. 6 CloudFormation templates on the AWS UPI install pages).
10
+ *
11
+ * This pass fetches each remote include ONCE (cached by URL) and inlines it as
12
+ * a fenced code block, baking the content into the migrated markdown so the
13
+ * build has no runtime network dependency. On fetch failure it leaves a visible
14
+ * link instead of a broken directive. Issue #007.
15
+ */
16
+ // Code-fence language inferred from the URL's file extension.
17
+ const LANG_BY_EXT = {
18
+ yaml: "yaml",
19
+ yml: "yaml",
20
+ json: "json",
21
+ sh: "bash",
22
+ bash: "bash",
23
+ py: "python",
24
+ rb: "ruby",
25
+ go: "go",
26
+ toml: "toml",
27
+ ini: "ini",
28
+ xml: "xml",
29
+ tf: "hcl",
30
+ };
31
+ // `{% include "./https://…" %}` (the `./` is the engine's local-path prefix,
32
+ // spurious for URLs) on its own line, capturing leading indent + the URL.
33
+ const remoteIncludeRx = /^([ \t]*)\{%\s*include\s*"\.?\/?(https?:\/\/[^"]+)"\s*%\}[ \t]*$/gm;
34
+ function langForUrl(url) {
35
+ const clean = url.split(/[?#]/)[0];
36
+ const ext = clean.slice(clean.lastIndexOf(".") + 1).toLowerCase();
37
+ return LANG_BY_EXT[ext] ?? "";
38
+ }
39
+ /** Choose a backtick fence longer than any run inside the content. */
40
+ function pickFence(content) {
41
+ const longest = (content.match(/`+/g) ?? []).reduce((n, run) => Math.max(n, run.length), 0);
42
+ return "`".repeat(Math.max(3, longest + 1));
43
+ }
44
+ /** True if `md` contains at least one remote include directive. */
45
+ export function hasRemoteIncludes(md) {
46
+ remoteIncludeRx.lastIndex = 0;
47
+ return remoteIncludeRx.test(md);
48
+ }
49
+ /**
50
+ * Replace every `{% include "https://…" %}` directive in `md` with the fetched
51
+ * content as a fenced code block. Returns `md` unchanged if there are none.
52
+ */
53
+ export async function inlineRemoteIncludes(md, options = {}) {
54
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch;
55
+ const cache = options.cache ?? new Map();
56
+ const onWarn = options.onWarn ?? ((m) => console.warn(m));
57
+ // Collect the distinct URLs first so each is fetched at most once.
58
+ const urls = new Set();
59
+ for (const m of md.matchAll(remoteIncludeRx))
60
+ urls.add(m[2]);
61
+ if (urls.size === 0)
62
+ return md;
63
+ for (const url of urls) {
64
+ if (cache.has(url))
65
+ continue;
66
+ try {
67
+ const res = await fetchImpl(url);
68
+ if (!res.ok)
69
+ throw new Error(`HTTP ${res.status}`);
70
+ cache.set(url, await res.text());
71
+ }
72
+ catch (err) {
73
+ cache.set(url, null);
74
+ onWarn(`remote include: failed to fetch ${url} (${err instanceof Error ? err.message : String(err)}); leaving a link`);
75
+ }
76
+ }
77
+ return md.replace(remoteIncludeRx, (_whole, indent, url) => {
78
+ const content = cache.get(url);
79
+ if (content == null) {
80
+ // Fetch failed (or not attempted): a visible link beats a broken directive.
81
+ return `${indent}See [${url}](${url}).`;
82
+ }
83
+ const body = content.replace(/\n$/, "");
84
+ const fence = pickFence(body);
85
+ const lang = langForUrl(url);
86
+ return `${indent}${fence}${lang}\n${body}\n${indent}${fence}`;
87
+ });
88
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dogsbay",
3
- "version": "0.2.0-beta.92",
3
+ "version": "0.2.0-beta.93",
4
4
  "description": "CLI for Dogsbay — scaffold, build, and serve documentation sites with markdown / MkDocs / Obsidian / OpenAPI sources",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,22 +33,22 @@
33
33
  "picocolors": "^1.1.0",
34
34
  "prompts": "^2.4.2",
35
35
  "yaml": "^2.8.3",
36
- "@dogsbay/autodoc-python": "0.2.0-beta.92",
37
- "@dogsbay/format-astro": "0.2.0-beta.92",
38
- "@dogsbay/format-mkdocs": "0.2.0-beta.92",
39
- "@dogsbay/format-obsidian": "0.2.0-beta.92",
40
- "@dogsbay/format-mdx": "0.2.0-beta.92",
41
- "@dogsbay/format-starlight": "0.2.0-beta.92",
42
- "@dogsbay/format-docusaurus": "0.2.0-beta.92",
43
- "@dogsbay/docusaurus-adapter-tigera": "0.2.0-beta.92",
44
- "@dogsbay/format-dogsbay-md": "0.2.0-beta.92",
45
- "@dogsbay/format-fluidtopics-markdown": "0.2.0-beta.92",
46
- "@dogsbay/format-fluidtopics-rest": "0.2.0-beta.92",
47
- "@dogsbay/format-openapi": "0.2.0-beta.92",
48
- "@dogsbay/adoc2md-modular": "0.2.0-beta.92",
49
- "@dogsbay/format-asciidoc": "0.2.0-beta.92",
50
- "@dogsbay/minja": "0.2.0-beta.92",
51
- "@dogsbay/types": "0.2.0-beta.92"
36
+ "@dogsbay/format-mkdocs": "0.2.0-beta.93",
37
+ "@dogsbay/autodoc-python": "0.2.0-beta.93",
38
+ "@dogsbay/format-astro": "0.2.0-beta.93",
39
+ "@dogsbay/format-obsidian": "0.2.0-beta.93",
40
+ "@dogsbay/format-mdx": "0.2.0-beta.93",
41
+ "@dogsbay/format-starlight": "0.2.0-beta.93",
42
+ "@dogsbay/format-docusaurus": "0.2.0-beta.93",
43
+ "@dogsbay/docusaurus-adapter-tigera": "0.2.0-beta.93",
44
+ "@dogsbay/format-dogsbay-md": "0.2.0-beta.93",
45
+ "@dogsbay/format-fluidtopics-markdown": "0.2.0-beta.93",
46
+ "@dogsbay/format-openapi": "0.2.0-beta.93",
47
+ "@dogsbay/format-fluidtopics-rest": "0.2.0-beta.93",
48
+ "@dogsbay/adoc2md-modular": "0.2.0-beta.93",
49
+ "@dogsbay/format-asciidoc": "0.2.0-beta.93",
50
+ "@dogsbay/minja": "0.2.0-beta.93",
51
+ "@dogsbay/types": "0.2.0-beta.93"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/markdown-it": "^14.1.0",