#!/usr/bin/env node import * as fs from 'fs-extra'; import * as child_process from 'child_process'; import * as glob from 'glob'; import * as path from 'path'; import * as yaml from 'js-yaml'; import * as program from 'commander'; import { Config } from './interfaces/Config'; let src: string; let repoRelativePath: string; let dest = 'docs-ref-autogen'; let packageWhiteList: string[] = []; let packageBlackList: string[] = []; let packageOnlyRootList: string[] = []; let config: Config; let pjson = require('../package.json'); let envPath = `${process.env['APPDATA']}/npm/node_modules/ts-reference-ci-scripts`; program .version(`v${pjson.version}`) .description('A tool to go through source code and convert it to yaml data model for docfx.') .option('--config [value]', 'The config file which will defined more specefied behaviour for the tool') .option('--destPath [value]', 'Path to output the autogen files.') .arguments(' [repoConfigPath]') .action(function (sourceFolder: string, repoConfig: string) { src = sourceFolder; repoRelativePath = repoConfig; }) .parse(process.argv); if (!src) { console.log('Error: The source file folder is not specified!'); program.help(); } if (program.config) { try { config = JSON.parse(program.config); } catch (e) { console.log(`Invalid json format of config, ignored! content: ${program.config}`); } } if (config) { if (config.package_white_list) { packageWhiteList = config.package_white_list; } if (config.package_black_list) { packageBlackList = config.package_black_list; } if (config.npm_package_sources && config.npm_package_sources.length) { config.npm_package_sources.forEach(npmPackageSource => { let npmPackageSourceName = npmPackageSource.name.trim(); if (!npmPackageSource.registry) { child_process.execSync(`npm install ${npmPackageSourceName} 2>&1`); } else { child_process.execSync(`npm install ${npmPackageSourceName} --registry ${npmPackageSource.registry} 2>&1`); } fs.copySync(`node_modules/${npmPackageSourceName}`, `${src}/${npmPackageSourceName}`); }); } if (config.package_only_root) { packageOnlyRootList = config.package_only_root; } } if (program.destPath) { if (config.target_repo.folder) { dest = `${program.destPath}/${config.target_repo.folder}/${dest}`; } else { dest = `${program.destPath}/${dest}`; } } // 1. prepare fs.removeSync(dest); fs.mkdirpSync(dest); let packagePaths = glob.sync(path.join(src, '**/package.json')); let toc: any[] = []; let tocDict: {[key: string]: any} = {}; let jsdocConfig = require('../config/node2docfx.json'); packagePaths.forEach((packagePath: string) => { if (packagePath.indexOf('node_modules/') >= 0) { return; } let dir = path.dirname(packagePath); if (!fs.existsSync(packagePath)) { return; } let packageName = fs.readJsonSync(packagePath).name; if (packageWhiteList.length === 0 || packageWhiteList.indexOf(packageName) >= 0) { if (packageBlackList.indexOf(packageName) >= 0) { return; } generatePackageDoc(packagePath, packageName, dest, jsdocConfig, config); } }); toc = JSON.parse(JSON.stringify(toc)); fs.writeFileSync(`${dest}/toc.yml`, yaml.safeDump(toc)); process.exit(0); function generatePackageDoc(packagePath: string, packageName: string, dest: string, jsdocConfig: any, config: Config): void { console.log(`${packageName} : ${packagePath}`); let dir = path.dirname(packagePath); let folder = dir.split('/')[1]; let sourcePath = dir; if (fs.existsSync(`${dir}/lib`)) { sourcePath = `${dir}/lib`; } jsdocConfig.source.include = sourcePath; if (config.source_repos && config.source_repos.length) { let folderIndex = parseInt(folder, 10); jsdocConfig.repo = [config.source_repos[folderIndex]]; } jsdocConfig.package = packagePath; jsdocConfig.readme = path.join(dir, 'README.md'); jsdocConfig.destination = path.join(dest, packageName); if (packageOnlyRootList.indexOf(packageName) >= 0) { jsdocConfig.recurseDepth = 1; } else { jsdocConfig.recurseDepth = 10; } fs.writeJsonSync('_node2docfx_temp.json', jsdocConfig); try { child_process.execSync('node2docfx ' + '_node2docfx_temp.json 2>&1'); let outputs = fs.readdirSync(jsdocConfig.destination); if (outputs.length === 1) { console.log('No YAML files genereated for ' + packageName); fs.removeSync(jsdocConfig.destination); } else { glob.sync(path.join(jsdocConfig.destination, '**/*..yml')).forEach(unwantedFile => { console.log(`DELETE ${unwantedFile}`); fs.unlinkSync(unwantedFile); }); if (fs.existsSync(`${jsdocConfig.destination}/toc.yml`)) { let subToc = yaml.safeLoad(fs.readFileSync(`${jsdocConfig.destination}/toc.yml`).toString()); if (tocDict[packageName]) { tocDict[packageName].item = tocDict[packageName].item.concat(subToc); } else { let tocContent = { name: packageName, uid: packageName, items: subToc }; tocDict[packageName] = tocContent; toc.push(tocContent); } fs.removeSync(`${jsdocConfig.destination}/toc.yml`); } console.log('Finish generating YAML files for ' + packageName); } } catch (e) { console.log(`Error happen in generating document. Error: ${e}`); } }