@kubb/renderer-jsx 5.0.0-beta.16 → 5.0.0-beta.18
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 +423 -176
- package/dist/index.d.ts +38 -10
- package/dist/index.js +423 -177
- 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 +285 -0
- package/src/constants.ts +19 -9
- package/src/createRenderer.tsx +46 -5
- package/src/dom.ts +3 -13
- package/src/index.ts +1 -1
- package/src/types.ts +1 -1
- package/src/utils.ts +174 -206
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,110 @@ function collectChildNodes(element: DOMElement): Array<CodeNode> {
|
|
|
108
126
|
}
|
|
109
127
|
|
|
110
128
|
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* Elements whose `nodeName` is in `ignores` are skipped entirely (including their subtrees).
|
|
114
|
-
* This is used to collect source blocks from a file node while excluding import/export subtrees.
|
|
129
|
+
* Yields every {@link SourceNode}, {@link ExportNode}, and {@link ImportNode}
|
|
130
|
+
* within a `<kubb-file>` subtree in a single tree walk.
|
|
115
131
|
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
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
|
-
if (child.nodeName !== TEXT_NODE_NAME && nodeNames.has(child.nodeName)) {
|
|
171
|
-
walk(child)
|
|
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
|
-
}
|
|
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') sources.push(node)
|
|
191
|
+
else if (node.kind === 'Export') exports.push(node)
|
|
192
|
+
else imports.push(node)
|
|
185
193
|
}
|
|
186
194
|
|
|
187
|
-
|
|
188
|
-
|
|
195
|
+
return {
|
|
196
|
+
baseName: child.attributes['baseName'],
|
|
197
|
+
path: child.attributes['path'],
|
|
198
|
+
meta: child.attributes['meta'] || {},
|
|
199
|
+
footer: child.attributes['footer'],
|
|
200
|
+
banner: child.attributes['banner'],
|
|
201
|
+
sources,
|
|
202
|
+
exports,
|
|
203
|
+
imports,
|
|
204
|
+
} as FileNode
|
|
189
205
|
}
|
|
190
206
|
|
|
191
207
|
/**
|
|
192
|
-
*
|
|
208
|
+
* Yields each {@link FileNode} as it is encountered during the tree walk,
|
|
209
|
+
* without collecting into an intermediate array. Callers can begin processing
|
|
210
|
+
* each file before the rest of the tree is traversed.
|
|
193
211
|
*/
|
|
194
|
-
function
|
|
195
|
-
const
|
|
212
|
+
export function* streamFiles(node: DOMElement): Generator<FileNode> {
|
|
213
|
+
for (const child of node.childNodes) {
|
|
214
|
+
if (!child) continue
|
|
196
215
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
continue
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (child.nodeName !== TEXT_NODE_NAME && nodeNames.has(child.nodeName)) {
|
|
204
|
-
walk(child)
|
|
205
|
-
}
|
|
216
|
+
if (child.nodeName !== TEXT_NODE_NAME && child.nodeName !== KUBB_FILE && nodeNames.has(child.nodeName)) {
|
|
217
|
+
yield* streamFiles(child)
|
|
218
|
+
}
|
|
206
219
|
|
|
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
|
-
}
|
|
220
|
+
if (child.nodeName === KUBB_FILE && child.attributes['baseName'] !== undefined && child.attributes['path'] !== undefined) {
|
|
221
|
+
yield createFileNode(child)
|
|
218
222
|
}
|
|
219
223
|
}
|
|
220
|
-
|
|
221
|
-
walk(node)
|
|
222
|
-
return imports
|
|
223
224
|
}
|
|
224
225
|
|
|
225
226
|
/**
|
|
226
227
|
* Walk the virtual DOM tree rooted at `node` and convert every `<kubb-file>` element
|
|
227
228
|
* into a {@link FileNode}, collecting its source blocks, imports, and exports.
|
|
228
229
|
*
|
|
229
|
-
* Returns the list of file nodes in document order. Nested files are supported
|
|
230
|
+
* Returns the list of file nodes in document order. Nested files are supported;
|
|
230
231
|
* the walker descends into non-file elements and recurses through them.
|
|
231
232
|
*/
|
|
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
|
|
233
|
+
export function collectFiles(node: DOMElement): FileNode[] {
|
|
234
|
+
return [...streamFiles(node)]
|
|
267
235
|
}
|