import * as ts from "typescript" import * as pathModule from "path" import * as fs from "fs-extra" export class TSConfigParser { public sourceFile: ts.SourceFile public result: { Template?: string Output?: string StyleOutput?: string Root?: string } = {} constructor(public readonly filePath: string) { let content = fs.readFileSync(this.filePath, "utf8") this.sourceFile = ts.createSourceFile(this.filePath, content, ts.ScriptTarget.ES5, true) this.traverseAndParse() } getTemplatePath(): string { let basedir = pathModule.dirname(this.filePath) + "/" let templatePath = pathModule.resolve(basedir, this.result.Template || "template") return templatePath } getOutputJavascriptPath(): string { let extname = pathModule.extname(this.result.Output) let basename = pathModule.basename(this.result.Output, extname) let dir = pathModule.dirname(this.result.Output) basename = [dir, basename].join("/") let basedir = pathModule.dirname(this.filePath) + "/" let outputPath = pathModule.join(basedir, basename + ".js") return outputPath } getOutputDefinitionPath(): string { let extname = pathModule.extname(this.result.Output) let basename = pathModule.basename(this.result.Output, extname) let dir = pathModule.dirname(this.result.Output) basename = [dir, basename].join("/") let basedir = pathModule.dirname(this.filePath) + "/" let outputPath = pathModule.join(basedir, basename + ".d.ts") return outputPath } getRootPath(): string { let basedir = pathModule.dirname(this.filePath) + "/" if (!this.result.Root) return basedir let outputPath = pathModule.resolve(basedir, this.result.Root) return outputPath } getStyleOutputPath(): string { if (!this.result.StyleOutput) return "" let basedir = pathModule.dirname(this.filePath) + "/" let styleOutputPath = pathModule.resolve(basedir, this.result.StyleOutput || "R.d.ts") return styleOutputPath } traverseAndParse() { ts.forEachChild(this.sourceFile, (child) => { if (child.kind === ts.SyntaxKind.TypeAliasDeclaration) { let node = child as ts.TypeAliasDeclaration let name = node.name as ts.Identifier let type = node.type as ts.LiteralTypeNode let typeLiteral = type.literal let nameString = name.text if (typeLiteral.kind !== ts.SyntaxKind.StringLiteral) { throw new Error("Invalid type declaration" + getSyntaxKindName(typeLiteral.kind)) } let stringLiteral = typeLiteral as ts.StringLiteral let contentString = stringLiteral.text this.result[nameString] = contentString } else { //console.error("pass", getSyntaxKindName(child.kind)) } }) } getDeclareName(node: ts.Node) { let name: string = null ts.forEachChild(node, (child) => { if (child.kind === ts.SyntaxKind.Identifier) { name = (child as ts.Identifier).text } }) return name } } interface KindTree { name: string children: KindTree[] } function getSyntaxKindName(kind) { for (let name in ts.SyntaxKind) { if (ts.SyntaxKind[name] === kind) { return name } } return "Unknown" } function getKindTree(node: ts.Node): KindTree { let tree: KindTree = { name: getSyntaxKindName(node.kind) , children: [] } ts.forEachChild(node, (child) => { tree.children.push(getKindTree(child)) }) return tree } function inspectKind(node: ts.Node) { let tree = getKindTree(node) console.log(JSON.stringify(tree, null, 2)) }