@mintlify/cli 4.0.1338 → 4.0.1340
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/__test__/brokenLinks.test.ts +59 -1
- package/bin/cli.js +23 -4
- package/bin/format.js +110 -0
- package/bin/tsconfig.build.tsbuildinfo +1 -1
- package/bin/vendor/converter.js +8691 -0
- package/package.json +15 -4
- package/scripts/bundle-converter.mjs +24 -0
- package/src/cli.tsx +40 -5
- package/src/format.tsx +67 -0
- package/src/vendor/converter.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mintlify/cli",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1340",
|
|
4
4
|
"description": "The Mintlify CLI",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"scripts": {
|
|
34
34
|
"dev": "yarn build && NODE_NO_WARNINGS=1 node bin/index.js",
|
|
35
35
|
"prepare": "npm run build",
|
|
36
|
-
"build": "tsc --project tsconfig.build.json",
|
|
36
|
+
"build": "tsc --project tsconfig.build.json && node scripts/bundle-converter.mjs",
|
|
37
37
|
"clean:build": "rimraf bin",
|
|
38
38
|
"clean:all": "rimraf node_modules .eslintcache && yarn clean:build",
|
|
39
39
|
"watch": "tsc --watch",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@inquirer/prompts": "7.9.0",
|
|
48
48
|
"@mintlify/common": "1.0.1042",
|
|
49
|
-
"@mintlify/link-rot": "3.0.
|
|
49
|
+
"@mintlify/link-rot": "3.0.1235",
|
|
50
50
|
"@mintlify/models": "0.0.343",
|
|
51
51
|
"@mintlify/prebuild": "1.0.1190",
|
|
52
52
|
"@mintlify/previewing": "4.0.1259",
|
|
@@ -64,9 +64,18 @@
|
|
|
64
64
|
"open": "8.4.2",
|
|
65
65
|
"openid-client": "6.8.2",
|
|
66
66
|
"posthog-node": "5.17.2",
|
|
67
|
+
"prosemirror-model": "^1.25.0",
|
|
67
68
|
"react": "19.2.3",
|
|
69
|
+
"remark": "^15.0.1",
|
|
70
|
+
"remark-frontmatter": "^5.0.0",
|
|
71
|
+
"remark-gfm": "^4.0.1",
|
|
72
|
+
"remark-math": "^6.0.0",
|
|
73
|
+
"remark-mdx": "^3.1.1",
|
|
74
|
+
"remark-stringify": "^11.0.0",
|
|
68
75
|
"semver": "7.7.2",
|
|
76
|
+
"unified": "^11.0.5",
|
|
69
77
|
"unist-util-visit": "5.0.0",
|
|
78
|
+
"yaml": "^2.8.3",
|
|
70
79
|
"yargs": "17.7.1",
|
|
71
80
|
"zod": "4.3.6"
|
|
72
81
|
},
|
|
@@ -74,6 +83,7 @@
|
|
|
74
83
|
"keytar": "7.9.0"
|
|
75
84
|
},
|
|
76
85
|
"devDependencies": {
|
|
86
|
+
"@mintlify/editor": "0.0.248",
|
|
77
87
|
"@mintlify/ts-config": "2.0.2",
|
|
78
88
|
"@tsconfig/recommended": "1.0.2",
|
|
79
89
|
"@types/adm-zip": "0.5.7",
|
|
@@ -82,6 +92,7 @@
|
|
|
82
92
|
"@types/mdast": "4.0.4",
|
|
83
93
|
"@types/node": "18.15.0",
|
|
84
94
|
"@types/yargs": "17.0.22",
|
|
95
|
+
"esbuild": "0.25.12",
|
|
85
96
|
"openapi-types": "12.1.3",
|
|
86
97
|
"oxfmt": "^0.51.0",
|
|
87
98
|
"oxlint": "1.66.0",
|
|
@@ -92,5 +103,5 @@
|
|
|
92
103
|
"vitest": "2.1.9",
|
|
93
104
|
"vitest-mock-process": "1.0.4"
|
|
94
105
|
},
|
|
95
|
-
"gitHead": "
|
|
106
|
+
"gitHead": "a35c4acbb224d6bfb0155931033e6c0c51896dc7"
|
|
96
107
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { build } from 'esbuild';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
const entry = require.resolve('@mintlify/editor/converter');
|
|
6
|
+
|
|
7
|
+
await build({
|
|
8
|
+
entryPoints: [entry],
|
|
9
|
+
outfile: 'bin/vendor/converter.js',
|
|
10
|
+
bundle: true,
|
|
11
|
+
format: 'esm',
|
|
12
|
+
platform: 'node',
|
|
13
|
+
target: 'node18',
|
|
14
|
+
external: [
|
|
15
|
+
'@mintlify/common',
|
|
16
|
+
'@mintlify/validation',
|
|
17
|
+
'mdast-util-*',
|
|
18
|
+
'prosemirror-*',
|
|
19
|
+
'remark*',
|
|
20
|
+
'unified',
|
|
21
|
+
'unist-util-*',
|
|
22
|
+
'yaml',
|
|
23
|
+
],
|
|
24
|
+
});
|
package/src/cli.tsx
CHANGED
|
@@ -24,6 +24,8 @@ import { setTelemetryEnabled } from './config.js';
|
|
|
24
24
|
import { getConfigValue, setConfigValue, clearConfigValue } from './config.js';
|
|
25
25
|
import { API_URL } from './constants.js';
|
|
26
26
|
import { deslopHandler } from './deslop/index.js';
|
|
27
|
+
import { resolveExplicitFiles } from './deslop/resolveFiles.js';
|
|
28
|
+
import { formatHandler } from './format.js';
|
|
27
29
|
import {
|
|
28
30
|
CMD_EXEC_PATH,
|
|
29
31
|
checkPort,
|
|
@@ -296,6 +298,11 @@ export const cli = ({ packageName = 'mint' }: { packageName?: string }) => {
|
|
|
296
298
|
'Check for broken links',
|
|
297
299
|
(yargs) =>
|
|
298
300
|
yargs
|
|
301
|
+
.option('files', {
|
|
302
|
+
type: 'string',
|
|
303
|
+
array: true,
|
|
304
|
+
description: 'Files or globs to check (defaults to the whole site)',
|
|
305
|
+
})
|
|
299
306
|
.option('check-anchors', {
|
|
300
307
|
type: 'boolean',
|
|
301
308
|
default: false,
|
|
@@ -315,19 +322,35 @@ export const cli = ({ packageName = 'mint' }: { packageName?: string }) => {
|
|
|
315
322
|
type: 'boolean',
|
|
316
323
|
default: false,
|
|
317
324
|
description: 'also check that docs.json redirect destinations resolve to valid paths',
|
|
318
|
-
})
|
|
325
|
+
})
|
|
326
|
+
.example('mint broken-links --files introduction.mdx', 'Check a specific page')
|
|
327
|
+
.example('mint broken-links --files "guides/**/*.mdx"', 'Check pages matching a glob'),
|
|
319
328
|
async (argv) => {
|
|
320
329
|
await autoUpgradeIfNeeded();
|
|
321
330
|
addLog(<SpinnerLog message="checking for broken links..." />);
|
|
322
331
|
try {
|
|
332
|
+
const fileArgs = (argv.files ?? []).map(String).filter(Boolean);
|
|
333
|
+
const sourceFiles =
|
|
334
|
+
fileArgs.length > 0
|
|
335
|
+
? new Set(
|
|
336
|
+
(await resolveExplicitFiles(CMD_EXEC_PATH, fileArgs)).map((file) =>
|
|
337
|
+
path.normalize(file)
|
|
338
|
+
)
|
|
339
|
+
)
|
|
340
|
+
: undefined;
|
|
323
341
|
const graph = await buildGraph(undefined, {
|
|
324
342
|
checkSnippets: argv['check-snippets'],
|
|
325
343
|
});
|
|
326
344
|
graph.precomputeFileResolutions();
|
|
327
345
|
|
|
328
|
-
const brokenInternalLinks = graph
|
|
329
|
-
|
|
330
|
-
|
|
346
|
+
const brokenInternalLinks = graph
|
|
347
|
+
.getBrokenInternalLinks({
|
|
348
|
+
checkAnchors: argv['check-anchors'],
|
|
349
|
+
})
|
|
350
|
+
.filter(
|
|
351
|
+
({ relativeDir, filename }) =>
|
|
352
|
+
!sourceFiles || sourceFiles.has(path.join(relativeDir, filename))
|
|
353
|
+
);
|
|
331
354
|
|
|
332
355
|
const brokenLinksByFile: Record<string, string[]> = {};
|
|
333
356
|
|
|
@@ -342,7 +365,10 @@ export const cli = ({ packageName = 'mint' }: { packageName?: string }) => {
|
|
|
342
365
|
});
|
|
343
366
|
|
|
344
367
|
if (argv['check-external']) {
|
|
345
|
-
const brokenExternalLinks = await getBrokenExternalLinks(
|
|
368
|
+
const brokenExternalLinks = await getBrokenExternalLinks(
|
|
369
|
+
graph,
|
|
370
|
+
sourceFiles ? { sourceFiles } : undefined
|
|
371
|
+
);
|
|
346
372
|
for (const result of brokenExternalLinks) {
|
|
347
373
|
for (const source of result.sources) {
|
|
348
374
|
const label = result.status
|
|
@@ -711,6 +737,15 @@ export const cli = ({ packageName = 'mint' }: { packageName?: string }) => {
|
|
|
711
737
|
),
|
|
712
738
|
deslopHandler
|
|
713
739
|
)
|
|
740
|
+
.command(
|
|
741
|
+
'format',
|
|
742
|
+
'Format MDX files in the current directory',
|
|
743
|
+
(yargs) =>
|
|
744
|
+
yargs
|
|
745
|
+
.usage('usage: mint format')
|
|
746
|
+
.example('mint format', 'format all MDX files in the current directory'),
|
|
747
|
+
formatHandler
|
|
748
|
+
)
|
|
714
749
|
// Coming soon commands — visible in help, tracked via telemetry to gauge interest.
|
|
715
750
|
.command(
|
|
716
751
|
'ai',
|
package/src/format.tsx
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { isMintIgnored, processMintIgnoreString } from '@mintlify/common';
|
|
2
|
+
import { getMintIgnore } from '@mintlify/prebuild';
|
|
3
|
+
import { addLog, ErrorLog, SuccessLog } from '@mintlify/previewing';
|
|
4
|
+
import fs from 'node:fs/promises';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
|
|
7
|
+
import { CMD_EXEC_PATH, terminate } from './helpers.js';
|
|
8
|
+
|
|
9
|
+
async function getGitIgnore(): Promise<string[]> {
|
|
10
|
+
try {
|
|
11
|
+
const content = await fs.readFile(path.join(CMD_EXEC_PATH, '.gitignore'), 'utf-8');
|
|
12
|
+
return processMintIgnoreString(content);
|
|
13
|
+
} catch {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function* walk(dir: string, ignores: string[]): AsyncGenerator<string> {
|
|
19
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
20
|
+
for (const entry of entries) {
|
|
21
|
+
const full = path.join(dir, entry.name);
|
|
22
|
+
const relative = path.relative(CMD_EXEC_PATH, full).split(path.sep).join('/');
|
|
23
|
+
if (entry.isDirectory()) {
|
|
24
|
+
if (isMintIgnored(`${relative}/`, ignores)) continue;
|
|
25
|
+
yield* walk(full, ignores);
|
|
26
|
+
} else if (entry.name.endsWith('.mdx')) {
|
|
27
|
+
if (isMintIgnored(relative, ignores)) continue;
|
|
28
|
+
yield full;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const formatHandler = async (): Promise<void> => {
|
|
34
|
+
const { mdxToPm, pmToMdx } = await import('./vendor/converter.js');
|
|
35
|
+
const ignores = [...(await getGitIgnore()), ...(await getMintIgnore(CMD_EXEC_PATH))];
|
|
36
|
+
let total = 0;
|
|
37
|
+
let changed = 0;
|
|
38
|
+
let failed = 0;
|
|
39
|
+
|
|
40
|
+
for await (const file of walk(CMD_EXEC_PATH, ignores)) {
|
|
41
|
+
total++;
|
|
42
|
+
const relative = path.relative(CMD_EXEC_PATH, file);
|
|
43
|
+
try {
|
|
44
|
+
const raw = await fs.readFile(file, 'utf-8');
|
|
45
|
+
const { doc, frontmatter } = mdxToPm(raw, { singleDollarTextMath: false });
|
|
46
|
+
const formatted = `${pmToMdx(doc, { frontmatter })}\n`;
|
|
47
|
+
if (formatted !== raw) {
|
|
48
|
+
await fs.writeFile(file, formatted);
|
|
49
|
+
changed++;
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
failed++;
|
|
53
|
+
addLog(
|
|
54
|
+
<ErrorLog
|
|
55
|
+
message={`${relative}: ${error instanceof Error ? error.message : 'unknown error'}`}
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
addLog(
|
|
62
|
+
<SuccessLog
|
|
63
|
+
message={`formatted ${changed} of ${total} mdx file${total === 1 ? '' : 's'}${failed > 0 ? ` (${failed} failed)` : ''}`}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
await terminate(failed > 0 ? 1 : 0);
|
|
67
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@mintlify/editor/converter';
|