@kubb/renderer-jsx 5.0.0-alpha.33 → 5.0.0-alpha.35

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.
@@ -1,27 +1,53 @@
1
1
  import type { JSDoc, Key, KubbReactElement, KubbReactNode } from '../types.ts'
2
2
 
3
- export type TypeProps = {
3
+ type TypeProps = {
4
4
  key?: Key
5
5
  /**
6
- * Name of the type, this needs to start with a capital letter.
6
+ * Identifier of the generated type alias.
7
+ * Must start with an uppercase letter to follow TypeScript naming conventions.
8
+ *
9
+ * @example
10
+ * `name: 'Pet'`
7
11
  */
8
12
  name: string
9
13
  /**
10
- * Does this type need to be exported.
14
+ * Emit the `export` keyword before the type alias declaration.
15
+ * - `true` generates `export type Name = …`
16
+ * - `false` generates `type Name = …`
17
+ * @default false
11
18
  */
12
19
  export?: boolean
13
20
  /**
14
- * Options for JSdocs.
21
+ * JSDoc block to prepend to the type alias declaration.
22
+ * Each entry in `comments` becomes one line inside the emitted `/** … *\/` block.
15
23
  */
16
24
  JSDoc?: JSDoc
17
25
  /**
18
- * Children nodes.
26
+ * Child nodes rendered as the type expression on the right-hand side of the alias.
19
27
  */
20
28
  children?: KubbReactNode
21
29
  }
22
30
 
23
31
  /**
24
- * Generates a TypeScript type declaration.
32
+ * Generates a TypeScript type alias declaration.
33
+ *
34
+ * Throws if `name` does not start with an uppercase letter — TypeScript type aliases
35
+ * should follow PascalCase naming conventions.
36
+ *
37
+ * @example Simple exported type alias
38
+ * ```tsx
39
+ * <Type export name="PetId">
40
+ * {`string | number`}
41
+ * </Type>
42
+ * // export type PetId = string | number
43
+ * ```
44
+ *
45
+ * @example Type alias with JSDoc
46
+ * ```tsx
47
+ * <Type export name="Pet" JSDoc={{ comments: ['@description A pet in the store.'] }}>
48
+ * {`{ id: number; name: string }`}
49
+ * </Type>
50
+ * ```
25
51
  */
26
52
  export function Type({ children, ...props }: TypeProps): KubbReactElement {
27
53
  const { name, export: canExport, JSDoc } = props
@@ -0,0 +1,28 @@
1
+ import type { ElementNames } from './types.ts'
2
+
3
+ /**
4
+ * Name used for text-node entries in the virtual DOM.
5
+ */
6
+ export const TEXT_NODE_NAME = '#text' as const
7
+
8
+ /**
9
+ * Set of all element names recognized by the Kubb renderer.
10
+ * Used to distinguish Kubb-owned elements from unrecognized or text nodes during tree traversal.
11
+ */
12
+ export const nodeNames = new Set<ElementNames>([
13
+ 'kubb-export',
14
+ 'kubb-file',
15
+ 'kubb-source',
16
+ 'kubb-import',
17
+ 'kubb-function',
18
+ 'kubb-arrow-function',
19
+ 'kubb-const',
20
+ 'kubb-type',
21
+ 'kubb-jsx',
22
+ 'kubb-text',
23
+ 'kubb-root',
24
+ 'kubb-app',
25
+ 'br',
26
+ 'indent',
27
+ 'dedent',
28
+ ] as const)
@@ -1,6 +1,6 @@
1
1
  import { createContext } from '@internals/utils'
2
2
 
3
- export type KubbContextValue = {
3
+ type KubbContextValue = {
4
4
  driver: unknown
5
5
  plugin: unknown
6
6
  mode: 'single' | 'split'
@@ -1,20 +1,58 @@
1
- import type { FileNode } from '@kubb/ast/types'
1
+ import type { FileNode } from '@kubb/ast'
2
2
  import { Runtime } from './Runtime.tsx'
3
3
  import type { KubbReactElement } from './types.ts'
4
4
 
5
5
  type Options = {
6
6
  /**
7
- * Set this to true to always see the result of the render in the console(line per render)
7
+ * Print each render result to the console for debugging.
8
+ * Useful when diagnosing output differences between renders.
9
+ * @default false
8
10
  */
9
11
  debug?: boolean
10
12
  }
11
13
 
12
- export type Renderer = {
14
+ /**
15
+ * The renderer instance returned by {@link createRenderer}.
16
+ */
17
+ type Renderer = {
18
+ /**
19
+ * Render a JSX element tree and collect the resulting {@link FileNode} entries.
20
+ * Resolves once all synchronous render work (including React's flush) is done.
21
+ */
13
22
  render(Element: KubbReactElement): Promise<void>
23
+ /**
24
+ * Tear down the renderer and release all React resources.
25
+ * Pass an `Error` to signal an abnormal shutdown.
26
+ */
14
27
  unmount(error?: Error | number | null): void
28
+ /**
29
+ * The {@link FileNode} entries collected from the most recent `render` call.
30
+ */
15
31
  files: Array<FileNode>
16
32
  }
17
33
 
34
+ /**
35
+ * Create a Kubb JSX renderer.
36
+ *
37
+ * The renderer converts a React JSX element tree — built from the components in this
38
+ * package — into an array of {@link FileNode} entries representing the generated files.
39
+ *
40
+ * @example Basic usage
41
+ * ```ts
42
+ * import { createRenderer, File } from '@kubb/renderer-jsx'
43
+ *
44
+ * const renderer = createRenderer()
45
+ * await renderer.render(
46
+ * <File baseName="pet.ts" path="src/models/pet.ts">
47
+ * <File.Source name="Pet" isExportable isIndexable>
48
+ * {`export type Pet = { id: number; name: string }`}
49
+ * </File.Source>
50
+ * </File>
51
+ * )
52
+ * console.log(renderer.files) // [FileNode]
53
+ * renderer.unmount()
54
+ * ```
55
+ */
18
56
  export function createRenderer(options: Options = {}): Renderer {
19
57
  const runtime = new Runtime(options)
20
58
 
@@ -30,3 +68,26 @@ export function createRenderer(options: Options = {}): Renderer {
30
68
  },
31
69
  }
32
70
  }
71
+
72
+ /**
73
+ * A renderer factory for generators that produce JSX output.
74
+ *
75
+ * Pass this as the `renderer` property of a `defineGenerator` call so that
76
+ * core can render the JSX element tree returned by your generator methods
77
+ * without a hard dependency on `@kubb/renderer-jsx`.
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * import { jsxRenderer } from '@kubb/renderer-jsx'
82
+ * import { defineGenerator } from '@kubb/core'
83
+ *
84
+ * export const myGenerator = defineGenerator<PluginTs>({
85
+ * name: 'my-generator',
86
+ * renderer: jsxRenderer,
87
+ * schema(node, options) {
88
+ * return <File baseName="output.ts" path="src/output.ts">...</File>
89
+ * },
90
+ * })
91
+ * ```
92
+ */
93
+ export const jsxRenderer: () => Renderer = () => createRenderer()
package/src/dom.ts CHANGED
@@ -1,5 +1,10 @@
1
- import type { DOMElement, DOMNode, DOMNodeAttribute, ElementNames, TextNode } from './types.ts'
1
+ import { TEXT_NODE_NAME } from './constants.ts'
2
+ import type { DOMElement, DOMNode, DOMNodeAttribute, TextNode } from './types.ts'
2
3
 
4
+ /**
5
+ * Create a new, empty {@link DOMElement} with the given node name.
6
+ * The element has no attributes, no children, and no parent.
7
+ */
3
8
  export const createNode = (nodeName: string): DOMElement => {
4
9
  const node: DOMElement = {
5
10
  nodeName: nodeName as DOMElement['nodeName'],
@@ -11,17 +16,30 @@ export const createNode = (nodeName: string): DOMElement => {
11
16
  return node
12
17
  }
13
18
 
19
+ /**
20
+ * Append `childNode` as the last child of `node`.
21
+ *
22
+ * If `childNode` already has a parent, it is removed from that parent first
23
+ * (matching standard DOM move semantics).
24
+ * Text nodes (`nodeName === '#text'`) are silently ignored.
25
+ */
14
26
  export const appendChildNode = (node: DOMNode, childNode: DOMElement | DOMNode): void => {
15
27
  if (childNode.parentNode) {
16
28
  removeChildNode(childNode.parentNode, childNode)
17
29
  }
18
30
 
19
- if (node.nodeName !== '#text') {
31
+ if (node.nodeName !== TEXT_NODE_NAME) {
20
32
  childNode.parentNode = node
21
33
  node.childNodes.push(childNode)
22
34
  }
23
35
  }
24
36
 
37
+ /**
38
+ * Insert `newChildNode` before `beforeChildNode` in `node`'s child list.
39
+ *
40
+ * If `newChildNode` already has a parent, it is removed from that parent first.
41
+ * If `beforeChildNode` is not found, `newChildNode` is appended at the end.
42
+ */
25
43
  export const insertBeforeNode = (node: DOMElement, newChildNode: DOMNode, beforeChildNode: DOMNode): void => {
26
44
  if (newChildNode.parentNode) {
27
45
  removeChildNode(newChildNode.parentNode, newChildNode)
@@ -39,6 +57,10 @@ export const insertBeforeNode = (node: DOMElement, newChildNode: DOMNode, before
39
57
  node.childNodes.push(newChildNode)
40
58
  }
41
59
 
60
+ /**
61
+ * Remove `removeNode` from `node`'s child list and clear its `parentNode` reference.
62
+ * Does nothing if `removeNode` is not a direct child of `node`.
63
+ */
42
64
  export const removeChildNode = (node: DOMElement, removeNode: DOMNode): void => {
43
65
  removeNode.parentNode = undefined
44
66
 
@@ -48,13 +70,19 @@ export const removeChildNode = (node: DOMElement, removeNode: DOMNode): void =>
48
70
  }
49
71
  }
50
72
 
73
+ /**
74
+ * Set an attribute on `node`, storing it in the node's `attributes` map.
75
+ */
51
76
  export const setAttribute = (node: DOMElement, key: string, value: DOMNodeAttribute): void => {
52
77
  node.attributes.set(key, value)
53
78
  }
54
79
 
80
+ /**
81
+ * Create a new {@link TextNode} with the given text value.
82
+ */
55
83
  export const createTextNode = (text: string): TextNode => {
56
84
  const node: TextNode = {
57
- nodeName: '#text',
85
+ nodeName: TEXT_NODE_NAME,
58
86
  nodeValue: text,
59
87
  parentNode: undefined,
60
88
  }
@@ -64,6 +92,10 @@ export const createTextNode = (text: string): TextNode => {
64
92
  return node
65
93
  }
66
94
 
95
+ /**
96
+ * Update the `nodeValue` of an existing {@link TextNode}.
97
+ * Non-string values are coerced to strings via `String(text)`.
98
+ */
67
99
  export const setTextNodeValue = (node: TextNode, text: string): void => {
68
100
  if (typeof text !== 'string') {
69
101
  text = String(text)
@@ -71,21 +103,3 @@ export const setTextNodeValue = (node: TextNode, text: string): void => {
71
103
 
72
104
  node.nodeValue = text
73
105
  }
74
-
75
- export const nodeNames = new Set<ElementNames>([
76
- 'kubb-export',
77
- 'kubb-file',
78
- 'kubb-source',
79
- 'kubb-import',
80
- 'kubb-function',
81
- 'kubb-arrow-function',
82
- 'kubb-const',
83
- 'kubb-type',
84
- 'kubb-jsx',
85
- 'kubb-text',
86
- 'kubb-root',
87
- 'kubb-app',
88
- 'br',
89
- 'indent',
90
- 'dedent',
91
- ])
package/src/index.ts CHANGED
@@ -7,4 +7,4 @@ export { Root } from './components/Root.tsx'
7
7
  export { Type } from './components/Type.tsx'
8
8
  export { KubbContext } from './context/KubbContext.ts'
9
9
  export { OasContext } from './context/OasContext.ts'
10
- export { createRenderer } from './createRenderer.tsx'
10
+ export { createRenderer, jsxRenderer } from './createRenderer.tsx'
package/src/types.ts CHANGED
@@ -1,9 +1,17 @@
1
- import type { ArrowFunctionNode, ConstNode, ExportNode, FileNode, FunctionNode, ImportNode, SourceNode, TypeNode } from '@kubb/ast/types'
1
+ import type { ArrowFunctionNode, ConstNode, ExportNode, FileNode, FunctionNode, ImportNode, SourceNode, TypeNode } from '@kubb/ast'
2
2
  import type React from 'react'
3
3
  import type { JSX, ReactNode } from 'react'
4
4
 
5
+ /**
6
+ * React reconciliation key type.
7
+ * Used to uniquely identify elements in lists and conditional renders.
8
+ */
5
9
  export type Key = string | number | bigint
6
10
 
11
+ /**
12
+ * All custom element names recognized by the Kubb JSX renderer.
13
+ * Each name maps to a corresponding AST node type emitted during code generation.
14
+ */
7
15
  export type ElementNames =
8
16
  | 'br'
9
17
  | 'div'
@@ -27,14 +35,28 @@ type Node = {
27
35
  internal_static?: boolean
28
36
  }
29
37
 
30
- export type DOMNodeAttribute = boolean | string | number | Record<string, unknown>
38
+ /**
39
+ * Allowed attribute value types stored on a {@link DOMElement}.
40
+ * Corresponds to the range of prop values JSX components may pass to intrinsic elements.
41
+ */
42
+ export type DOMNodeAttribute = boolean | string | number | Record<string, unknown> | Array<unknown>
31
43
 
32
44
  type TextName = '#text'
45
+
46
+ /**
47
+ * A leaf DOM node that holds a raw text string.
48
+ * Created by the renderer whenever a JSX expression produces a plain string child.
49
+ */
33
50
  export type TextNode = {
34
51
  nodeName: TextName
35
52
  nodeValue: string
36
53
  } & Node
37
54
 
55
+ /**
56
+ * Discriminated union of all virtual DOM nodes.
57
+ * Resolves to {@link TextNode} when `nodeName` is `'#text'`, or {@link DOMElement} for
58
+ * any named Kubb element.
59
+ */
38
60
  export type DOMNode<T = { nodeName: NodeNames }> = T extends {
39
61
  nodeName: infer U
40
62
  }
@@ -45,9 +67,19 @@ export type DOMNode<T = { nodeName: NodeNames }> = T extends {
45
67
 
46
68
  type OutputTransformer = (s: string, index: number) => string
47
69
 
70
+ /**
71
+ * A named element node in the Kubb virtual DOM tree.
72
+ * Holds attributes, child nodes, and optional lifecycle callbacks used by the renderer.
73
+ */
48
74
  export type DOMElement = {
49
75
  nodeName: ElementNames
76
+ /**
77
+ * Key/value attributes passed as JSX props to this element.
78
+ */
50
79
  attributes: Map<string, DOMNodeAttribute>
80
+ /**
81
+ * Ordered list of child nodes attached to this element.
82
+ */
51
83
  childNodes: DOMNode[]
52
84
  internal_transform?: OutputTransformer
53
85
 
@@ -61,17 +93,38 @@ export type DOMElement = {
61
93
 
62
94
  type NodeNames = ElementNames | TextName
63
95
 
96
+ /**
97
+ * React node type used throughout Kubb JSX components.
98
+ * Alias for React's `ReactNode`.
99
+ */
64
100
  export type KubbReactNode = ReactNode
101
+
102
+ /**
103
+ * React element type returned by Kubb JSX components.
104
+ * Alias for `JSX.Element`.
105
+ */
65
106
  export type KubbReactElement = JSX.Element
66
107
 
108
+ /**
109
+ * Props for the `<kubb-jsx>` intrinsic element.
110
+ * Embeds a raw JSX string verbatim in the generated source.
111
+ */
67
112
  export type KubbJsxProps = {
68
113
  children?: string
69
114
  }
70
115
 
116
+ /**
117
+ * Props for the `<kubb-text>` intrinsic element.
118
+ * Wraps arbitrary React children as plain text in the output.
119
+ */
71
120
  export type KubbTextProps = {
72
121
  children?: KubbReactNode
73
122
  }
74
123
 
124
+ /**
125
+ * Props for the `<kubb-file>` intrinsic element.
126
+ * Represents a generated file entry collected by the renderer.
127
+ */
75
128
  export type KubbFileProps = {
76
129
  id?: string
77
130
  children?: KubbReactNode
@@ -80,34 +133,83 @@ export type KubbFileProps = {
80
133
  override?: boolean
81
134
  meta?: FileNode['meta']
82
135
  }
136
+
137
+ /**
138
+ * Props for the `<kubb-source>` intrinsic element.
139
+ * Marks a block of source text associated with the enclosing file.
140
+ */
83
141
  export type KubbSourceProps = Omit<SourceNode, 'kind'> & {
84
142
  children?: KubbReactNode
85
143
  }
86
144
 
145
+ /**
146
+ * Props for the `<kubb-import>` intrinsic element.
147
+ * Declares an import entry for the enclosing file.
148
+ */
87
149
  export type KubbImportProps = Omit<ImportNode, 'kind'> & {}
88
150
 
151
+ /**
152
+ * Props for the `<kubb-export>` intrinsic element.
153
+ * Declares an export entry for the enclosing file.
154
+ */
89
155
  export type KubbExportProps = Omit<ExportNode, 'kind'> & {}
90
156
 
157
+ /**
158
+ * Props for the `<kubb-function>` intrinsic element.
159
+ * Describes a function declaration node in the generated output.
160
+ */
91
161
  export type KubbFunctionProps = Omit<FunctionNode, 'kind'> & {
92
162
  children?: KubbReactNode
93
163
  }
94
164
 
165
+ /**
166
+ * Props for the `<kubb-arrow-function>` intrinsic element.
167
+ * Describes an arrow function declaration node in the generated output.
168
+ */
95
169
  export type KubbArrowFunctionProps = Omit<ArrowFunctionNode, 'kind'> & {
96
170
  children?: KubbReactNode
97
171
  }
98
172
 
173
+ /**
174
+ * Props for the `<kubb-const>` intrinsic element.
175
+ * Describes a constant declaration node in the generated output.
176
+ */
99
177
  export type KubbConstProps = Omit<ConstNode, 'kind'> & {
100
178
  children?: KubbReactNode
101
179
  }
102
180
 
181
+ /**
182
+ * Props for the `<kubb-type>` intrinsic element.
183
+ * Describes a TypeScript type alias declaration node in the generated output.
184
+ */
103
185
  export type KubbTypeProps = Omit<TypeNode, 'kind'> & {
104
186
  children?: KubbReactNode
105
187
  }
106
188
 
189
+ /**
190
+ * Props forwarded to the HTML `<br>` element within intrinsic element declarations.
191
+ */
107
192
  export type LineBreakProps = React.DetailedHTMLProps<React.HTMLAttributes<HTMLBRElement>, HTMLBRElement>
108
193
 
194
+ /**
195
+ * JSDoc block to attach to a generated declaration.
196
+ *
197
+ * Each string in `comments` becomes one line inside the emitted `/** … *\/` block.
198
+ *
199
+ * @example
200
+ * ```ts
201
+ * { comments: ['@description A pet object.', '@deprecated Use PetV2 instead.'] }
202
+ * // Emits:
203
+ * // /**
204
+ * // * @description A pet object.
205
+ * // * @deprecated Use PetV2 instead.
206
+ * // *\/
207
+ * ```
208
+ */
109
209
  export type JSDoc = {
110
- comments: string[]
210
+ /**
211
+ * Lines to emit inside the JSDoc block, in source order.
212
+ * Use standard JSDoc tags such as `@description`, `@deprecated`, `@see`, etc.
213
+ */
214
+ comments: Array<string>
111
215
  }
112
-
113
- export type { Context } from '@internals/utils'