UNPKG

@vuedoc/parser

Version:

Generate a JSON documentation for a Vue file

159 lines 5.74 kB
import { VuedocParser } from './parsers/VuedocParser.js'; import { Feature, DEFAULT_IGNORED_VISIBILITIES, DEFAULT_ENCODING, FeatureEvent } from './lib/Enum.js'; import { KeywordsUtils } from './utils/KeywordsUtils.js'; import { PropEntry } from './entity/PropEntry.js'; export * from './lib/Enum.js'; export { Loader } from './lib/Loader.js'; export { VuedocParser } from './parsers/VuedocParser.js'; export async function parseOptions(options) { if (!options) { throw new Error('Missing options argument'); } const _options = { ...options }; if (!_options.encoding) { _options.encoding = DEFAULT_ENCODING; } if ('filename' in _options && !_options.filename) { throw new Error('options.filename cannot be empty'); } if (!_options.ignoredVisibilities) { _options.ignoredVisibilities = DEFAULT_IGNORED_VISIBILITIES; } _options.composition = { data: _options.composition?.data || [], methods: _options.composition?.methods || [], computed: _options.composition?.computed || [], props: _options.composition?.props || [], }; if (!_options.resolver) { _options.resolver = {}; } return _options; } export function synchronizeParsingResult(parser, component) { const defaultModelProp = parser.file.script?.attrs.setup ? 'model-value' : 'value'; const additionalProps = []; if (!component.props) { component.props = []; } component.model?.forEach((model) => { const props = component.props?.filter((prop) => prop.name === model.prop); if (props?.length) { for (const prop of props) { prop.describeModel = true; } } else { const prop = new PropEntry({ name: model.prop, describeModel: true, }); prop.description = model.description; prop.keywords = model.keywords; additionalProps.push(prop); } }); component.props.push(...additionalProps); delete component.model; if (Feature.props in component) { for (const prop of component.props) { if (prop.name === defaultModelProp) { prop.describeModel = true; } if (prop.describeModel) { prop.name = 'v-model'; } else if (parser.file.script?.attrs.setup && Feature.events in component) { const hasUpdateEvent = component.events?.some((event) => event.name === `update:${prop.name}`); if (hasUpdateEvent) { prop.name = `v-model:${prop.name}`; prop.describeModel = true; } } } } } export async function parseComponent(options) { const resolvedOptions = await parseOptions(options); return new Promise((resolve, reject) => { const component = { name: undefined, description: undefined, category: undefined, since: undefined, version: undefined, see: undefined, inheritAttrs: true, errors: [], warnings: [], keywords: [], model: [], props: undefined, data: undefined, computed: undefined, methods: undefined, events: undefined, slots: undefined, }; const parser = new VuedocParser(resolvedOptions); parser.addEventListener('error', (event) => { component.errors.push(event.message); }); parser.addEventListener('warning', (event) => { component.warnings.push(event.message); }); parser.addEventListener('keyword', ({ entry }) => { component.keywords.push(...entry.value); KeywordsUtils.parseCommonEntryTags(component); }); parser.addEventListener('inheritAttrs', ({ entry }) => { component.inheritAttrs = entry.value; }); parser.addEventListener('model', handleEventEntry(component.model)); parser.addEventListener('fatal', (event) => reject(event.error)); parser.addEventListener('end', () => { if ('file' in parser && parser.file) { synchronizeParsingResult(parser, component); } for (const plugin of parser.plugins) { if ('handleParsingResult' in plugin) { plugin.handleParsingResult(component); } } resolve(component); }); for (const feature of parser.features) { const eventName = FeatureEvent[feature]; switch (feature) { case Feature.name: case Feature.description: parser.addEventListener(eventName, ({ entry }) => { component[feature] = entry.value; }); break; case Feature.keywords: // already handled break; default: { const items = []; component[feature] = items; parser.addEventListener(eventName, handleEventEntry(items)); break; } } } parser.walk(); }); } function handleEventEntry(items) { return ({ entry }) => { const index = items.findIndex((item) => item.name === entry.name); if (index > -1) { items.splice(index, 1, entry); } else { items.push(entry); } }; } //# sourceMappingURL=main.js.map