@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 CHANGED
@@ -346,7 +346,7 @@ function Jsx({ children }) {
346
346
  Jsx.displayName = "Jsx";
347
347
  //#endregion
348
348
  //#region src/components/Root.tsx
349
- var import_react = require_jsx_runtime.require_react();
349
+ var import_react = /* @__PURE__ */ require_jsx_runtime.__toESM(require_jsx_runtime.require_react());
350
350
  var ErrorBoundary = class extends import_react.Component {
351
351
  state = { hasError: false };
352
352
  static displayName = "ErrorBoundary";
@@ -454,20 +454,29 @@ var import_constants = (/* @__PURE__ */ require_jsx_runtime.__commonJSMin(((expo
454
454
  * Name used for text-node entries in the virtual DOM.
455
455
  */
456
456
  const TEXT_NODE_NAME = "#text";
457
+ const KUBB_FILE = "kubb-file";
458
+ const KUBB_SOURCE = "kubb-source";
459
+ const KUBB_EXPORT = "kubb-export";
460
+ const KUBB_IMPORT = "kubb-import";
461
+ const KUBB_FUNCTION = "kubb-function";
462
+ const KUBB_ARROW_FUNCTION = "kubb-arrow-function";
463
+ const KUBB_CONST = "kubb-const";
464
+ const KUBB_TYPE = "kubb-type";
465
+ const KUBB_JSX = "kubb-jsx";
457
466
  /**
458
467
  * Set of all element names recognized by the Kubb renderer.
459
468
  * Used to distinguish Kubb-owned elements from unrecognized or text nodes during tree traversal.
460
469
  */
461
470
  const nodeNames = new Set([
462
- "kubb-export",
463
- "kubb-file",
464
- "kubb-source",
465
- "kubb-import",
466
- "kubb-function",
467
- "kubb-arrow-function",
468
- "kubb-const",
469
- "kubb-type",
470
- "kubb-jsx",
471
+ KUBB_EXPORT,
472
+ KUBB_FILE,
473
+ KUBB_SOURCE,
474
+ KUBB_IMPORT,
475
+ KUBB_FUNCTION,
476
+ KUBB_ARROW_FUNCTION,
477
+ KUBB_CONST,
478
+ KUBB_TYPE,
479
+ KUBB_JSX,
471
480
  "kubb-text",
472
481
  "kubb-root",
473
482
  "kubb-app",
@@ -484,7 +493,7 @@ const nodeNames = new Set([
484
493
  const createNode = (nodeName) => {
485
494
  return {
486
495
  nodeName,
487
- attributes: /* @__PURE__ */ new Map(),
496
+ attributes: Object.create(null),
488
497
  childNodes: [],
489
498
  parentNode: void 0
490
499
  };
@@ -532,26 +541,22 @@ const removeChildNode = (node, removeNode) => {
532
541
  * Set an attribute on `node`, storing it in the node's `attributes` map.
533
542
  */
534
543
  const setAttribute = (node, key, value) => {
535
- node.attributes.set(key, value);
544
+ node.attributes[key] = value;
536
545
  };
537
546
  /**
538
547
  * Create a new {@link TextNode} with the given text value.
539
548
  */
540
549
  const createTextNode = (text) => {
541
- const node = {
550
+ return {
542
551
  nodeName: TEXT_NODE_NAME,
543
552
  nodeValue: text,
544
553
  parentNode: void 0
545
554
  };
546
- setTextNodeValue(node, text);
547
- return node;
548
555
  };
549
556
  /**
550
557
  * Update the `nodeValue` of an existing {@link TextNode}.
551
- * Non-string values are coerced to strings via `String(text)`.
552
558
  */
553
559
  const setTextNodeValue = (node, text) => {
554
- if (typeof text !== "string") text = String(text);
555
560
  node.nodeValue = text;
556
561
  };
557
562
  //#endregion
@@ -17823,7 +17828,7 @@ const Renderer = (0, import_react_reconciler.default)({
17823
17828
  return false;
17824
17829
  },
17825
17830
  supportsMutation: true,
17826
- isPrimaryRenderer: true,
17831
+ isPrimaryRenderer: false,
17827
17832
  supportsPersistence: false,
17828
17833
  supportsHydration: false,
17829
17834
  scheduleTimeout: setTimeout,
@@ -17889,187 +17894,190 @@ const Renderer = (0, import_react_reconciler.default)({
17889
17894
  });
17890
17895
  //#endregion
17891
17896
  //#region src/utils.ts
17897
+ function toBool$1(val) {
17898
+ return val ?? false;
17899
+ }
17900
+ require_jsx_runtime.__name(toBool$1, "toBool");
17892
17901
  /**
17893
17902
  * Collect the text and nested AST-node children of a single kubb-* element.
17894
17903
  *
17895
- * `#text` children become raw {@link TextNode}s; nested `kubb-function`, `kubb-const`,
17904
+ * `#text` children become raw text nodes; nested `kubb-function`, `kubb-const`,
17896
17905
  * `kubb-type`, and similar elements are converted into their respective {@link CodeNode}s.
17897
- * Any unrecognized DOM elements are silently skipped.
17906
+ * Any unrecognized element names are silently skipped.
17898
17907
  */
17899
- function collectChildNodes(element) {
17908
+ function collectCodeNodes$1(element) {
17900
17909
  const result = [];
17901
17910
  for (const child of element.childNodes) {
17902
17911
  if (!child) continue;
17903
- if (child.nodeName === "#text") {
17904
- const text = child.nodeValue;
17905
- if (text && text.trim().length > 0) result.push((0, _kubb_ast.createText)(text));
17906
- continue;
17907
- }
17908
- if (child.nodeName === "br") {
17909
- result.push((0, _kubb_ast.createBreak)());
17910
- continue;
17911
- }
17912
- if (child.nodeName === "kubb-function") {
17913
- const attrs = child.attributes;
17914
- result.push((0, _kubb_ast.createFunction)({
17915
- name: attrs.get("name"),
17916
- params: attrs.get("params"),
17917
- export: attrs.get("export"),
17918
- default: attrs.get("default"),
17919
- async: attrs.get("async"),
17920
- generics: attrs.get("generics"),
17921
- returnType: attrs.get("returnType"),
17922
- JSDoc: attrs.get("JSDoc"),
17923
- nodes: collectChildNodes(child)
17924
- }));
17925
- } else if (child.nodeName === "kubb-arrow-function") {
17926
- const attrs = child.attributes;
17927
- result.push((0, _kubb_ast.createArrowFunction)({
17928
- name: attrs.get("name"),
17929
- params: attrs.get("params"),
17930
- export: attrs.get("export"),
17931
- default: attrs.get("default"),
17932
- async: attrs.get("async"),
17933
- generics: attrs.get("generics"),
17934
- returnType: attrs.get("returnType"),
17935
- singleLine: attrs.get("singleLine"),
17936
- JSDoc: attrs.get("JSDoc"),
17937
- nodes: collectChildNodes(child)
17938
- }));
17939
- } else if (child.nodeName === "kubb-const") {
17940
- const attrs = child.attributes;
17941
- result.push((0, _kubb_ast.createConst)({
17942
- name: attrs.get("name"),
17943
- type: attrs.get("type"),
17944
- export: attrs.get("export"),
17945
- asConst: attrs.get("asConst"),
17946
- JSDoc: attrs.get("JSDoc"),
17947
- nodes: collectChildNodes(child)
17948
- }));
17949
- } else if (child.nodeName === "kubb-type") {
17950
- const attrs = child.attributes;
17951
- result.push((0, _kubb_ast.createType)({
17952
- name: attrs.get("name"),
17953
- export: attrs.get("export"),
17954
- JSDoc: attrs.get("JSDoc"),
17955
- nodes: collectChildNodes(child)
17956
- }));
17957
- } else if (child.nodeName === "kubb-jsx") {
17958
- const textChild = child.childNodes[0];
17959
- const value = textChild?.nodeName === "#text" ? textChild.nodeValue : "";
17960
- if (value) result.push((0, _kubb_ast.createJsx)(value));
17912
+ switch (child.nodeName) {
17913
+ case TEXT_NODE_NAME: {
17914
+ const text = child.nodeValue;
17915
+ if (text && text.trim()) result.push((0, _kubb_ast.createText)(text));
17916
+ break;
17917
+ }
17918
+ case "br":
17919
+ result.push((0, _kubb_ast.createBreak)());
17920
+ break;
17921
+ case KUBB_FUNCTION: {
17922
+ const attrs = child.attributes;
17923
+ result.push((0, _kubb_ast.createFunction)({
17924
+ name: attrs["name"],
17925
+ params: attrs["params"],
17926
+ export: attrs["export"],
17927
+ default: attrs["default"],
17928
+ async: attrs["async"],
17929
+ generics: attrs["generics"],
17930
+ returnType: attrs["returnType"],
17931
+ JSDoc: attrs["JSDoc"],
17932
+ nodes: collectCodeNodes$1(child)
17933
+ }));
17934
+ break;
17935
+ }
17936
+ case KUBB_ARROW_FUNCTION: {
17937
+ const attrs = child.attributes;
17938
+ result.push((0, _kubb_ast.createArrowFunction)({
17939
+ name: attrs["name"],
17940
+ params: attrs["params"],
17941
+ export: attrs["export"],
17942
+ default: attrs["default"],
17943
+ async: attrs["async"],
17944
+ generics: attrs["generics"],
17945
+ returnType: attrs["returnType"],
17946
+ singleLine: attrs["singleLine"],
17947
+ JSDoc: attrs["JSDoc"],
17948
+ nodes: collectCodeNodes$1(child)
17949
+ }));
17950
+ break;
17951
+ }
17952
+ case KUBB_CONST: {
17953
+ const attrs = child.attributes;
17954
+ result.push((0, _kubb_ast.createConst)({
17955
+ name: attrs["name"],
17956
+ type: attrs["type"],
17957
+ export: attrs["export"],
17958
+ asConst: attrs["asConst"],
17959
+ JSDoc: attrs["JSDoc"],
17960
+ nodes: collectCodeNodes$1(child)
17961
+ }));
17962
+ break;
17963
+ }
17964
+ case KUBB_TYPE: {
17965
+ const attrs = child.attributes;
17966
+ result.push((0, _kubb_ast.createType)({
17967
+ name: attrs["name"],
17968
+ export: attrs["export"],
17969
+ JSDoc: attrs["JSDoc"],
17970
+ nodes: collectCodeNodes$1(child)
17971
+ }));
17972
+ break;
17973
+ }
17974
+ case KUBB_JSX: {
17975
+ const textChild = child.childNodes[0];
17976
+ const value = textChild?.nodeName === "#text" ? textChild.nodeValue : "";
17977
+ if (value) result.push((0, _kubb_ast.createJsx)(value));
17978
+ break;
17979
+ }
17961
17980
  }
17962
17981
  }
17963
17982
  return result;
17964
17983
  }
17984
+ require_jsx_runtime.__name(collectCodeNodes$1, "collectCodeNodes");
17965
17985
  /**
17966
- * Traverse `node` and collect all `<kubb-source>` elements into a `Set<SourceNode>`.
17967
- *
17968
- * Elements whose `nodeName` is in `ignores` are skipped entirely (including their subtrees).
17969
- * This is used to collect source blocks from a file node while excluding import/export subtrees.
17986
+ * Yields every {@link SourceNode}, {@link ExportNode}, and {@link ImportNode}
17987
+ * within a `<kubb-file>` subtree in a single tree walk.
17970
17988
  *
17971
- * @example Collect sources while ignoring export and import elements
17972
- * ```ts
17973
- * const sources = squashSourceNodes(fileElement, ['kubb-export', 'kubb-import'])
17974
- * ```
17989
+ * Import and export elements are leaf nodes. Once yielded, the walker does not
17990
+ * recurse into them, which also prevents source collection from descending into
17991
+ * their subtrees. Dispatch on `.kind` (`'Source'`, `'Export'`, `'Import'`) to
17992
+ * separate the results.
17975
17993
  */
17976
- function squashSourceNodes(node, ignores) {
17977
- const ignoreSet = new Set(ignores);
17978
- const sources = /* @__PURE__ */ new Set();
17979
- const walk = (current) => {
17980
- for (const child of current.childNodes) {
17981
- if (!child) continue;
17982
- if (child.nodeName !== "#text" && ignoreSet.has(child.nodeName)) continue;
17983
- if (child.nodeName === "kubb-source") {
17984
- const source = (0, _kubb_ast.createSource)({
17985
- name: child.attributes.get("name")?.toString(),
17986
- isTypeOnly: child.attributes.get("isTypeOnly") ?? false,
17987
- isExportable: child.attributes.get("isExportable") ?? false,
17988
- isIndexable: child.attributes.get("isIndexable") ?? false,
17989
- nodes: collectChildNodes(child)
17990
- });
17991
- sources.add(source);
17992
- continue;
17993
- }
17994
- if (child.nodeName !== "#text" && nodeNames.has(child.nodeName)) walk(child);
17994
+ function* collectFileEntries(node) {
17995
+ for (const child of node.childNodes) {
17996
+ if (!child || child.nodeName === "#text") continue;
17997
+ if (child.nodeName === "kubb-source") {
17998
+ yield (0, _kubb_ast.createSource)({
17999
+ name: child.attributes["name"]?.toString(),
18000
+ isTypeOnly: toBool$1(child.attributes["isTypeOnly"]),
18001
+ isExportable: toBool$1(child.attributes["isExportable"]),
18002
+ isIndexable: toBool$1(child.attributes["isIndexable"]),
18003
+ nodes: collectCodeNodes$1(child)
18004
+ });
18005
+ continue;
17995
18006
  }
17996
- };
17997
- walk(node);
17998
- return sources;
18007
+ if (child.nodeName === "kubb-export") {
18008
+ yield (0, _kubb_ast.createExport)({
18009
+ name: child.attributes["name"],
18010
+ path: child.attributes["path"],
18011
+ isTypeOnly: toBool$1(child.attributes["isTypeOnly"]),
18012
+ asAlias: toBool$1(child.attributes["asAlias"])
18013
+ });
18014
+ continue;
18015
+ }
18016
+ if (child.nodeName === "kubb-import") {
18017
+ yield (0, _kubb_ast.createImport)({
18018
+ name: child.attributes["name"],
18019
+ path: child.attributes["path"],
18020
+ root: child.attributes["root"],
18021
+ isTypeOnly: toBool$1(child.attributes["isTypeOnly"]),
18022
+ isNameSpace: toBool$1(child.attributes["isNameSpace"])
18023
+ });
18024
+ continue;
18025
+ }
18026
+ if (nodeNames.has(child.nodeName)) yield* collectFileEntries(child);
18027
+ }
17999
18028
  }
18000
18029
  /**
18001
- * Traverse `node` and collect all `<kubb-export>` elements into a `Set<ExportNode>`.
18030
+ * Runs a single {@link collectFileEntries} pass over a `<kubb-file>` DOM element
18031
+ * and assembles the result into a {@link FileNode}, bucketing each yielded
18032
+ * node by its `.kind`.
18002
18033
  */
18003
- function squashExportNodes(node) {
18004
- const exports = /* @__PURE__ */ new Set();
18005
- const walk = (current) => {
18006
- for (const child of current.childNodes) {
18007
- if (!child) continue;
18008
- if (child.nodeName !== "#text" && nodeNames.has(child.nodeName)) walk(child);
18009
- if (child.nodeName === "kubb-export") exports.add((0, _kubb_ast.createExport)({
18010
- name: child.attributes.get("name"),
18011
- path: child.attributes.get("path"),
18012
- isTypeOnly: child.attributes.get("isTypeOnly") ?? false,
18013
- asAlias: child.attributes.get("asAlias") ?? false
18014
- }));
18034
+ function createFileNode(child) {
18035
+ const sources = [];
18036
+ const exports = [];
18037
+ const imports = [];
18038
+ for (const node of collectFileEntries(child)) {
18039
+ if (node.kind === "Source") {
18040
+ sources.push(node);
18041
+ continue;
18042
+ }
18043
+ if (node.kind === "Export") {
18044
+ exports.push(node);
18045
+ continue;
18015
18046
  }
18047
+ imports.push(node);
18048
+ }
18049
+ return {
18050
+ baseName: child.attributes["baseName"],
18051
+ path: child.attributes["path"],
18052
+ meta: child.attributes["meta"] || {},
18053
+ footer: child.attributes["footer"],
18054
+ banner: child.attributes["banner"],
18055
+ sources,
18056
+ exports,
18057
+ imports
18016
18058
  };
18017
- walk(node);
18018
- return exports;
18019
18059
  }
18020
18060
  /**
18021
- * Traverse `node` and collect all `<kubb-import>` elements into a `Set<ImportNode>`.
18061
+ * Yields each {@link FileNode} as it is encountered during the tree walk,
18062
+ * without collecting into an intermediate array. Callers can begin processing
18063
+ * each file before the rest of the tree is traversed.
18022
18064
  */
18023
- function squashImportNodes(node) {
18024
- const imports = /* @__PURE__ */ new Set();
18025
- const walk = (current) => {
18026
- for (const child of current.childNodes) {
18027
- if (!child) continue;
18028
- if (child.nodeName !== "#text" && nodeNames.has(child.nodeName)) walk(child);
18029
- if (child.nodeName === "kubb-import") imports.add((0, _kubb_ast.createImport)({
18030
- name: child.attributes.get("name"),
18031
- path: child.attributes.get("path"),
18032
- root: child.attributes.get("root"),
18033
- isTypeOnly: child.attributes.get("isTypeOnly") ?? false,
18034
- isNameSpace: child.attributes.get("isNameSpace") ?? false
18035
- }));
18036
- }
18037
- };
18038
- walk(node);
18039
- return imports;
18065
+ function* streamFiles(node) {
18066
+ for (const child of node.childNodes) {
18067
+ if (!child) continue;
18068
+ if (child.nodeName !== "#text" && child.nodeName !== "kubb-file" && nodeNames.has(child.nodeName)) yield* streamFiles(child);
18069
+ if (child.nodeName === "kubb-file" && child.attributes["baseName"] !== void 0 && child.attributes["path"] !== void 0) yield createFileNode(child);
18070
+ }
18040
18071
  }
18041
18072
  /**
18042
18073
  * Walk the virtual DOM tree rooted at `node` and convert every `<kubb-file>` element
18043
18074
  * into a {@link FileNode}, collecting its source blocks, imports, and exports.
18044
18075
  *
18045
- * Returns the list of file nodes in document order. Nested files are supported
18076
+ * Returns the list of file nodes in document order. Nested files are supported;
18046
18077
  * the walker descends into non-file elements and recurses through them.
18047
18078
  */
18048
- function processFiles(node) {
18049
- const collected = [];
18050
- function walk(current) {
18051
- for (const child of current.childNodes) {
18052
- if (!child) continue;
18053
- if (child.nodeName !== "#text" && child.nodeName !== "kubb-file" && nodeNames.has(child.nodeName)) walk(child);
18054
- if (child.nodeName === "kubb-file") {
18055
- if (child.attributes.has("baseName") && child.attributes.has("path")) {
18056
- const sources = squashSourceNodes(child, ["kubb-export", "kubb-import"]);
18057
- collected.push({
18058
- baseName: child.attributes.get("baseName"),
18059
- path: child.attributes.get("path"),
18060
- meta: child.attributes.get("meta") || {},
18061
- footer: child.attributes.get("footer"),
18062
- banner: child.attributes.get("banner"),
18063
- sources: [...sources],
18064
- exports: [...squashExportNodes(child)],
18065
- imports: [...squashImportNodes(child)]
18066
- });
18067
- }
18068
- }
18069
- }
18070
- }
18071
- walk(node);
18072
- return collected;
18079
+ function collectFiles(node) {
18080
+ return [...streamFiles(node)];
18073
18081
  }
18074
18082
  //#endregion
18075
18083
  //#region src/Runtime.tsx
@@ -18094,7 +18102,7 @@ var Runtime = class {
18094
18102
  console.log(data);
18095
18103
  };
18096
18104
  const logRecoverableError = typeof reportError === "function" ? reportError : console.error;
18097
- const rootTag = import_constants.ConcurrentRoot;
18105
+ const rootTag = import_constants.LegacyRoot;
18098
18106
  this.#container = Renderer.createContainer(this.#rootNode, rootTag, null, false, false, "id", logRecoverableError, logRecoverableError, logRecoverableError, null);
18099
18107
  this.unsubscribeExit = onProcessExit((code) => {
18100
18108
  this.unmount(code);
@@ -18107,7 +18115,7 @@ var Runtime = class {
18107
18115
  onRender = () => {
18108
18116
  const task = this.#renderPromise.catch(() => {}).then(() => {
18109
18117
  if (this.#isUnmounted) return;
18110
- const files = processFiles(this.#rootNode);
18118
+ const files = collectFiles(this.#rootNode);
18111
18119
  this.nodes.push(...files);
18112
18120
  if (!this.#options?.debug) return;
18113
18121
  });
@@ -18154,21 +18162,234 @@ var Runtime = class {
18154
18162
  }
18155
18163
  };
18156
18164
  //#endregion
18165
+ //#region src/SyncRuntime.tsx
18166
+ /**
18167
+ * Walks `element`, resolving arrays, Fragments, and function components
18168
+ * transparently, then calls `onText` for primitive values and `onHost` for
18169
+ * every host element encountered. Pure function components are called
18170
+ * synchronously; hooks and class components are not supported.
18171
+ */
18172
+ function walkElement(element, onText, onHost) {
18173
+ if (element == null || typeof element === "boolean") return;
18174
+ if (typeof element === "string" || typeof element === "number" || typeof element === "bigint") {
18175
+ onText(String(element));
18176
+ return;
18177
+ }
18178
+ if (Array.isArray(element)) {
18179
+ for (const child of element) walkElement(child, onText, onHost);
18180
+ return;
18181
+ }
18182
+ if (typeof element === "object" && "$$typeof" in element) {
18183
+ const el = element;
18184
+ const { type } = el;
18185
+ const props = el.props;
18186
+ if (type === import_react.Fragment) {
18187
+ walkElement(props["children"], onText, onHost);
18188
+ return;
18189
+ }
18190
+ if (typeof type === "function") {
18191
+ walkElement(type(props), onText, onHost);
18192
+ return;
18193
+ }
18194
+ if (typeof type === "string") onHost(type, props);
18195
+ }
18196
+ }
18197
+ function toBool(val) {
18198
+ return val ?? false;
18199
+ }
18200
+ function collectCodeNodes(props) {
18201
+ const nodes = [];
18202
+ collectCode(props["children"], nodes);
18203
+ return nodes;
18204
+ }
18205
+ function collectCode(element, nodes) {
18206
+ walkElement(element, (text) => {
18207
+ if (text.trim()) nodes.push((0, _kubb_ast.createText)(text));
18208
+ }, (type, props) => resolveCodeNode(type, props, nodes));
18209
+ }
18210
+ function resolveCodeNode(type, props, nodes) {
18211
+ if (type === "br") {
18212
+ nodes.push((0, _kubb_ast.createBreak)());
18213
+ return;
18214
+ }
18215
+ if (type === "kubb-jsx") {
18216
+ let value = "";
18217
+ walkElement(props["children"], (t) => {
18218
+ value += t;
18219
+ }, () => {});
18220
+ if (value) nodes.push((0, _kubb_ast.createJsx)(value));
18221
+ return;
18222
+ }
18223
+ if (type === "kubb-function") {
18224
+ nodes.push((0, _kubb_ast.createFunction)({
18225
+ name: props["name"],
18226
+ params: props["params"],
18227
+ export: props["export"],
18228
+ default: props["default"],
18229
+ async: props["async"],
18230
+ generics: props["generics"],
18231
+ returnType: props["returnType"],
18232
+ JSDoc: props["JSDoc"],
18233
+ nodes: collectCodeNodes(props)
18234
+ }));
18235
+ return;
18236
+ }
18237
+ if (type === "kubb-arrow-function") {
18238
+ nodes.push((0, _kubb_ast.createArrowFunction)({
18239
+ name: props["name"],
18240
+ params: props["params"],
18241
+ export: props["export"],
18242
+ default: props["default"],
18243
+ async: props["async"],
18244
+ generics: props["generics"],
18245
+ returnType: props["returnType"],
18246
+ singleLine: props["singleLine"],
18247
+ JSDoc: props["JSDoc"],
18248
+ nodes: collectCodeNodes(props)
18249
+ }));
18250
+ return;
18251
+ }
18252
+ if (type === "kubb-const") {
18253
+ nodes.push((0, _kubb_ast.createConst)({
18254
+ name: props["name"],
18255
+ type: props["type"],
18256
+ export: props["export"],
18257
+ asConst: props["asConst"],
18258
+ JSDoc: props["JSDoc"],
18259
+ nodes: collectCodeNodes(props)
18260
+ }));
18261
+ return;
18262
+ }
18263
+ if (type === "kubb-type") {
18264
+ nodes.push((0, _kubb_ast.createType)({
18265
+ name: props["name"],
18266
+ export: props["export"],
18267
+ JSDoc: props["JSDoc"],
18268
+ nodes: collectCodeNodes(props)
18269
+ }));
18270
+ return;
18271
+ }
18272
+ }
18273
+ function collectFileChildren(element) {
18274
+ const sources = [];
18275
+ const exports = [];
18276
+ const imports = [];
18277
+ walkElement(element, (text) => {
18278
+ if (text.trim()) throw new Error(`[react] '${text}' should be part of <File.Source> component when using the <File/> component`);
18279
+ }, (type, props) => {
18280
+ if (type === "kubb-source") {
18281
+ sources.push((0, _kubb_ast.createSource)({
18282
+ name: props["name"]?.toString(),
18283
+ isTypeOnly: toBool(props["isTypeOnly"]),
18284
+ isExportable: toBool(props["isExportable"]),
18285
+ isIndexable: toBool(props["isIndexable"]),
18286
+ nodes: collectCodeNodes(props)
18287
+ }));
18288
+ return;
18289
+ }
18290
+ if (type === "kubb-export") {
18291
+ exports.push((0, _kubb_ast.createExport)({
18292
+ name: props["name"],
18293
+ path: props["path"],
18294
+ isTypeOnly: toBool(props["isTypeOnly"]),
18295
+ asAlias: toBool(props["asAlias"])
18296
+ }));
18297
+ return;
18298
+ }
18299
+ if (type === "kubb-import") {
18300
+ imports.push((0, _kubb_ast.createImport)({
18301
+ name: props["name"],
18302
+ path: props["path"],
18303
+ root: props["root"],
18304
+ isTypeOnly: toBool(props["isTypeOnly"]),
18305
+ isNameSpace: toBool(props["isNameSpace"])
18306
+ }));
18307
+ return;
18308
+ }
18309
+ const nested = collectFileChildren(props["children"]);
18310
+ sources.push(...nested.sources);
18311
+ exports.push(...nested.exports);
18312
+ imports.push(...nested.imports);
18313
+ });
18314
+ return {
18315
+ sources,
18316
+ exports,
18317
+ imports
18318
+ };
18319
+ }
18320
+ function* walkFiles(element) {
18321
+ const files = [];
18322
+ function onHost(type, props) {
18323
+ if (!(type === "kubb-file" && props["baseName"] !== void 0 && props["path"] !== void 0)) {
18324
+ walkElement(props["children"], () => {}, onHost);
18325
+ return;
18326
+ }
18327
+ const { sources, exports, imports } = collectFileChildren(props["children"]);
18328
+ files.push({
18329
+ baseName: props["baseName"],
18330
+ path: props["path"],
18331
+ meta: props["meta"] || {},
18332
+ footer: props["footer"],
18333
+ banner: props["banner"],
18334
+ sources,
18335
+ exports,
18336
+ imports
18337
+ });
18338
+ }
18339
+ walkElement(element, () => {}, onHost);
18340
+ yield* files;
18341
+ }
18342
+ /**
18343
+ * Synchronous JSX renderer that walks the element tree in a single pass,
18344
+ * producing {@link FileNode} objects directly without an intermediate virtual
18345
+ * DOM. No React fiber, scheduler, or work loop is involved.
18346
+ *
18347
+ * All components must be pure functions; hooks and class components are not
18348
+ * supported. Produces identical output to the React-backed {@link Runtime} at
18349
+ * approximately 2–4× the speed and a fraction of the allocations.
18350
+ */
18351
+ var SyncRuntime = class {
18352
+ /**
18353
+ * Accumulated {@link FileNode} results from every {@link render} call.
18354
+ */
18355
+ nodes = [];
18356
+ /**
18357
+ * Walks `element` synchronously, converts every `<kubb-file>` subtree into
18358
+ * a {@link FileNode} with no intermediate virtual DOM, and appends the results
18359
+ * to {@link nodes}.
18360
+ */
18361
+ render(element) {
18362
+ for (const file of walkFiles(element)) this.nodes.push(file);
18363
+ }
18364
+ /**
18365
+ * Walks `element` synchronously and yields each {@link FileNode} as it is
18366
+ * produced, without buffering into an intermediate array first. Callers can
18367
+ * begin processing each file before the rest of the element tree is traversed.
18368
+ *
18369
+ * @example
18370
+ * ```ts
18371
+ * for (const file of runtime.stream(element)) {
18372
+ * await writeFile(file)
18373
+ * }
18374
+ * ```
18375
+ */
18376
+ *stream(element) {
18377
+ yield* walkFiles(element);
18378
+ }
18379
+ };
18380
+ //#endregion
18157
18381
  //#region src/createRenderer.tsx
18158
18382
  /**
18159
- * A renderer factory for generators that produce JSX output.
18383
+ * Renderer factory for generators that produce JSX output.
18160
18384
  *
18161
- * Pass this as the `renderer` property of a `defineGenerator` call so that
18162
- * core can render the JSX element tree returned by your generator methods
18385
+ * Pass as the `renderer` property of `defineGenerator`. Core drives rendering
18163
18386
  * without a hard dependency on `@kubb/renderer-jsx`.
18164
18387
  *
18165
18388
  * @example
18166
18389
  * ```ts
18167
18390
  * import { jsxRenderer } from '@kubb/renderer-jsx'
18168
- * import { defineGenerator } from '@kubb/core'
18169
18391
  *
18170
18392
  * export const myGenerator = defineGenerator<PluginTs>({
18171
- * name: 'my-generator',
18172
18393
  * renderer: jsxRenderer,
18173
18394
  * schema(node, options) {
18174
18395
  * return <File baseName="output.ts" path="src/output.ts">...</File>
@@ -18190,6 +18411,47 @@ const jsxRenderer = () => {
18190
18411
  }
18191
18412
  };
18192
18413
  };
18414
+ /**
18415
+ * Lightweight renderer factory with no React fiber, scheduler, or work loop.
18416
+ *
18417
+ * Walks the JSX element tree in a single recursive pass. All components must be
18418
+ * pure functions; hooks and class components are not supported. Drop-in
18419
+ * replacement for {@link jsxRenderer} at approximately 2–4× the speed.
18420
+ *
18421
+ * @example Drop-in replacement
18422
+ * ```ts
18423
+ * import { jsxRendererSync } from '@kubb/renderer-jsx'
18424
+ *
18425
+ * export const myGenerator = defineGenerator<PluginTs>({
18426
+ * renderer: jsxRendererSync,
18427
+ * schema(node, options) {
18428
+ * return <File baseName="output.ts" path="src/output.ts">...</File>
18429
+ * },
18430
+ * })
18431
+ * ```
18432
+ *
18433
+ * @example Stream files as they are produced
18434
+ * ```ts
18435
+ * for await (const file of jsxRendererSync().stream(element)) {
18436
+ * await writeFile(file)
18437
+ * }
18438
+ * ```
18439
+ */
18440
+ const jsxRendererSync = () => {
18441
+ const runtime = new SyncRuntime();
18442
+ return {
18443
+ async render(element) {
18444
+ runtime.render(element);
18445
+ },
18446
+ get files() {
18447
+ return runtime.nodes;
18448
+ },
18449
+ stream(element) {
18450
+ return runtime.stream(element);
18451
+ },
18452
+ unmount(_error) {}
18453
+ };
18454
+ };
18193
18455
  //#endregion
18194
18456
  exports.Const = Const;
18195
18457
  exports.File = File;
@@ -18200,6 +18462,7 @@ exports.Type = Type;
18200
18462
  exports.createContext = createContext;
18201
18463
  exports.inject = inject;
18202
18464
  exports.jsxRenderer = jsxRenderer;
18465
+ exports.jsxRendererSync = jsxRendererSync;
18203
18466
  exports.provide = provide;
18204
18467
  exports.unprovide = unprovide;
18205
18468