UNPKG

@vuedoc/parser

Version:

Generate a JSON documentation for a Vue file

207 lines 7.19 kB
import { lstat, writeFile } from 'node:fs/promises'; import { readFileSync, createWriteStream } from 'node:fs'; import { dirname, isAbsolute, join, parse } from 'node:path'; import { fileURLToPath } from 'node:url'; import { VuedocParser, parseComponent } from '../main.js'; import merge from 'deepmerge'; import JsonSchemav from 'jsonschemav'; import ValidationError from 'jsonschemav/lib/error.js'; import schema from '../schema/options.js'; const jsv = new JsonSchemav(); const validator = jsv.compile(schema); const ARG_IGNORE_PREFIX = '--ignore-'; const usage = 'Usage: vuedoc-json [*.{js,vue} files]...'; export const MISSING_FILENAME_MESSAGE = `Missing filenames. ${usage}\n`; async function validateOptions(options) { if (options.join && options.output) { if ((await lstat(options.output)).isDirectory()) { throw new Error('--output value must be a file when using --join'); } } } async function parseArgs(argv, requireFiles) { const parsing = { filecontent: '', features: VuedocParser.SUPPORTED_FEATURES, }; const options = { join: false, stream: true, reduce: false, filenames: [], output: '', parsing, }; const promises = []; for (let i = 0; i < argv.length; i++) { const arg = argv[i]; switch (arg) { /* istanbul ignore next */ case '-v': /* istanbul ignore next */ case '--version': { const __dirname = dirname(fileURLToPath(import.meta.url)); const packageFilename = join(__dirname, '../package.json'); const { name, version } = JSON.parse(readFileSync(packageFilename, 'utf-8')); const output = `${name} v${version}\n`; process.stdout.write(output); return null; } case '-c': case '--config': { const configFile = argv[i + 1] || 'vuedoc.config.js'; const configPath = isAbsolute(configFile) ? configFile : join(process.cwd(), configFile); promises.push((async () => { const config = await import(configPath); if (config.default) { Object.assign(options, config.default); if (config.default.parsing) { options.parsing = { ...parsing, ...config.default.parsing }; } } })()); i++; break; } case '-o': case '--output': if (!argv[i + 1]) { throw new Error('Missing output value. Usage: --output [file or directory]\n'); } options.output = argv[i + 1]; i++; break; case '-j': case '--join': options.join = true; break; default: { if (arg.startsWith(ARG_IGNORE_PREFIX)) { const feature = arg.substring(ARG_IGNORE_PREFIX.length); options.parsing.features = options.parsing.features.filter((item) => item !== feature); } else { options.filenames.push(arg); } break; } } } await Promise.all(promises); if (requireFiles && options.filenames.length === 0) { throw new Error(MISSING_FILENAME_MESSAGE); } await validateOptions(options); return options; } async function parseComponentOptions({ filename, ...options }) { if (!options.parsing) { options.parsing = {}; } // compatibility with previous versions if (filename && !options.filenames) { options.filenames = [filename]; } try { const instance = await validator; const { parsing: parsingOptions, join, filenames } = await instance.validate(options); const promises = await new Promise((resolve, reject) => { if (filenames.length) { const promises = filenames.map((filename) => parseComponent({ ...parsingOptions, filename })); if (join) { resolve([ Promise.all(promises).then(merge.all), ]); } else { resolve(promises); } } else if (parsingOptions.filecontent) { resolve([ parseComponent(parsingOptions), ]); } else { reject(new Error('Invalid options. Missing options.filenames')); } }); const docs = await Promise.all(promises); if (filenames.length === 1 && docs.length === 1) { return docs[0]; } return docs; } catch (err) { if (err instanceof ValidationError) { err.message = 'Invalid options'; } throw err; } } export async function processRawContent(argv, componentRawContent) { const options = await parseArgs(argv, false); if (options) { options.stream = process.stdout; options.parsing.filecontent = componentRawContent; return parseComponentOptions(options); } return ''; } async function prepareOutput(options) { const stat = await lstat(options.output); if (stat.isDirectory()) { options.stream = (filename) => { const info = parse(filename); const mdname = `${info.name}.md`; const dest = join(options.output, mdname); return createWriteStream(dest); }; } else { options.stream = createWriteStream(options.output); } return parseComponentOptions(options); } async function prepare(options, filenames) { options.filenames = filenames; if (options.output) { return prepareOutput(options); } options.stream = process.stdout; return parseComponentOptions(options); } export async function processWithOutputOption(options) { const generatedDocs = await prepare(options, options.filenames); await writeFile(options.output, JSON.stringify(generatedDocs, null, 2)); } export async function processWithoutOutputOption(options) { return prepare(options, options.filenames); } export async function exec(argv, componentRawContent = '') { if (componentRawContent) { await processRawContent(argv, componentRawContent); } else { const options = await parseArgs(argv, true); if (options) { if (options.output) { await processWithOutputOption(options); } else { await processWithoutOutputOption(options); } } } } export async function silenceExec(argv, componentRawContent = '') { try { await exec(argv, componentRawContent); } catch (err) { process.stderr.write(`${err.message}\n`); } } //# sourceMappingURL=CLI.js.map