Skip to content

feat(*): add params information to func proptypes where possible #79

Merged
merged 8 commits into from
Jun 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ before_script:

script:
- npm run lint
- npm test

after_script:
- greenkeeper-lockfile-upload
Expand Down
3 changes: 2 additions & 1 deletion gulp-tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ function createTasks(packageName, options = {}) {
}))
.pipe(filter(file => !fs.existsSync(
// ignore all files, that already emit d.ts file
path.join(options.publishDir, file.relative).replace(/\.ts$/, '.d.ts')
path.join(process.cwd(), options.publishDir, file.relative)
.replace(/\.tsx?$/, '.d.ts')
)))
.pipe(ts(tsOptions, ts.reporter.nullReporter())) // ignore all errors at compile time
.dts.pipe(gulp.dest(options.publishDir));
Expand Down
2 changes: 2 additions & 0 deletions gulp/component-docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ function componentDocs(libraryName) {
contents: Buffer.from(doc)
}));
} catch (e) {
// eslint-disable-next-line no-console
console.warn(`unable to build docs for ${file.path}`);
// eslint-disable-next-line no-console
console.warn(e);
callback(null);
}
Expand Down
3 changes: 2 additions & 1 deletion gulp/component-typings.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const getReactComponentDefinitionsContent = require('../typings/index');
/**
* Gulp plugin to generate react typings and root package.json for each component.
*
* @param {String} libraryName Library name, will be used in typescript declarations.
* @returns {Function}
*/
function componentTypings() {
Expand All @@ -18,6 +17,7 @@ function componentTypings() {
const componentName = path.parse(file.path).name;
getReactComponentDefinitionsContent(file.path).then((definitionsContent) => {
if (!definitionsContent) {
// eslint-disable-next-line no-console
console.warn(`Unable to create typings for ${file.path}`);
return callback(null);
}
Expand All @@ -28,6 +28,7 @@ function componentTypings() {
contents: Buffer.from(definitionsContent)
}));
}).catch((e) => {
// eslint-disable-next-line no-console
console.error(e);
});
}
Expand Down
1 change: 1 addition & 0 deletions gulp/library-doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ function libraryDoc(libraryName) {
try {
components.push(structureForFile(content, componentName));
} catch (e) {
// eslint-disable-next-line no-console
console.warn(`unable to build docs for ${file.path}`);
}

Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,16 @@
"arui-presets": "4.11.9",
"conventional-changelog-cli": "1.3.14",
"conventional-github-releaser": "2.0.0",
"husky": "0.14.3"
"husky": "0.14.3",
"jest": "^23.1.0"
},
"scripts": {
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"github-release": "conventional-github-releaser -p angular",
"lint": "eslint ./*.js ./gulp/*.js ./typings/*.js",
"test": "jest",
"postversion": "git push origin master && git push --tags && npm publish",
"precommit": "npm run lint",
"precommit": "npm run lint && npm run test",
"release-patch": "npm version patch -m 'chore(*): patch version'",
"release-minor": "npm version minor -m 'chore(*): minor version'",
"release-major": "npm version major -m 'chore(*): major version'",
Expand Down
36 changes: 36 additions & 0 deletions react-doc/component-prop-types-js-doc-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const getMemberValuePath = require('react-docgen/dist/utils/getMemberValuePath').default;
const resolveToValue = require('react-docgen/dist/utils/resolveToValue').default;
const getPropertyName = require('react-docgen/dist/utils/getPropertyName').default;
const parseJsDoc = require('react-docgen/dist/utils/parseJsDoc').default;
const recast = require('recast');

const { types: { namedTypes: types } } = recast;
// component-prop-types-js-doc-handler
function componentPropTypesJsDocHandler(documentation, path) {
let propTypesPath = getMemberValuePath(path, 'propTypes');

if (!propTypesPath) {
return;
}
propTypesPath = resolveToValue(propTypesPath);
if (!propTypesPath || !types.ObjectExpression.check(propTypesPath.node)) {
return;
}

propTypesPath.get('properties').each((propertyPath) => {
// we only support documentation of actual properties, not spread
if (types.Property.check(propertyPath.node)) {
const propName = getPropertyName(propertyPath);
const propDescriptor = documentation.getPropDescriptor(propName);
if (!propDescriptor.description || !propDescriptor.type) {
return;
}
const jsDoc = parseJsDoc(propDescriptor.description);
propDescriptor.description = jsDoc.description || propDescriptor.description;
propDescriptor.type.params = jsDoc.params || [];
propDescriptor.type.returns = jsDoc.returns;
}
});
}

module.exports = componentPropTypesJsDocHandler;
9 changes: 6 additions & 3 deletions react-doc/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
const path = require('path');
const reactDocGen = require('react-docgen');
const { createDisplayNameHandler } = require('react-docgen-displayname-handler');
const getSourceFileContent = require('./get-source-file-content');
const createResolver = require('./create-resolver');
const createDisplayNameHandler = require('react-docgen-displayname-handler').createDisplayNameHandler;
const componentPropTypesJsDocHandler = require('./component-prop-types-js-doc-handler');

const documentation = {};
const defaultHandlers = [
Expand All @@ -15,7 +16,8 @@ const defaultHandlers = [
reactDocGen.handlers.componentDocblockHandler,
reactDocGen.handlers.displayNameHandler,
reactDocGen.handlers.componentMethodsHandler,
reactDocGen.handlers.componentMethodsJsDocHandler
reactDocGen.handlers.componentMethodsJsDocHandler,
componentPropTypesJsDocHandler
];

function getReactComponentInfo(filePath, parentPath) {
Expand All @@ -24,7 +26,7 @@ function getReactComponentInfo(filePath, parentPath) {
}

const src = getSourceFileContent(filePath, parentPath);
const content = src.content;
const { content } = src;
filePath = src.filePath;
const info = reactDocGen.parse(
content,
Expand All @@ -45,4 +47,5 @@ function getReactComponentInfo(filePath, parentPath) {
return info;
}


module.exports = getReactComponentInfo;
122 changes: 122 additions & 0 deletions typings/__examples__/a.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/* eslint-disable */
import React from 'react';
import PropTypes from 'prop-types';

/**
* Component description.
*/
export default class A extends React.Component {
static propTypes = {
optionalArray: PropTypes.array,
requiredArray: PropTypes.array.isRequired,
/**
* Prop documentation
*/
optionalBool: PropTypes.bool,
requiredBool: PropTypes.bool.isRequired,
optionalFunc: PropTypes.func,
requiredFunc: PropTypes.func.isRequired,
optionalNumber: PropTypes.number,
requiredNumber: PropTypes.number.isRequired,
optionalObject: PropTypes.object,
requiredObject: PropTypes.object.isRequired,
optionalString: PropTypes.string,
requiredString: PropTypes.string.isRequired,
optionalSymbol: PropTypes.symbol,
requiredSymbol: PropTypes.symbol.isRequired,
optionalNode: PropTypes.node,
requiredNode: PropTypes.node.isRequired,
optionalElement: PropTypes.element,
requiredElement: PropTypes.element.isRequired,
optionalMessage: PropTypes.instanceOf(Message),
requiredMessage: PropTypes.instanceOf(Message).isRequired,
optionalEnum: PropTypes.oneOf(['News', 'Photos']),
requiredEnum: PropTypes.oneOf(['News', 'Photos']).isRequired,
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number
]),
requiredUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number
]).isRequired,
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
requiredArrayOf: PropTypes.arrayOf(PropTypes.number).isRequired,
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
requiredObjectOf: PropTypes.objectOf(PropTypes.number).isRequired,
optionalAny: PropTypes.any,
requiredAny: PropTypes.any.isRequired,
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
/**
* Sub prop documentation
*/
fontSize: PropTypes.number.isRequired,
/**
* @param {string} value
*/
onChange: PropTypes.func,
subShape: PropTypes.shape({
/**
* Even deeper documentation
*/
name: PropTypes.string,
size: PropTypes.number
})
}),
/**
* Callback with documentation
*
* @param {String} stringParam
* @param {number} count
* @param {React.MouseEvent} event
* @param {React.KeyboardEvent} anotherEvent
* @param {HTMLDivElement} element some html element
*
* @returns {string|number}
*/
onClick: PropTypes.func,
onChange: PropTypes.func
};

render() {
return null;
}

privateMethod(name) {
}

/**
* Some description.
*
* @public
*/
publicMethod1() {

}

/**
* Maybe we just forgot to add params?
*
* @public
*/
publicMethodWithouParams() {

}

/**
* Some description.
*
* @public
* @param {string} str1 Some description.
* @param {String} str2 Some description.
* @param {number} num1 Some description.
* @param {Number} num2 Some description.
* @param {Boolean} bool1 Some description.
* @param {bool} bool2 Some description.
* @param {boolean} bool3 Some description.
* @param {string|number} union Some description.
*/
publicWithParams(str1, str2, num1, num2, bool1, bool2, bool3, union) {
}
}
Loading