Added support to autogen react method markdown

This commit is contained in:
Nick
2017-10-23 16:41:50 -07:00
parent 61e9d6f954
commit cd7c8dbff7
3 changed files with 136 additions and 11 deletions
+4 -2
View File
@@ -24,7 +24,7 @@
},
"scripts": {
"fetch:ios:sdk": "node ./scripts/download-mapbox-gl-native-ios-if-on-mac.js 3.6.1",
"docs:parse": "react-docgen ./javascript/components --pretty -o ./docs/docs.json",
"docs:parse": "node ./scripts/generateDocJSON.js",
"docs:build:md": "node ./scripts/buildMarkdown.js",
"docs:generate": "npm run docs:parse && npm run docs:build:md",
"preinstall": "npm run fetch:ios:sdk",
@@ -37,7 +37,9 @@
"eslint": "^3.19.0",
"eslint-config-strict-react": "^8.0.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-react": "^5.2.2"
"eslint-plugin-react": "^5.2.2",
"node-dir": "^0.1.17",
"react-docgen": "^2.18.0"
},
"dependencies": {
"@turf/helpers": "^4.6.0"
+68 -9
View File
@@ -11,9 +11,46 @@ class MarkdownBuilder {
return Object.keys(this.json);
}
getComponentName (componenPath) {
// Example: javascript/components/MapView.js
return `${componenPath.split('/').pop()}`.replace('.js', '');
getComponentName (fileName) {
return `${fileName}`.replace('.js', '');
}
getMethodSignature (method) {
const params = method.params.map((param, i) => {
const isOptional = param.optional;
let name = '';
if (i !== 0) {
name += ', ';
}
name += param.name;
return isOptional ? `[${name}]` : name;
}).join('');
return `${method.name}(${params})`;
}
getMethodExamples (method) {
return method.examples.map((example) => {
return `
\`\`\`javascript
${example.trim()}
\`\`\`
`;
}).join('');
}
getMethodArguments (method) {
return `
| Name | Type | Required | Description |
| ---- | :--: | :------: | :----------: |
${method.params.map((param) => {
return `| \`${param.name}\` | \`${param.type.name}\` | \`${param.optional ? 'No' : 'Yes'}\` | ${param.description} |`;
}).join('\n')}`;
}
generateComponentHeaderMarkdown (componentJSON, componentName) {
@@ -37,23 +74,45 @@ class MarkdownBuilder {
return `
#### props
### props
| Prop | Type | Default | Required | Description |
| ---- | :--: | :-----: | :------: | ----------: |
| ---- | :--: | :-----: | :------: | :----------: |
${props.map((prop) => {
return `| ${prop.name} | \`${prop.type}\` | \`${prop.default}\` | \`${prop.required}\` | ${prop.description} |`
}).join('\n')}
`
`;
}
generateComponentFile (componentPath) {
generateComponentMethodsMarkdown (componentJSON) {
const methods = componentJSON.methods;
if (!Array.isArray(methods) || !methods.length) {
return '';
}
return `
### methods
${methods.map((method) => {
return `
#### ${this.getMethodSignature(method)}
##### arguments
${this.getMethodArguments(method)}
${this.getMethodExamples(method)}`
}).join('\n')}`;
}
generateComponentFile (componentName) {
let fileContents = '';
const componentJSON = this.json[componentPath];
const componentName = this.getComponentName(componentPath);
const componentJSON = this.json[componentName];
fileContents += this.generateComponentHeaderMarkdown(componentJSON, componentName);
fileContents += this.generateComponentPropsMarkdown(componentJSON);
fileContents += this.generateComponentMethodsMarkdown(componentJSON);
fs.writeFileSync(path.join(__dirname, '..', 'docs', `${componentName}.md`), fileContents);
}
+64
View File
@@ -0,0 +1,64 @@
const docgen = require('react-docgen');
const dir = require('node-dir');
const fs = require('fs');
const path = require('path');
const INPUT_PATH = path.join(__dirname, '..', 'javascript', 'components');
const OUTPUT_PATH = path.join(__dirname, '..', 'docs', 'docs.json');
class DocJSONBuilder {
constructor (filePath) {
this._filePath = filePath;
}
get options () {
return {
match: /.js$/,
shortName: true,
};
}
isPrivateMethod (methodName = '') {
return !methodName || methodName.charAt(0) === '_';
}
postprocess (component) {
// Remove all private methods and parse examples from docblock
if (!Array.isArray(component.methods)) {
return;
}
const privateMethods = [];
for (let method of component.methods) {
if (this.isPrivateMethod(method.name)) {
privateMethods.push(method.name);
continue;
}
const examples = method.docblock.split('@').filter((block) => block.startsWith('example'));
method.examples = examples.map((example) => example.substring('example'.length));
}
component.methods = component.methods.filter((method) => !privateMethods.includes(method.name));
}
generate () {
let results = {};
dir.readFiles(this._filePath, this.options, (err, content, fileName, next) => {
if (err) {
throw err;
}
fileName = fileName.replace('.js', '');
results[fileName] = docgen.parse(content);
this.postprocess(results[fileName]);
next();
}, () => fs.writeFileSync(OUTPUT_PATH, JSON.stringify(results, null, 2)));
}
}
const docJSONBuilder = new DocJSONBuilder(INPUT_PATH);
docJSONBuilder.generate();