@kubb/renderer-jsx 5.0.0-beta.17 → 5.0.0-beta.19
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.
- package/dist/index.cjs +438 -175
- package/dist/index.d.ts +38 -10
- package/dist/index.js +438 -176
- package/dist/jsx-dev-runtime.d.ts +2 -2
- package/dist/{jsx-namespace-CNp0arTN.d.ts → jsx-namespace-BLGeMDcR.d.ts} +2 -2
- package/dist/jsx-runtime.d.ts +2 -2
- package/dist/{types-nAFMiWFw.d.ts → types-Dk7A1Y5U.d.ts} +2 -2
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
- package/src/Renderer.ts +1 -1
- package/src/Runtime.tsx +4 -4
- package/src/SyncRuntime.tsx +289 -0
- package/src/constants.ts +19 -9
- package/src/createRenderer.tsx +47 -5
- package/src/dom.ts +3 -13
- package/src/index.ts +1 -1
- package/src/types.ts +1 -1
- package/src/utils.ts +179 -205
package/src/utils.ts
CHANGED
|
@@ -11,95 +11,113 @@ import {
|
|
|
11
11
|
createText,
|
|
12
12
|
createType,
|
|
13
13
|
} from '@kubb/ast'
|
|
14
|
-
import {
|
|
15
|
-
|
|
14
|
+
import {
|
|
15
|
+
KUBB_ARROW_FUNCTION,
|
|
16
|
+
KUBB_CONST,
|
|
17
|
+
KUBB_EXPORT,
|
|
18
|
+
KUBB_FILE,
|
|
19
|
+
KUBB_FUNCTION,
|
|
20
|
+
KUBB_IMPORT,
|
|
21
|
+
KUBB_JSX,
|
|
22
|
+
KUBB_SOURCE,
|
|
23
|
+
KUBB_TYPE,
|
|
24
|
+
TEXT_NODE_NAME,
|
|
25
|
+
nodeNames,
|
|
26
|
+
} from './constants.ts'
|
|
27
|
+
import type { DOMElement, DOMNode } from './types.ts'
|
|
28
|
+
|
|
29
|
+
function toBool(val: unknown): boolean {
|
|
30
|
+
return (val ?? false) as boolean
|
|
31
|
+
}
|
|
16
32
|
|
|
17
33
|
/**
|
|
18
34
|
* Collect the text and nested AST-node children of a single kubb-* element.
|
|
19
35
|
*
|
|
20
|
-
* `#text` children become raw
|
|
36
|
+
* `#text` children become raw text nodes; nested `kubb-function`, `kubb-const`,
|
|
21
37
|
* `kubb-type`, and similar elements are converted into their respective {@link CodeNode}s.
|
|
22
|
-
* Any unrecognized
|
|
38
|
+
* Any unrecognized element names are silently skipped.
|
|
23
39
|
*/
|
|
24
|
-
function
|
|
25
|
-
const result:
|
|
40
|
+
function collectCodeNodes(element: DOMElement): CodeNode[] {
|
|
41
|
+
const result: CodeNode[] = []
|
|
26
42
|
|
|
27
43
|
for (const child of element.childNodes) {
|
|
28
|
-
if (!child)
|
|
29
|
-
continue
|
|
30
|
-
}
|
|
44
|
+
if (!child) continue
|
|
31
45
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
result.push(createText(text))
|
|
46
|
+
switch (child.nodeName) {
|
|
47
|
+
case TEXT_NODE_NAME: {
|
|
48
|
+
const text = (child as DOMNode<{ nodeName: '#text' }>).nodeValue
|
|
49
|
+
if (text && text.trim()) result.push(createText(text))
|
|
50
|
+
break
|
|
36
51
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
52
|
+
case 'br':
|
|
53
|
+
result.push(createBreak())
|
|
54
|
+
break
|
|
55
|
+
case KUBB_FUNCTION: {
|
|
56
|
+
const attrs = child.attributes
|
|
57
|
+
result.push(
|
|
58
|
+
createFunction({
|
|
59
|
+
name: attrs['name'] as string,
|
|
60
|
+
params: attrs['params'] as string | undefined,
|
|
61
|
+
export: attrs['export'] as boolean | undefined,
|
|
62
|
+
default: attrs['default'] as boolean | undefined,
|
|
63
|
+
async: attrs['async'] as boolean | undefined,
|
|
64
|
+
generics: attrs['generics'] as string | undefined,
|
|
65
|
+
returnType: attrs['returnType'] as string | undefined,
|
|
66
|
+
JSDoc: attrs['JSDoc'] as JSDocNode | undefined,
|
|
67
|
+
nodes: collectCodeNodes(child),
|
|
68
|
+
}),
|
|
69
|
+
)
|
|
70
|
+
break
|
|
71
|
+
}
|
|
72
|
+
case KUBB_ARROW_FUNCTION: {
|
|
73
|
+
const attrs = child.attributes
|
|
74
|
+
result.push(
|
|
75
|
+
createArrowFunction({
|
|
76
|
+
name: attrs['name'] as string,
|
|
77
|
+
params: attrs['params'] as string | undefined,
|
|
78
|
+
export: attrs['export'] as boolean | undefined,
|
|
79
|
+
default: attrs['default'] as boolean | undefined,
|
|
80
|
+
async: attrs['async'] as boolean | undefined,
|
|
81
|
+
generics: attrs['generics'] as string | undefined,
|
|
82
|
+
returnType: attrs['returnType'] as string | undefined,
|
|
83
|
+
singleLine: attrs['singleLine'] as boolean | undefined,
|
|
84
|
+
JSDoc: attrs['JSDoc'] as JSDocNode | undefined,
|
|
85
|
+
nodes: collectCodeNodes(child),
|
|
86
|
+
} as Omit<ArrowFunctionNode, 'kind'>),
|
|
87
|
+
)
|
|
88
|
+
break
|
|
89
|
+
}
|
|
90
|
+
case KUBB_CONST: {
|
|
91
|
+
const attrs = child.attributes
|
|
92
|
+
result.push(
|
|
93
|
+
createConst({
|
|
94
|
+
name: attrs['name'] as string,
|
|
95
|
+
type: attrs['type'] as string | undefined,
|
|
96
|
+
export: attrs['export'] as boolean | undefined,
|
|
97
|
+
asConst: attrs['asConst'] as boolean | undefined,
|
|
98
|
+
JSDoc: attrs['JSDoc'] as JSDocNode | undefined,
|
|
99
|
+
nodes: collectCodeNodes(child),
|
|
100
|
+
}),
|
|
101
|
+
)
|
|
102
|
+
break
|
|
103
|
+
}
|
|
104
|
+
case KUBB_TYPE: {
|
|
105
|
+
const attrs = child.attributes
|
|
106
|
+
result.push(
|
|
107
|
+
createType({
|
|
108
|
+
name: attrs['name'] as string,
|
|
109
|
+
export: attrs['export'] as boolean | undefined,
|
|
110
|
+
JSDoc: attrs['JSDoc'] as JSDocNode | undefined,
|
|
111
|
+
nodes: collectCodeNodes(child),
|
|
112
|
+
}),
|
|
113
|
+
)
|
|
114
|
+
break
|
|
115
|
+
}
|
|
116
|
+
case KUBB_JSX: {
|
|
117
|
+
const textChild = child.childNodes[0]
|
|
118
|
+
const value = textChild?.nodeName === TEXT_NODE_NAME ? (textChild as DOMNode<{ nodeName: '#text' }>).nodeValue : ''
|
|
119
|
+
if (value) result.push(createJsx(value))
|
|
120
|
+
break
|
|
103
121
|
}
|
|
104
122
|
}
|
|
105
123
|
}
|
|
@@ -108,160 +126,116 @@ function collectChildNodes(element: DOMElement): Array<CodeNode> {
|
|
|
108
126
|
}
|
|
109
127
|
|
|
110
128
|
/**
|
|
111
|
-
*
|
|
129
|
+
* Yields every {@link SourceNode}, {@link ExportNode}, and {@link ImportNode}
|
|
130
|
+
* within a `<kubb-file>` subtree in a single tree walk.
|
|
112
131
|
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* ```ts
|
|
118
|
-
* const sources = squashSourceNodes(fileElement, ['kubb-export', 'kubb-import'])
|
|
119
|
-
* ```
|
|
132
|
+
* Import and export elements are leaf nodes. Once yielded, the walker does not
|
|
133
|
+
* recurse into them, which also prevents source collection from descending into
|
|
134
|
+
* their subtrees. Dispatch on `.kind` (`'Source'`, `'Export'`, `'Import'`) to
|
|
135
|
+
* separate the results.
|
|
120
136
|
*/
|
|
121
|
-
function
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
137
|
+
function* collectFileEntries(node: DOMElement): Generator<SourceNode | ExportNode | ImportNode> {
|
|
138
|
+
for (const child of node.childNodes) {
|
|
139
|
+
if (!child || child.nodeName === TEXT_NODE_NAME) continue
|
|
140
|
+
|
|
141
|
+
if (child.nodeName === KUBB_SOURCE) {
|
|
142
|
+
yield createSource({
|
|
143
|
+
name: child.attributes['name']?.toString(),
|
|
144
|
+
isTypeOnly: toBool(child.attributes['isTypeOnly']),
|
|
145
|
+
isExportable: toBool(child.attributes['isExportable']),
|
|
146
|
+
isIndexable: toBool(child.attributes['isIndexable']),
|
|
147
|
+
nodes: collectCodeNodes(child),
|
|
148
|
+
})
|
|
149
|
+
continue
|
|
150
|
+
}
|
|
134
151
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
152
|
+
if (child.nodeName === KUBB_EXPORT) {
|
|
153
|
+
yield createExport({
|
|
154
|
+
name: child.attributes['name'] as ExportNode['name'],
|
|
155
|
+
path: child.attributes['path'] as string,
|
|
156
|
+
isTypeOnly: toBool(child.attributes['isTypeOnly']),
|
|
157
|
+
asAlias: toBool(child.attributes['asAlias']),
|
|
158
|
+
})
|
|
159
|
+
continue
|
|
160
|
+
}
|
|
143
161
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
162
|
+
if (child.nodeName === KUBB_IMPORT) {
|
|
163
|
+
yield createImport({
|
|
164
|
+
name: child.attributes['name'] as ImportNode['name'],
|
|
165
|
+
path: child.attributes['path'] as string,
|
|
166
|
+
root: child.attributes['root'] as string | undefined,
|
|
167
|
+
isTypeOnly: toBool(child.attributes['isTypeOnly']),
|
|
168
|
+
isNameSpace: toBool(child.attributes['isNameSpace']),
|
|
169
|
+
})
|
|
170
|
+
continue
|
|
171
|
+
}
|
|
147
172
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
173
|
+
if (nodeNames.has(child.nodeName)) {
|
|
174
|
+
yield* collectFileEntries(child)
|
|
151
175
|
}
|
|
152
176
|
}
|
|
153
|
-
|
|
154
|
-
walk(node)
|
|
155
|
-
return sources
|
|
156
177
|
}
|
|
157
178
|
|
|
158
179
|
/**
|
|
159
|
-
*
|
|
180
|
+
* Runs a single {@link collectFileEntries} pass over a `<kubb-file>` DOM element
|
|
181
|
+
* and assembles the result into a {@link FileNode}, bucketing each yielded
|
|
182
|
+
* node by its `.kind`.
|
|
160
183
|
*/
|
|
161
|
-
function
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if (child.nodeName === 'kubb-export') {
|
|
175
|
-
exports.add(
|
|
176
|
-
createExport({
|
|
177
|
-
name: child.attributes.get('name') as ExportNode['name'],
|
|
178
|
-
path: child.attributes.get('path') as string,
|
|
179
|
-
isTypeOnly: (child.attributes.get('isTypeOnly') ?? false) as boolean,
|
|
180
|
-
asAlias: (child.attributes.get('asAlias') ?? false) as boolean,
|
|
181
|
-
}),
|
|
182
|
-
)
|
|
183
|
-
}
|
|
184
|
+
function createFileNode(child: DOMElement): FileNode {
|
|
185
|
+
const sources: SourceNode[] = []
|
|
186
|
+
const exports: ExportNode[] = []
|
|
187
|
+
const imports: ImportNode[] = []
|
|
188
|
+
|
|
189
|
+
for (const node of collectFileEntries(child)) {
|
|
190
|
+
if (node.kind === 'Source') {
|
|
191
|
+
sources.push(node)
|
|
192
|
+
continue
|
|
193
|
+
}
|
|
194
|
+
if (node.kind === 'Export') {
|
|
195
|
+
exports.push(node)
|
|
196
|
+
continue
|
|
184
197
|
}
|
|
198
|
+
imports.push(node)
|
|
185
199
|
}
|
|
186
200
|
|
|
187
|
-
|
|
188
|
-
|
|
201
|
+
return {
|
|
202
|
+
baseName: child.attributes['baseName'],
|
|
203
|
+
path: child.attributes['path'],
|
|
204
|
+
meta: child.attributes['meta'] || {},
|
|
205
|
+
footer: child.attributes['footer'],
|
|
206
|
+
banner: child.attributes['banner'],
|
|
207
|
+
sources,
|
|
208
|
+
exports,
|
|
209
|
+
imports,
|
|
210
|
+
} as FileNode
|
|
189
211
|
}
|
|
190
212
|
|
|
191
213
|
/**
|
|
192
|
-
*
|
|
214
|
+
* Yields each {@link FileNode} as it is encountered during the tree walk,
|
|
215
|
+
* without collecting into an intermediate array. Callers can begin processing
|
|
216
|
+
* each file before the rest of the tree is traversed.
|
|
193
217
|
*/
|
|
194
|
-
function
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
const walk = (current: DOMElement): void => {
|
|
198
|
-
for (const child of current.childNodes) {
|
|
199
|
-
if (!child) {
|
|
200
|
-
continue
|
|
201
|
-
}
|
|
218
|
+
export function* streamFiles(node: DOMElement): Generator<FileNode> {
|
|
219
|
+
for (const child of node.childNodes) {
|
|
220
|
+
if (!child) continue
|
|
202
221
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
222
|
+
if (child.nodeName !== TEXT_NODE_NAME && child.nodeName !== KUBB_FILE && nodeNames.has(child.nodeName)) {
|
|
223
|
+
yield* streamFiles(child)
|
|
224
|
+
}
|
|
206
225
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
createImport({
|
|
210
|
-
name: child.attributes.get('name') as ImportNode['name'],
|
|
211
|
-
path: child.attributes.get('path') as string,
|
|
212
|
-
root: child.attributes.get('root') as string | undefined,
|
|
213
|
-
isTypeOnly: (child.attributes.get('isTypeOnly') ?? false) as boolean,
|
|
214
|
-
isNameSpace: (child.attributes.get('isNameSpace') ?? false) as boolean,
|
|
215
|
-
}),
|
|
216
|
-
)
|
|
217
|
-
}
|
|
226
|
+
if (child.nodeName === KUBB_FILE && child.attributes['baseName'] !== undefined && child.attributes['path'] !== undefined) {
|
|
227
|
+
yield createFileNode(child)
|
|
218
228
|
}
|
|
219
229
|
}
|
|
220
|
-
|
|
221
|
-
walk(node)
|
|
222
|
-
return imports
|
|
223
230
|
}
|
|
224
231
|
|
|
225
232
|
/**
|
|
226
233
|
* Walk the virtual DOM tree rooted at `node` and convert every `<kubb-file>` element
|
|
227
234
|
* into a {@link FileNode}, collecting its source blocks, imports, and exports.
|
|
228
235
|
*
|
|
229
|
-
* Returns the list of file nodes in document order. Nested files are supported
|
|
236
|
+
* Returns the list of file nodes in document order. Nested files are supported;
|
|
230
237
|
* the walker descends into non-file elements and recurses through them.
|
|
231
238
|
*/
|
|
232
|
-
export function
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
function walk(current: DOMElement) {
|
|
236
|
-
for (const child of current.childNodes) {
|
|
237
|
-
if (!child) {
|
|
238
|
-
continue
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (child.nodeName !== TEXT_NODE_NAME && child.nodeName !== 'kubb-file' && nodeNames.has(child.nodeName)) {
|
|
242
|
-
walk(child)
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
if (child.nodeName === 'kubb-file') {
|
|
246
|
-
if (child.attributes.has('baseName') && child.attributes.has('path')) {
|
|
247
|
-
const sources = squashSourceNodes(child, ['kubb-export', 'kubb-import'])
|
|
248
|
-
|
|
249
|
-
collected.push({
|
|
250
|
-
baseName: child.attributes.get('baseName'),
|
|
251
|
-
path: child.attributes.get('path'),
|
|
252
|
-
meta: child.attributes.get('meta') || {},
|
|
253
|
-
footer: child.attributes.get('footer'),
|
|
254
|
-
banner: child.attributes.get('banner'),
|
|
255
|
-
sources: [...sources],
|
|
256
|
-
exports: [...squashExportNodes(child)],
|
|
257
|
-
imports: [...squashImportNodes(child)],
|
|
258
|
-
} as FileNode)
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
walk(node)
|
|
265
|
-
|
|
266
|
-
return collected
|
|
239
|
+
export function collectFiles(node: DOMElement): FileNode[] {
|
|
240
|
+
return [...streamFiles(node)]
|
|
267
241
|
}
|