@tarojs/plugin-platform-h5 3.7.0-alpha.2 → 3.7.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ import { parseDefinitionJSON } from './parser'
2
+
3
+ parseDefinitionJSON()
@@ -0,0 +1,112 @@
1
+ import { fs } from '@tarojs/helper'
2
+ import { paramCase } from 'change-case'
3
+ import ts from 'typescript'
4
+
5
+ import { generateDocumentation } from '../utils/ast'
6
+
7
+ import type { DocEntry } from '../utils/ast'
8
+
9
+ const tsconfig: ts.CompilerOptions = {
10
+ target: ts.ScriptTarget.ES5,
11
+ module: ts.ModuleKind.NodeNext,
12
+ moduleResolution: ts.ModuleResolutionKind.NodeNext,
13
+ noResolve: false,
14
+ paths: {
15
+ '@tarojs/api': ['node_modules/@tarojs/taro/types']
16
+ },
17
+ 'types': ['@tarojs/taro-h5/types']
18
+ }
19
+ const CompRGX = /^Taro(.*)Core$/
20
+ const IgnoreSymbols = [
21
+ ts.SymbolFlags.Interface,
22
+ ts.SymbolFlags.TypeLiteral,
23
+ ts.SymbolFlags.TypeAlias,
24
+ ]
25
+
26
+ export function parseComponents (docTree: DocEntry[]) {
27
+ // ${component}.${attribute}.${option}
28
+ return docTree.reduce((p, e) => {
29
+ let { name = '', members = [] } = e
30
+ if (CompRGX.test(name)) {
31
+ name = paramCase(name.replace(CompRGX, '$1'))
32
+ p[name] = members.reduce((p2, e2) => {
33
+ p2[e2.name ?? ''] = parseComponentAttribute(e2)
34
+
35
+ return p2
36
+ }, {})
37
+ }
38
+ return p
39
+ }, {})
40
+ }
41
+
42
+ export function parseAPIs (docTree: DocEntry[]) {
43
+ // ${API}.${method}.${param}.${option}
44
+ return docTree.reduce((p, e) => {
45
+ if (!IgnoreSymbols.includes(e.flags!)) {
46
+ p[e.name ?? ''] = parseAPIMethod(e)
47
+ }
48
+
49
+ return p
50
+ }, {})
51
+ }
52
+
53
+ const anyTypes = ['any', 'TaroStatic', '{}', 'IAnyObject', 'T']
54
+ const voidTypes = ['', 'void', 'null', 'undefined']
55
+ const anyStr = '*'
56
+ const voidStr = 'void'
57
+ export function parseComponentAttribute (e: DocEntry) {
58
+ return parseAnyOrVoid(e.type, e.type)
59
+ }
60
+
61
+ export function parseAPIMethod (e: DocEntry) {
62
+ const o: Record<string, any> = {}
63
+ const { type = 'any', flags = ts.SymbolFlags.None, declarations = [] } = e
64
+ if (anyTypes.includes(type)) {
65
+ return anyStr
66
+ } else if (flags === ts.SymbolFlags.BlockScopedVariable && declarations.length > 0) {
67
+ const [declaration = {}] = declarations
68
+ const { parameters = [], returnType = '' } = declaration
69
+ const [parameter] = parameters
70
+ const isCallback = parameter?.name === 'callback'
71
+ // console.log('parseAPIMethod', e.name, parameters)
72
+ if (isCallback) {
73
+ const [callback] = parameter?.declarations || []
74
+ const obj = callback?.parameters?.[0] || {}
75
+ // FIXME parse callback ${param}.${option}
76
+ o.callback = parseAnyOrVoid(obj?.type)
77
+ } else {
78
+ // FIXME parse parameter ${param}.${option}
79
+ o.object = parseAnyOrVoid(parameter?.type)
80
+ // FIXME parse successCallback ${param}.${option}
81
+ o.success = voidStr
82
+ }
83
+ // FIXME parse returnType ${param}.${option}
84
+ const returnValue = parseAnyOrVoid(returnType)
85
+ if (returnValue !== voidStr) {
86
+ o.return = returnValue
87
+ }
88
+ }
89
+ return o
90
+ }
91
+
92
+ export function parseAnyOrVoid (str = '', obj: unknown = str) {
93
+ return anyTypes.includes(str) ? anyStr : voidTypes.includes(str) ? voidStr : obj || str
94
+ }
95
+
96
+ export function parseDefinitionJSON ({
97
+ apisPath = require.resolve('@tarojs/taro-h5/dist/index.esm.d.ts'),
98
+ componentsPath = require.resolve('@tarojs/components/dist/types/components.d.ts'),
99
+ } = {},
100
+ config: ts.CompilerOptions = tsconfig,
101
+ ) {
102
+ const apis = parseAPIs(generateDocumentation([apisPath], config))
103
+ const Components = generateDocumentation([componentsPath], config).find(e => e.name === 'Components')?.children || []
104
+ const components = parseComponents(Components)
105
+
106
+ // Note: 写入文件
107
+ fs.ensureDirSync('dist')
108
+ fs.writeJSONSync('dist/definition.json', {
109
+ apis,
110
+ components,
111
+ }, { spaces: 2 })
112
+ }
@@ -0,0 +1,16 @@
1
+ export default function exportNameOnly () {
2
+ const emptyMap = { mappings: '' }
3
+ return {
4
+ name: 'export-name-only',
5
+ renderChunk (code, chunk) {
6
+ const pos = chunk.exports.indexOf('default')
7
+ if (pos > -1) {
8
+ chunk.exports.splice(pos, 1)
9
+ }
10
+ return {
11
+ code: `module.exports = new Set(${JSON.stringify(chunk.exports)})`,
12
+ map: emptyMap
13
+ }
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,172 @@
1
+ import ts from 'typescript'
2
+
3
+ export interface DocEntry {
4
+ name?: string
5
+ kind?: ts.SyntaxKind
6
+ flags?: ts.SymbolFlags
7
+ fileName?: string
8
+ type?: string
9
+ constructors?: DocEntry[]
10
+ parameters?: DocEntry[]
11
+ returnType?: string
12
+ members?: DocEntry[]
13
+ exports?: DocEntry[]
14
+ children?: DocEntry[]
15
+ declarations?: DocEntry[]
16
+ symbol?: DocEntry
17
+ }
18
+
19
+ export function generateDocumentation (
20
+ filepaths: string[],
21
+ options: ts.CompilerOptions,
22
+ param: {
23
+ mapAll?: boolean
24
+ withDeclaration?: boolean
25
+ } = {},
26
+ output: DocEntry[] = []
27
+ ): DocEntry[] {
28
+ const program = ts.createProgram(filepaths, options)
29
+ const checker = program.getTypeChecker()
30
+
31
+ for (const sourceFile of program.getSourceFiles()) {
32
+ if (param.withDeclaration !== false || !sourceFile.isDeclarationFile) {
33
+ if (
34
+ (param.mapAll === true && filepaths.includes(sourceFile.fileName))
35
+ || sourceFile.fileName === filepaths[0]
36
+ ) {
37
+ ts.forEachChild(sourceFile, (n) => visitAST(n, output))
38
+ }
39
+ }
40
+ }
41
+
42
+ return output
43
+
44
+ function visitAST (node: ts.Node, o: DocEntry[]) {
45
+ // Only consider exported nodes
46
+ if (!isNodeExported(node as ts.Declaration) || node.kind === ts.SyntaxKind.EndOfFileToken || node.kind === ts.SyntaxKind.DeclareKeyword
47
+ || ts.isImportDeclaration(node) || ts.isImportEqualsDeclaration(node) || ts.isImportClause(node)
48
+ || ts.isExportAssignment(node) || ts.isExportDeclaration(node)
49
+ || ts.isExpressionStatement(node) || ts.isEmptyStatement(node)
50
+ || ts.isStringLiteral(node)
51
+ || node.kind === ts.SyntaxKind.ExportKeyword) {
52
+ return
53
+ }
54
+
55
+ if (ts.isVariableDeclaration(node) || ts.isClassDeclaration(node) && node.name) {
56
+ const symbol = checker.getSymbolAtLocation(node)
57
+ symbol && o.push(serializeClass(symbol))
58
+ } else if (ts.isFunctionDeclaration(node)) {
59
+ const signature = checker.getSignatureFromDeclaration(node)
60
+ signature && o.push(serializeSignature(signature, node.name && ts.idText(node.name)))
61
+ } else if (ts.isInterfaceDeclaration(node)) {
62
+ const symbol = checker.getTypeAtLocation(node).getSymbol()
63
+ symbol && o.push(serializeType(symbol, undefined, 'InterfaceDeclaration'))
64
+ } else if (ts.isTypeAliasDeclaration(node)) {
65
+ const type = checker.getTypeAtLocation(node)
66
+ const symbol = type.getSymbol()
67
+ if (symbol) {
68
+ const st = serializeType(symbol, ts.idText(node.name))
69
+ o.push(st)
70
+ } else {
71
+ // @ts-ignore
72
+ const sym = node.symbol; const type = node.type?.types?.map(e => checker.typeToString(checker.getTypeFromTypeNode(e))).join(' | ')
73
+ o.push(
74
+ serializeSymbol(sym, sym.getName(), type)
75
+ )
76
+ }
77
+ } else if (ts.isEnumDeclaration(node)) {
78
+ const symbol = checker.getTypeAtLocation(node).getSymbol()
79
+ symbol && o.push(serializeType(symbol))
80
+ } else if (ts.isIdentifier(node)) {
81
+ const symbol = checker.getTypeAtLocation(node).getSymbol()
82
+ symbol && o.push(serializeType(symbol))
83
+ } else if (ts.isModuleDeclaration(node) || ts.isVariableStatement(node)) {
84
+ // This is a namespace, visitAST its children
85
+ ts.forEachChild(node, (n) => visitAST(n, o))
86
+ } else if (ts.isModuleBlock(node)) {
87
+ // This is a namespace, visitAST its children
88
+ const out: DocEntry = {
89
+ name: ts.isIdentifier(node.parent.name) ? ts.idText(node.parent.name) : '',
90
+ kind: node.kind,
91
+ children: []
92
+ }
93
+ ts.forEachChild(node, (n) => visitAST(n, out.children!))
94
+ o.push(out)
95
+ } else if (ts.isVariableDeclarationList(node)) {
96
+ node.declarations.forEach(d => {
97
+ // @ts-ignore
98
+ const symbol = d.symbol // checker.getSymbolsInScope(d, d.symbol.flags)
99
+ symbol && o.push(serializeType(symbol))
100
+ })
101
+ } else {
102
+ console.warn(`WARN: Statement kind ${node.kind} is missing parse!\n\n${node.getText()}\n\n`)
103
+ }
104
+ }
105
+
106
+ /** Serialize a symbol into a json object */
107
+ function serializeSymbol (symbol: ts.Symbol, name?: string, type?: string): DocEntry {
108
+ const declarations: DocEntry[] = [];
109
+ (symbol.getDeclarations() || []).map(
110
+ d => checker.getSignaturesOfType(checker.getTypeAtLocation(d), ts.SignatureKind.Call).map(
111
+ e => declarations.push(serializeSignature(e))
112
+ )
113
+ )
114
+
115
+ return {
116
+ name: name || symbol.getName(),
117
+ flags: symbol.flags,
118
+ type: type || checker.typeToString(
119
+ checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration!)
120
+ ),
121
+ declarations
122
+ }
123
+ }
124
+
125
+ /** Serialize a class symbol information */
126
+ function serializeClass (symbol: ts.Symbol) {
127
+ const details = serializeSymbol(symbol)
128
+ // Get the construct signatures
129
+ const constructorType = checker.getTypeOfSymbolAtLocation(
130
+ symbol,
131
+ symbol.valueDeclaration!
132
+ )
133
+ const signatures = constructorType.getConstructSignatures()
134
+ details.constructors = signatures.map(n => serializeSignature(n))
135
+ return details
136
+ }
137
+
138
+ /** Serialize a types (type or interface) symbol information */
139
+ function serializeType (symbol: ts.Symbol, name?: string, type?: keyof typeof ts.SyntaxKind): DocEntry {
140
+ // console.log(type, Object.keys(symbol))
141
+ const doc: DocEntry = serializeSymbol(symbol, name, type)
142
+ symbol.exports && symbol.exports.forEach((value) => {
143
+ if (!doc.exports) doc.exports = []
144
+ doc.exports.push(serializeSymbol(value))
145
+ })
146
+ symbol.members && symbol.members.forEach((value) => {
147
+ if (!doc.members) doc.members = []
148
+ doc.members.push(serializeSymbol(value))
149
+ })
150
+ return doc
151
+ }
152
+
153
+ /** Serialize a signature (call or construct) */
154
+ function serializeSignature (signature: ts.Signature, name?: string) {
155
+ const typeParameters = signature.getTypeParameters() || []
156
+
157
+ return {
158
+ name,
159
+ parameters: signature.getParameters().map((e, i) =>
160
+ serializeSymbol(e, undefined, typeParameters[i] && checker.typeToString(typeParameters[i]))),
161
+ returnType: checker.typeToString(signature.getReturnType())
162
+ }
163
+ }
164
+
165
+ /** True if this is visible outside this file, false otherwise */
166
+ function isNodeExported (node: ts.Declaration): boolean {
167
+ return (
168
+ (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0 ||
169
+ (!!node.parent/* && node.parent.kind === ts.SyntaxKind.SourceFile */)
170
+ )
171
+ }
172
+ }
@@ -0,0 +1,56 @@
1
+ import ts from 'typescript'
2
+
3
+ const SymbolFlags = Object.values(ts.SymbolFlags)
4
+
5
+ export function splicing (arr: (string | undefined)[] = [], lf = '\n') {
6
+ return arr.filter(e => typeof e === 'string').join(lf)
7
+ }
8
+
9
+ export function parseLineFeed (s?: string, isCode = false) {
10
+ if (!s) return ''
11
+ const r = s.split('|').join('or').split('\n').join('<br />')
12
+ return isCode && !s.includes('|') ? `\`${r}\`` : r
13
+ }
14
+
15
+ export function isShowMembers (flags?: ts.SymbolFlags, used: ts.SymbolFlags[] = []) {
16
+ return [
17
+ ts.SymbolFlags.EnumMember,
18
+ ts.SymbolFlags.Function,
19
+ ts.SymbolFlags.Class,
20
+ ts.SymbolFlags.Interface,
21
+ ts.SymbolFlags.ValueModule,
22
+ ts.SymbolFlags.NamespaceModule,
23
+ ts.SymbolFlags.TypeLiteral,
24
+ ts.SymbolFlags.Method,
25
+ ts.SymbolFlags.TypeAlias,
26
+ ].some(v => {
27
+ const e = (flags || -1) - v
28
+ return e > -1 && !used.includes(v) && (e === 0 || isShowMembers(e, [...used, v]))
29
+ })
30
+ }
31
+
32
+ export function isShowAPI (flags?: ts.SymbolFlags): flags is ts.SymbolFlags.Property | ts.SymbolFlags.Method {
33
+ return [
34
+ ts.SymbolFlags.Property,
35
+ ts.SymbolFlags.Method,
36
+ ts.SymbolFlags.Optional + ts.SymbolFlags.Property,
37
+ ts.SymbolFlags.Optional + ts.SymbolFlags.Method,
38
+ ].includes(flags || -1)
39
+ }
40
+
41
+ export function isNotAPI (flags?: ts.SymbolFlags): flags is ts.SymbolFlags.Signature | ts.SymbolFlags.TypeParameter {
42
+ return [
43
+ -1,
44
+ ts.SymbolFlags.Signature,
45
+ ts.SymbolFlags.TypeParameter,
46
+ ].includes(flags || -1)
47
+ }
48
+
49
+ export function isFunction (flags?: ts.SymbolFlags): flags is ts.SymbolFlags.Function | ts.SymbolFlags.Method {
50
+ return SymbolFlags.includes((flags || -1) - ts.SymbolFlags.Function)
51
+ || SymbolFlags.includes((flags || -1) - ts.SymbolFlags.Method)
52
+ }
53
+
54
+ export function isOptional (flags?: ts.SymbolFlags): flags is ts.SymbolFlags.Optional {
55
+ return SymbolFlags.includes((flags || -1) - ts.SymbolFlags.Optional)
56
+ }
@@ -0,0 +1,43 @@
1
+ import { isFunction } from './helper'
2
+
3
+ import type { DocEntry } from './ast'
4
+
5
+ export async function childrenMerge (d: DocEntry[] = [], o: DocEntry[] = []) {
6
+ for (const e of d) {
7
+ const name = e.name || 'undefined'
8
+ if (!o.find(v => v.name === name)) o.push(e)
9
+ const target = o.find(v => v.name === name) || {}
10
+ for (const key in e) {
11
+ if (e.hasOwnProperty(key) && e[key] && !['name', 'kind'].includes(key)) {
12
+ if (key === 'flags') {
13
+ if (!target.flags || !isFunction(e.flags)) target.flags = e.flags
14
+ } else if (key === 'children') {
15
+ target.children = await childrenMerge(e.children, target.children)
16
+ } else if (key === 'exports') {
17
+ target.exports = await childrenMerge(e.exports, target.exports)
18
+ target[key] = e[key] || target[key]
19
+ }
20
+ }
21
+ }
22
+ }
23
+
24
+ return o.map(e => {
25
+ if (e.children) {
26
+ if (!e.exports) e.exports = []
27
+ for (const k of e.children) {
28
+ const kk = e.exports!.find(kk => kk.name === k.name)
29
+ if (!kk) {
30
+ e.exports!.push(k)
31
+ } else {
32
+ for (const key in k) {
33
+ if (k.hasOwnProperty(key) && !kk[key]) {
34
+ kk[key] = k[key]
35
+ }
36
+ }
37
+ }
38
+ }
39
+ delete e.children
40
+ }
41
+ return e
42
+ })
43
+ }