Skip to content

Instantly share code, notes, and snippets.

@markmur
Created March 26, 2018 14:53
Show Gist options
  • Save markmur/58663c02969bfc111ce292db1053fbce to your computer and use it in GitHub Desktop.
Save markmur/58663c02969bfc111ce292db1053fbce to your computer and use it in GitHub Desktop.
Generate a documentation JSON file for React Components
const docgen = require('react-docgen');
const fs = require('fs');
const glob = require('glob');
const chalk = require('chalk');
const chokidar = require('chokidar');
const _ = require('lodash/fp');
const fmap = require('lodash/map');
const { flow, mapValues } = _;
const args = [...process.argv].slice(2);
const DEFAULTS = {
watch: false,
verbose: false
};
const opts = {
...DEFAULTS,
verbose: args.includes('--verbose'),
watch: args.includes('--watch')
};
const verbose = (...messages) => {
if (opts.verbose) {
console.log(...messages);
}
};
const FILES = './src/components/*/!(*.spec).js';
const toArray = key => obj =>
fmap(obj, (obj, name) => ({
[key]: name,
...obj
}));
const formatDataForClient = components =>
flow(
mapValues(component => ({
...component,
props: toArray('name')(component.props).map(prop => ({
...prop,
defaultValue: prop.defaultValue || {
value: null,
computed: false
}
}))
}))
)(components);
const parseName = name => name.split(/(\w+)\.js$/)[1];
const generateComponents = () => {
const components = glob.sync(FILES);
const docs = {};
const notWrittenToDocs = [];
components.forEach(component => {
let parsed, displayName;
try {
parsed = docgen.parse(fs.readFileSync(component, 'utf8'));
} catch (parseError) {
notWrittenToDocs.push(component);
verbose(chalk.white(`[${component}]`), chalk.grey(`(${parseError})`));
return;
}
if (!parsed) {
verbose(chalk.red(`[${component}] Not parsed`), parsed);
return;
}
displayName = parsed.displayName || parseName(component);
docs[displayName] = parsed;
verbose(chalk.green(`✓ ${displayName}`));
});
fs.writeFileSync(
'docs.json',
JSON.stringify(formatDataForClient(docs), null, 2)
);
console.log(
chalk.green(
`✓ ${Object.keys(docs).length} of ${
components.length
} components written to ./docs.json`
)
);
console.log(chalk.grey('The following components were not documented:'));
notWrittenToDocs.forEach(x => {
console.log(x);
});
};
generateComponents();
if (opts.watch) {
chokidar.watch([FILES, './docs.js']).on('change', (event, path) => {
generateComponents();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment