create-dox 0.3.4 → 0.5.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.
|
@@ -19,9 +19,9 @@ function shouldInclude(path) {
|
|
|
19
19
|
}
|
|
20
20
|
return true;
|
|
21
21
|
}
|
|
22
|
-
async function downloadTemplate(targetDir) {
|
|
22
|
+
async function downloadTemplate(targetDir, siteName) {
|
|
23
23
|
console.log("");
|
|
24
|
-
console.log(
|
|
24
|
+
console.log(` \u23F3 Creating ${siteName?.trim() || "your docs site"}...`);
|
|
25
25
|
const response = await fetch(TARBALL_URL);
|
|
26
26
|
if (!response.ok) {
|
|
27
27
|
throw new Error(`Failed to download template: ${response.status} ${response.statusText}`);
|
|
@@ -135,6 +135,11 @@ function buildStarterDocsJson({
|
|
|
135
135
|
i18nLocales
|
|
136
136
|
}) {
|
|
137
137
|
const config = {};
|
|
138
|
+
config.theme = "sharp";
|
|
139
|
+
config.fonts = {
|
|
140
|
+
body: { family: "Plus Jakarta Sans", weight: ["400", "500", "600", "700"] },
|
|
141
|
+
heading: { family: "Outfit", weight: ["600", "700"] }
|
|
142
|
+
};
|
|
138
143
|
if (enableAiChat) {
|
|
139
144
|
config.ai = { chat: true };
|
|
140
145
|
}
|
|
@@ -201,20 +206,15 @@ function updateSiteConfig(targetDir, projectName, description, brandPreset, repo
|
|
|
201
206
|
/const brandPreset:\s*BrandPresetKey\s*=\s*'[^']*'/,
|
|
202
207
|
`const brandPreset: BrandPresetKey = '${brandPreset}'`
|
|
203
208
|
);
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
source = source.replace(
|
|
214
|
-
/\{\s*label:\s*'Support',\s*href:\s*'[^']*'\s*\}/,
|
|
215
|
-
`{ label: 'Support', href: '${repoUrl}/issues/new' }`
|
|
216
|
-
);
|
|
217
|
-
}
|
|
209
|
+
source = source.replace(/repoUrl:\s*'[^']*'/, `repoUrl: '${repoUrl}'`);
|
|
210
|
+
source = source.replace(
|
|
211
|
+
/\{\s*label:\s*'GitHub',\s*href:\s*'[^']*'\s*\}/,
|
|
212
|
+
`{ label: 'GitHub', href: '${repoUrl}' }`
|
|
213
|
+
);
|
|
214
|
+
source = source.replace(
|
|
215
|
+
/\{\s*label:\s*'Support',\s*href:\s*'[^']*'\s*\}/,
|
|
216
|
+
`{ label: 'Support', href: '${repoUrl ? `${repoUrl}/issues/new` : ""}' }`
|
|
217
|
+
);
|
|
218
218
|
writeFileSync(siteFile, source, "utf8");
|
|
219
219
|
}
|
|
220
220
|
function patchApiReferenceGuard(targetDir) {
|
|
@@ -366,7 +366,7 @@ async function scaffold(options) {
|
|
|
366
366
|
}
|
|
367
367
|
mkdirSync2(targetDir, { recursive: true });
|
|
368
368
|
const slug = slugify(projectName);
|
|
369
|
-
await downloadTemplate(targetDir);
|
|
369
|
+
await downloadTemplate(targetDir, projectName);
|
|
370
370
|
writeStarterContent(targetDir, projectName, slug, enableAiChat, repoUrl, i18nLocales);
|
|
371
371
|
updateSiteConfig(targetDir, projectName, description, brandPreset, repoUrl);
|
|
372
372
|
patchApiReferenceGuard(targetDir);
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
initGit,
|
|
4
4
|
installDeps,
|
|
5
5
|
scaffold
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-23YWNWTH.js";
|
|
7
7
|
|
|
8
8
|
// src/migrate/index.ts
|
|
9
9
|
import { mkdirSync as mkdirSync2, copyFileSync as copyFileSync2, readFileSync as readFileSync3, writeFileSync, existsSync as existsSync3, mkdtempSync, rmSync } from "fs";
|
package/dist/index.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import {
|
|
3
3
|
migrateDocs,
|
|
4
4
|
parseGitHubUrl
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GVYVHLAP.js";
|
|
6
6
|
import {
|
|
7
7
|
logo,
|
|
8
8
|
scaffold,
|
|
9
9
|
slugify,
|
|
10
10
|
success
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-23YWNWTH.js";
|
|
12
12
|
|
|
13
13
|
// src/index.ts
|
|
14
14
|
import { existsSync as existsSync3, readdirSync as readdirSync2 } from "fs";
|
|
@@ -99,7 +99,9 @@ async function gatherAnswers(dirArg, useDefaults) {
|
|
|
99
99
|
// src/check.ts
|
|
100
100
|
import { existsSync, readFileSync as readFileSync2, readdirSync, statSync } from "fs";
|
|
101
101
|
import { join as join2, extname, relative } from "path";
|
|
102
|
+
import { execFileSync } from "child_process";
|
|
102
103
|
import matter from "gray-matter";
|
|
104
|
+
import { parse as parseYaml } from "yaml";
|
|
103
105
|
|
|
104
106
|
// src/docs-json.ts
|
|
105
107
|
import { readFileSync, writeFileSync } from "fs";
|
|
@@ -115,14 +117,62 @@ function writeDocsJson(projectDir, config) {
|
|
|
115
117
|
}
|
|
116
118
|
|
|
117
119
|
// src/check.ts
|
|
120
|
+
function gitLocal(projectDir, args2) {
|
|
121
|
+
try {
|
|
122
|
+
const out = execFileSync("git", args2, { cwd: projectDir, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
123
|
+
return { ok: true, out: out.trim() };
|
|
124
|
+
} catch {
|
|
125
|
+
return { ok: false, out: "" };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function checkDrift(projectDir, file, data, issues) {
|
|
129
|
+
const sources = data.sources;
|
|
130
|
+
const verifiedCommit = data.verifiedCommit;
|
|
131
|
+
if (!Array.isArray(sources) || sources.length === 0 || typeof verifiedCommit !== "string" || !verifiedCommit.trim()) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const commit = verifiedCommit.trim();
|
|
135
|
+
if (!gitLocal(projectDir, ["cat-file", "-e", `${commit}^{commit}`]).ok) {
|
|
136
|
+
issues.push({
|
|
137
|
+
severity: "warning",
|
|
138
|
+
message: `Cannot verify freshness: verifiedCommit "${commit.slice(0, 8)}" is not in git history \u2014 run with a full clone (fetch-depth: 0).`,
|
|
139
|
+
file
|
|
140
|
+
});
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
for (const src of sources) {
|
|
144
|
+
if (typeof src !== "string" || !src.trim()) continue;
|
|
145
|
+
const colon = src.indexOf(":");
|
|
146
|
+
let filePath = src;
|
|
147
|
+
if (colon > 0) {
|
|
148
|
+
const alias = src.slice(0, colon);
|
|
149
|
+
if (alias !== "." && alias !== "self") {
|
|
150
|
+
issues.push({
|
|
151
|
+
severity: "warning",
|
|
152
|
+
message: `Cross-repo source "${src}" \u2014 drift check skipped (needs the referenced repo; see multi-repo setup).`,
|
|
153
|
+
file
|
|
154
|
+
});
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
filePath = src.slice(colon + 1);
|
|
158
|
+
}
|
|
159
|
+
filePath = filePath.replace(/^\.\//, "").replace(/#.*$/, "");
|
|
160
|
+
const changed = gitLocal(projectDir, ["log", "--format=%H", `${commit}..HEAD`, "--", filePath]).out;
|
|
161
|
+
if (changed) {
|
|
162
|
+
const n = changed.split("\n").filter(Boolean).length;
|
|
163
|
+
issues.push({
|
|
164
|
+
severity: "warning",
|
|
165
|
+
message: `Drift: source "${src}" changed in ${n} commit(s) since it was verified \u2014 this page may be stale.`,
|
|
166
|
+
file
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
118
171
|
function collectNavPageIds(groups, seen, duplicates) {
|
|
119
172
|
for (const page of groups) {
|
|
120
173
|
if (typeof page === "string") {
|
|
121
|
-
if (seen.has(page))
|
|
122
|
-
|
|
123
|
-
} else {
|
|
124
|
-
seen.add(page);
|
|
125
|
-
}
|
|
174
|
+
if (seen.has(page)) duplicates.add(page);
|
|
175
|
+
else seen.add(page);
|
|
126
176
|
} else if (page.pages) {
|
|
127
177
|
collectNavPageIds(page.pages, seen, duplicates);
|
|
128
178
|
}
|
|
@@ -139,11 +189,8 @@ function scanMdx(dir, results) {
|
|
|
139
189
|
const fullPath = join2(dir, entry);
|
|
140
190
|
try {
|
|
141
191
|
const stat = statSync(fullPath);
|
|
142
|
-
if (stat.isDirectory())
|
|
143
|
-
|
|
144
|
-
} else if (extname(entry).toLowerCase() === ".mdx") {
|
|
145
|
-
results.push(fullPath);
|
|
146
|
-
}
|
|
192
|
+
if (stat.isDirectory()) scanMdx(fullPath, results);
|
|
193
|
+
else if (extname(entry).toLowerCase() === ".mdx") results.push(fullPath);
|
|
147
194
|
} catch {
|
|
148
195
|
}
|
|
149
196
|
}
|
|
@@ -159,7 +206,80 @@ function addOrphanToNav(projectDir, pageId) {
|
|
|
159
206
|
writeDocsJson(projectDir, config);
|
|
160
207
|
}
|
|
161
208
|
}
|
|
162
|
-
|
|
209
|
+
function slugify2(text) {
|
|
210
|
+
return text.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
211
|
+
}
|
|
212
|
+
function extractHeadingAnchors(content) {
|
|
213
|
+
const anchors = /* @__PURE__ */ new Set();
|
|
214
|
+
for (const line of content.split("\n")) {
|
|
215
|
+
const m = /^#{1,6}\s+(.+?)\s*#*\s*$/.exec(line);
|
|
216
|
+
if (m) anchors.add(slugify2(m[1]));
|
|
217
|
+
}
|
|
218
|
+
return anchors;
|
|
219
|
+
}
|
|
220
|
+
function extractLinks(content) {
|
|
221
|
+
const links = [];
|
|
222
|
+
const lines = content.split("\n");
|
|
223
|
+
let inFence = false;
|
|
224
|
+
for (let i = 0; i < lines.length; i++) {
|
|
225
|
+
if (/^\s*(```|~~~)/.test(lines[i])) {
|
|
226
|
+
inFence = !inFence;
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
if (inFence) continue;
|
|
230
|
+
const line = lines[i].replace(/`[^`]*`/g, "");
|
|
231
|
+
for (const m of line.matchAll(/\[[^\]]*\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g)) {
|
|
232
|
+
links.push({ target: m[1], line: i + 1 });
|
|
233
|
+
}
|
|
234
|
+
for (const m of line.matchAll(/href=["']([^"']+)["']/g)) {
|
|
235
|
+
links.push({ target: m[1], line: i + 1 });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return links;
|
|
239
|
+
}
|
|
240
|
+
function pageIdToPath(pageId) {
|
|
241
|
+
return pageId === "introduction" ? "/" : `/${pageId}`;
|
|
242
|
+
}
|
|
243
|
+
function validateOpenApi(projectDir, source, issues) {
|
|
244
|
+
const specPath = join2(projectDir, source);
|
|
245
|
+
if (!existsSync(specPath)) {
|
|
246
|
+
issues.push({ severity: "error", message: `API reference points at "${source}" but the file does not exist`, file: source });
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
let spec;
|
|
250
|
+
try {
|
|
251
|
+
const raw = readFileSync2(specPath, "utf8");
|
|
252
|
+
spec = source.endsWith(".json") ? JSON.parse(raw) : parseYaml(raw);
|
|
253
|
+
} catch (err) {
|
|
254
|
+
issues.push({ severity: "error", message: `OpenAPI spec is not valid ${source.endsWith(".json") ? "JSON" : "YAML"}: ${err.message}`, file: source });
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const s = spec;
|
|
258
|
+
if (typeof s?.openapi !== "string" && typeof s?.swagger !== "string") {
|
|
259
|
+
issues.push({ severity: "error", message: 'OpenAPI spec is missing the "openapi" (or "swagger") version field', file: source });
|
|
260
|
+
}
|
|
261
|
+
if (typeof s?.info !== "object" || s.info === null) {
|
|
262
|
+
issues.push({ severity: "error", message: 'OpenAPI spec is missing the "info" object', file: source });
|
|
263
|
+
}
|
|
264
|
+
const paths = s?.paths;
|
|
265
|
+
if (typeof paths !== "object" || paths === null) {
|
|
266
|
+
issues.push({ severity: "error", message: 'OpenAPI spec is missing the "paths" object', file: source });
|
|
267
|
+
} else {
|
|
268
|
+
const methods = /* @__PURE__ */ new Set(["get", "post", "put", "patch", "delete", "options", "head", "trace"]);
|
|
269
|
+
for (const [p, ops] of Object.entries(paths)) {
|
|
270
|
+
if (typeof ops !== "object" || ops === null) {
|
|
271
|
+
issues.push({ severity: "error", message: `OpenAPI path "${p}" is not an object`, file: source });
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
const hasOp = Object.keys(ops).some((k) => methods.has(k.toLowerCase()));
|
|
275
|
+
if (!hasOp) {
|
|
276
|
+
issues.push({ severity: "warning", message: `OpenAPI path "${p}" has no operations`, file: source });
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
async function runCheck(projectDir, options) {
|
|
282
|
+
const { fix, ci } = options;
|
|
163
283
|
if (!existsSync(join2(projectDir, "docs.json"))) {
|
|
164
284
|
console.error(`
|
|
165
285
|
\u274C Not a Dox project: docs.json not found in ${projectDir}
|
|
@@ -172,7 +292,11 @@ async function runCheck(projectDir, fix) {
|
|
|
172
292
|
const navPageIds = /* @__PURE__ */ new Set();
|
|
173
293
|
const duplicates = /* @__PURE__ */ new Set();
|
|
174
294
|
for (const tab of config.tabs) {
|
|
175
|
-
if (tab.href
|
|
295
|
+
if (tab.href) {
|
|
296
|
+
if (tab.href.startsWith("/")) navPageIds.add(tab.href.slice(1) || "introduction");
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (tab.api) continue;
|
|
176
300
|
if (!tab.groups || tab.groups.length === 0) {
|
|
177
301
|
issues.push({ severity: "error", message: `Tab "${tab.tab}" has no groups and no href \u2014 it will render empty` });
|
|
178
302
|
continue;
|
|
@@ -183,21 +307,17 @@ async function runCheck(projectDir, fix) {
|
|
|
183
307
|
issues.push({ severity: "error", message: `[duplicate] "${dup}" appears more than once in docs.json` });
|
|
184
308
|
}
|
|
185
309
|
for (const pageId of navPageIds) {
|
|
186
|
-
const candidates = [
|
|
187
|
-
join2(contentDir, `${pageId}.mdx`),
|
|
188
|
-
join2(contentDir, `${pageId}/index.mdx`)
|
|
189
|
-
];
|
|
310
|
+
const candidates = [join2(contentDir, `${pageId}.mdx`), join2(contentDir, `${pageId}/index.mdx`)];
|
|
190
311
|
if (!candidates.some((c) => existsSync(c))) {
|
|
191
|
-
issues.push({
|
|
192
|
-
severity: "error",
|
|
193
|
-
message: `"${pageId}" is in docs.json but has no MDX file`,
|
|
194
|
-
file: `src/content/${pageId}.mdx`
|
|
195
|
-
});
|
|
312
|
+
issues.push({ severity: "error", message: `"${pageId}" is in docs.json but has no MDX file`, file: `src/content/${pageId}.mdx` });
|
|
196
313
|
}
|
|
197
314
|
}
|
|
198
315
|
const allFiles = [];
|
|
199
316
|
if (existsSync(contentDir)) scanMdx(contentDir, allFiles);
|
|
200
317
|
const fixedOrphans = [];
|
|
318
|
+
const validPaths = /* @__PURE__ */ new Set(["/"]);
|
|
319
|
+
const anchorsByPath = /* @__PURE__ */ new Map();
|
|
320
|
+
const linksByFile = [];
|
|
201
321
|
for (const filePath of allFiles) {
|
|
202
322
|
const rel = filePath.slice(contentDir.length + 1).replace(/\.mdx$/, "").replace(/\\/g, "/");
|
|
203
323
|
const pageId = rel.endsWith("/index") ? rel.slice(0, -6) : rel;
|
|
@@ -206,37 +326,70 @@ async function runCheck(projectDir, fix) {
|
|
|
206
326
|
addOrphanToNav(projectDir, pageId);
|
|
207
327
|
fixedOrphans.push(pageId);
|
|
208
328
|
} else {
|
|
209
|
-
issues.push({
|
|
210
|
-
severity: "warning",
|
|
211
|
-
message: `"${pageId}" is not in docs.json nav (orphan)`,
|
|
212
|
-
file: relative(projectDir, filePath)
|
|
213
|
-
});
|
|
329
|
+
issues.push({ severity: "warning", message: `"${pageId}" is not in docs.json nav (orphan)`, file: relative(projectDir, filePath) });
|
|
214
330
|
}
|
|
215
331
|
}
|
|
216
332
|
let data = {};
|
|
217
333
|
let content = "";
|
|
334
|
+
let lineOffset = 0;
|
|
218
335
|
try {
|
|
219
336
|
const raw = readFileSync2(filePath, "utf8");
|
|
220
337
|
const parsed = matter(raw);
|
|
221
338
|
data = parsed.data;
|
|
222
339
|
content = parsed.content;
|
|
340
|
+
lineOffset = raw.slice(0, raw.indexOf(content)).split("\n").length - 1;
|
|
223
341
|
} catch {
|
|
224
342
|
issues.push({ severity: "error", message: `Could not parse frontmatter`, file: relative(projectDir, filePath) });
|
|
225
343
|
continue;
|
|
226
344
|
}
|
|
227
345
|
const rel2 = relative(projectDir, filePath);
|
|
228
|
-
if (!data.title) {
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
if (
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
346
|
+
if (!data.title) issues.push({ severity: "warning", message: `Missing "title" in frontmatter`, file: rel2 });
|
|
347
|
+
if (!data.description) issues.push({ severity: "warning", message: `Missing "description" in frontmatter`, file: rel2 });
|
|
348
|
+
if (content.trim().length < 50) issues.push({ severity: "warning", message: `Very short body (${content.trim().length} chars) \u2014 page may be empty`, file: rel2 });
|
|
349
|
+
if (options.drift) checkDrift(projectDir, rel2, data, issues);
|
|
350
|
+
const path = pageIdToPath(pageId);
|
|
351
|
+
const anchors = extractHeadingAnchors(content);
|
|
352
|
+
validPaths.add(path);
|
|
353
|
+
anchorsByPath.set(path, anchors);
|
|
354
|
+
linksByFile.push({ file: rel2, path, anchors, links: extractLinks(content), offset: lineOffset });
|
|
355
|
+
}
|
|
356
|
+
for (const { file, anchors, links, offset } of linksByFile) {
|
|
357
|
+
for (const { target, line: contentLine } of links) {
|
|
358
|
+
const line = contentLine + offset;
|
|
359
|
+
if (/^(https?:|mailto:|tel:)/i.test(target)) continue;
|
|
360
|
+
if (target.startsWith("#")) {
|
|
361
|
+
const anchor2 = target.slice(1);
|
|
362
|
+
if (anchor2 && !anchors.has(anchor2)) {
|
|
363
|
+
issues.push({ severity: "warning", message: `Broken anchor: "${target}" not found on this page`, file, line });
|
|
364
|
+
}
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (!target.startsWith("/")) continue;
|
|
368
|
+
const [beforeHash, anchor] = target.split("#");
|
|
369
|
+
let path = beforeHash.split("?")[0];
|
|
370
|
+
if (path.length > 1) path = path.replace(/\/$/, "");
|
|
371
|
+
if (path.startsWith("/api") || path.startsWith("/_next") || /\.[a-z0-9]+$/i.test(path)) continue;
|
|
372
|
+
if (!validPaths.has(path)) {
|
|
373
|
+
issues.push({ severity: "error", message: `Broken link: "${target}" \u2014 no page at "${path}"`, file, line });
|
|
374
|
+
} else if (anchor && !anchorsByPath.get(path)?.has(anchor)) {
|
|
375
|
+
issues.push({ severity: "warning", message: `Broken anchor: "${target}" \u2014 no heading "#${anchor}" on that page`, file, line });
|
|
376
|
+
}
|
|
236
377
|
}
|
|
237
378
|
}
|
|
379
|
+
for (const tab of config.tabs) {
|
|
380
|
+
if (tab.api?.source) validateOpenApi(projectDir, tab.api.source, issues);
|
|
381
|
+
}
|
|
238
382
|
const errors = issues.filter((i) => i.severity === "error");
|
|
239
383
|
const warnings = issues.filter((i) => i.severity === "warning");
|
|
384
|
+
if (ci) {
|
|
385
|
+
for (const issue of issues) {
|
|
386
|
+
const loc = issue.file ? `file=${issue.file}${issue.line ? `,line=${issue.line}` : ""}` : "";
|
|
387
|
+
console.log(`::${issue.severity} ${loc}::${issue.message}`);
|
|
388
|
+
}
|
|
389
|
+
console.log(`
|
|
390
|
+
dox check: ${errors.length} error(s), ${warnings.length} warning(s)`);
|
|
391
|
+
return errors.length > 0 ? 1 : 0;
|
|
392
|
+
}
|
|
240
393
|
console.log(`
|
|
241
394
|
Linting ${projectDir}...
|
|
242
395
|
`);
|
|
@@ -250,7 +403,7 @@ async function runCheck(projectDir, fix) {
|
|
|
250
403
|
console.log(" ERRORS:");
|
|
251
404
|
for (const issue of errors) {
|
|
252
405
|
console.log(` ${issue.message}`);
|
|
253
|
-
if (issue.file) console.log(` \u2192 ${issue.file}`);
|
|
406
|
+
if (issue.file) console.log(` \u2192 ${issue.file}${issue.line ? `:${issue.line}` : ""}`);
|
|
254
407
|
}
|
|
255
408
|
console.log("");
|
|
256
409
|
}
|
|
@@ -258,7 +411,7 @@ async function runCheck(projectDir, fix) {
|
|
|
258
411
|
console.log(" WARNINGS:");
|
|
259
412
|
for (const issue of warnings) {
|
|
260
413
|
console.log(` ${issue.message}`);
|
|
261
|
-
if (issue.file) console.log(` \u2192 ${issue.file}`);
|
|
414
|
+
if (issue.file) console.log(` \u2192 ${issue.file}${issue.line ? `:${issue.line}` : ""}`);
|
|
262
415
|
}
|
|
263
416
|
console.log("");
|
|
264
417
|
}
|
|
@@ -601,8 +754,12 @@ async function runScaffoldCommand() {
|
|
|
601
754
|
}
|
|
602
755
|
async function runCheckCommand() {
|
|
603
756
|
const projectDir = resolve2(positional[1] ?? ".");
|
|
604
|
-
const
|
|
605
|
-
|
|
757
|
+
const exitCode = await runCheck(projectDir, {
|
|
758
|
+
fix: flags.includes("--fix"),
|
|
759
|
+
ci: flags.includes("--ci"),
|
|
760
|
+
external: flags.includes("--external"),
|
|
761
|
+
drift: flags.includes("--drift")
|
|
762
|
+
});
|
|
606
763
|
process.exit(exitCode);
|
|
607
764
|
}
|
|
608
765
|
async function runTranslateSubcommand() {
|
package/dist/migrate/index.js
CHANGED
package/dist/scaffold.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-dox",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Scaffold a new Dox documentation project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"@inquirer/prompts": "^7.0.0",
|
|
29
29
|
"gray-matter": "^4.0.3",
|
|
30
30
|
"p-limit": "^6.1.0",
|
|
31
|
-
"tar": "^6.2.0"
|
|
31
|
+
"tar": "^6.2.0",
|
|
32
|
+
"yaml": "^2.6.0"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
34
35
|
"@types/node": "^22.0.0",
|