feat: use parseJsDoc to parse propType docblock

This commit is contained in:
gengyang 2020-10-15 21:43:38 +08:00
parent 2c7dbe37f1
commit 0b80be68ae
7 changed files with 101 additions and 28 deletions

View File

@ -31,6 +31,7 @@ export default async (args: IParseArgs) => {
try {
return parseJS(moduleFileAbsolutePath);
} catch (e) {
log(e);
await install(args);
const info = parseDynamic(mainFileAbsolutePath);
if (!info || !info.length) {

View File

@ -3,6 +3,7 @@ import defaultPropsHandler from './defaultPropsHandler';
import flowTypeHandler from './flowTypeHandler';
import componentMethodsHandler from './componentMethodsHandler';
import preProcessHandler from './preProcessHandler';
import propTypeJsDocHandler from './propTypeJsDocHandler';
const { handlers } = require('react-docgen');
@ -13,6 +14,7 @@ const defaultHandlers = [
childContextTypeHandler,
handlers.propTypeCompositionHandler,
handlers.propDocBlockHandler,
propTypeJsDocHandler,
flowTypeHandler,
defaultPropsHandler,
handlers.componentDocblockHandler,

View File

@ -0,0 +1,36 @@
/* eslint-disable no-param-reassign */
const parseJsDoc = require('react-docgen/dist/utils/parseJsDoc').default;
const { getMemberValuePath, resolveToValue } = require('react-docgen').utils;
function resolveDocumentation(documentation) {
documentation._props.forEach(propDescriptor => {
const { description } = propDescriptor;
if (description.includes('@')) {
const jsDoc = parseJsDoc(description);
propDescriptor.description = jsDoc.description;
if (jsDoc.params) {
propDescriptor.params = jsDoc.params;
}
if (jsDoc.returns) {
propDescriptor.returns = jsDoc.returns;
}
}
});
}
/**
* Extract info from the propType jsdoc blocks. Must be run after
* propDocBlockHandler.
*/
export default function propTypeJsDocHandler(documentation, path) {
let propTypesPath = getMemberValuePath(path, 'propTypes');
if (!propTypesPath) {
return;
}
propTypesPath = resolveToValue(propTypesPath);
if (!propTypesPath) {
return;
}
resolveDocumentation(documentation);
}

View File

@ -6,7 +6,17 @@ const log = debug.extend('parse:transform');
export function transformType(itemType: any) {
if (typeof itemType === 'string') return itemType;
const { name, elements, value = elements, computed, required, type, raw } = itemType;
const {
name,
elements,
value = elements,
computed,
required,
type,
raw,
params,
returns,
} = itemType;
if (computed !== undefined && value) {
return safeEval(value);
}
@ -29,11 +39,19 @@ export function transformType(itemType: any) {
case 'node':
break;
case 'func':
if (value) {
result.value = value.map(x => ({
if (params) {
result.params = params.map(x => ({
...x,
propType: transformType(x.propType),
}));
}
if (returns) {
result.returns = returns.map(x => ({
...x,
propType: transformType(x.propType),
}));
}
if (raw) {
result.raw = raw;
}
break;

View File

@ -321,7 +321,7 @@ function getDocgenTypeHelper(
} else if (type?.symbol?.valueDeclaration?.parameters?.length) {
return makeResult({
name: 'func',
value: getFunctionParams(
params: getFunctionParams(
// @ts-ignore
type?.symbol?.valueDeclaration?.parameters,
checker,
@ -335,7 +335,7 @@ function getDocgenTypeHelper(
) {
return makeResult({
name: 'func',
value: getFunctionParams(
params: getFunctionParams(
// @ts-ignore
type?.members?.get('__call')?.declarations[0]?.symbol?.declarations[0]?.parameters,
checker,

View File

@ -1,40 +1,47 @@
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/inherits";
import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
import _createClass from '@babel/runtime/helpers/createClass';
import _possibleConstructorReturn from '@babel/runtime/helpers/possibleConstructorReturn';
import _getPrototypeOf from '@babel/runtime/helpers/getPrototypeOf';
import _inherits from '@babel/runtime/helpers/inherits';
/* eslint-disable react/no-unused-prop-types */
/* eslint-disable react/require-default-props */
import React from 'react';
import PropTypes from 'prop-types';
import "./main.css";
import './main.css';
const Demo =
/* #__PURE__ */
function (_React$Component) {
_inherits(Demo, _React$Component);
/* #__PURE__ */
(function(_React$Component) {
_inherits(Demo, _React$Component);
function Demo() {
_classCallCheck(this, Demo);
function Demo() {
_classCallCheck(this, Demo);
return _possibleConstructorReturn(this, _getPrototypeOf(Demo).apply(this, arguments));
}
return _possibleConstructorReturn(this, _getPrototypeOf(Demo).apply(this, arguments));
}
_createClass(Demo, [{
key: "render",
value: function render() {
return React.createElement("div", null, " Test ");
},
}]);
_createClass(Demo, [
{
key: 'render',
value: function render() {
return React.createElement('div', null, ' Test ');
},
},
]);
return Demo;
}(React.Component);
return Demo;
})(React.Component);
Demo.propTypes = {
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
/**
* desc
* @param {{ok:String}} userName
* @returns {any}
*/
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
@ -54,7 +61,11 @@ Demo.propTypes = {
// it as an enum.
optionalEnum: PropTypes.oneOf(['News', 'Photos']),
// An object that could be one of many types
optionalUnion: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.instanceOf(Demo)]),
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Demo),
]),
// An array of a certain type
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
// An object with property values of a certain type
@ -82,4 +93,4 @@ Demo.propTypes = {
Demo.defaultProps = {
optionalNumber: 123,
};
export default Demo;
export default Demo;

View File

@ -14,6 +14,11 @@ class Demo extends React.Component {
Demo.propTypes = {
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
/**
* desc
* @param {{ok:String}} userName
* @returns {any}
*/
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,