@kubb/renderer-jsx 5.0.0-beta.6 → 5.0.0-beta.60
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/LICENSE +17 -10
- package/README.md +134 -0
- package/dist/chunk-C0LytTxp.js +8 -0
- package/dist/index.cjs +386 -17922
- package/dist/index.d.ts +232 -147
- package/dist/index.js +370 -17903
- package/dist/jsx-dev-runtime.cjs +3 -10
- package/dist/jsx-dev-runtime.d.ts +4 -8
- package/dist/jsx-dev-runtime.js +1 -9
- package/dist/jsx-runtime-3ncySO6L.cjs +89 -0
- package/dist/jsx-runtime.cjs +5 -14
- package/dist/jsx-runtime.d.ts +60 -10
- package/dist/jsx-runtime.js +24 -7
- package/dist/types-UI1cZVah.d.ts +115 -0
- package/dist/types.d.ts +2 -2
- package/package.json +6 -29
- package/src/SyncRuntime.tsx +298 -0
- package/src/components/Callout.tsx +59 -0
- package/src/components/Const.tsx +4 -4
- package/src/components/File.tsx +7 -5
- package/src/components/Frontmatter.tsx +38 -0
- package/src/components/Function.tsx +8 -8
- package/src/components/Heading.tsx +34 -0
- package/src/components/Jsx.tsx +1 -1
- package/src/components/List.tsx +40 -0
- package/src/components/Paragraph.tsx +28 -0
- package/src/components/Type.tsx +3 -3
- package/src/constants.ts +9 -28
- package/src/createRenderer.tsx +38 -75
- package/src/globals.ts +14 -6
- package/src/index.ts +6 -3
- package/src/jsx-dev-runtime.ts +1 -3
- package/src/jsx-namespace.d.ts +21 -13
- package/src/jsx-runtime.ts +22 -6
- package/src/types.ts +16 -100
- package/dist/chunk-Bb7HlUDG.js +0 -28
- package/dist/jsx-namespace-CNp0arTN.d.ts +0 -39
- package/dist/jsx-runtime-Cvu_ZYgL.js +0 -1448
- package/dist/jsx-runtime-DdmO3p0U.cjs +0 -1503
- package/dist/types-nAFMiWFw.d.ts +0 -168
- package/src/Renderer.ts +0 -184
- package/src/Runtime.tsx +0 -170
- package/src/components/Root.tsx +0 -70
- package/src/dom.ts +0 -105
- package/src/utils.ts +0 -267
package/dist/types-nAFMiWFw.d.ts
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { n as __name } from "./chunk-Bb7HlUDG.js";
|
|
2
|
-
import { ArrowFunctionNode, ConstNode, ExportNode, FileNode, FunctionNode, ImportNode, SourceNode, TypeNode } from "@kubb/ast";
|
|
3
|
-
import React, { JSX, ReactNode } from "react";
|
|
4
|
-
|
|
5
|
-
//#region src/types.d.ts
|
|
6
|
-
/**
|
|
7
|
-
* Unique identifier for a React element in lists or conditional renders.
|
|
8
|
-
*/
|
|
9
|
-
type Key = string | number | bigint;
|
|
10
|
-
/**
|
|
11
|
-
* Custom element names recognized by the Kubb JSX renderer.
|
|
12
|
-
* Each name maps to a corresponding AST node type in the generated code.
|
|
13
|
-
*/
|
|
14
|
-
type ElementNames = 'br' | 'div' | 'indent' | 'dedent' | 'kubb-jsx' | 'kubb-text' | 'kubb-file' | 'kubb-source' | 'kubb-import' | 'kubb-export' | 'kubb-function' | 'kubb-arrow-function' | 'kubb-const' | 'kubb-type' | 'kubb-root' | 'kubb-app';
|
|
15
|
-
type Node = {
|
|
16
|
-
parentNode: DOMElement | undefined;
|
|
17
|
-
internal_static?: boolean;
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* Allowed attribute value types for DOM elements.
|
|
21
|
-
*/
|
|
22
|
-
type DOMNodeAttribute = boolean | string | number | Record<string, unknown> | Array<unknown>;
|
|
23
|
-
type TextName = '#text';
|
|
24
|
-
/**
|
|
25
|
-
* Leaf DOM node containing raw text.
|
|
26
|
-
*/
|
|
27
|
-
type TextNode = {
|
|
28
|
-
nodeName: TextName;
|
|
29
|
-
nodeValue: string;
|
|
30
|
-
} & Node;
|
|
31
|
-
/**
|
|
32
|
-
* Virtual DOM node — either a text node or a named element.
|
|
33
|
-
*/
|
|
34
|
-
type DOMNode<T = {
|
|
35
|
-
nodeName: NodeNames;
|
|
36
|
-
}> = T extends {
|
|
37
|
-
nodeName: infer U;
|
|
38
|
-
} ? U extends '#text' ? TextNode : DOMElement : never;
|
|
39
|
-
type OutputTransformer = (s: string, index: number) => string;
|
|
40
|
-
/**
|
|
41
|
-
* Named element in the Kubb virtual DOM tree.
|
|
42
|
-
* Stores attributes, child nodes, and lifecycle callbacks for rendering.
|
|
43
|
-
*/
|
|
44
|
-
type DOMElement = {
|
|
45
|
-
nodeName: ElementNames;
|
|
46
|
-
/**
|
|
47
|
-
* Key/value attributes passed as JSX props to this element.
|
|
48
|
-
*/
|
|
49
|
-
attributes: Map<string, DOMNodeAttribute>;
|
|
50
|
-
/**
|
|
51
|
-
* Ordered list of child nodes attached to this element.
|
|
52
|
-
*/
|
|
53
|
-
childNodes: DOMNode[];
|
|
54
|
-
internal_transform?: OutputTransformer;
|
|
55
|
-
isStaticDirty?: boolean;
|
|
56
|
-
staticNode?: DOMElement;
|
|
57
|
-
onComputeLayout?: () => void;
|
|
58
|
-
onRender?: () => void;
|
|
59
|
-
onImmediateRender?: () => void;
|
|
60
|
-
} & Node;
|
|
61
|
-
type NodeNames = ElementNames | TextName;
|
|
62
|
-
/**
|
|
63
|
-
* React node type for Kubb JSX components.
|
|
64
|
-
*/
|
|
65
|
-
type KubbReactNode = ReactNode;
|
|
66
|
-
/**
|
|
67
|
-
* React element type returned by Kubb JSX components.
|
|
68
|
-
*/
|
|
69
|
-
type KubbReactElement = JSX.Element;
|
|
70
|
-
/**
|
|
71
|
-
* Props for the `<kubb-jsx>` element.
|
|
72
|
-
* Embeds a raw JSX string verbatim in generated output.
|
|
73
|
-
*/
|
|
74
|
-
type KubbJsxProps = {
|
|
75
|
-
children?: string;
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Props for the `<kubb-text>` element.
|
|
79
|
-
* Wraps React children as plain text in the output.
|
|
80
|
-
*/
|
|
81
|
-
type KubbTextProps = {
|
|
82
|
-
children?: KubbReactNode;
|
|
83
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
* Props for the `<kubb-file>` element.
|
|
86
|
-
* Represents a generated file.
|
|
87
|
-
*/
|
|
88
|
-
type KubbFileProps = {
|
|
89
|
-
id?: string;
|
|
90
|
-
children?: KubbReactNode;
|
|
91
|
-
baseName: string;
|
|
92
|
-
path: string;
|
|
93
|
-
override?: boolean;
|
|
94
|
-
meta?: FileNode['meta'];
|
|
95
|
-
};
|
|
96
|
-
/**
|
|
97
|
-
* Props for the `<kubb-source>` element.
|
|
98
|
-
* Marks a block of source text associated with a file.
|
|
99
|
-
*/
|
|
100
|
-
type KubbSourceProps = Omit<SourceNode, 'kind'> & {
|
|
101
|
-
children?: KubbReactNode;
|
|
102
|
-
};
|
|
103
|
-
/**
|
|
104
|
-
* Props for the `<kubb-import>` element.
|
|
105
|
-
* Declares an import statement in the generated file.
|
|
106
|
-
*/
|
|
107
|
-
type KubbImportProps = Omit<ImportNode, 'kind'> & {};
|
|
108
|
-
/**
|
|
109
|
-
* Props for the `<kubb-export>` element.
|
|
110
|
-
* Declares an export statement in the generated file.
|
|
111
|
-
*/
|
|
112
|
-
type KubbExportProps = Omit<ExportNode, 'kind'> & {};
|
|
113
|
-
/**
|
|
114
|
-
* Props for the `<kubb-function>` element.
|
|
115
|
-
* Generates a function declaration.
|
|
116
|
-
*/
|
|
117
|
-
type KubbFunctionProps = Omit<FunctionNode, 'kind'> & {
|
|
118
|
-
children?: KubbReactNode;
|
|
119
|
-
};
|
|
120
|
-
/**
|
|
121
|
-
* Props for the `<kubb-arrow-function>` element.
|
|
122
|
-
* Generates an arrow function declaration.
|
|
123
|
-
*/
|
|
124
|
-
type KubbArrowFunctionProps = Omit<ArrowFunctionNode, 'kind'> & {
|
|
125
|
-
children?: KubbReactNode;
|
|
126
|
-
};
|
|
127
|
-
/**
|
|
128
|
-
* Props for the `<kubb-const>` element.
|
|
129
|
-
* Generates a constant declaration.
|
|
130
|
-
*/
|
|
131
|
-
type KubbConstProps = Omit<ConstNode, 'kind'> & {
|
|
132
|
-
children?: KubbReactNode;
|
|
133
|
-
};
|
|
134
|
-
/**
|
|
135
|
-
* Props for the `<kubb-type>` element.
|
|
136
|
-
* Generates a TypeScript type alias declaration.
|
|
137
|
-
*/
|
|
138
|
-
type KubbTypeProps = Omit<TypeNode, 'kind'> & {
|
|
139
|
-
children?: KubbReactNode;
|
|
140
|
-
};
|
|
141
|
-
/**
|
|
142
|
-
* Props for the HTML `<br>` element.
|
|
143
|
-
*/
|
|
144
|
-
type LineBreakProps = React.DetailedHTMLProps<React.HTMLAttributes<HTMLBRElement>, HTMLBRElement>;
|
|
145
|
-
/**
|
|
146
|
-
* JSDoc comment block to attach to a generated declaration.
|
|
147
|
-
* Each string in `comments` becomes one line inside the `/** … *\/` block.
|
|
148
|
-
*
|
|
149
|
-
* @example
|
|
150
|
-
* ```ts
|
|
151
|
-
* { comments: ['@description A pet object.', '@deprecated Use PetV2 instead.'] }
|
|
152
|
-
* // Emits:
|
|
153
|
-
* // /**
|
|
154
|
-
* // * @description A pet object.
|
|
155
|
-
* // * @deprecated Use PetV2 instead.
|
|
156
|
-
* // *\/
|
|
157
|
-
* ```
|
|
158
|
-
*/
|
|
159
|
-
type JSDoc = {
|
|
160
|
-
/**
|
|
161
|
-
* Lines to emit inside the JSDoc block, in source order.
|
|
162
|
-
* Use standard JSDoc tags such as `@description`, `@deprecated`, `@see`, etc.
|
|
163
|
-
*/
|
|
164
|
-
comments: Array<string>;
|
|
165
|
-
};
|
|
166
|
-
//#endregion
|
|
167
|
-
export { KubbTextProps as _, JSDoc as a, TextNode as b, KubbConstProps as c, KubbFunctionProps as d, KubbImportProps as f, KubbSourceProps as g, KubbReactNode as h, ElementNames as i, KubbExportProps as l, KubbReactElement as m, DOMNode as n, Key as o, KubbJsxProps as p, DOMNodeAttribute as r, KubbArrowFunctionProps as s, DOMElement as t, KubbFileProps as u, KubbTypeProps as v, LineBreakProps as y };
|
|
168
|
-
//# sourceMappingURL=types-nAFMiWFw.d.ts.map
|
package/src/Renderer.ts
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
import { createContext } from 'react'
|
|
2
|
-
import Reconciler, { type ReactContext } from 'react-reconciler'
|
|
3
|
-
import { DefaultEventPriority, NoEventPriority } from 'react-reconciler/constants.js'
|
|
4
|
-
import { appendChildNode, createNode, createTextNode, insertBeforeNode, removeChildNode, setAttribute, setTextNodeValue } from './dom.ts'
|
|
5
|
-
import type { KubbReactNode } from './types'
|
|
6
|
-
import type { DOMElement, DOMNodeAttribute, ElementNames, TextNode } from './types.ts'
|
|
7
|
-
|
|
8
|
-
declare module 'react-reconciler' {
|
|
9
|
-
// @ts-expect-error custom override
|
|
10
|
-
interface Reconciler {
|
|
11
|
-
updateContainerSync(element: KubbReactNode, container: unknown, parentComponent: any, callback?: null | (() => void)): void
|
|
12
|
-
flushSyncWork(): void
|
|
13
|
-
createContainer(
|
|
14
|
-
containerInfo: unknown,
|
|
15
|
-
tag: Reconciler.RootTag,
|
|
16
|
-
hydrationCallbacks: null | Reconciler.SuspenseHydrationCallbacks<any>,
|
|
17
|
-
isStrictMode: boolean,
|
|
18
|
-
concurrentUpdatesByDefaultOverride: null | boolean,
|
|
19
|
-
identifierPrefix: string,
|
|
20
|
-
onUncaughtError: (error: Error) => void,
|
|
21
|
-
onCaughtError: (error: Error) => void,
|
|
22
|
-
onRecoverableError: (error: Error) => void,
|
|
23
|
-
transitionCallbacks: null | Reconciler.TransitionTracingCallbacks,
|
|
24
|
-
): Reconciler.OpaqueRoot
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
type Props = Record<string, unknown>
|
|
29
|
-
|
|
30
|
-
type HostContext = {
|
|
31
|
-
type: ElementNames
|
|
32
|
-
isFile: boolean
|
|
33
|
-
isSource: boolean
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let currentUpdatePriority = NoEventPriority
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @link https://www.npmjs.com/package/react-devtools-inline
|
|
40
|
-
* @link https://github.com/nitin42/Making-a-custom-React-renderer/blob/master/part-one.md
|
|
41
|
-
* @link https://github.com/facebook/react/tree/main/packages/react-reconciler#practical-examples
|
|
42
|
-
* @link https://github.com/vadimdemedes/ink
|
|
43
|
-
* @link https://github.com/pixijs/pixi-react/tree/main/packages
|
|
44
|
-
* @link https://github.com/diegomura/react-pdf/blob/master/packages/reconciler/src/reconciler-31.ts
|
|
45
|
-
*/
|
|
46
|
-
export const Renderer = Reconciler({
|
|
47
|
-
getRootHostContext: () => ({
|
|
48
|
-
type: 'kubb-root',
|
|
49
|
-
isFile: false,
|
|
50
|
-
isSource: false,
|
|
51
|
-
}),
|
|
52
|
-
prepareForCommit: () => {
|
|
53
|
-
return null
|
|
54
|
-
},
|
|
55
|
-
preparePortalMount: () => null,
|
|
56
|
-
clearContainer: () => false,
|
|
57
|
-
resetAfterCommit(rootNode: DOMElement) {
|
|
58
|
-
if (typeof rootNode.onRender === 'function') {
|
|
59
|
-
rootNode.onRender()
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
getChildHostContext(parentHostContext: HostContext, type: ElementNames) {
|
|
63
|
-
const isInsideText = type === 'kubb-text'
|
|
64
|
-
const isFile = type === 'kubb-file' || parentHostContext.isFile
|
|
65
|
-
const isSource = type === 'kubb-source' || parentHostContext.isSource
|
|
66
|
-
|
|
67
|
-
return { isInsideText, isFile, isSource, type }
|
|
68
|
-
},
|
|
69
|
-
shouldSetTextContent: () => false,
|
|
70
|
-
createInstance(originalType: ElementNames, newProps: Props, _root: DOMElement) {
|
|
71
|
-
const node = createNode(originalType)
|
|
72
|
-
|
|
73
|
-
for (const [key, value] of Object.entries(newProps)) {
|
|
74
|
-
if (key === 'children') {
|
|
75
|
-
continue
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Skip undefined values to match React's behavior
|
|
79
|
-
if (value !== undefined) {
|
|
80
|
-
setAttribute(node, key, value as DOMNodeAttribute)
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return node
|
|
85
|
-
},
|
|
86
|
-
createTextInstance(text: string, _root: DOMElement, hostContext: HostContext) {
|
|
87
|
-
if (hostContext.isFile && !hostContext.isSource) {
|
|
88
|
-
throw new Error(`[react] '${text}' should be part of <File.Source> component when using the <File/> component`)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return createTextNode(text)
|
|
92
|
-
},
|
|
93
|
-
resetTextContent() {},
|
|
94
|
-
hideTextInstance(node: TextNode) {
|
|
95
|
-
setTextNodeValue(node, '')
|
|
96
|
-
},
|
|
97
|
-
unhideTextInstance(node: TextNode, text: string) {
|
|
98
|
-
setTextNodeValue(node, text)
|
|
99
|
-
},
|
|
100
|
-
getPublicInstance: (instance) => instance,
|
|
101
|
-
appendInitialChild: appendChildNode,
|
|
102
|
-
appendChild: appendChildNode,
|
|
103
|
-
insertBefore: insertBeforeNode,
|
|
104
|
-
finalizeInitialChildren(_node, _type, _props, _rootNode) {
|
|
105
|
-
return false
|
|
106
|
-
},
|
|
107
|
-
supportsMutation: true,
|
|
108
|
-
isPrimaryRenderer: true,
|
|
109
|
-
supportsPersistence: false,
|
|
110
|
-
supportsHydration: false,
|
|
111
|
-
scheduleTimeout: setTimeout,
|
|
112
|
-
cancelTimeout: clearTimeout,
|
|
113
|
-
noTimeout: -1,
|
|
114
|
-
beforeActiveInstanceBlur() {},
|
|
115
|
-
afterActiveInstanceBlur() {},
|
|
116
|
-
detachDeletedInstance() {},
|
|
117
|
-
getInstanceFromNode: () => null,
|
|
118
|
-
prepareScopeUpdate() {},
|
|
119
|
-
getInstanceFromScope: () => null,
|
|
120
|
-
appendChildToContainer: appendChildNode,
|
|
121
|
-
insertInContainerBefore: insertBeforeNode,
|
|
122
|
-
removeChildFromContainer(node: DOMElement, removeNode: TextNode) {
|
|
123
|
-
removeChildNode(node, removeNode)
|
|
124
|
-
},
|
|
125
|
-
commitMount() {},
|
|
126
|
-
commitUpdate(node: DOMElement, _payload, _type, _oldProps: Props, newProps: Props) {
|
|
127
|
-
const { props } = newProps
|
|
128
|
-
|
|
129
|
-
if (props) {
|
|
130
|
-
for (const [key, value] of Object.entries(props)) {
|
|
131
|
-
// Skip undefined values to match React's behavior
|
|
132
|
-
if (value !== undefined) {
|
|
133
|
-
setAttribute(node, key, value as DOMNodeAttribute)
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
commitTextUpdate(node: TextNode, _oldText, newText) {
|
|
139
|
-
setTextNodeValue(node, newText)
|
|
140
|
-
},
|
|
141
|
-
removeChild(node: DOMElement, removeNode: TextNode) {
|
|
142
|
-
removeChildNode(node, removeNode)
|
|
143
|
-
},
|
|
144
|
-
setCurrentUpdatePriority: (newPriority: number) => {
|
|
145
|
-
currentUpdatePriority = newPriority
|
|
146
|
-
},
|
|
147
|
-
getCurrentUpdatePriority: () => currentUpdatePriority,
|
|
148
|
-
resolveUpdatePriority() {
|
|
149
|
-
if (currentUpdatePriority !== NoEventPriority) {
|
|
150
|
-
return currentUpdatePriority
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return DefaultEventPriority
|
|
154
|
-
},
|
|
155
|
-
maySuspendCommit() {
|
|
156
|
-
return false
|
|
157
|
-
},
|
|
158
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
159
|
-
NotPendingTransition: undefined,
|
|
160
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
161
|
-
HostTransitionContext: createContext(null) as unknown as ReactContext<unknown>,
|
|
162
|
-
resetFormInstance() {},
|
|
163
|
-
requestPostPaintCallback() {},
|
|
164
|
-
shouldAttemptEagerTransition() {
|
|
165
|
-
return false
|
|
166
|
-
},
|
|
167
|
-
trackSchedulerEvent() {},
|
|
168
|
-
resolveEventType() {
|
|
169
|
-
return null
|
|
170
|
-
},
|
|
171
|
-
resolveEventTimeStamp() {
|
|
172
|
-
return -1.1
|
|
173
|
-
},
|
|
174
|
-
preloadInstance() {
|
|
175
|
-
return true
|
|
176
|
-
},
|
|
177
|
-
startSuspendingCommit() {},
|
|
178
|
-
suspendInstance() {},
|
|
179
|
-
waitForCommitToBeReady() {
|
|
180
|
-
return null
|
|
181
|
-
},
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
export type { FiberRoot } from 'react-reconciler'
|
package/src/Runtime.tsx
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import { onProcessExit } from '@internals/utils'
|
|
2
|
-
import type { FileNode } from '@kubb/ast'
|
|
3
|
-
import { ConcurrentRoot } from 'react-reconciler/constants.js'
|
|
4
|
-
import { Root } from './components/Root.tsx'
|
|
5
|
-
import { createNode } from './dom.ts'
|
|
6
|
-
import type { FiberRoot } from './Renderer.ts'
|
|
7
|
-
import { Renderer } from './Renderer.ts'
|
|
8
|
-
import type { DOMElement, KubbReactElement } from './types.ts'
|
|
9
|
-
import { processFiles } from './utils.ts'
|
|
10
|
-
|
|
11
|
-
type Options = {
|
|
12
|
-
/**
|
|
13
|
-
* Set this to true to always see the result of the render in the console(line per render)
|
|
14
|
-
*/
|
|
15
|
-
debug?: boolean
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export class Runtime {
|
|
19
|
-
readonly #options: Options
|
|
20
|
-
#isUnmounted: boolean
|
|
21
|
-
#renderError?: Error
|
|
22
|
-
|
|
23
|
-
exitPromise?: Promise<void>
|
|
24
|
-
|
|
25
|
-
nodes: FileNode[] = []
|
|
26
|
-
readonly #container: FiberRoot
|
|
27
|
-
readonly #rootNode: DOMElement
|
|
28
|
-
|
|
29
|
-
constructor(options: Options) {
|
|
30
|
-
this.#options = options
|
|
31
|
-
this.#rootNode = createNode('kubb-root')
|
|
32
|
-
this.#rootNode.onRender = this.onRender
|
|
33
|
-
this.#rootNode.onImmediateRender = this.onRender
|
|
34
|
-
this.#isUnmounted = false
|
|
35
|
-
this.unmount.bind(this)
|
|
36
|
-
|
|
37
|
-
// Intercept noisy React errors
|
|
38
|
-
console.error = (data: string | Error) => {
|
|
39
|
-
const message = typeof data === 'string' ? data : data?.message
|
|
40
|
-
if (
|
|
41
|
-
message?.match(/Encountered two children with the same key/gi) ||
|
|
42
|
-
message?.match(/React will try to recreat/gi) ||
|
|
43
|
-
message?.match(/Each child in a list should have a unique/gi) ||
|
|
44
|
-
message?.match(/The above error occurred in the <KubbErrorBoundary/gi) ||
|
|
45
|
-
message?.match(/A React Element from an older version of React was render/gi)
|
|
46
|
-
) {
|
|
47
|
-
return
|
|
48
|
-
}
|
|
49
|
-
console.log(data)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const logRecoverableError = typeof reportError === 'function' ? reportError : console.error
|
|
53
|
-
|
|
54
|
-
const rootTag = ConcurrentRoot
|
|
55
|
-
this.#container = Renderer.createContainer(
|
|
56
|
-
this.#rootNode,
|
|
57
|
-
rootTag,
|
|
58
|
-
null,
|
|
59
|
-
false,
|
|
60
|
-
false,
|
|
61
|
-
'id',
|
|
62
|
-
logRecoverableError,
|
|
63
|
-
logRecoverableError,
|
|
64
|
-
logRecoverableError,
|
|
65
|
-
null,
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
// Unmount when process exits
|
|
69
|
-
this.unsubscribeExit = onProcessExit((code) => {
|
|
70
|
-
this.unmount(code)
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
#renderPromise: Promise<void> = Promise.resolve()
|
|
75
|
-
resolveExitPromise: () => void = () => {}
|
|
76
|
-
rejectExitPromise: (reason?: Error) => void = () => {}
|
|
77
|
-
unsubscribeExit: () => void = () => {}
|
|
78
|
-
|
|
79
|
-
onRender: () => Promise<void> = () => {
|
|
80
|
-
const previous = this.#renderPromise
|
|
81
|
-
|
|
82
|
-
const task = previous
|
|
83
|
-
.catch(() => {})
|
|
84
|
-
.then(() => {
|
|
85
|
-
if (this.#isUnmounted) {
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const files = processFiles(this.#rootNode)
|
|
90
|
-
|
|
91
|
-
this.nodes.push(...files)
|
|
92
|
-
|
|
93
|
-
if (!this.#options?.debug) {
|
|
94
|
-
return
|
|
95
|
-
}
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
this.#renderPromise = task.catch((error) => {
|
|
99
|
-
this.onError(error as Error)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
return this.#renderPromise
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
onError(error: Error): void {
|
|
106
|
-
// Store the error to be thrown after render completes
|
|
107
|
-
this.#renderError = error
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
onExit(error?: Error): void {
|
|
111
|
-
setTimeout(() => {
|
|
112
|
-
this.unmount(error)
|
|
113
|
-
}, 0)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
async render(node: KubbReactElement): Promise<void> {
|
|
117
|
-
const props = {
|
|
118
|
-
onExit: this.onExit.bind(this),
|
|
119
|
-
onError: this.onError.bind(this),
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const element = <Root {...props}>{node}</Root>
|
|
123
|
-
|
|
124
|
-
Renderer.updateContainerSync(element, this.#container, null, null)
|
|
125
|
-
Renderer.flushSyncWork()
|
|
126
|
-
await this.#renderPromise
|
|
127
|
-
|
|
128
|
-
// Throw any errors that occurred during rendering
|
|
129
|
-
if (this.#renderError) {
|
|
130
|
-
const error = this.#renderError
|
|
131
|
-
this.#renderError = undefined
|
|
132
|
-
throw error
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
unmount(error?: Error | number | null): void {
|
|
137
|
-
if (this.#isUnmounted) {
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (this.#options?.debug) {
|
|
142
|
-
console.log('Unmount', error)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
this.onRender()
|
|
146
|
-
this.unsubscribeExit()
|
|
147
|
-
|
|
148
|
-
this.#isUnmounted = true
|
|
149
|
-
|
|
150
|
-
Renderer.updateContainerSync(null, this.#container, null, null)
|
|
151
|
-
|
|
152
|
-
if (error instanceof Error) {
|
|
153
|
-
this.rejectExitPromise(error)
|
|
154
|
-
return
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
this.resolveExitPromise()
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
async waitUntilExit(): Promise<void> {
|
|
161
|
-
if (!this.exitPromise) {
|
|
162
|
-
this.exitPromise = new Promise((resolve, reject) => {
|
|
163
|
-
this.resolveExitPromise = resolve
|
|
164
|
-
this.rejectExitPromise = reject
|
|
165
|
-
})
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return this.exitPromise
|
|
169
|
-
}
|
|
170
|
-
}
|
package/src/components/Root.tsx
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { Component } from 'react'
|
|
2
|
-
import type { KubbReactElement, KubbReactNode } from '../types.ts'
|
|
3
|
-
|
|
4
|
-
type ErrorBoundaryProps = {
|
|
5
|
-
onError: (error: Error) => void
|
|
6
|
-
children?: KubbReactNode
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
class ErrorBoundary extends Component<{
|
|
10
|
-
onError: ErrorBoundaryProps['onError']
|
|
11
|
-
children?: KubbReactNode
|
|
12
|
-
}> {
|
|
13
|
-
state = { hasError: false }
|
|
14
|
-
|
|
15
|
-
static displayName = 'ErrorBoundary'
|
|
16
|
-
static getDerivedStateFromError(_error: Error) {
|
|
17
|
-
return { hasError: true }
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
componentDidCatch(error: Error) {
|
|
21
|
-
if (error) {
|
|
22
|
-
this.props.onError(error)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
render() {
|
|
27
|
-
if (this.state.hasError) {
|
|
28
|
-
return null
|
|
29
|
-
}
|
|
30
|
-
return this.props.children
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
type RootProps = {
|
|
35
|
-
/**
|
|
36
|
-
* Callback invoked to unmount the entire renderer tree.
|
|
37
|
-
* Called with an `Error` when the exit is caused by a render error,
|
|
38
|
-
* or with `undefined` for a clean shutdown.
|
|
39
|
-
*/
|
|
40
|
-
onExit: (error?: Error) => void
|
|
41
|
-
/**
|
|
42
|
-
* Callback invoked whenever a render error is caught by the error boundary.
|
|
43
|
-
* Use this to propagate errors up to the caller of {@link createRenderer}.
|
|
44
|
-
*/
|
|
45
|
-
onError: (error: Error) => void
|
|
46
|
-
/**
|
|
47
|
-
* Child nodes rendered inside the error boundary.
|
|
48
|
-
*/
|
|
49
|
-
children?: KubbReactNode
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Root component for the Kubb renderer tree.
|
|
54
|
-
*
|
|
55
|
-
* Wraps all children in an `ErrorBoundary` so that render errors are caught
|
|
56
|
-
* and forwarded to `onError` rather than crashing the process.
|
|
57
|
-
*/
|
|
58
|
-
export function Root({ onError, children }: RootProps): KubbReactElement {
|
|
59
|
-
return (
|
|
60
|
-
<ErrorBoundary
|
|
61
|
-
onError={(error) => {
|
|
62
|
-
onError(error)
|
|
63
|
-
}}
|
|
64
|
-
>
|
|
65
|
-
{children}
|
|
66
|
-
</ErrorBoundary>
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
Root.displayName = 'Root'
|
package/src/dom.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { TEXT_NODE_NAME } from './constants.ts'
|
|
2
|
-
import type { DOMElement, DOMNode, DOMNodeAttribute, TextNode } from './types.ts'
|
|
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
|
-
*/
|
|
8
|
-
export const createNode = (nodeName: string): DOMElement => {
|
|
9
|
-
const node: DOMElement = {
|
|
10
|
-
nodeName: nodeName as DOMElement['nodeName'],
|
|
11
|
-
attributes: new Map(),
|
|
12
|
-
childNodes: [],
|
|
13
|
-
parentNode: undefined,
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return node
|
|
17
|
-
}
|
|
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
|
-
*/
|
|
26
|
-
export const appendChildNode = (node: DOMNode, childNode: DOMElement | DOMNode): void => {
|
|
27
|
-
if (childNode.parentNode) {
|
|
28
|
-
removeChildNode(childNode.parentNode, childNode)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (node.nodeName !== TEXT_NODE_NAME) {
|
|
32
|
-
childNode.parentNode = node
|
|
33
|
-
node.childNodes.push(childNode)
|
|
34
|
-
}
|
|
35
|
-
}
|
|
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
|
-
*/
|
|
43
|
-
export const insertBeforeNode = (node: DOMElement, newChildNode: DOMNode, beforeChildNode: DOMNode): void => {
|
|
44
|
-
if (newChildNode.parentNode) {
|
|
45
|
-
removeChildNode(newChildNode.parentNode, newChildNode)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
newChildNode.parentNode = node
|
|
49
|
-
|
|
50
|
-
const index = node.childNodes.indexOf(beforeChildNode)
|
|
51
|
-
if (index >= 0) {
|
|
52
|
-
node.childNodes.splice(index, 0, newChildNode)
|
|
53
|
-
|
|
54
|
-
return
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
node.childNodes.push(newChildNode)
|
|
58
|
-
}
|
|
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
|
-
*/
|
|
64
|
-
export const removeChildNode = (node: DOMElement, removeNode: DOMNode): void => {
|
|
65
|
-
removeNode.parentNode = undefined
|
|
66
|
-
|
|
67
|
-
const index = node.childNodes.indexOf(removeNode)
|
|
68
|
-
if (index >= 0) {
|
|
69
|
-
node.childNodes.splice(index, 1)
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Set an attribute on `node`, storing it in the node's `attributes` map.
|
|
75
|
-
*/
|
|
76
|
-
export const setAttribute = (node: DOMElement, key: string, value: DOMNodeAttribute): void => {
|
|
77
|
-
node.attributes.set(key, value)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Create a new {@link TextNode} with the given text value.
|
|
82
|
-
*/
|
|
83
|
-
export const createTextNode = (text: string): TextNode => {
|
|
84
|
-
const node: TextNode = {
|
|
85
|
-
nodeName: TEXT_NODE_NAME,
|
|
86
|
-
nodeValue: text,
|
|
87
|
-
parentNode: undefined,
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
setTextNodeValue(node, text)
|
|
91
|
-
|
|
92
|
-
return node
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Update the `nodeValue` of an existing {@link TextNode}.
|
|
97
|
-
* Non-string values are coerced to strings via `String(text)`.
|
|
98
|
-
*/
|
|
99
|
-
export const setTextNodeValue = (node: TextNode, text: string): void => {
|
|
100
|
-
if (typeof text !== 'string') {
|
|
101
|
-
text = String(text)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
node.nodeValue = text
|
|
105
|
-
}
|