Yesterday vuese1.0, my new open source project for parsing Vue SFC and generating Markdown documentation, was released: github.com/HcySunYang/… .

This article won’t show you how to use it, but you can check out readme to see how to use it.

A, motivation

You or your team may have a component library of your own (or just a component), and often after you develop a component, you need to manually write markdown documentation to let others know how the component is used. The problem here is that if the component is constantly updated, you have to manually maintain the corresponding documentation to keep it consistent with the functionality of the component. Actually this process is somewhat disgusting 🤢, so what better way? I developed Vuese based on this.

Second, the idea

We know that the interfaces exposed by a VUE component are props, Events, slots(or scopedSlots), and some methods. Can we implement a tool to analyze a VUE component and extract this information? The document is then generated automatically, so that no matter how the component changes, we don’t need to maintain the document manually, just use the tool to regenerate it.

Third, basic ideas

For a VUE component, if we discard style and custom blocks, it consists of two parts: template and script blocks. Even if you use the render function instead of the template, you only have one script left.

For props, methods, they can only be defined in the SCirpt block, as in:

props: {
  name: String
}
methods: {
  clear () {/ *... * /}}Copy the code

For slots, we can define both a script block and a template, for example:

<! -- Define in template -->
<div>
  <slot name="header" />
</div>
Copy the code
// Defines slots within the script block
render (h) {
  return h('div'.this.$slots.header)
}
Copy the code

The two notations are equivalent, so we need to consider both the slots in the template and the slots in the script block when extracting the slots information.

And in a functional component, the following should be treated as slots:

// ctx.slots()
render (h, ctx) {
  return h('div', ctx.slots().xxx)
}

// ctx.children
render (h, ctx) {
  return h('div', ctx.children)
}
Copy the code

This is also what we need to take into account when extracting the slots information.

Similarly, events can appear in both templates and script blocks as follows:

<! -- Events in template -->
<div @click="$emit('onclear')"></div>
Copy the code
// Events defined in script
methods: {
  someMethod () {
    this.$meit('onclear')}}Copy the code

Therefore, both template and script blocks need to be considered when extracting events information.

We default to HTML syntax for templates and JS for script blocks. The first thing we need to do is separate out HTML and JS and analyze them separately. Fortunately, the giants have big shoulders and already have @vue/component-compiler-utils and vue-template-Compiler modules. We use @vue/component-compiler-utils module to parse VUE SFC and get HTML (template) and JavaScript(script block) source code respectively. For THE HTML source, we can use the VUE – template-Compiler module to parse it into the AST of the template again, and then write a traverse function to analyze it and read the slots content.

For JavaScript source code processing, I chose to use Babel7, those of you who have written the Babel plug-in may have guessed the idea of implementation. We hand over the source code to the @babel/travers module, and then write some helper functions to help us determine what we really need to work on, as shown in the source code snippet below:

const mainTraveres = {
  ObjectProperty(path: any) {
    // Processing name
    if (isVueOption(path, 'name')) {
      if (onName) onName(path.node.value.value)
    }
    // Processing props
    if (isVueOption(path, 'props')) {
      // Some logic
    }
    // more...}}Copy the code

IsVueOption function isVueOption function is our own written helper function, to assist us to determine whether the property of an object is a specific property in the Vue option object, if it is, we can further process it, for js processing is basically this idea, more content you can view the source code: Github.com/HcySunYang/…

Generate goals

After the previous step, we can write a Parser module that parses and assembles the desired content. Once we have the desired content, we can write a Render module based on that information, which is essentially a code generation process, depending on what you want to do. Vuese’s built-in Render will generate markdown files for you based on this information, or an integrated Docute document. But you can actually generate anything if you can imagine, imagine if our Parser module was better written, if we analyzed a Vue component carefully enough, so that we could get all the information about a VUE component, Then generate a TS Compatible component during the code generation phase. Doesn’t that implement a plug-in that converts non-JS-written VUE components into TS compatible VUE components? (Note: later, a buddy came up with a better way to do this. To avoid embarrassment, I can only say that this is also an idea……)

Return to vuese built-in Render module, Render result is markdown resources, essentially is a string splicing process, you can view the source github.com/HcySunYang/… It’s not complicated.

In fact, Vuese provides a lot of useful information and features not covered in the documentation, which will be added later. For example, the markdown file generated using Vuese looks something like this:

You may have noticed that the markdown file above contains a lot of things like:

<! -- @vuese:CompName:props:start -->

<! -- @vuese:CompName:props:end -->
Copy the code

This tells Vuese where to place the generated Markdown code when generating the document. If a component does not already have a corresponding Markdown document, it should be generated, otherwise it will be updated based on the existing document. The purpose of doing this is to actually use the scenario, because a component’s documentation can’t just contain what is shown above, it can also contain a demo written by the developer, along with other descriptions. Instead of overwriting the developer’s own content when we generate the document, we insert the generated content into the specified location.

Five, planning,

Vuese has implemented the following features:

In addition, the plugin system is not supported at present, which is also planned in the future. We also plan to focus on vue3.0 and make it compatible with the documentation maintenance of component libraries that have been applied internally within our team. Finally, Vuese has a lot of shortcomings just released, but it will get better and better with the subsequent iterations, and we welcome those who are interested to build it.

Other plans: Template support for PUG, plugin system, and what else ??????