119 lines
3.4 KiB
TypeScript
119 lines
3.4 KiB
TypeScript
import { relative, resolve } from 'node:path';
|
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
import { format } from 'prettier';
|
|
import consola from 'consola';
|
|
import { execaCommand } from 'execa';
|
|
|
|
let hasGenerated = false;
|
|
|
|
const cliDir = resolve('packages/wxt/src/cli/commands');
|
|
const cliDirGlob = resolve(cliDir, '**');
|
|
const cliTemplatePath = resolve('docs/.vitepress/plugins/cli.tpl.md');
|
|
const cliPath = resolve('docs/api/cli.md');
|
|
|
|
const PREFACE = `<!--
|
|
DO NOT EDIT
|
|
Generated by \`wxt/docs/.vitepress/plugins/generate-config-docs.ts\`
|
|
To make changes to the config reference, update the JSDoc in \`src/core/types/external.ts\`.
|
|
-->`;
|
|
|
|
export function generateCliDocs() {
|
|
writeFileSync(cliPath, '');
|
|
|
|
const generateDocs = async () => {
|
|
consola.info(`Generating ${relative(process.cwd(), cliPath)}`);
|
|
try {
|
|
const res = await execaCommand('pnpm -s wxt --help', {
|
|
cwd: 'packages/wxt',
|
|
});
|
|
const dev = splitInfo(res.stdout);
|
|
const lines: Array<string | string[]> = [
|
|
`## \`wxt\``,
|
|
'```sh',
|
|
dev.rest,
|
|
'```',
|
|
];
|
|
|
|
const commands = await Promise.allSettled(
|
|
extractCommands(dev.info).map(async (command) => {
|
|
const res = await execaCommand(`pnpm -s wxt ${command} --help`, {
|
|
cwd: 'packages/wxt',
|
|
});
|
|
const { rest: docs } = splitInfo(res.stdout);
|
|
return [`## \`wxt ${command}\``, '```sh', docs, '```'];
|
|
}),
|
|
);
|
|
lines.push(
|
|
...commands
|
|
.filter((res) => res.status === 'fulfilled')
|
|
.map(
|
|
(res) => (res as unknown as PromiseFulfilledResult<string>).value,
|
|
),
|
|
);
|
|
|
|
const text = await format(
|
|
PREFACE +
|
|
'\n\n' +
|
|
readFileSync(cliTemplatePath, 'utf-8').replace(
|
|
'{{ DOCS }}',
|
|
lines.flat().join('\n'),
|
|
),
|
|
{ parser: 'markdown' },
|
|
);
|
|
|
|
writeFileSync(cliPath, text);
|
|
consola.success(`Generated ${relative(process.cwd(), cliPath)}`);
|
|
} catch (err) {
|
|
consola.fail(`Failed to generate ${relative(process.cwd(), cliPath)}`);
|
|
consola.error(err.message);
|
|
}
|
|
};
|
|
|
|
return {
|
|
name: 'docs:generate-cli-docs',
|
|
async config() {
|
|
if (!hasGenerated) {
|
|
hasGenerated = true;
|
|
await generateDocs();
|
|
}
|
|
},
|
|
configureServer(server: any) {
|
|
server.watcher.add(cliDirGlob);
|
|
},
|
|
async handleHotUpdate(ctx: { file: string }) {
|
|
if (ctx.file === cliTemplatePath || ctx.file.includes(cliDir)) {
|
|
await generateDocs();
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
function splitInfo(text: string): { info: string; rest: string } {
|
|
const infoStart = text.indexOf('For more info,');
|
|
const infoEnd = text.indexOf('\n\nOptions:');
|
|
|
|
if (infoStart === -1 || infoEnd === -1) {
|
|
return { info: '', rest: text };
|
|
}
|
|
|
|
const info = text.substring(infoStart, infoEnd).trim();
|
|
const rest = text.replace(info, '').trim().replace('\n\n\n\n', '\n\n');
|
|
|
|
return { info, rest };
|
|
}
|
|
|
|
function extractCommands(info: string): string[] {
|
|
const commands: string[] = [];
|
|
|
|
// Split the info by line and iterate through each line
|
|
info.split('\n').forEach((line) => {
|
|
// Use regex to capture the command after "$ wxt " and before "--help"
|
|
const match = line.match(/\$ wxt (\w+) --help/);
|
|
if (match && match[1]) {
|
|
commands.push(match[1]);
|
|
}
|
|
});
|
|
|
|
return commands;
|
|
}
|