type2docfx
Version:
A tool to convert json format output from TypeDoc to universal reference model for DocFx to consume.
152 lines (131 loc) • 5.76 kB
text/typescript
import * as fs from 'fs-extra';
import * as serializer from 'js-yaml';
import * as program from 'commander';
import { traverse } from './jsonTraverse';
import { groupOrphanFunctions, insertFunctionToIndex, postTransform } from './postTransformer';
import { generateToc } from './tocGenerator';
import { generatePackage } from './packageGenerator';
import { generateModules } from './moduleGenerator';
import { resolveIds } from './idResolver';
import { YamlModel, Syntax, YamlParameter, Root } from './interfaces/YamlModel';
import { TocItem } from './interfaces/TocItem';
import { UidMapping } from './interfaces/UidMapping';
import { RepoConfig } from './interfaces/RepoConfig';
import { yamlHeader } from './common/constants';
import { flags } from './common/flags';
import { ReferenceMapping } from './interfaces/ReferenceMapping';
let pjson = require('../package.json');
let path: string;
let outputPath: string;
let repoConfigPath: string;
program
.version(`v${pjson.version}`)
.description('A tool to convert the json format api file generated by TypeDoc to yaml format output files for docfx.')
.option('--hasModule', 'Add the option if the source repository contains module.')
.option('--disableAlphabetOrder', 'Add the option if you want to disable the alphabet order in output yaml.')
.option('--basePath [value]', 'Current base path to the repository.')
.option('--sourceUrl [value]', 'Define the source repository address.')
.option('--sourceBranch [value]', 'Define the branch of source repository.')
.arguments('<inputFile> <outputFolder> [repoConfigureFile]')
.action(function (input: string, output: string, repoConfig: string) {
path = input;
outputPath = output;
repoConfigPath = repoConfig;
})
.parse(process.argv);
if (!path || !outputPath) {
console.log('Error: The input file path and output folder path is not specified!');
program.help();
}
let repoConfig: RepoConfig;
if (repoConfigPath && program.basePath) {
if (fs.existsSync(repoConfigPath)) {
let temp = JSON.parse(fs.readFileSync(repoConfigPath).toString());
repoConfig = {
repo: temp.repo,
branch: temp.branch,
basePath: program.basePath
};
} else {
console.log(`Error: repository config file path {${repoConfigPath}} doesn't exit!`);
program.help();
}
}
if (!repoConfig && program.sourceUrl && program.sourceBranch && program.basePath) {
repoConfig = {
repo: program.sourceUrl,
branch: program.sourceBranch,
basePath: program.basePath
};
}
if (program.hasModule) {
flags.hasModule = true;
}
if (program.disableAlphabetOrder) {
flags.enableAlphabetOrder = false;
}
let json = null;
if (fs.existsSync(path)) {
let dataStr = fs.readFileSync(path).toString();
json = JSON.parse(dataStr);
} else {
console.error('Api doc file ' + path + ' doesn\'t exist.');
program.help();
}
let rootElements: YamlModel[] = [];
let uidMapping: UidMapping = {};
let referenceMappings: ReferenceMapping[] = [];
if (json) {
traverse(json, '', rootElements, null, uidMapping, repoConfig);
}
if (rootElements && rootElements.length) {
rootElements.forEach(rootElement => {
let referenceMapping = {};
resolveIds(rootElement, uidMapping, referenceMapping);
referenceMappings.push(referenceMapping);
});
let functionsMapping = groupOrphanFunctions(rootElements);
let flattenElements = rootElements.map((rootElement, index) => {
if (rootElement.uid.indexOf('constructor') >= 0) {
return [];
}
return postTransform(rootElement, referenceMappings[index]);
}).reduce(function(a, b) {
return a.concat(b);
}, []);
console.log('Yaml dump start.');
fs.ensureDir(outputPath);
flattenElements.forEach(transfomredClass => {
transfomredClass = JSON.parse(JSON.stringify(transfomredClass));
let filename = transfomredClass.items[0].uid.replace(`${transfomredClass.items[0].package}.`, '');
filename = filename.split('(')[0];
console.log(`Dump ${outputPath}/${filename}.yml`);
fs.writeFileSync(`${outputPath}/${filename}.yml`, `${yamlHeader}\n${serializer.safeDump(transfomredClass)}`);
});
console.log('Yaml dump end.');
let yamlModels: YamlModel[] = [];
flattenElements.forEach(element => {
yamlModels.push(element.items[0]);
});
let packageIndex = generatePackage(yamlModels);
insertFunctionToIndex(packageIndex, functionsMapping['ParentToPackage']);
packageIndex = JSON.parse(JSON.stringify(packageIndex));
fs.writeFileSync(`${outputPath}/index.yml`, `${yamlHeader}\n${serializer.safeDump(packageIndex)}`);
console.log('Package index genrated.');
let toc = generateToc(yamlModels, flattenElements[0].items[0].package);
toc = JSON.parse(JSON.stringify(toc));
fs.writeFileSync(`${outputPath}/toc.yml`, serializer.safeDump(toc));
console.log('Toc genrated.');
if (flags.hasModule) {
let moduleIndexes = generateModules(toc[0].items);
moduleIndexes.forEach(moduleIndex => {
if (moduleIndex.items && moduleIndex.items.length) {
insertFunctionToIndex(moduleIndex, functionsMapping[moduleIndex.items[0].name]);
moduleIndex = JSON.parse(JSON.stringify(moduleIndex));
fs.writeFileSync(`${outputPath}/${moduleIndex.items[0].uid}.yml`, `${yamlHeader}\n${serializer.safeDump(moduleIndex)}`);
}
});
console.log('Module indexes generated.');
}
}