dogsbay 0.2.0-beta.118 → 0.2.0-beta.119
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-gitbook.js +29 -2
- package/dist/resolve-autodoc.js +7 -4
- package/dist/resolve-openapi.js +13 -4
- package/package.json +30 -30
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
* Source-of-truth becomes `./content/*.md`; the GitBook source can be
|
|
21
21
|
* deleted. Mirrors migrate-asciidoc / migrate-mkdocs in shape.
|
|
22
22
|
*/
|
|
23
|
-
import { copyFileSync, existsSync, mkdirSync, readdirSync, rmSync, statSync, writeFileSync, } from "node:fs";
|
|
24
|
-
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
23
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync, rmSync, realpathSync, statSync, writeFileSync, } from "node:fs";
|
|
24
|
+
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
25
25
|
import pc from "picocolors";
|
|
26
26
|
import { stringify as stringifyYaml } from "yaml";
|
|
27
27
|
import { emitSiteScaffold } from "@dogsbay/format-astro";
|
|
@@ -104,6 +104,27 @@ function mirrorAssets(roots, contentDir) {
|
|
|
104
104
|
let count = 0;
|
|
105
105
|
for (const root of roots) {
|
|
106
106
|
const destBase = root.prefix ? join(contentDir, root.prefix) : contentDir;
|
|
107
|
+
// Only what is inside the space once links resolve: a symlink in someone
|
|
108
|
+
// else's repo must not copy a file from outside it into content/, where
|
|
109
|
+
// a `:::openapi` spec, for one, is rendered into the page.
|
|
110
|
+
let realRoot;
|
|
111
|
+
try {
|
|
112
|
+
realRoot = realpathSync(root.dir);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const inside = (p) => {
|
|
118
|
+
try {
|
|
119
|
+
const real = realpathSync(p);
|
|
120
|
+
return real === realRoot || real.startsWith(realRoot + sep);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
// Each directory once: two links to `.` made the walk branch twice per level until ELOOP.
|
|
127
|
+
const seen = new Set([realRoot]);
|
|
107
128
|
const walk = (dir) => {
|
|
108
129
|
let entries;
|
|
109
130
|
try {
|
|
@@ -118,6 +139,8 @@ function mirrorAssets(roots, contentDir) {
|
|
|
118
139
|
const full = join(dir, name);
|
|
119
140
|
let st;
|
|
120
141
|
try {
|
|
142
|
+
if (!inside(full))
|
|
143
|
+
continue;
|
|
121
144
|
st = statSync(full);
|
|
122
145
|
}
|
|
123
146
|
catch {
|
|
@@ -127,6 +150,10 @@ function mirrorAssets(roots, contentDir) {
|
|
|
127
150
|
// Skip hidden dirs EXCEPT `.gitbook` (holds assets + includes).
|
|
128
151
|
if (name.startsWith(".") && name !== ".gitbook")
|
|
129
152
|
continue;
|
|
153
|
+
const real = realpathSync(full);
|
|
154
|
+
if (seen.has(real))
|
|
155
|
+
continue;
|
|
156
|
+
seen.add(real);
|
|
130
157
|
walk(full);
|
|
131
158
|
continue;
|
|
132
159
|
}
|
package/dist/resolve-autodoc.js
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import { resolve as resolvePath } from "node:path";
|
|
23
23
|
import MarkdownIt from "markdown-it";
|
|
24
24
|
import pc from "picocolors";
|
|
25
|
+
import { apiSymbolLevels } from "@dogsbay/serialize-core";
|
|
25
26
|
import { resolveIdentifier, symbolToTreeNode, } from "@dogsbay/autodoc-python";
|
|
26
27
|
/**
|
|
27
28
|
* Default render options for autodoc directives. Mirrors
|
|
@@ -127,9 +128,9 @@ function treeHasApiHeading(node) {
|
|
|
127
128
|
}
|
|
128
129
|
/**
|
|
129
130
|
* Walk the page's TreeNode tree for api-class / api-member nodes
|
|
130
|
-
* and append a Heading entry for each
|
|
131
|
-
*
|
|
132
|
-
*
|
|
131
|
+
* and append a Heading entry for each, at the level the page renders it
|
|
132
|
+
* (`apiSymbolLevels` in @dogsbay/serialize-core: below the last heading
|
|
133
|
+
* before it, nested symbols below their parent). The
|
|
133
134
|
* `kind` prop is preserved on the heading so the TOC component
|
|
134
135
|
* can render type-colored badges (class blue, method green, etc.).
|
|
135
136
|
*
|
|
@@ -142,12 +143,14 @@ function appendApiHeadings(page) {
|
|
|
142
143
|
seen.set(h.slug, (seen.get(h.slug) ?? 0) + 1);
|
|
143
144
|
}
|
|
144
145
|
const headings = [];
|
|
146
|
+
const levels = apiSymbolLevels(page.tree);
|
|
145
147
|
function walk(nodes) {
|
|
146
148
|
for (const node of nodes) {
|
|
147
149
|
if (node.type === "api-class" || node.type === "api-member") {
|
|
148
150
|
const name = node.props?.name || "";
|
|
149
151
|
const kind = node.props?.kind || "";
|
|
150
|
-
|
|
152
|
+
// The level the page renders the symbol at (apiSymbolLevels), so the TOC nests as the page does.
|
|
153
|
+
const depth = levels.get(node) ?? (node.type === "api-class" ? 2 : 3);
|
|
151
154
|
const baseSlug = slugify(name);
|
|
152
155
|
const count = seen.get(baseSlug) ?? 0;
|
|
153
156
|
const slug = count === 0 ? baseSlug : `${baseSlug}-${count}`;
|
package/dist/resolve-openapi.js
CHANGED
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
* - inside a content root once symlinks are resolved;
|
|
15
15
|
* - `.yaml`, `.yml` or `.json`.
|
|
16
16
|
*
|
|
17
|
+
* `path` and `method` together select one operation instead of the whole
|
|
18
|
+
* spec: `:::openapi{spec="api.yaml" path="/pets" method="get"}`, what a GitBook
|
|
19
|
+
* `{% openapi %}` block shows (migrate-gitbook writes it).
|
|
20
|
+
*
|
|
17
21
|
* A leading `/` is the content root. A relative path is tried against the
|
|
18
22
|
* page's folder, then the page's own folder for an index page (slug
|
|
19
23
|
* `reference` may be `reference/index.md`). Importers write root-relative
|
|
@@ -79,7 +83,7 @@ export function findOpenApiSpec(spec, slug, roots) {
|
|
|
79
83
|
* mutated in place; tag sections are added to the page's headings.
|
|
80
84
|
*/
|
|
81
85
|
export async function resolveOpenApiRefs(pages, options) {
|
|
82
|
-
const { embedSpec, createSpecCache } = await import("@dogsbay/format-openapi/core");
|
|
86
|
+
const { embedSpec, createSpecCache, directiveOperation } = await import("@dogsbay/format-openapi/core");
|
|
83
87
|
const { parse: parseYaml } = await import("yaml");
|
|
84
88
|
// Each spec is parsed and dereferenced once, however many pages embed it.
|
|
85
89
|
const specs = createSpecCache((path) => readFile(path, "utf-8"), parseYaml);
|
|
@@ -107,7 +111,9 @@ export async function resolveOpenApiRefs(pages, options) {
|
|
|
107
111
|
// A relative spec resolves against the page as authored, before any
|
|
108
112
|
// version/namespace prefix was put on its slug.
|
|
109
113
|
const slug = page.multiSource?.originalSlug ?? page.slug;
|
|
110
|
-
|
|
114
|
+
// `path` + `method` select one operation (GitBook's `{% openapi %}` block).
|
|
115
|
+
const selected = directiveOperation(node.props);
|
|
116
|
+
const found = "error" in selected ? selected : findOpenApiSpec(spec, slug, options.rootsFor(page));
|
|
111
117
|
if ("error" in found) {
|
|
112
118
|
failed++;
|
|
113
119
|
console.warn(pc.yellow(` Warning: :::openapi on ${page.slug}: ${found.error}`));
|
|
@@ -116,7 +122,10 @@ export async function resolveOpenApiRefs(pages, options) {
|
|
|
116
122
|
try {
|
|
117
123
|
// Parsed once per build; the nodes are built per embed, with ids that avoid this page's.
|
|
118
124
|
const headings = page.headings ?? [];
|
|
119
|
-
const embed = embedSpec(await specs.get(found.path), {
|
|
125
|
+
const embed = embedSpec(await specs.get(found.path), {
|
|
126
|
+
usedIds: headings.map((h) => h.slug),
|
|
127
|
+
operation: "operation" in selected ? selected.operation : undefined,
|
|
128
|
+
});
|
|
120
129
|
nodes.splice(i, 1, ...embed.tree);
|
|
121
130
|
i += embed.tree.length - 1;
|
|
122
131
|
const at = Math.min(headingsBefore + inserted, headings.length);
|
|
@@ -127,7 +136,7 @@ export async function resolveOpenApiRefs(pages, options) {
|
|
|
127
136
|
}
|
|
128
137
|
catch (err) {
|
|
129
138
|
failed++;
|
|
130
|
-
console.warn(pc.yellow(` Warning: :::openapi on ${page.slug}: cannot
|
|
139
|
+
console.warn(pc.yellow(` Warning: :::openapi on ${page.slug}: cannot use ${spec}: ${err.message}`));
|
|
131
140
|
}
|
|
132
141
|
}
|
|
133
142
|
};
|
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.119",
|
|
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": {
|
|
@@ -43,34 +43,34 @@
|
|
|
43
43
|
"typescript": "^5.9.3",
|
|
44
44
|
"valibot": "1.1.0",
|
|
45
45
|
"yaml": "^2.9.0",
|
|
46
|
-
"@dogsbay/adoc2md-modular": "0.2.0-beta.
|
|
47
|
-
"@dogsbay/
|
|
48
|
-
"@dogsbay/
|
|
49
|
-
"@dogsbay/autodoc-python": "0.2.0-beta.
|
|
50
|
-
"@dogsbay/format-astro": "0.2.0-beta.
|
|
51
|
-
"@dogsbay/format-dita": "0.2.0-beta.
|
|
52
|
-
"@dogsbay/format-docusaurus": "0.2.0-beta.
|
|
53
|
-
"@dogsbay/format-dogsbay-md": "0.2.0-beta.
|
|
54
|
-
"@dogsbay/format-fluidtopics-markdown": "0.2.0-beta.
|
|
55
|
-
"@dogsbay/format-fluidtopics-rest": "0.2.0-beta.
|
|
56
|
-
"@dogsbay/format-gatsby": "0.2.0-beta.
|
|
57
|
-
"@dogsbay/format-gitbook": "0.2.0-beta.
|
|
58
|
-
"@dogsbay/format-hugo": "0.2.0-beta.
|
|
59
|
-
"@dogsbay/format-
|
|
60
|
-
"@dogsbay/format-
|
|
61
|
-
"@dogsbay/format-myst": "0.2.0-beta.
|
|
62
|
-
"@dogsbay/format-obsidian": "0.2.0-beta.
|
|
63
|
-
"@dogsbay/format-
|
|
64
|
-
"@dogsbay/format-
|
|
65
|
-
"@dogsbay/format-rst": "0.2.0-beta.
|
|
66
|
-
"@dogsbay/format-
|
|
67
|
-
"@dogsbay/format-
|
|
68
|
-
"@dogsbay/format-vitepress": "0.2.0-beta.
|
|
69
|
-
"@dogsbay/minja": "0.2.0-beta.
|
|
70
|
-
"@dogsbay/
|
|
71
|
-
"@dogsbay/
|
|
72
|
-
"@dogsbay/site-check": "0.2.0-beta.
|
|
73
|
-
"@dogsbay/types": "0.2.0-beta.
|
|
46
|
+
"@dogsbay/adoc2md-modular": "0.2.0-beta.119",
|
|
47
|
+
"@dogsbay/commands": "0.2.0-beta.119",
|
|
48
|
+
"@dogsbay/format-asciidoc": "0.2.0-beta.119",
|
|
49
|
+
"@dogsbay/autodoc-python": "0.2.0-beta.119",
|
|
50
|
+
"@dogsbay/format-astro": "0.2.0-beta.119",
|
|
51
|
+
"@dogsbay/format-dita": "0.2.0-beta.119",
|
|
52
|
+
"@dogsbay/format-docusaurus": "0.2.0-beta.119",
|
|
53
|
+
"@dogsbay/format-dogsbay-md": "0.2.0-beta.119",
|
|
54
|
+
"@dogsbay/format-fluidtopics-markdown": "0.2.0-beta.119",
|
|
55
|
+
"@dogsbay/format-fluidtopics-rest": "0.2.0-beta.119",
|
|
56
|
+
"@dogsbay/format-gatsby": "0.2.0-beta.119",
|
|
57
|
+
"@dogsbay/format-gitbook": "0.2.0-beta.119",
|
|
58
|
+
"@dogsbay/format-hugo": "0.2.0-beta.119",
|
|
59
|
+
"@dogsbay/format-mdx": "0.2.0-beta.119",
|
|
60
|
+
"@dogsbay/format-mkdocs": "0.2.0-beta.119",
|
|
61
|
+
"@dogsbay/format-myst": "0.2.0-beta.119",
|
|
62
|
+
"@dogsbay/format-obsidian": "0.2.0-beta.119",
|
|
63
|
+
"@dogsbay/format-openapi": "0.2.0-beta.119",
|
|
64
|
+
"@dogsbay/format-openknowledge": "0.2.0-beta.119",
|
|
65
|
+
"@dogsbay/format-rst": "0.2.0-beta.119",
|
|
66
|
+
"@dogsbay/format-starlight": "0.2.0-beta.119",
|
|
67
|
+
"@dogsbay/format-topicmap": "0.2.0-beta.119",
|
|
68
|
+
"@dogsbay/format-vitepress": "0.2.0-beta.119",
|
|
69
|
+
"@dogsbay/minja": "0.2.0-beta.119",
|
|
70
|
+
"@dogsbay/render": "0.2.0-beta.119",
|
|
71
|
+
"@dogsbay/serialize-core": "0.2.0-beta.119",
|
|
72
|
+
"@dogsbay/site-check": "0.2.0-beta.119",
|
|
73
|
+
"@dogsbay/types": "0.2.0-beta.119"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@mdx-js/mdx": "^3.1.1",
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
"remark-rehype": "^11.1.2",
|
|
88
88
|
"unified": "^11.0.5",
|
|
89
89
|
"vitest": "^4.1.10",
|
|
90
|
-
"@dogsbay/adapter-posthog": "0.2.0-beta.93",
|
|
91
90
|
"@dogsbay/adapter-camunda": "0.2.0-beta.93",
|
|
91
|
+
"@dogsbay/adapter-posthog": "0.2.0-beta.93",
|
|
92
92
|
"@dogsbay/adapter-tigera": "0.2.0-beta.93"
|
|
93
93
|
},
|
|
94
94
|
"license": "MIT",
|