Skip to content

Commit

Permalink
fix: move scripts docs in @tarojs/taro
Browse files Browse the repository at this point in the history
  • Loading branch information
ZakaryCode committed Nov 7, 2019
1 parent e430863 commit ac3705b
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 117 deletions.
70 changes: 0 additions & 70 deletions build/docs-api.ts

This file was deleted.

6 changes: 0 additions & 6 deletions build/tsconfig.json

This file was deleted.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
"release:lerna": "lerna publish --force-publish=* --exact --skip-temp-tag",
"release:beta": "lerna publish --force-publish=* --exact --skip-temp-tag --preid=beta --npm-tag=beta",
"release": "npm-run-all build release:lerna && npm run changelog && node ./build/docs-version.js",
"test": "lerna run --scope eslint-plugin-taro --scope @tarojs/transformer-wx test",
"test:docs": "ts-node -P ./build/tsconfig.json ./build/docs-api.ts"
"test": "lerna run --scope eslint-plugin-taro --scope @tarojs/transformer-wx test"
},
"repository": {
"type": "git",
Expand Down
3 changes: 2 additions & 1 deletion packages/taro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c rollup.config.js"
"build": "rollup -c rollup.config.js",
"docs": "ts-node ./scripts/docs-api.ts"
},
"repository": {
"type": "git",
Expand Down
134 changes: 134 additions & 0 deletions packages/taro/scripts/docs-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import * as fs from "fs"
import * as path from "path"
import * as ts from "typescript"
import { generateDocumentation, DocEntry } from "./parser"

// import * as h5 from '@tarojs/taro-h5'
// console.log(h5)

interface DocNode {
fileName?: string
documentation?: string
jsTags?: { [key: string]: string }
type?: string
constructors?: DocEntry[]
parameters?: DocEntry[]
returnType?: string
members?: DocNode
exports?: DocNode
children?: DocNode
}

export default function docsAPI (base: string = '.', out: string, files: string[]) {
const cwd: string = process.cwd();
const basepath: string = path.resolve(cwd, base);
files.forEach(async s => {
compile(cwd, s, (routepath, doc) => {
console.log(routepath) // , doc.length)
if (doc.length < 1) return
const outpath: string = routepath
.replace(basepath, path.resolve(cwd, out))
.replace(/(.[a-z]+)$|(.d.ts)$/ig, '')
try {
writeDoc(outpath, doc)
} catch (error) {
const _p = path.parse(outpath)
fs.mkdirSync(_p.name === 'index' ? _p.dir : outpath, { recursive: true })
writeDoc(outpath, doc)
}
})
})
}

export function compile (p: string, n: string, callback?: (routepath: string, doc: DocEntry[]) => void) {
const route = path.resolve(p, n)
const stat = fs.statSync(route)
if (stat.isDirectory()) {
fs.readdirSync(route, {
encoding: 'utf8'
}).forEach(filename => ![
'node_modules', 'bin', 'templates', 'dist', '__tests__', '__mocks__', '_book', '.vscode', '.idea'
].includes(filename) && compile(route, filename, callback))
} else {
const docTree = generateDocumentation(route, {
target: ts.ScriptTarget.ES5,
module: ts.ModuleKind.ESNext
})
callback && callback(route, docTree)
}
}

export function writeJson (routepath: string, doc: DocEntry[]) {
fs.writeFileSync(
`${routepath}.json`,
JSON.stringify(doc, undefined, 4),
{}
)
}

export function writeDoc (routepath: string, doc: DocEntry[]) {
const _p = path.parse(routepath)
const Taro = merge().Taro

function merge (d: DocEntry[] = doc, o: any = {}) {
d.forEach(e => {
const name = e.name || 'undefined'
if (!o[name]) o[name] = {}
for (const key in e) {
if (e.hasOwnProperty(key) && e[key] && !['name', 'kind', 'flags'].includes(key)) {
if (key === 'children') {
if (!o[name].children) {
o[name].children = merge(e.children)
}
} else if (key === 'exports') {
if (!o[name].exports) {
o[name].exports = merge(e.exports)
}
} else {
o[name][key] = e[key]
}
}
}
})
Object.values(o).forEach((e: DocNode) => {
if (e.children) {
if (!e.exports) e.exports = {};
for (const k in e.children) {
if (e.exports[k]) {
Object.assign(e.exports[k], e.children[k])
} else {
e.exports[k] = e.children[k]
}
}
delete e.children
}
const jsTags = {}
if (e.jsTags) {
const tags: ts.JSDocTagInfo[] = e.jsTags as unknown as []
tags.forEach((k: ts.JSDocTagInfo) => jsTags[k.name] = k.text || '')
}
e.jsTags = jsTags
})
return o
}

Object.keys(Taro.exports).forEach(name => {
const e = Taro.exports[name]
const tags = e.jsTags || {}
const params = e.parameters || []
const md: string[] = ['---', `title: Taro.${name}(${params.map(param => param.name).join(', ')})`, `sidebar_label: ${name}`, '---', '']
e.documentation && md.push(e.documentation, '')
e.type && md.push('## 类型', '```typescript', e.type, '```', '')
tags.example && md.push('## 参数', tags.exports, '')
tags.example && md.push('## 示例代码', '', tags.example, '')
md.push(JSON.stringify(e, undefined, 2))
fs.writeFileSync(
path.resolve(_p.name === 'index' ? _p.dir : routepath, `${name}.md`),
md.join('\n'),
{}
)
})
}

// docsAPI('.', process.argv[2], process.argv.slice(3))
docsAPI('./types/api', '../../api', ['./types/api/'])
42 changes: 27 additions & 15 deletions build/parser/index.ts → packages/taro/scripts/parser/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as ts from "typescript"

export interface DocEntry {
name?: string | ts.__String
name?: string
kind?: ts.SyntaxKind
flags?: ts.SymbolFlags
fileName?: string
documentation?: string
jsTags?: ts.JSDocTagInfo[]
Expand All @@ -11,27 +13,27 @@ export interface DocEntry {
returnType?: string
members?: DocEntry[]
exports?: DocEntry[]
children?: DocEntry[]
}

export function generateDocumentation(
filepath: string,
options: ts.CompilerOptions
options: ts.CompilerOptions,
output: DocEntry[] = []
): DocEntry[] {
const program = ts.createProgram([filepath], options)
const checker = program.getTypeChecker()

const output: DocEntry[] = []

for (const sourceFile of program.getSourceFiles()) {
// if (!sourceFile.isDeclarationFile) {}
if (filepath === sourceFile.fileName) {
ts.forEachChild(sourceFile, visitAST)
ts.forEachChild(sourceFile, (n) => visitAST(n, output))
}
}

return output

function visitAST(node: ts.Node) {
function visitAST(node: ts.Node, o: DocEntry[]) {
// Only consider exported nodes
if (!isNodeExported(node as ts.Declaration) || node.kind === ts.SyntaxKind.EndOfFileToken || node.kind === ts.SyntaxKind.DeclareKeyword
|| ts.isImportDeclaration(node) || ts.isImportEqualsDeclaration(node) || ts.isImportClause(node)
Expand All @@ -43,29 +45,38 @@ export function generateDocumentation(

if (ts.isVariableDeclaration(node) || ts.isClassDeclaration(node) && node.name) {
const symbol = checker.getSymbolAtLocation(node)
symbol && output.push(serializeClass(symbol))
symbol && o.push(serializeClass(symbol))
} else if (ts.isFunctionDeclaration(node)) {
const signature = checker.getSignatureFromDeclaration(node)
signature && output.push(serializeSignature(signature, node.name && ts.idText(node.name)))
signature && o.push(serializeSignature(signature, node.name && ts.idText(node.name)))
} else if (ts.isInterfaceDeclaration(node)) {
const symbol = checker.getTypeAtLocation(node).getSymbol()
symbol && output.push(serializeType(symbol, undefined, 'InterfaceDeclaration'))
symbol && o.push(serializeType(symbol, undefined, 'InterfaceDeclaration'))
} else if (ts.isTypeAliasDeclaration(node)) {
const symbol = checker.getTypeAtLocation(node).getSymbol()
symbol && output.push(serializeType(symbol, ts.idText(node.name), 'TypeAliasDeclaration'))
symbol && o.push(serializeType(symbol, ts.idText(node.name), 'TypeAliasDeclaration'))
} else if (ts.isEnumDeclaration(node)) {
const symbol = checker.getTypeAtLocation(node).getSymbol()
symbol && output.push(serializeType(symbol))
symbol && o.push(serializeType(symbol))
} else if (ts.isIdentifier(node)) {
const symbol = checker.getTypeAtLocation(node).getSymbol()
symbol && output.push(serializeType(symbol))
} else if (ts.isModuleDeclaration(node) || ts.isModuleBlock(node) || ts.isVariableStatement(node)) {
symbol && o.push(serializeType(symbol))
} else if (ts.isModuleDeclaration(node) || ts.isVariableStatement(node)) {
// This is a namespace, visitAST its children
ts.forEachChild(node, (n) => visitAST(n, o))
} else if (ts.isModuleBlock(node)) {
// This is a namespace, visitAST its children
ts.forEachChild(node, visitAST)
const out: DocEntry = {
name: ts.isIdentifier(node.parent.name) ? ts.idText(node.parent.name) : '',
kind: node.kind,
children: []
}
ts.forEachChild(node, (n) => visitAST(n, out.children!))
o.push(out)
} else if (ts.isVariableDeclarationList(node)) {
node.declarations.forEach(d => {
const symbol = d['symbol']
symbol && output.push(serializeType(symbol))
symbol && o.push(serializeType(symbol))
})
} else {
console.log(`WARN: Statement kind ${node.kind} is missing parse!\n\n${node.getText()}`)
Expand All @@ -77,6 +88,7 @@ export function generateDocumentation(
return {
jsTags: symbol.getJsDocTags(),
name: name || symbol.getName(),
flags: symbol.flags,
documentation: ts.displayPartsToString(symbol.getDocumentationComment(checker)),
type: type || checker.typeToString(
checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration!)
Expand Down
File renamed without changes.
10 changes: 10 additions & 0 deletions packages/taro/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"module": "umd",
"resolveJsonModule": false,
"paths": {
"@tarojs/taro-h5": ["packages/taro-h5"]
}
}
}
Loading

0 comments on commit ac3705b

Please sign in to comment.