The text/no

preface

Business is evolving rapidly and business component libraries are iterating rapidly. When component Props change, development takes an extra effort to keep the code and documentation consistent. The following table is an API document for a Select component (the fields are taken from fusion’s Select component).

| parameters | | | | | alternatives, a default value type | -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - | -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - | -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - | -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - | -- - | | dataSource _ (required) _ | incoming data sources, To dynamically render items | ` string [] ` | | | | onChange | Select changes triggered the callback | ` (item: String) = > void ` | | | | readOnly | is read-only, Read-only mode can expand layer but cannot choose | ` Boolean ` | false, true | false | | size size | | selector ` "medium" | | "small" "large" ` | "medium", "Small", "large" | medium | | value | current value, is used to control mode | ` string | number ` | string, number | |Copy the code

Earlier this year, the group began embracing TypeScript with its static type checking and code hints to make development more productive. PropTypes have also been abandoned during component development, choosing instead to define the corresponding Props Interface (also the TS type of component Props), such as the Select component definition mentioned above.

import * as React from 'react'; Export interface ISelectProps {/** */ dataSource: string[]; /** * Select callback triggered when change occurs */ onChange? : (item: string) => void; /** * readOnly. In readOnly mode, shells can be expanded but not readOnly. : boolean; /** * select size */ size? : 'small' | 'medium' | 'large'; /** * current value for controlled mode */ value? : string | number; } /** * class Select extends react.props > {static defaultProps = {readOnly: false, size: 'medium', }; render() { return <div>Test</div>; } } export default Select;Copy the code

As you can see, the component API documentation is really a mapping of the component Props (usually Markdown), and when we have such a Props Interface, there should be some way to generate the API documentation automatically. React-docgen-typescript iS a library for parsing the REACT TS component AST. This is used to develop VSCode and Remark plug-ins. Component documentation can be generated automatically in a project.

Research and analysis

Let’s go back to where the props information can come from in the code in the API documentation.

As can be seen from the above table, the props data can come from multiple sources, and both propTypes and props Interface have complete description capabilities for props. (On the other hand, TS is not only used for React components. Has an advantage over propTypes in type reuse). The React component and the Props interface are also part of the TS code, which should be able to get the corresponding information with the help of the TS parser, which can then be converted into the required data through processing. Initial association should have the following steps:

  1. Parse source gets the TypeScript AST
  2. Check whether the exported Class/Function is the React component based on the AST
  3. Extract the types of component props and comments for interfaces to generate another tree containing only component information
  4. The component information tree is then converted into Markdown code

Like the image below

In the process of tool research, we found existing similar solutions. Among the existing tools, there are some technical points worth learning, mainly including the following solutions:

api-extractor

  • Based on the React-DocGen library, the extension supports sub-components and enhances JSDoc support, such as supporting @default, @enumdesc and other annotations
  • Use remark to generate markDown

ts-props-gen

  • Based on react-DocGen, it extends the processing of multiple files and classifies the interface for exporting each file. However, it does not support importing TS type from other files

styleguidist

  • Dynamically generate component documentation based on React-Docgen-typescript and Webpack

Current solutions mainly use react-Docgen or React-Docgen-typescript. Through reading the key code of the two libraries and running the corresponding debugging demo, WE know that there are great differences between them.

React-docgen vs React-Docgen-typescript

react-docgen

  • From Facebook Open Source
  • Parsing source code based on Babel, good support for propTypes
  • Although new versions support TypeScript, type information imported from other files cannot be retrieved
  • Instead of parsing the JSDoc part, the entire comment is used as a description part, but you can add your own handler to complement the parsing

react-docgen-typescript

  • From Styleguidist, the main goal is to service the TS React component API documentation generation
  • PropTypes are not supported. Props Interface types are available
  • JSDoc @type and @default are read as type and default value information

The two libraries read and compare the field information

At first glance, React-DocGen is more comprehensive and also supports TS. Why not use React-DocGen? React-docgen parses the source code based on Babel, and only retrieves the content of parsed component files. It cannot analyze dependencies like TS. As a common scenario, when a type is inherited from another file, Babel theoretically cannot get information from the other file, resulting in missing props types for the final output.

Define ICustomSelectProps as follows. The component inherits the ISelectProps property because ISelectProps is in a separate file. The react-Docgen only gets the customProp field, The dataSource and onChange fields defined in ISelectProps are missing.

import * as React from "react"; import { ISelectProps } from './Select'; interface ICustomSelectProps extends ISelectProps { customProp: string; } export class CustomSelect extends React.Component<ICustomSelectProps> { render() { return <div>Test</div>; }}Copy the code

In summary, it is more appropriate to use React-Docgen-typescript for component output when we are fully using TypeScript.

Design and Implementation

With React-Docgen-typescript, the overall difficulty of typescript is much reduced. You can input component source code to get a tree of component information, and then the next problem is how to apply that tree and export component documentation.

whale-component-docgen

The first thing that comes to mind is to export documents directly from components. A common component directory structure is as follows, when the directory conforms to the following specification

Component // Component name, ├─ ├─ ├─ ├─ class.txt // [required] ├─ ├─ class.txt // [required].├ ─ class.txt // [required].├ ─ ├─ class.txt // [for] component and API └ ─ ─ package. The json / / 【 for 】 component package. The jsonCopy the code

You can combine component export files with package.json to quickly output readme.md files. At the same time, refer to the README specification of the material, so there is @alife/ whale-component-docGen after installation, run the whale-component-docgen command in the material directory, and you can get the following README file that meets the material specification standard

Business component description # # # test - select installation method ` ` ` sh $TNPM install test - select - save ` ` ` # # API selector # # # # # # # the select Props parameter | | | type Default value | optional value | | | -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - | -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - | -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - | -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - | -- - | | dataSource _ (required) _ | incoming data sources, To dynamically render items | ` string [] ` | | | | onChange | Select changes triggered the callback | ` (item: String) = > void ` | | | | readOnly | is read-only, Read-only mode can expand layer but cannot choose | ` Boolean ` | false, true | false | | size size | | selector ` "medium" | | "small" "large" ` | "medium", "Small", "large" | medium | | value | current value, is used to control mode | ` string | number ` | string, number | |Copy the code

If the generation fails, note that the document generation has the following two prerequisites

Install @types/react. Import * as react from ‘react’;

Remark-react-docgen-typescript remark-react-docgen-typescript

The advantage of fully generated documentation is simplicity, but some complex materials may contain other content in their README, and a full generation of all at once will not work.

Remark is now the most popular Markdown processor, and remark-React-Docgen-typescript is a plug-in for Remark.

[cytle/remark-react-docgen-typescript​

github.com] (Link.zhihu.com/?target=htt…)

Just as Markdown can import images, with this plug-in you can import component documents using the following syntax

[Select](./src/Select.tsx "react-docgen-typescript:")
Copy the code

The above whale-component-docgen also integrates remark-react-docgen-typescript, which converts documents by specifying Markdown files

whale-component-docgen README.md
Copy the code

Remark also has corresponding cli and vscode tools

  • remark-cli
  • vscode-remark

VSCode plug-in

Compared to VScode-remark, which formats the code on the original Markdown document, it is not flexible enough. In fact, it can generate/insert component document fragments more directly and clearly.

[React Docgen TypeScript – Visual Studio Marketplace​

marketplace.visualstudio.com] (Link.zhihu.com/?target=htt…)

React Docgen TypeScript is one such plug-in that provides two ways to get component documentation

  1. TSX files generate documents to the clipboard
  2. The MD file selection file inserts the component document

TSX files generate documents to the clipboard

The MD file selection file inserts the component document

conclusion

TypeScript brings types to JS, does static type checking and code hints, and uses them all over again after a lot of work. During the whole process, I have got all the data I want from the components. Besides generating material documents, I can make other tools around these data, such as

  • Multi-component whole site document generation, to solve the current unresolved sub-type display problem
  • LowCode component configuration items are generated for platform building