UNPKG

@pshaw/writeme

Version:
321 lines (265 loc) 9.07 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.genReadmeFromPackageDir = genReadmeFromPackageDir; exports.writeReadmeFromPackageDir = writeReadmeFromPackageDir; exports.default = void 0; var _fsExtra = require("fs-extra"); var _globby = _interopRequireDefault(require("globby")); var _hookSchema = require("hook-schema"); var _fs = require("mz/fs"); var _path = require("path"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function section(title, content) { let md = ''; if (content) { md += `## ${title}\n`; md += '\n'; md += content; md += '\n'; } return md; } const suffixedVersionRegex = /\d+\.\d+\.\d+-/; /** * Removes @ scopes, replaces "-"" with a space and capitalises each word */ function packageNameToTitle(packageName) { return packageName.replace(/^@[^/]+\//, '').replace(/-+/g, ' ').replace(/\b\w/g, l => l.toUpperCase()); } function getTitle(options) { return options.title ? options.title : packageNameToTitle(options.name); } function packageInstallation(command, flag, packageNames) { let md = ''; md += '```bash\n'; md += `${command}${flag} ${packageNames.join(' ')}\n`; md += '```\n'; return md; } function installationInstructions(isDevPackage, allDependenciesToInstall) { const yarnSaveFlag = isDevPackage ? ' --dev' : ''; const npmSaveFlag = isDevPackage ? ' --save-dev' : ' --save'; let md = ''; md += packageInstallation('npm install', npmSaveFlag, allDependenciesToInstall); md += 'or\n'; md += packageInstallation('yarn add', yarnSaveFlag, allDependenciesToInstall); md += '\n'; return md; } function packagesToProjectMd(packages, rootDir) { let md = 'Version | Package | Description\n'; md += '--- | --- | ---\n'; for (const packageOptions of packages) { const relativePackageLink = (0, _path.join)((0, _path.relative)((0, _path.resolve)(rootDir), (0, _path.resolve)(packageOptions.dir)), 'README.md').replace(/\\/g, '/'); md += `${packageOptions.version} | [\`${packageOptions.name}\`](${relativePackageLink}) | ${packageOptions.description ? packageOptions.description : ''}\n`; } return `${md}\n`; } function projectOptionsToMd(projects, rootDir) { let md = ''; for (const project of projects) { const filteredPackages = project.packages.filter(packageOptions => !packageOptions.private).sort((a, b) => a.name < b.name ? -1 : a.name == b.name ? 0 : 1); if (filteredPackages.length <= 0) { continue; } if (project.category) { md += `### ${project.category}\n`; } md += packagesToProjectMd(filteredPackages, rootDir); } return section('Packages', md); } function genReadme({ name, dir, version, isDevPackage, description, projects, sections = {}, peerDependencies = {}, ...other }) { const title = getTitle({ name, ...other }); const { examples, howTo, development = '' } = sections; if (!name) { throw new Error(`Name was ${name}`); } let md = ''; md += `# ${title}\n`; md += '\n'; if (description) { md += `${description}\n`; md += '\n'; } if (other.private !== true) { if (!version) { throw new Error(`${name} does not have a version`); } md += '## Installation\n'; md += '\n'; const installPackageName = version.match(suffixedVersionRegex) ? `${name}@${version}` : name; const peerDependenciesToInstall = Object.keys(peerDependencies); const allDependenciesToInstall = [installPackageName].concat(...Array.from(peerDependenciesToInstall)); md += installationInstructions(isDevPackage, allDependenciesToInstall); } if (projects) { md += projectOptionsToMd(projects, dir); } md += section('How to use it', howTo); md += section('Examples', examples); md += section('Development', development); md += '---\n'; md += 'This documentation was generated using [writeme](https://www.npmjs.com/package/@pshaw/writeme)\n'; return md; } async function readPackageJson(packageDir) { const packageJsonText = await (0, _fs.readFile)((0, _path.join)(packageDir, 'package.json'), { encoding: 'utf-8' }); return JSON.parse(packageJsonText); } const genReadmeFromPackageDirSchema = { readConfig: null, readPackageJson: null, genReadme: null }; const errorSchema = { error: null }; const genReadmeFromPackageDirHookUtil = (0, _hookSchema.fromSchema)(genReadmeFromPackageDirSchema, errorSchema); function getProjects(writemeOptions) { if (writemeOptions.projects === null) { return null; } else if (!writemeOptions.projects) { if (!writemeOptions.workspaces) { return null; } return { test: writemeOptions.workspaces }; } else if (!writemeOptions.projects.test) { if (!writemeOptions.workspaces) { throw new Error("Projects object does not have 'test' field, nor does package.json have 'workspaces'"); } return { ...writemeOptions.projects, test: writemeOptions.workspaces }; } return writemeOptions.projects; } function testToGlobs(test) { if (typeof test === 'string') { return [test]; } else { return test; } } async function testToPaths(packageDir, test) { if (!test) { throw new Error("'test' was undefined"); } const joinedGlobs = testToGlobs(test).map(glob => (0, _path.join)(packageDir, glob)); return await (0, _globby.default)(joinedGlobs, { onlyFiles: false }); } async function genReadmeFromPackageDir(packageDir, hooks) { const h = genReadmeFromPackageDirHookUtil.withHooks(hooks); const context = { packageDir }; async function readConfig() { context.configRequirePath = (0, _path.join)(context.packageDir, 'writeme.config'); context.configPath = `${context.configRequirePath}.js`; async function getConfigModule() { if (await (0, _fsExtra.pathExists)(context.configPath)) { return require(context.configPath); } else { return null; } } const configModule = await getConfigModule(); const configModuleType = typeof configModule; if (configModuleType === 'function') { return await Promise.resolve(configModule()); } else { return configModule; } } try { await h.before.readPackageJson(context); context.packageJson = await readPackageJson(context.packageDir); await h.after.readPackageJson(context); await h.before.readConfig(context); context.config = await readConfig(); await h.after.readConfig(context); context.writemeOptions = { ...context.packageJson, ...context.config, dir: packageDir }; const projectsConfig = getProjects(context.writemeOptions); if (projectsConfig) { const overrideProjects = projectsConfig.overrides ? await Promise.all(projectsConfig.overrides.map(async project => ({ ...project, testPaths: await testToPaths(packageDir, project.test) }))) : []; const defaultPaths = await testToPaths(packageDir, projectsConfig.test); const allProjects = [{ ...projectsConfig, testPaths: defaultPaths.filter(path => !overrideProjects.some(project => project.testPaths.includes(path))) }].concat(overrideProjects); const expandedProjectsConfig = await Promise.all(allProjects.map(async project => { const packages = await Promise.all(project.testPaths.map(async path => { let writemeOptions; const nestedHooks = genReadmeFromPackageDirHookUtil.mergeHookOptions([{ after: { async genReadme(innerContext) { writemeOptions = innerContext.writemeOptions; } } }, h]); await genReadmeFromPackageDir(path, nestedHooks); return writemeOptions; })); return { ...project, packages }; })); // TODO: Going a little overboard with the mutability here... context.writemeOptions.projects = expandedProjectsConfig; } await h.before.genReadme(context); context.readmeText = genReadme(context.writemeOptions); await h.after.genReadme(context); } catch (err) { await h.on.error(err); } } const writeReadmeFromPackageDirHookSchema = { ...genReadmeFromPackageDirSchema, writeReadme: null }; const writeReadmeFromPackageDirUtil = (0, _hookSchema.fromSchema)(writeReadmeFromPackageDirHookSchema, errorSchema); async function writeReadmeFromPackageDir(packageDir, hooks) { const h = writeReadmeFromPackageDirUtil.withHooks(hooks); await genReadmeFromPackageDir(packageDir, writeReadmeFromPackageDirUtil.mergeHookOptions([{ after: { async genReadme(context) { await h.before.writeReadme(context); await (0, _fs.writeFile)((0, _path.join)(context.packageDir, 'README.md'), context.readmeText, { encoding: 'utf-8' }); await h.after.writeReadme(context); } } }, h])); } var _default = writeReadmeFromPackageDir; exports.default = _default; //# sourceMappingURL=index.js.map