The Vuedoc Parser
Generate a JSON documentation for a Vue file component.
Table of Contents
Install
This package is ESM only
: Node 16+ is needed to use it and it must be imported instead of required.
npm install --save @vuedoc/parser
Features
- Extract the component name (from the
name
field or from the filename) - Extract the component description
- Keywords support
- Extract component
model
, props
, data
, computed properties
,
events
, slots
and methods
- Vue 3 support with Composition API
- JSX support
- Class Component support
- Vue Property Decorator support
- Prop Types support
- JSDoc support
(
@type
,
@param
,
@returns
,
@version
,
@since
,
@deprecated
,
@see
,
@kind
,
@author
and
@ignore
tags) - TypeDoc tags
support (
@param <param name>
, @return(s)
, @hidden
, @category
)
Options
Name | Description |
---|
filename | The filename to parse. Required unless filecontent is passed |
filecontent | The file content to parse. Required unless filename is passed |
encoding | The file encoding. Default is 'utf8' |
features | The component features to parse and extract. Default features: ['name', 'description', 'slots', 'props', 'data', 'computed', 'events', 'methods'] |
loaders | Use this option to define custom loaders for specific languages |
ignoredVisibilities | List of ignored visibilities. Default: ['protected', 'private'] |
composition | Additional composition tokens for advanced components. Default value: { data: [], methods: [], computed: [], props: [] } |
resolver | A resolver object used to resolve imports statements. See definition file types/ImportResolver.d.ts |
plugins | An array of plugins to activate. See Using Plugins section |
jsx | Set to true to enable JSX parsing. Default false |
Found TypeScript definition here.
Programmatic usage
Given the folowing SFC file test/examples/circle-drawer/circle-drawer-composition.vue, the parsing usage would be:
import { parseComponent } from '@vuedoc/parser';
const options = {
filename: 'test/examples/circle-drawer/circle-drawer-composition.vue',
};
parseComponent(options)
.then((component) => console.log(component))
.catch((err) => console.error(err));
This will print this JSON output:
{
"name": "CircleDrawer",
"description": "Circle Drawer’s goal is, among other things, to test how good the common\nchallenge of implementing an undo/redo functionality for a GUI application\ncan be solved.",
"see": "https://eugenkiss.github.io/7guis/tasks/#circle",
"inheritAttrs": true,
"errors": [],
"warnings": [],
"keywords": [
{
"name": "usage",
"description": "Click on the canvas to draw a circle. Click on a circle to select it.\nRight-click on the canvas to adjust the radius of the selected circle."
}
],
"props": [ ],
"data": [ ],
"computed": [ ],
"slots": [ ],
"events": [ ],
"methods": [ ]
}
Found the complete result here: test/examples/circle-drawer/parsing-result.json
Found more examples here: test/examples
Command line options
-j, --join
-c, --config <filename>
-o, --output <file or dir>
--ignore-name
--ignore-description
--ignore-keywords
--ignore-slots
--ignore-props
--ignore-computed
--ignore-data
--ignore-methods
--ignore-events
Overwrite Vuedoc Parser configuration using vuedoc.config.js
import { Loader } from '@vuedoc/parser';
import { PugLoader } from '@vuedoc/parser/loaders/pug';
export default {
output: 'docs/',
parsing: {
features: ['name', 'description', 'keywords', 'slots', 'model', 'props', 'events', 'methods'],
loaders: [
Loader.extend('pug', PugLoader),
],
},
};
Command line usage
vuedoc-json --version
vuedoc-json components/textarea.vue
vuedoc-json components/textarea.vue --output docs/textarea.json
vuedoc-json components/*.vue --output docs/
vuedoc-json --join components/*.vue --output components.json
cat components/textarea.vue | vuedoc-json -
vuedoc-json --config vuedoc.config.js components/*.vue
vuedoc-json -c components/*.vue
Syntax
Add component name
By default, Vuedoc Parser uses the component's filename to generate the
component name.
To set a custom name, use the name
option:
<script>
export default {
name: 'my-checkbox',
};
</script>
You can also use the @name
tag:
<script>
export default {
};
</script>
Composition usage
When using <script setup>
, you need to define a comment block as a first
node of your script.
<script setup>
import { ref } from 'vue';
const checked = ref(false);
</script>
Add component description
To add a component description, just add a comment before the export default
statement like:
<script>
export default {
};
</script>
When using <script setup>
, you need to define a comment block as a first
node of your script.
<script setup>
import { ref } from 'vue';
const checked = ref(false);
</script>
Annotate props
To document props, annotate your code like:
Legacy usage
<script>
export default {
props: {
id: {
type: String,
required: true,
},
value: {
type: String,
default: '',
},
},
};
</script>
Vuedoc Parser will automatically extract type
, required
and default
values for
properties.
Composition usage
<script setup>
const props = defineProps({
id: {
type: String,
required: true,
},
value: {
type: String,
default: '',
},
});
</script>
Vuedoc Parser will automatically extract type
, required
and default
values for
properties.
Composition usage with TypeScript
<script lang="ts" setup>
type Props = {
id: string;
value?: string;
};
const props = withDefaults(defineProps<Props>(), {
value: '',
});
</script>
Vuedoc Parser will automatically extract type
, required
and default
values from
the type definition.
Annotate a v-model
prop
Legacy usage
<script>
export default {
props: [
'modelValue',
],
emits: ['update:modelValue'],
};
</script>
Composition usage
To document a v-model
prop using Composition API, use
defineProps()
macro.
<script setup>
const props = defineProps([
'modelValue',
]);
const emit = defineEmits(['update:modelValue']);
</script>
Vue 2 usage
To document a v-model
prop legacy Vue, use the Vue's
model field.
<script>
export default {
model: {
prop: 'checked',
event: 'change',
},
props: {
checked: Boolean,
},
};
</script>
Annotate Vue Array String Props
To document Vue array string props, just attach a Vuedoc comment to each prop:
Legacy usage
<script>
export default {
props: [
'id',
'value',
],
};
</script>
Composition usage
<script setup>
const props = defineProps([
'id',
'value',
]);
</script>
Special tags for props
@type {typeName}
Commented prop will use provided type name as type instead of type in source
code. This option may be helpful in case the prop type is a complex object or
a function@default {value}
Commented prop will use the provided value as default prop value. This option
may be helpful in case the prop type is a complex object or function@kind function
Force parsing of a prop as a function
<script>
export default {
props: {
custom: {
type: Object,
default: () => {
return anythingExpression();
},
},
validator: {
type: Function,
default: (value) => !Number.isNaN(value),
},
},
};
</script>
Prop Entry Interface
interface PropEntry {
kind: 'prop';
name: string;
type: string | string[];
default: string;
required: boolean;
description?: string;
describeModel: boolean;
keywords: Keyword[];
category?: string;
version?: string;
since?: string;
visibility: 'public' | 'protected' | 'private';
}
type Keyword = {
name: string;
description?: string;
};
Annotate data
To document data, annotate your code like:
Legacy usage
<script>
export default {
data() {
return {
checked: false,
};
},
};
</script>
Composition usage
<script>
import { ref } from 'vue';
export default {
setup() {
return {
checked: ref(false),
};
},
};
</script>
Vuedoc Parser will automatically detect type for each defined data field and
catch their initial value.
Special tags for data
@type {typeName}
Commented data will use provided type name as type instead of type in source
code. This option may be helpful in case the data type is a complex object or
a function@initialValue {value}
Commented data will use the provided value as initial data value. This option
may be helpful in case the data type is a complex object or function
<script>
export default {
data() {
return {
checked: ExternalHelper.getDefaultValue(),
};
},
};
</script>
Data Entry Interface
interface DataEntry {
kind: 'data';
name: string;
type: string;
initialValue: string;
description?: string;
keywords: Keyword[];
category?: string;
version?: string;
since?: string;
visibility: 'public' | 'protected' | 'private';
}
type Keyword = {
name: string;
description?: string;
};
Annotate computed properties
To document computed properties, annotate your code like:
Legacy usage
<script>
export default {
props: {
checked: Boolean,
},
computed: {
selected () {
return this.checked;
},
},
};
</script>
Vuedoc Parser will automatically extract computed properties dependencies.
Composition usage
<script>
import { computed } from 'vue';
export default {
props: {
checked: Boolean,
},
setup(props) {
return {
selected: computed(() => props.checked),
};
},
};
</script>
Usage with <script setup>
<script setup>
import { computed } from 'vue';
const props = defineProps({
checked: Boolean,
});
const selected = computed(() => props.checked);
</script>
Computed Property Entry Interface
interface ComputedEntry {
kind: 'computed';
name: string;
type: string;
dependencies: string[];
description?: string;
keywords: Keyword[];
category?: string;
version?: string;
since?: string;
visibility: 'public' | 'protected' | 'private';
}
type Keyword = {
name: string;
description?: string;
};
Annotate methods
To document methods, simply use JSDoc tags
@param
and
@returns
:
Legacy usage
<script>
export default {
methods: {
submit(data) {
return true;
},
},
};
</script>
Composition usage
<script setup>
function submit(data) {
return true;
}
</script>
Special tags for methods
-
@method <method name>
You can use special tag @method
for non primitive name:
<script>
const METHODS = {
CLOSE: 'closeModal',
};
export default {
methods: {
[METHODS.CLOSE] () {},
},
};
</script>
-
@syntax <custom method syntax>
By default, Vuedoc Parser automatically generates method syntax with typing.
For example, the previous example will generate:
{
kind: 'method',
name: 'closeModal',
params: [],
returns: { type: 'void', description: undefined },
syntax: [
'closeModal(): void'
],
category: undefined,
version: undefined,
description: undefined,
keywords: [],
visibility: 'public'
}
You can overwrite syntax generation by using tag @syntax
. You can also
define multiple syntax examples:
<script>
export default {
methods: {
addEventListener(type, listener, options, useCapture) {},
},
};
</script>
Method Entry Interface
interface MethodEntry {
kind: 'method';
name: string;
params: MethodParam[];
returns: MethodReturn;
syntax: string[];
description?: string;
keywords: Keyword[];
category?: string;
version?: string;
since?: string;
visibility: 'public' | 'protected' | 'private';
}
type Keyword = {
name: string;
description?: string;
};
type MethodParam = {
name: string;
type: NativeTypeEnum | string;
description?: string;
defaultValue?: string;
rest: boolean;
};
type MethodReturn = {
type: string;
description?: string;
};
Annotate events
Legacy usage
To document events using the legacy syntax, use the
emits
field and tags @arg
or @argument
to define arguments:
Array syntax:
<script>
export default {
emits: [
'loading',
'input',
],
};
</script>
Object syntax with validation:
<script>
export default {
emits: {
loading: null,
input: (payload) => {
if (payload.email && payload.password) {
return true
} else {
console.warn(`Invalid submit event payload!`)
return false
}
},
},
};
</script>
Composition usage
Array syntax:
<script setup>
const emit = defineEmits([
'loading',
'input',
]);
</script>
Object syntax with validation:
<script setup>
const emit = defineEmits({
loading: null,
input: (payload) => {
if (payload.email && payload.password) {
return true
} else {
console.warn(`Invalid submit event payload!`)
return false
}
},
});
</script>
Composition usage with TypeScript
<script setup>
const emit = defineEmits<{
(e: 'loading', value: boolean): void
(e: 'input', value: boolean): void
}>()
</script>
Vue 2 usage
Vuedoc Parser automatically extracts events from component template, hooks and
methods when using Vue 2:
<script>
export default {
created() {
this.$emit('loading', true);
},
methods: {
submit() {
this.$emit('input', true);
},
},
};
</script>
<template>
<div>
<button @click="$emit('click', $event)">Submit</button>
</div>
</template>
You can use special keyword @event
for non primitive name:
<script>
const EVENTS = {
CLOSE: 'close',
};
export default {
methods: {
closeModal() {
this.$emit(EVENTS.CLOSE, true);
},
},
};
</script>
Event Entry Interface
interface EventEntry {
kind: 'event';
name: string;
description?: string;
arguments: EventArgument[];
keywords: Keyword[];
category?: string;
version?: string;
since?: string;
visibility: 'public' | 'protected' | 'private';
}
type Keyword = {
name: string;
description?: string;
};
type EventArgument = {
name: string;
type: NativeTypeEnum | string;
description?: string;
rest: boolean;
};
Annotate slots
Vuedoc Parser automatically extracts slots from template. You must use @prop
tag to define properties of a slot:
<template>
<div>
<slot></slot>
<slot name="label">Unnamed checkbox</slot>
<slot name="header" v-bind:user="user" v-bind:profile="profile"/>
</div>
</template>
Annotate slots defined in Render Functions
To annotate slots defined in Render Functions, just attach the tag @slot
to the component definition:
<script>
export default {
functional: true,
render(h, { slots }) {
return h('div', [
h('h1', slots().title),
h('p', slots().default),
]);
},
};
</script>
You can also use the tag @slot
to define dynamic slots on template:
<template>
<div>
<template v-for="name in ['title', 'default']">
<slot :name="name"></slot>
</template>
</div>
</template>
Slot Entry Interface
interface SlotEntry {
kind: 'slot';
name: string;
description?: string;
props: SlotProp[];
keywords: Keyword[];
category?: string;
version?: string;
since?: string;
visibility: 'public' | 'protected' | 'private';
}
type Keyword = {
name: string;
description?: string;
};
type SlotProp = {
name: string;
type: string;
description?: string;
};
Ignore items from parsing
Use the JSDoc's tag @ignore
to keeps the
subsequent code from being documented.
<script>
export default {
data: () => ({
checked: false,
}),
};
</script>
You can also use the TypeDoc's tag @hidden
.
You can attach keywords (or tags) to any comment and then extract them using
the parser.
Usage
<script>
export default { };
</script>
Note that the description must always appear before keywords definition.
Parsing result:
{
"name": "my-checkbox",
"description": "Component description",
"keywords": [
{
"name": "license",
"description": "MIT"
}
]
}
Supported Tags
Tag | Scope | Description |
---|
@name | component | Provide a custom name of the component |
@type | props , data , computed | Provide a type expression identifying the type of value that a prop or a data may contain |
@default | props | Provide a default value of a prop |
@kind | props | Used to document what kind of symbol is being documented |
@initialValue | data | Provide an initial value of a data |
@method | methods | Force the name of a specific method |
@syntax | methods | Provide the custom method syntax |
@param | methods | Provide the name, type, and description of a function parameter |
@returns , @return | methods | Document the value that a function returns |
@event | events | Force the name of a specific event |
@arg , @argument | events | Provide the name, type, and description of an event argument |
@slot | slots | Document slot defined in render function |
@prop | slots | Provide the name, type, and description of a slot prop |
@mixin deprecated | component | Force parsing of the exported item as a mixin component. This is deprecated since v4.0.0 |
@version | all | Assign a version to an item |
@since | all | Indicate that an item was added in a specific version |
@author | all | Identify authors of an item |
@deprecated | all | Mark an item as being deprecated |
@see | all | Allow to refer to a resource that may be related to the item being documented |
@ignore | * | Keep the subsequent code from being documented |
TypeDoc | | |
@category | all | Attach a category to an item |
@hidden | * | Keep the subsequent code from being documented |
Visibilities | | |
@public | * | Mark a symbol as public |
@protected | * | Mark a symbol as private |
@private | * | Mark a symbol as protected |
*
stand for props
, data
, methods
, events
, slots
Working with Mixins
Starting v4.0.0
, Vuedoc Parser implements a mechanism to automatically
load needed import declarations to parse and extract metadata.
With this new capability, Vuedoc Parser is now able to handle Vue mixins
automatically.
Parsing control with options.features
options.features
lets you select which Vue Features you want to parse and
extract.
The default value is defined by VuedocParser.SUPPORTED_FEATURES
array.
Usage
Only parse name
, props
, computed properties
, slots
and events
:
import { parseComponent } from '@vuedoc/parser';
const options = {
filename: 'test/examples/circle-drawer/circle-drawer-composition.vue',
features: [ 'name', 'props', 'computed', 'slots', 'events' ],
};
parseComponent(options)
.then((component) => Object.keys(component))
.then((keys) => console.log(keys));
Parse all features except data
:
import { parseComponent, VuedocParser } from '@vuedoc/parser';
const options = {
filename: 'test/examples/circle-drawer/circle-drawer-composition.vue',
features: VuedocParser.SUPPORTED_FEATURES.filter((feature) => feature !== 'data'),
};
parseComponent(options)
.then((component) => Object.keys(component))
.then((keys) => console.log(keys));
Using Plugins
Vuedoc can be extended using plugins.
Adding a Plugin
To use a plugin, it needs to be added to the devDependencies
of the project
and included in the plugins array options.plugins
. For example, to provide
support of Vue Router, the official @vuedoc/plugin-vue-router
can be used:
$ npm add -D @vuedoc/plugin-vue-router
import { parseComponent } from '@vuedoc/parser';
import { VueRouterPlugin } from '@vuedoc/plugin-vue-router';
const component = await parseComponent({
plugins: [
VueRouterPlugin,
],
});
Official Plugins
Building Plugins
Plugins Overview
A Vuedoc plugin is an object with one or more of the properties, parsing hooks
described below, and which follows our conventions.
A plugin should be distributed as a package which exports a function
that can be called with plugin specific options and returns such an
object.
Plugins allow you to customise Vuedoc's behaviour by, for example,
handling and parse parsing result object before sending the final result, or
adding support of a third-party modules in your node_modules
folder.
Conventions
- Plugins should have a clear name with
vuedoc-plugin-
prefix. - Include
vuedoc-plugin
keyword in package.json
. - Plugins should be tested.
- Document your plugin in English.
Interface
type Plugin = (parser: Parser) => PluginDefinition;
interface PluginDefinition {
resolver?: ImportResolver;
preload?: string[];
composition?: Partial<ParsingComposition>;
handleParsingResult?(component: ParseResult): void;
}
interface Parser extends EventTarget {
readonly options: ResolvedOptions;
addEventListener(
type: EventType,
callback: EventListener<EntryEvent<EventType>>,
options?: boolean | AddEventListenerOptions
): void;
addEventListener<T extends MessageEventType>(
type: EventType,
callback: EventListener<MessageEvent<EventType>>,
options?: boolean | AddEventListenerOptions
): void;
addEventListener(
type: 'end',
callback: EventListener<EndEvent>,
options?: boolean | AddEventListenerOptions
): void;
): void;
addEventListener(
type: 'fatal',
callback: EventListener<FatalErrorEvent>,
options?: boolean | AddEventListenerOptions
): void;
}
type EventType = 'computed' | 'data' | 'description' | 'event' | 'inheritAttrs' | 'keyword' | 'method' | 'model' | 'name' | 'prop';
Please see PluginInterface from types/index.d.ts from detailled types.
Language Processing
Loader API
Please see TypeScript definition file for the Loader class.
Built-in loaders
Create a custom loader
The example below uses the abstract Vuedoc.Loader
class to create a
specialized class to handle a template with the
CoffeeScript language.
It uses the built-in PugLoader
to load Pug template:
import { parseComponent, Loader } from '@vuedoc/parser';
import { PugLoader } from '@vuedoc/parser/loaders/pug';
import { compile } from 'coffeescript';
class CoffeeScriptLoader extends Loader {
load (source) {
const outputText = compile(source);
this.emitScript(outputText);
}
}
const options = {
filecontent: `
<template lang="pug">
div.page
h1 Vuedoc Parser with Pug
// Use this slot to define a subtitle
slot(name='subtitle')
</template>
<script lang="coffee">
###
# Description of MyInput component
###
export default
name: 'MyInput'
</script>
`,
loaders: [
Loader.extend('coffee', CoffeeScriptLoader),
Loader.extend('pug', PugLoader),
],
};
parseComponent(options).then((component) => {
console.log(component);
});
Output
{
name: 'MyInput',
description: 'Description of MyInput component',
slots: [
{
kind: 'slot',
visibility: 'public',
description: 'Use this slot to define a subtitle',
keywords: [],
name: 'subtitle',
props: []
}
],
}
Parsing Output Interface
Please see TypeScript definition file.
Generate Markdown Documentation
To generate a markdown documentation, please use the @vuedoc/md package.
Contribute
Please follow CONTRIBUTING.md.
Versioning
Given a version number MAJOR.MINOR.PATCH
, increment the:
MAJOR
version when you make incompatible API changes,MINOR
version when you add functionality in a backwards-compatible manner,
andPATCH
version when you make backwards-compatible bug fixes.
Additional labels for pre-release and build metadata are available as extensions
to the MAJOR.MINOR.PATCH
format.
See SemVer.org for more details.
License
Under the MIT license.
See LICENSE file for
more details.