dogsbay 0.2.0-beta.41 → 0.2.0-beta.43
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/commands/migrate-mkdocs.js +125 -19
- package/dist/commands/site-build.js +4 -0
- package/dist/config/load.js +56 -0
- package/dist/index.js +7 -0
- package/dist/resolve-autodoc.js +14 -8
- package/package.json +10 -10
- package/skills/platform/migration-shape/SKILL.md +34 -0
|
@@ -99,7 +99,15 @@ export async function migrateMkdocs(source, options) {
|
|
|
99
99
|
// snippets, macros, autodoc, variants — see @dogsbay/format-
|
|
100
100
|
// mkdocs's CLAUDE.md) runs identically to import-mkdocs; only
|
|
101
101
|
// the final write target differs.
|
|
102
|
-
|
|
102
|
+
// Lift the mkdocstrings Python handler options from mkdocs.yml.
|
|
103
|
+
// These become the project-level `autodoc.python` config block and
|
|
104
|
+
// also feed `--inline-autodoc`'s parser globalOptions — see
|
|
105
|
+
// plans/autodoc-mkdocstrings-options.md.
|
|
106
|
+
const autodocPythonOptions = extractAutodocOptions(config);
|
|
107
|
+
const { pageCount, lossy } = await collectAndWriteContent(sourceDir, fullDocsDir, outputDir, config, {
|
|
108
|
+
inlineAutodoc: options.inlineAutodoc ?? false,
|
|
109
|
+
autodocPythonOptions,
|
|
110
|
+
});
|
|
103
111
|
console.log(pc.green(`Wrote`) + ` ${pageCount} pages to ./content/ as Dogsbay-MD`);
|
|
104
112
|
// 3. Convert MkDocs nav: → ./content/nav.yml in canonical
|
|
105
113
|
// single-key-map shape (- Label: file.md / nested children).
|
|
@@ -131,15 +139,28 @@ export async function migrateMkdocs(source, options) {
|
|
|
131
139
|
// makes the migrated config self-documenting. NO `output:`
|
|
132
140
|
// field — the default (./astro) is what we want; flat layout
|
|
133
141
|
// (`output: "."`) triggers a rebuild loop in `site dev`.
|
|
134
|
-
|
|
142
|
+
// site.url is NOT inherited from the source mkdocs.yml. A
|
|
143
|
+
// migration almost always moves to a new host, so copying the
|
|
144
|
+
// source's site_url silently bakes the wrong origin into
|
|
145
|
+
// robots.txt, sitemap, canonical tags, and llms.txt. The user
|
|
146
|
+
// supplies the destination explicitly with --site-url; absent,
|
|
147
|
+
// site.url is left unset and the build emits relative URLs.
|
|
148
|
+
// sourceSiteUrl is kept only to warn the user it was dropped.
|
|
149
|
+
const sourceSiteUrl = config.site_url || undefined;
|
|
150
|
+
const siteUrl = options.siteUrl || undefined;
|
|
135
151
|
const repoUrl = config.repo_url || undefined;
|
|
152
|
+
// --base-path controls where docs sit under the host. Default
|
|
153
|
+
// /docs (matches every scaffolded dogsbay site); pass --base-path
|
|
154
|
+
// "" to serve at the host root — common for a dedicated repo or
|
|
155
|
+
// GitHub Pages project site.
|
|
156
|
+
const basePath = options.basePath !== undefined ? options.basePath : "/docs";
|
|
136
157
|
const siteDescription = config.site_description || undefined;
|
|
137
158
|
const dogsbayConfig = {
|
|
138
159
|
schemaVersion: 1,
|
|
139
160
|
site: {
|
|
140
161
|
name: siteName,
|
|
141
162
|
url: siteUrl,
|
|
142
|
-
basePath
|
|
163
|
+
basePath,
|
|
143
164
|
description: siteDescription,
|
|
144
165
|
repoUrl,
|
|
145
166
|
},
|
|
@@ -150,9 +171,26 @@ export async function migrateMkdocs(source, options) {
|
|
|
150
171
|
llmsTxt: true,
|
|
151
172
|
mdMirror: true,
|
|
152
173
|
},
|
|
174
|
+
// Project-level autodoc render options lifted from the source
|
|
175
|
+
// mkdocs.yml's mkdocstrings handler. resolve-autodoc applies
|
|
176
|
+
// these under per-directive props so migrated reference pages
|
|
177
|
+
// render with the same signature/member-order behaviour the
|
|
178
|
+
// MkDocs site configured. Omitted when the source declared no
|
|
179
|
+
// renderer-relevant options.
|
|
180
|
+
...(autodocPythonOptions
|
|
181
|
+
? { autodoc: { python: autodocPythonOptions } }
|
|
182
|
+
: {}),
|
|
153
183
|
};
|
|
154
184
|
writeFileSync(join(outputDir, "dogsbay.config.yml"), serializeConfig(dogsbayConfig, "yaml"));
|
|
155
185
|
console.log(pc.green(`Wrote`) + ` dogsbay.config.yml`);
|
|
186
|
+
if (sourceSiteUrl && !siteUrl) {
|
|
187
|
+
console.log(pc.yellow(`Note:`) +
|
|
188
|
+
` source site_url (${sourceSiteUrl}) was not carried over —` +
|
|
189
|
+
` a migration moves hosts.`);
|
|
190
|
+
console.log(` Set site.url in dogsbay.config.yml (or re-run with` +
|
|
191
|
+
` --site-url) so robots.txt,`);
|
|
192
|
+
console.log(` sitemap, and llms.txt point at your host.`);
|
|
193
|
+
}
|
|
156
194
|
// 6. Scaffold the Astro project under ./astro/ (theme,
|
|
157
195
|
// package.json, astro.config.mjs, tsconfig, copied UI
|
|
158
196
|
// components). Same emitter `dogsbay site init` uses, just
|
|
@@ -160,7 +198,7 @@ export async function migrateMkdocs(source, options) {
|
|
|
160
198
|
emitSiteScaffold(astroDir, siteName, {
|
|
161
199
|
siteName,
|
|
162
200
|
siteUrl,
|
|
163
|
-
basePath
|
|
201
|
+
basePath,
|
|
164
202
|
repoUrl,
|
|
165
203
|
llmsTxt: true,
|
|
166
204
|
mdMirror: true,
|
|
@@ -187,6 +225,9 @@ export async function migrateMkdocs(source, options) {
|
|
|
187
225
|
pageCount,
|
|
188
226
|
assetCount,
|
|
189
227
|
lossy,
|
|
228
|
+
siteUrl,
|
|
229
|
+
sourceSiteUrl,
|
|
230
|
+
basePath,
|
|
190
231
|
}));
|
|
191
232
|
console.log(pc.green(`Wrote`) + ` MIGRATION.md`);
|
|
192
233
|
if (!options.quiet) {
|
|
@@ -280,8 +321,16 @@ async function collectAndWriteContent(sourceDir, fullDocsDir, outputDir, mkdocsC
|
|
|
280
321
|
if (opts.inlineAutodoc && autodocSourceRootAbs) {
|
|
281
322
|
// Snapshot mode: resolve at migration time. The resolved api-*
|
|
282
323
|
// TreeNodes serialize to Dogsbay-MD `:::api-*` directives via
|
|
283
|
-
// format-dogsbay-md's Phase 4a cases.
|
|
284
|
-
|
|
324
|
+
// format-dogsbay-md's Phase 4a cases. globalOptions carries the
|
|
325
|
+
// mkdocstrings handler options so the snapshot matches what the
|
|
326
|
+
// MkDocs site configured (members_order, merge_init_into_class,
|
|
327
|
+
// …) rather than the bare mkdocstrings defaults.
|
|
328
|
+
parseOpts.autodoc = {
|
|
329
|
+
sourceRoot: autodocSourceRootAbs,
|
|
330
|
+
...(opts.autodocPythonOptions
|
|
331
|
+
? { globalOptions: opts.autodocPythonOptions }
|
|
332
|
+
: {}),
|
|
333
|
+
};
|
|
285
334
|
}
|
|
286
335
|
// Preserve mode (default): no `autodoc` in parseOpts. The `:::`
|
|
287
336
|
// paragraphs stay as raw text; we walk them in post-process and
|
|
@@ -429,6 +478,60 @@ function extractMkdocstringsConfig(mkdocsConfig) {
|
|
|
429
478
|
}
|
|
430
479
|
return null;
|
|
431
480
|
}
|
|
481
|
+
/**
|
|
482
|
+
* snake_case mkdocstrings handler option → camelCase Dogsbay
|
|
483
|
+
* `AutodocPythonOptions` key. Options the autodoc renderer doesn't
|
|
484
|
+
* understand (e.g. `extensions`, `preload_modules`,
|
|
485
|
+
* `docstring_section_style`) are intentionally absent — they fall
|
|
486
|
+
* through and are dropped. Mirrors the map in
|
|
487
|
+
* `format-mkdocs/src/importer.ts` so `migrate-mkdocs` and
|
|
488
|
+
* `import-mkdocs` honour the same handler options.
|
|
489
|
+
*/
|
|
490
|
+
const MKDOCSTRINGS_OPTION_MAP = {
|
|
491
|
+
show_source: "showSource",
|
|
492
|
+
show_bases: "showBases",
|
|
493
|
+
show_signature: "showSignature",
|
|
494
|
+
unwrap_annotated: "unwrapAnnotated",
|
|
495
|
+
group_by_category: "groupByCategory",
|
|
496
|
+
show_root_full_path: "showRootFullPath",
|
|
497
|
+
show_root_heading: "showRootHeading",
|
|
498
|
+
show_if_no_docstring: "showIfNoDocstring",
|
|
499
|
+
inherited_members: "inheritedMembers",
|
|
500
|
+
merge_init_into_class: "mergeInitIntoClass",
|
|
501
|
+
separate_signature: "separateSignature",
|
|
502
|
+
members_order: "membersOrder",
|
|
503
|
+
filters: "filters",
|
|
504
|
+
heading_level: "headingLevel",
|
|
505
|
+
};
|
|
506
|
+
/**
|
|
507
|
+
* Lift the mkdocstrings Python handler `options:` block out of
|
|
508
|
+
* mkdocs.yml and map it to `AutodocPythonOptions`.
|
|
509
|
+
*
|
|
510
|
+
* A MkDocs site configures the handler once; `import-mkdocs` threads
|
|
511
|
+
* those options into the autodoc renderer as `globalOptions`. Without
|
|
512
|
+
* this, migrated `:::autodoc` directives fall back to the bare
|
|
513
|
+
* mkdocstrings defaults (`merge_init_into_class: false`,
|
|
514
|
+
* `members_order: alphabetical`) — the reference pages lose the
|
|
515
|
+
* expanded constructor signature and the document-order member list.
|
|
516
|
+
*
|
|
517
|
+
* Returns null when mkdocstrings isn't declared or sets no
|
|
518
|
+
* renderer-relevant options. See plans/autodoc-mkdocstrings-options.md.
|
|
519
|
+
*/
|
|
520
|
+
function extractAutodocOptions(mkdocsConfig) {
|
|
521
|
+
const mkdocstrings = extractMkdocstringsConfig(mkdocsConfig);
|
|
522
|
+
if (!mkdocstrings)
|
|
523
|
+
return null;
|
|
524
|
+
const raw = mkdocstrings.handlers?.python?.options;
|
|
525
|
+
if (!raw || typeof raw !== "object")
|
|
526
|
+
return null;
|
|
527
|
+
const src = raw;
|
|
528
|
+
const out = {};
|
|
529
|
+
for (const [snake, camel] of Object.entries(MKDOCSTRINGS_OPTION_MAP)) {
|
|
530
|
+
if (src[snake] !== undefined)
|
|
531
|
+
out[camel] = src[snake];
|
|
532
|
+
}
|
|
533
|
+
return Object.keys(out).length > 0 ? out : null;
|
|
534
|
+
}
|
|
432
535
|
/**
|
|
433
536
|
* Extract macros plugin data file mappings from mkdocs.yml.
|
|
434
537
|
* Returns { varName: absolutePath } for each `include_yaml` entry,
|
|
@@ -785,7 +888,7 @@ function labelFromPath(path) {
|
|
|
785
888
|
}
|
|
786
889
|
// ── MIGRATION.md ────────────────────────────────────────
|
|
787
890
|
function buildMigrationNotes(args) {
|
|
788
|
-
const { sourceDir, outputDir, siteName, pageCount, assetCount, lossy } = args;
|
|
891
|
+
const { sourceDir, outputDir, siteName, pageCount, assetCount, lossy, siteUrl, sourceSiteUrl, basePath, } = args;
|
|
789
892
|
const lines = [
|
|
790
893
|
`# Migration: ${siteName}`,
|
|
791
894
|
"",
|
|
@@ -811,19 +914,22 @@ function buildMigrationNotes(args) {
|
|
|
811
914
|
"npx dogsbay site dev # watch + preview",
|
|
812
915
|
"```",
|
|
813
916
|
"",
|
|
814
|
-
"## Re-running the migration",
|
|
815
|
-
"",
|
|
816
|
-
"If you find a regression and we ship a fix, re-run with `--force`:",
|
|
817
|
-
"",
|
|
818
|
-
"```bash",
|
|
819
|
-
`npx dogsbay migrate-mkdocs ${sourceDir} --output ${outputDir} --force`,
|
|
820
|
-
"```",
|
|
821
|
-
"",
|
|
822
|
-
"Note that `--force` overwrites all generated files; any hand edits",
|
|
823
|
-
"to `./content/*.md` since the last migration will be lost. Commit",
|
|
824
|
-
"your work first.",
|
|
825
|
-
"",
|
|
826
917
|
];
|
|
918
|
+
// Site URL section — the destination URL is not inherited from the
|
|
919
|
+
// source mkdocs.yml, so spell out what was written and what (if
|
|
920
|
+
// anything) was dropped.
|
|
921
|
+
lines.push("## Site URL", "");
|
|
922
|
+
if (siteUrl) {
|
|
923
|
+
lines.push(`\`site.url\` is set to \`${siteUrl}\` (from \`--site-url\`).`, `\`site.basePath\` is \`${basePath || '""'}\`. robots.txt, the`, "sitemap, canonical tags, and llms.txt all derive from these —", "edit `dogsbay.config.yml` and rebuild to change them.", "");
|
|
924
|
+
}
|
|
925
|
+
else {
|
|
926
|
+
lines.push("`site.url` was left **unset** — a migration moves hosts, so the", "source's `site_url` is intentionally not carried over. The build", "emits relative URLs until you set it.", "");
|
|
927
|
+
if (sourceSiteUrl) {
|
|
928
|
+
lines.push(`The source \`mkdocs.yml\` had \`site_url: ${sourceSiteUrl}\` —`, "that points at the *old* host and was dropped on purpose.", "");
|
|
929
|
+
}
|
|
930
|
+
lines.push("Set the destination URL in `dogsbay.config.yml`:", "", "```yaml", "site:", " url: https://you.github.io/your-repo # drives sitemap, llms.txt, canonical", ` basePath: ${basePath || '""'}`, "```", "", "Or re-run the migration with `--site-url` (and optionally", "`--base-path`).", "");
|
|
931
|
+
}
|
|
932
|
+
lines.push("## Re-running the migration", "", "If you find a regression and we ship a fix, re-run with `--force`:", "", "```bash", `npx dogsbay migrate-mkdocs ${sourceDir} --output ${outputDir} --force`, "```", "", "Note that `--force` overwrites all generated files; any hand edits", "to `./content/*.md` since the last migration will be lost. Commit", "your work first.", "");
|
|
827
933
|
if (lossy.length > 0) {
|
|
828
934
|
lines.push("## Known limitations", "");
|
|
829
935
|
lines.push("The following files have content that didn't fully round-trip", "into Dogsbay-MD. Review each one and fix manually:", "");
|
|
@@ -176,6 +176,10 @@ export async function siteBuild(cwd, options) {
|
|
|
176
176
|
const { resolveAutodocRefs } = await import("../resolve-autodoc.js");
|
|
177
177
|
const autodocResult = await resolveAutodocRefs(pages, {
|
|
178
178
|
configDir: dirname(configPath),
|
|
179
|
+
// Project-level autodoc render options (lifted from the source
|
|
180
|
+
// mkdocs.yml by migrate-mkdocs). Layered under per-directive
|
|
181
|
+
// props — see plans/autodoc-mkdocstrings-options.md.
|
|
182
|
+
pythonOptions: config.autodoc?.python,
|
|
179
183
|
});
|
|
180
184
|
if (autodocResult.resolved > 0 || autodocResult.failed > 0) {
|
|
181
185
|
const parts = [];
|
package/dist/config/load.js
CHANGED
|
@@ -94,6 +94,7 @@ function validate(parsed, sourcePath) {
|
|
|
94
94
|
throw new Error(`analytics must be an object in ${sourcePath}`);
|
|
95
95
|
}
|
|
96
96
|
const agent = validateAgent(obj.agent, sourcePath);
|
|
97
|
+
const autodoc = validateAutodoc(obj.autodoc, sourcePath);
|
|
97
98
|
const taxonomies = validateTaxonomies(obj.taxonomies, sourcePath);
|
|
98
99
|
const propSchema = validatePropSchema(obj.propSchema, sourcePath);
|
|
99
100
|
const plugins = validatePlugins(obj.plugins, sourcePath);
|
|
@@ -108,11 +109,66 @@ function validate(parsed, sourcePath) {
|
|
|
108
109
|
deploy: obj.deploy,
|
|
109
110
|
analytics: obj.analytics,
|
|
110
111
|
agent,
|
|
112
|
+
autodoc,
|
|
111
113
|
taxonomies,
|
|
112
114
|
propSchema,
|
|
113
115
|
plugins,
|
|
114
116
|
};
|
|
115
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Validate the optional `autodoc:` block. One sub-block per language
|
|
120
|
+
* handler — only `python` exists today. Field names mirror
|
|
121
|
+
* `AutodocPythonOptions`; type-checked individually so a typo'd
|
|
122
|
+
* boolean doesn't silently flip a render default.
|
|
123
|
+
*/
|
|
124
|
+
function validateAutodoc(raw, sourcePath) {
|
|
125
|
+
if (raw === undefined)
|
|
126
|
+
return undefined;
|
|
127
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
128
|
+
throw new Error(`autodoc must be an object in ${sourcePath}`);
|
|
129
|
+
}
|
|
130
|
+
const a = raw;
|
|
131
|
+
if (a.python === undefined)
|
|
132
|
+
return {};
|
|
133
|
+
if (typeof a.python !== "object" || a.python === null || Array.isArray(a.python)) {
|
|
134
|
+
throw new Error(`autodoc.python must be an object in ${sourcePath}`);
|
|
135
|
+
}
|
|
136
|
+
const p = a.python;
|
|
137
|
+
const booleanKeys = [
|
|
138
|
+
"mergeInitIntoClass",
|
|
139
|
+
"separateSignature",
|
|
140
|
+
"unwrapAnnotated",
|
|
141
|
+
"inheritedMembers",
|
|
142
|
+
"showIfNoDocstring",
|
|
143
|
+
"showRootHeading",
|
|
144
|
+
"showRootFullPath",
|
|
145
|
+
"showBases",
|
|
146
|
+
"showSource",
|
|
147
|
+
"showSignature",
|
|
148
|
+
"groupByCategory",
|
|
149
|
+
];
|
|
150
|
+
for (const key of booleanKeys) {
|
|
151
|
+
if (p[key] !== undefined && typeof p[key] !== "boolean") {
|
|
152
|
+
throw new Error(`autodoc.python.${key} must be a boolean in ${sourcePath}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (p.membersOrder !== undefined &&
|
|
156
|
+
p.membersOrder !== "source" &&
|
|
157
|
+
p.membersOrder !== "alphabetical") {
|
|
158
|
+
throw new Error(`autodoc.python.membersOrder must be "source" or "alphabetical" ` +
|
|
159
|
+
`in ${sourcePath}; got ${JSON.stringify(p.membersOrder)}`);
|
|
160
|
+
}
|
|
161
|
+
if (p.headingLevel !== undefined && typeof p.headingLevel !== "number") {
|
|
162
|
+
throw new Error(`autodoc.python.headingLevel must be a number in ${sourcePath}`);
|
|
163
|
+
}
|
|
164
|
+
if (p.filters !== undefined) {
|
|
165
|
+
if (!Array.isArray(p.filters) ||
|
|
166
|
+
p.filters.some((f) => typeof f !== "string")) {
|
|
167
|
+
throw new Error(`autodoc.python.filters must be an array of strings in ${sourcePath}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return { python: p };
|
|
171
|
+
}
|
|
116
172
|
function validatePlugins(raw, sourcePath) {
|
|
117
173
|
if (raw === undefined)
|
|
118
174
|
return undefined;
|
package/dist/index.js
CHANGED
|
@@ -184,6 +184,13 @@ program
|
|
|
184
184
|
.argument("<source>", "Path to MkDocs project (containing mkdocs.yml)")
|
|
185
185
|
.option("-o, --output <dir>", "Output directory (default: {source}-dogsbay)")
|
|
186
186
|
.option("--force", "Overwrite an existing Dogsbay site at the output dir")
|
|
187
|
+
.option("--site-url <url>", "Canonical URL of the destination site (e.g. " +
|
|
188
|
+
"https://you.github.io/repo). Drives robots.txt, sitemap, " +
|
|
189
|
+
"canonical tags, and llms.txt. NOT inherited from the source " +
|
|
190
|
+
"mkdocs.yml — a migration moves hosts.")
|
|
191
|
+
.option("--base-path <path>", 'Path under the host where docs are served (default "/docs"). ' +
|
|
192
|
+
'Pass --base-path "" to serve at the host root — common for a ' +
|
|
193
|
+
"dedicated repo / GitHub Pages project site.")
|
|
187
194
|
.option("--inline-autodoc", "Resolve mkdocstrings ::: directives at migration time (snapshot). " +
|
|
188
195
|
"Default is :::autodoc directives that site-build resolves on " +
|
|
189
196
|
"every build (live re-rendering).")
|
package/dist/resolve-autodoc.js
CHANGED
|
@@ -75,6 +75,7 @@ export async function resolveAutodocRefs(pages, options) {
|
|
|
75
75
|
for (const page of pages) {
|
|
76
76
|
await walkAndResolve(page.tree, {
|
|
77
77
|
configDir: options.configDir,
|
|
78
|
+
pythonOptions: options.pythonOptions,
|
|
78
79
|
md,
|
|
79
80
|
onResolved: () => {
|
|
80
81
|
resolved++;
|
|
@@ -187,16 +188,21 @@ async function resolveOne(node, ctx) {
|
|
|
187
188
|
// Resolve against configDir so the resolver doesn't depend on
|
|
188
189
|
// process.cwd().
|
|
189
190
|
const sourceRoot = resolvePath(ctx.configDir, sourceRootRaw);
|
|
190
|
-
//
|
|
191
|
-
// mkdocstrings
|
|
192
|
-
// truthy-checks
|
|
193
|
-
//
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
//
|
|
191
|
+
// Layer rendering options, lowest → highest precedence:
|
|
192
|
+
// 1. AUTODOC_RENDER_DEFAULTS — bare mkdocstrings defaults.
|
|
193
|
+
// tree-builder.ts truthy-checks several of these, so without
|
|
194
|
+
// them the collapsible source block, attribute signatures,
|
|
195
|
+
// and class bases silently drop.
|
|
196
|
+
// 2. ctx.pythonOptions — project-level `config.autodoc.python`,
|
|
197
|
+
// lifted by migrate-mkdocs from the source mkdocs.yml's
|
|
198
|
+
// mkdocstrings handler (members_order, merge_init_into_class,
|
|
199
|
+
// …). This is what makes a migrated reference page match the
|
|
200
|
+
// original instead of the bare-defaults render.
|
|
201
|
+
// 3. props — the per-directive `:::autodoc` YAML body, so an
|
|
202
|
+
// individual symbol can still override the project default.
|
|
198
203
|
const renderOptions = {
|
|
199
204
|
...AUTODOC_RENDER_DEFAULTS,
|
|
205
|
+
...(ctx.pythonOptions ?? {}),
|
|
200
206
|
...props,
|
|
201
207
|
};
|
|
202
208
|
delete renderOptions.ref;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dogsbay",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.43",
|
|
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": {
|
|
@@ -32,15 +32,15 @@
|
|
|
32
32
|
"picocolors": "^1.1.0",
|
|
33
33
|
"prompts": "^2.4.2",
|
|
34
34
|
"yaml": "^2.8.3",
|
|
35
|
-
"@dogsbay/autodoc-python": "0.2.0-beta.
|
|
36
|
-
"@dogsbay/format-mkdocs": "0.2.0-beta.
|
|
37
|
-
"@dogsbay/format-astro": "0.2.0-beta.
|
|
38
|
-
"@dogsbay/format-obsidian": "0.2.0-beta.
|
|
39
|
-
"@dogsbay/format-mdx": "0.2.0-beta.
|
|
40
|
-
"@dogsbay/format-
|
|
41
|
-
"@dogsbay/format-
|
|
42
|
-
"@dogsbay/format-openapi": "0.2.0-beta.
|
|
43
|
-
"@dogsbay/types": "0.2.0-beta.
|
|
35
|
+
"@dogsbay/autodoc-python": "0.2.0-beta.43",
|
|
36
|
+
"@dogsbay/format-mkdocs": "0.2.0-beta.43",
|
|
37
|
+
"@dogsbay/format-astro": "0.2.0-beta.43",
|
|
38
|
+
"@dogsbay/format-obsidian": "0.2.0-beta.43",
|
|
39
|
+
"@dogsbay/format-mdx": "0.2.0-beta.43",
|
|
40
|
+
"@dogsbay/format-starlight": "0.2.0-beta.43",
|
|
41
|
+
"@dogsbay/format-dogsbay-md": "0.2.0-beta.43",
|
|
42
|
+
"@dogsbay/format-openapi": "0.2.0-beta.43",
|
|
43
|
+
"@dogsbay/types": "0.2.0-beta.43"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/markdown-it": "^14.1.0",
|
|
@@ -62,6 +62,39 @@ This was learned the hard way during Phase 3 of
|
|
|
62
62
|
emitted `output: "."` and `dogsbay site dev` rebuild-looped on the
|
|
63
63
|
result. The fix was to revert to the standard `output: "./astro"`.
|
|
64
64
|
|
|
65
|
+
### Destination URL — supplied, not inherited
|
|
66
|
+
|
|
67
|
+
**Do NOT copy the source format's site URL into `site.url`.** A
|
|
68
|
+
migration almost always moves the docs to a *new* host — GitHub
|
|
69
|
+
Pages, a Cloudflare project, a custom domain. The source's
|
|
70
|
+
`site_url` (MkDocs), `url` (Jekyll `_config.yml`), `baseURL`
|
|
71
|
+
(Hugo), etc. points at the *old* host.
|
|
72
|
+
|
|
73
|
+
`site.url` feeds `robots.txt`, the sitemap XML, the `Sitemap:` /
|
|
74
|
+
`Llms-Txt:` lines, canonical tags, `llms.txt` absolute URLs, and
|
|
75
|
+
Astro's `site` / `base`. Inheriting the wrong origin silently
|
|
76
|
+
breaks every one of those — and the breakage only shows up after
|
|
77
|
+
a build, in generated files the user doesn't normally read.
|
|
78
|
+
|
|
79
|
+
**Required:**
|
|
80
|
+
- Migration commands take a `--site-url <url>` flag. Its value
|
|
81
|
+
goes to `dogsbay.config.yml`'s `site.url` *and* the scaffold
|
|
82
|
+
emitter's `siteUrl` option. The URL may carry a path component
|
|
83
|
+
(`https://you.github.io/repo`); `format-astro`'s `parseSiteUrl`
|
|
84
|
+
splits it into Astro `site` (origin) + `base` (urlBase) — this
|
|
85
|
+
is exactly how GitHub Pages **project** sites work.
|
|
86
|
+
- Take a `--base-path <path>` flag too. Default `/docs`; `""`
|
|
87
|
+
serves at the host root. Check `!== undefined` (not truthiness)
|
|
88
|
+
so the empty string is honoured.
|
|
89
|
+
- When `--site-url` is absent, leave `site.url` **unset** (the
|
|
90
|
+
build degrades cleanly to relative URLs) — do NOT fall back to
|
|
91
|
+
the source value.
|
|
92
|
+
- Keep the dropped source URL only to (a) print a one-line note
|
|
93
|
+
after writing the config and (b) record it in `MIGRATION.md`'s
|
|
94
|
+
"Site URL" section so the user knows what to set.
|
|
95
|
+
- The *code* repo URL (`repo_url` etc.) **is** inherited — that
|
|
96
|
+
doesn't change in a docs migration.
|
|
97
|
+
|
|
65
98
|
## 2. Asset folder (`content/_assets/`)
|
|
66
99
|
|
|
67
100
|
All images, diagrams, screenshots, icons, PDFs, and downloadable
|
|
@@ -247,6 +280,7 @@ Every migration command MUST have a fixture test asserting all of:
|
|
|
247
280
|
| `<output>/content/nav.json` does NOT exist | Avoid loader precedence trap |
|
|
248
281
|
| `<output>/dogsbay.config.yml` has `sources: [{ path: ./content, from: dogsbay-md }]` | Config wires content to source |
|
|
249
282
|
| `<output>/dogsbay.config.yml` does NOT set `output:` | Use default `./astro` |
|
|
283
|
+
| `site.url` reflects `--site-url`, NOT the source's URL; absent → unset | Destination URL not inherited |
|
|
250
284
|
| `<output>/astro/package.json` exists | Scaffold under astro/ |
|
|
251
285
|
| `<output>/astro/astro.config.mjs` exists | Scaffold under astro/ |
|
|
252
286
|
| `<output>/astro/src/styles/theme.css` exists | Scaffold under astro/ |
|