@khairold/xml-render 0.1.0

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.
Files changed (58) hide show
  1. package/README.md +372 -0
  2. package/dist/index.d.ts +33 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +41 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/parser.d.ts +129 -0
  7. package/dist/parser.d.ts.map +1 -0
  8. package/dist/parser.js +321 -0
  9. package/dist/parser.js.map +1 -0
  10. package/dist/react/ErrorBoundary.d.ts +56 -0
  11. package/dist/react/ErrorBoundary.d.ts.map +1 -0
  12. package/dist/react/ErrorBoundary.js +69 -0
  13. package/dist/react/ErrorBoundary.js.map +1 -0
  14. package/dist/react/XmlRender.d.ts +62 -0
  15. package/dist/react/XmlRender.d.ts.map +1 -0
  16. package/dist/react/XmlRender.js +90 -0
  17. package/dist/react/XmlRender.js.map +1 -0
  18. package/dist/react/catalog.d.ts +99 -0
  19. package/dist/react/catalog.d.ts.map +1 -0
  20. package/dist/react/catalog.js +55 -0
  21. package/dist/react/catalog.js.map +1 -0
  22. package/dist/react/context.d.ts +66 -0
  23. package/dist/react/context.d.ts.map +1 -0
  24. package/dist/react/context.js +63 -0
  25. package/dist/react/context.js.map +1 -0
  26. package/dist/react/index.d.ts +35 -0
  27. package/dist/react/index.d.ts.map +1 -0
  28. package/dist/react/index.js +41 -0
  29. package/dist/react/index.js.map +1 -0
  30. package/dist/react-native/ErrorBoundary.d.ts +60 -0
  31. package/dist/react-native/ErrorBoundary.d.ts.map +1 -0
  32. package/dist/react-native/ErrorBoundary.js +84 -0
  33. package/dist/react-native/ErrorBoundary.js.map +1 -0
  34. package/dist/react-native/XmlRender.d.ts +62 -0
  35. package/dist/react-native/XmlRender.d.ts.map +1 -0
  36. package/dist/react-native/XmlRender.js +91 -0
  37. package/dist/react-native/XmlRender.js.map +1 -0
  38. package/dist/react-native/catalog.d.ts +100 -0
  39. package/dist/react-native/catalog.d.ts.map +1 -0
  40. package/dist/react-native/catalog.js +56 -0
  41. package/dist/react-native/catalog.js.map +1 -0
  42. package/dist/react-native/context.d.ts +66 -0
  43. package/dist/react-native/context.d.ts.map +1 -0
  44. package/dist/react-native/context.js +63 -0
  45. package/dist/react-native/context.js.map +1 -0
  46. package/dist/react-native/index.d.ts +35 -0
  47. package/dist/react-native/index.d.ts.map +1 -0
  48. package/dist/react-native/index.js +41 -0
  49. package/dist/react-native/index.js.map +1 -0
  50. package/dist/registry.d.ts +99 -0
  51. package/dist/registry.d.ts.map +1 -0
  52. package/dist/registry.js +93 -0
  53. package/dist/registry.js.map +1 -0
  54. package/dist/types.d.ts +436 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +28 -0
  57. package/dist/types.js.map +1 -0
  58. package/package.json +60 -0
package/dist/parser.js ADDED
@@ -0,0 +1,321 @@
1
+ /**
2
+ * Decode basic XML entities
3
+ */
4
+ function decodeXmlEntities(text) {
5
+ return text
6
+ .replace(/&lt;/g, "<")
7
+ .replace(/&gt;/g, ">")
8
+ .replace(/&amp;/g, "&")
9
+ .replace(/&quot;/g, '"');
10
+ }
11
+ /**
12
+ * Parse attributes from an attribute string
13
+ * Handles both single and double quoted values
14
+ */
15
+ function parseAttributes(attrString) {
16
+ const attrs = {};
17
+ if (!attrString)
18
+ return attrs;
19
+ // Match key="value" or key='value' patterns
20
+ const pattern = /(\w+)=["']([^"']*)["']/g;
21
+ let match;
22
+ while ((match = pattern.exec(attrString)) !== null) {
23
+ attrs[match[1]] = decodeXmlEntities(match[2]);
24
+ }
25
+ return attrs;
26
+ }
27
+ /**
28
+ * Create a parser instance bound to a registry.
29
+ *
30
+ * The parser recognizes tags defined in the registry and converts them
31
+ * into typed segments. Unknown tags are treated as literal text.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * import { z } from 'zod';
36
+ * import { createRegistry, createParser } from '@aura/xml-render';
37
+ *
38
+ * const registry = createRegistry({
39
+ * callout: {
40
+ * schema: z.object({ type: z.enum(['info', 'warning', 'error']) }),
41
+ * hasContent: true,
42
+ * },
43
+ * image: {
44
+ * schema: z.object({ src: z.string(), alt: z.string().optional() }),
45
+ * selfClosing: true,
46
+ * },
47
+ * });
48
+ *
49
+ * const parser = createParser(registry);
50
+ *
51
+ * const segments = parser.parse('Hello <callout type="info">Important!</callout> World');
52
+ * // [
53
+ * // { type: 'text', content: 'Hello ' },
54
+ * // { type: 'callout', content: 'Important!', attributes: { type: 'info' } },
55
+ * // { type: 'text', content: ' World' },
56
+ * // ]
57
+ * ```
58
+ *
59
+ * @param registry - The tag registry to use for parsing
60
+ * @returns A parser instance
61
+ */
62
+ export function createParser(registry) {
63
+ // Build regex patterns for registered tags
64
+ const tagNames = registry.tagNames;
65
+ // Pattern to match opening tags: <tagname ...> or <tagname ... />
66
+ // Using alternation for exact tag name matching
67
+ const tagNamesPattern = tagNames.map(escapeRegex).join("|");
68
+ const openingTagPattern = new RegExp(`<(${tagNamesPattern})(\\s+[^>]*)?(\\/)?>`, "i");
69
+ /**
70
+ * Create a segment from parsed tag information
71
+ */
72
+ function createSegment(tagName, attrString, content) {
73
+ const rawAttrs = parseAttributes(attrString);
74
+ const normalizedTagName = tagName.toLowerCase();
75
+ // Validate and transform attributes using registry schema
76
+ const validationResult = registry.validateAttributes(normalizedTagName, rawAttrs);
77
+ return {
78
+ type: normalizedTagName,
79
+ content: decodeXmlEntities(content),
80
+ attributes: validationResult.success
81
+ ? validationResult.data
82
+ : rawAttrs,
83
+ };
84
+ }
85
+ /**
86
+ * Add text to segments if non-empty
87
+ */
88
+ function addTextSegment(segments, text) {
89
+ const trimmed = text;
90
+ if (trimmed) {
91
+ segments.push({
92
+ type: "text",
93
+ content: decodeXmlEntities(trimmed),
94
+ attributes: undefined,
95
+ });
96
+ }
97
+ }
98
+ /**
99
+ * Parse complete text into segments
100
+ */
101
+ function parse(text) {
102
+ const segments = [];
103
+ let remaining = text;
104
+ let textBuffer = "";
105
+ while (remaining.length > 0) {
106
+ // Check for opening tag
107
+ const openMatch = remaining.match(openingTagPattern);
108
+ if (openMatch) {
109
+ const tagIndex = remaining.indexOf(openMatch[0]);
110
+ if (tagIndex > 0) {
111
+ // Add text before the tag to buffer
112
+ textBuffer += remaining.slice(0, tagIndex);
113
+ remaining = remaining.slice(tagIndex);
114
+ continue;
115
+ }
116
+ const tagName = openMatch[1].toLowerCase();
117
+ const attrStr = openMatch[2] || "";
118
+ const isSelfClosing = openMatch[3] === "/" || registry.isSelfClosing(tagName);
119
+ if (isSelfClosing) {
120
+ // Flush text buffer
121
+ if (textBuffer) {
122
+ addTextSegment(segments, textBuffer);
123
+ textBuffer = "";
124
+ }
125
+ // Create segment for self-closing tag
126
+ const segment = createSegment(tagName, attrStr, "");
127
+ segments.push(segment);
128
+ remaining = remaining.slice(openMatch[0].length);
129
+ continue;
130
+ }
131
+ // Look for closing tag
132
+ const closingTagPattern = new RegExp(`</${escapeRegex(tagName)}>`, "i");
133
+ const closeMatch = remaining.match(closingTagPattern);
134
+ if (closeMatch) {
135
+ const closeIndex = remaining.indexOf(closeMatch[0]);
136
+ // Flush text buffer
137
+ if (textBuffer) {
138
+ addTextSegment(segments, textBuffer);
139
+ textBuffer = "";
140
+ }
141
+ // Extract content between tags
142
+ const contentStart = openMatch[0].length;
143
+ const content = remaining.slice(contentStart, closeIndex);
144
+ // Create segment
145
+ const segment = createSegment(tagName, attrStr, content);
146
+ segments.push(segment);
147
+ // Move past closing tag
148
+ remaining = remaining.slice(closeIndex + closeMatch[0].length);
149
+ }
150
+ else {
151
+ // No closing tag found - treat as malformed, add as text
152
+ textBuffer += openMatch[0];
153
+ remaining = remaining.slice(openMatch[0].length);
154
+ }
155
+ }
156
+ else {
157
+ // No more tags, add rest to text buffer
158
+ textBuffer += remaining;
159
+ remaining = "";
160
+ }
161
+ }
162
+ // Flush remaining text
163
+ if (textBuffer) {
164
+ addTextSegment(segments, textBuffer);
165
+ }
166
+ return segments;
167
+ }
168
+ /**
169
+ * Create initial parser state for streaming
170
+ */
171
+ function createState() {
172
+ return {
173
+ buffer: "",
174
+ inComponent: false,
175
+ currentTag: null,
176
+ currentAttrs: "",
177
+ tagStartIndex: 0,
178
+ };
179
+ }
180
+ /**
181
+ * Parse a streaming chunk with state management
182
+ */
183
+ function parseChunk(chunk, state) {
184
+ const newState = { ...state };
185
+ newState.buffer += chunk;
186
+ const segments = [];
187
+ let textBuffer = "";
188
+ let remaining = newState.buffer;
189
+ let processedUpTo = 0;
190
+ while (remaining.length > 0) {
191
+ if (newState.inComponent && newState.currentTag) {
192
+ // Look for closing tag
193
+ const closingPattern = new RegExp(`</${escapeRegex(newState.currentTag)}>`, "i");
194
+ const closeMatch = remaining.match(closingPattern);
195
+ if (closeMatch) {
196
+ const closeIndex = remaining.indexOf(closeMatch[0]);
197
+ // We have a complete component
198
+ const content = remaining.slice(0, closeIndex);
199
+ const segment = createSegment(newState.currentTag, newState.currentAttrs, content);
200
+ segments.push(segment);
201
+ // Reset state
202
+ remaining = remaining.slice(closeIndex + closeMatch[0].length);
203
+ processedUpTo = newState.buffer.length - remaining.length;
204
+ newState.inComponent = false;
205
+ newState.currentTag = null;
206
+ newState.currentAttrs = "";
207
+ }
208
+ else {
209
+ // Still waiting for closing tag
210
+ break;
211
+ }
212
+ }
213
+ else {
214
+ // Check for opening tag
215
+ const openMatch = remaining.match(openingTagPattern);
216
+ if (openMatch) {
217
+ const tagIndex = remaining.indexOf(openMatch[0]);
218
+ if (tagIndex > 0) {
219
+ // Text before the tag
220
+ textBuffer += remaining.slice(0, tagIndex);
221
+ remaining = remaining.slice(tagIndex);
222
+ continue;
223
+ }
224
+ // Check if it might be an incomplete tag at the end
225
+ // Only buffer if the potential tag is at the very end and looks incomplete
226
+ if (remaining.endsWith("<") || /^<[^>]*$/.test(remaining)) {
227
+ // Potentially incomplete tag, keep buffering
228
+ break;
229
+ }
230
+ const tagName = openMatch[1].toLowerCase();
231
+ const attrStr = openMatch[2] || "";
232
+ const isSelfClosing = openMatch[3] === "/" ||
233
+ registry.isSelfClosing(tagName);
234
+ if (isSelfClosing) {
235
+ // Flush text buffer
236
+ if (textBuffer) {
237
+ addTextSegment(segments, textBuffer);
238
+ textBuffer = "";
239
+ }
240
+ // Create segment for self-closing tag
241
+ const segment = createSegment(tagName, attrStr, "");
242
+ segments.push(segment);
243
+ remaining = remaining.slice(openMatch[0].length);
244
+ processedUpTo = newState.buffer.length - remaining.length;
245
+ continue;
246
+ }
247
+ // Start of a component tag with content
248
+ if (textBuffer) {
249
+ addTextSegment(segments, textBuffer);
250
+ textBuffer = "";
251
+ }
252
+ newState.inComponent = true;
253
+ newState.currentTag = tagName;
254
+ newState.currentAttrs = attrStr;
255
+ newState.tagStartIndex = processedUpTo;
256
+ remaining = remaining.slice(openMatch[0].length);
257
+ processedUpTo = newState.buffer.length - remaining.length;
258
+ }
259
+ else {
260
+ // No tag found, check for potential incomplete tag at end
261
+ const potentialTagStart = remaining.lastIndexOf("<");
262
+ if (potentialTagStart !== -1 &&
263
+ potentialTagStart > remaining.length - 20) {
264
+ // Might be start of a tag, buffer it
265
+ textBuffer += remaining.slice(0, potentialTagStart);
266
+ remaining = remaining.slice(potentialTagStart);
267
+ break;
268
+ }
269
+ // No tags, all text
270
+ textBuffer += remaining;
271
+ remaining = "";
272
+ processedUpTo = newState.buffer.length;
273
+ }
274
+ }
275
+ }
276
+ // Add remaining text to complete segments if not buffering
277
+ if (!newState.inComponent && textBuffer) {
278
+ addTextSegment(segments, textBuffer);
279
+ textBuffer = "";
280
+ }
281
+ // Update buffer to only contain unprocessed content
282
+ newState.buffer = remaining + textBuffer;
283
+ return {
284
+ segments,
285
+ state: newState,
286
+ isBuffering: newState.inComponent || newState.buffer.length > 0,
287
+ bufferingTag: newState.inComponent
288
+ ? newState.currentTag
289
+ : null,
290
+ };
291
+ }
292
+ /**
293
+ * Finalize parsing, returning any remaining buffered content as text
294
+ */
295
+ function finalize(state) {
296
+ const segments = [];
297
+ if (state.buffer) {
298
+ // Return buffered content as raw text (malformed component fallback)
299
+ segments.push({
300
+ type: "text",
301
+ content: decodeXmlEntities(state.buffer),
302
+ attributes: undefined,
303
+ });
304
+ }
305
+ return segments;
306
+ }
307
+ return {
308
+ parse,
309
+ createState,
310
+ parseChunk,
311
+ finalize,
312
+ registry,
313
+ };
314
+ }
315
+ /**
316
+ * Escape special regex characters in a string
317
+ */
318
+ function escapeRegex(str) {
319
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
320
+ }
321
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * ErrorBoundary Component for React
3
+ *
4
+ * Catches render errors in segment components and displays a fallback UI.
5
+ * Prevents a single segment error from crashing the entire content area.
6
+ */
7
+ import { Component, type ReactNode, type ErrorInfo } from "react";
8
+ /**
9
+ * Props for the ErrorBoundary component
10
+ */
11
+ export interface ErrorBoundaryProps {
12
+ /** The child components to render */
13
+ children: ReactNode;
14
+ /** The segment type being rendered (for error messages) */
15
+ segmentType: string;
16
+ /** Optional custom fallback renderer */
17
+ fallback?: (error: Error, segmentType: string) => ReactNode;
18
+ }
19
+ /**
20
+ * State for the ErrorBoundary component
21
+ */
22
+ interface ErrorBoundaryState {
23
+ hasError: boolean;
24
+ error: Error | null;
25
+ }
26
+ /**
27
+ * Error boundary component that catches render errors in child components.
28
+ *
29
+ * In development mode, displays a visible error message with segment type and error details.
30
+ * In production mode, renders a minimal hidden fallback to avoid disrupting the UI.
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * <ErrorBoundary segmentType="chart">
35
+ * <ChartComponent data={data} />
36
+ * </ErrorBoundary>
37
+ * ```
38
+ *
39
+ * @example With custom fallback
40
+ * ```tsx
41
+ * <ErrorBoundary
42
+ * segmentType="table"
43
+ * fallback={(error, type) => <div>Failed to render {type}: {error.message}</div>}
44
+ * >
45
+ * <TableComponent data={data} />
46
+ * </ErrorBoundary>
47
+ * ```
48
+ */
49
+ export declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
50
+ constructor(props: ErrorBoundaryProps);
51
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
52
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
53
+ render(): ReactNode;
54
+ }
55
+ export {};
56
+ //# sourceMappingURL=ErrorBoundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/react/ErrorBoundary.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAc,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,qCAAqC;IACrC,QAAQ,EAAE,SAAS,CAAC;IACpB,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,SAAS,CAAC;CAC7D;AAED;;GAEG;AACH,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,aAAc,SAAQ,SAAS,CAC1C,kBAAkB,EAClB,kBAAkB,CACnB;gBACa,KAAK,EAAE,kBAAkB;IAKrC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,kBAAkB;IAIjE,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI;IAS3D,MAAM,IAAI,SAAS;CAiCpB"}
@@ -0,0 +1,69 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * ErrorBoundary Component for React
4
+ *
5
+ * Catches render errors in segment components and displays a fallback UI.
6
+ * Prevents a single segment error from crashing the entire content area.
7
+ */
8
+ import { Component } from "react";
9
+ /**
10
+ * Error boundary component that catches render errors in child components.
11
+ *
12
+ * In development mode, displays a visible error message with segment type and error details.
13
+ * In production mode, renders a minimal hidden fallback to avoid disrupting the UI.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * <ErrorBoundary segmentType="chart">
18
+ * <ChartComponent data={data} />
19
+ * </ErrorBoundary>
20
+ * ```
21
+ *
22
+ * @example With custom fallback
23
+ * ```tsx
24
+ * <ErrorBoundary
25
+ * segmentType="table"
26
+ * fallback={(error, type) => <div>Failed to render {type}: {error.message}</div>}
27
+ * >
28
+ * <TableComponent data={data} />
29
+ * </ErrorBoundary>
30
+ * ```
31
+ */
32
+ export class ErrorBoundary extends Component {
33
+ constructor(props) {
34
+ super(props);
35
+ this.state = { hasError: false, error: null };
36
+ }
37
+ static getDerivedStateFromError(error) {
38
+ return { hasError: true, error };
39
+ }
40
+ componentDidCatch(error, errorInfo) {
41
+ // Log the error for debugging
42
+ console.error(`XmlRender ErrorBoundary: Failed to render segment type "${this.props.segmentType}"`, error, errorInfo.componentStack);
43
+ }
44
+ render() {
45
+ if (this.state.hasError && this.state.error) {
46
+ // Use custom fallback if provided
47
+ if (this.props.fallback) {
48
+ return this.props.fallback(this.state.error, this.props.segmentType);
49
+ }
50
+ // Development: show detailed error info
51
+ if (process.env.NODE_ENV === "development") {
52
+ return (_jsxs("span", { style: {
53
+ display: "inline-block",
54
+ padding: "4px 8px",
55
+ backgroundColor: "#fee2e2",
56
+ border: "1px solid #ef4444",
57
+ borderRadius: "4px",
58
+ color: "#991b1b",
59
+ fontSize: "12px",
60
+ fontFamily: "monospace",
61
+ }, children: ["Error in [", this.props.segmentType, "]: ", this.state.error.message] }));
62
+ }
63
+ // Production: minimal hidden fallback
64
+ return _jsx("span", { style: { display: "none" } });
65
+ }
66
+ return this.props.children;
67
+ }
68
+ }
69
+ //# sourceMappingURL=ErrorBoundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorBoundary.js","sourceRoot":"","sources":["../../src/react/ErrorBoundary.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AACH,OAAc,EAAE,SAAS,EAAkC,MAAM,OAAO,CAAC;AAsBzE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,aAAc,SAAQ,SAGlC;IACC,YAAY,KAAyB;QACnC,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAChD,CAAC;IAED,MAAM,CAAC,wBAAwB,CAAC,KAAY;QAC1C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACnC,CAAC;IAED,iBAAiB,CAAC,KAAY,EAAE,SAAoB;QAClD,8BAA8B;QAC9B,OAAO,CAAC,KAAK,CACX,2DAA2D,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,EACpF,KAAK,EACL,SAAS,CAAC,cAAc,CACzB,CAAC;IACJ,CAAC;IAED,MAAM;QACJ,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YAC5C,kCAAkC;YAClC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACxB,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YACvE,CAAC;YAED,wCAAwC;YACxC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;gBAC3C,OAAO,CACL,gBACE,KAAK,EAAE;wBACL,OAAO,EAAE,cAAc;wBACvB,OAAO,EAAE,SAAS;wBAClB,eAAe,EAAE,SAAS;wBAC1B,MAAM,EAAE,mBAAmB;wBAC3B,YAAY,EAAE,KAAK;wBACnB,KAAK,EAAE,SAAS;wBAChB,QAAQ,EAAE,MAAM;wBAChB,UAAU,EAAE,WAAW;qBACxB,2BAEU,IAAI,CAAC,KAAK,CAAC,WAAW,SAAK,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,IACzD,CACR,CAAC;YACJ,CAAC;YAED,sCAAsC;YACtC,OAAO,eAAM,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAI,CAAC;QAC9C,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * XmlRender Component for React
3
+ *
4
+ * Renders an array of parsed segments using the component catalog.
5
+ * Each segment is rendered by its corresponding component from the catalog.
6
+ */
7
+ import { type ReactElement, type ReactNode } from "react";
8
+ import type { TagDefinitions } from "../registry";
9
+ import type { Segments, ParsedSegment } from "../parser";
10
+ import type { Catalog } from "./catalog";
11
+ /**
12
+ * Props for the XmlRender component
13
+ */
14
+ export interface XmlRenderProps<TDefs extends TagDefinitions> {
15
+ /** Array of parsed segments to render */
16
+ segments: Segments<TDefs>;
17
+ /** Optional fallback renderer for unknown segment types */
18
+ fallback?: (segment: ParsedSegment<TDefs>, index: number) => ReactNode;
19
+ /** Optional catalog override (uses context catalog if not provided) */
20
+ catalog?: Catalog<TDefs>;
21
+ /** Optional custom error fallback renderer */
22
+ errorFallback?: (error: Error, segmentType: string) => ReactNode;
23
+ }
24
+ /**
25
+ * Renders an array of parsed XML segments using the component catalog.
26
+ *
27
+ * Each segment is matched to its corresponding renderer component from the catalog.
28
+ * Text segments use the catalog's text renderer or a default span renderer.
29
+ * Unknown segment types use the fallback prop or render content as plain text.
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * import { XmlRender, XmlRenderProvider } from '@aura/xml-render/react';
34
+ * import { createParser } from '@aura/xml-render';
35
+ * import { registry, catalog } from './xml-config';
36
+ *
37
+ * function RichContent({ text }: { text: string }) {
38
+ * const parser = createParser(registry);
39
+ * const segments = parser.parse(text);
40
+ *
41
+ * return (
42
+ * <XmlRenderProvider catalog={catalog}>
43
+ * <XmlRender segments={segments} />
44
+ * </XmlRenderProvider>
45
+ * );
46
+ * }
47
+ * ```
48
+ *
49
+ * @example With custom fallback
50
+ * ```tsx
51
+ * <XmlRender
52
+ * segments={segments}
53
+ * fallback={(segment, index) => (
54
+ * <div className="unknown-segment">
55
+ * Unknown: {segment.type} - {segment.content}
56
+ * </div>
57
+ * )}
58
+ * />
59
+ * ```
60
+ */
61
+ export declare function XmlRender<TDefs extends TagDefinitions>({ segments, fallback, catalog: catalogProp, errorFallback, }: XmlRenderProps<TDefs>): ReactElement;
62
+ //# sourceMappingURL=XmlRender.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XmlRender.d.ts","sourceRoot":"","sources":["../../src/react/XmlRender.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAc,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAEzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,KAAK,SAAS,cAAc;IAC1D,yCAAyC;IACzC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;IACvE,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACzB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,SAAS,CAAC;CAClE;AAqED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,SAAS,CAAC,KAAK,SAAS,cAAc,EAAE,EACtD,QAAQ,EACR,QAAQ,EACR,OAAO,EAAE,WAAW,EACpB,aAAa,GACd,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAwBtC"}
@@ -0,0 +1,90 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useXmlRenderContext } from "./context";
3
+ import { ErrorBoundary } from "./ErrorBoundary";
4
+ /**
5
+ * Default text renderer - renders plain text in a span
6
+ */
7
+ function DefaultTextRenderer({ segment, }) {
8
+ return _jsx("span", { children: segment.content });
9
+ }
10
+ /**
11
+ * Default fallback renderer for unknown segment types
12
+ */
13
+ function DefaultFallback({ segment, }) {
14
+ // In development, show a warning; in production, render content as text
15
+ if (process.env.NODE_ENV === "development") {
16
+ console.warn(`XmlRender: No renderer found for segment type "${String(segment.type)}"`);
17
+ }
18
+ return _jsx("span", { children: segment.content });
19
+ }
20
+ /**
21
+ * Render a single segment using the catalog (without key or ErrorBoundary wrapper)
22
+ */
23
+ function renderSegmentContent(segment, index, catalog, fallback) {
24
+ const segmentType = segment.type;
25
+ // Handle text segments
26
+ if (segmentType === "text") {
27
+ const TextRenderer = catalog.getTextRenderer();
28
+ if (TextRenderer) {
29
+ return (_jsx(TextRenderer, { segment: segment, index: index }));
30
+ }
31
+ return _jsx(DefaultTextRenderer, { segment: segment });
32
+ }
33
+ // Handle registered tag segments
34
+ const Renderer = catalog.getRenderer(segmentType);
35
+ if (Renderer) {
36
+ return _jsx(Renderer, { segment: segment, index: index });
37
+ }
38
+ // Use fallback for unknown segment types
39
+ if (fallback) {
40
+ return fallback(segment, index);
41
+ }
42
+ return _jsx(DefaultFallback, { segment: segment });
43
+ }
44
+ /**
45
+ * Renders an array of parsed XML segments using the component catalog.
46
+ *
47
+ * Each segment is matched to its corresponding renderer component from the catalog.
48
+ * Text segments use the catalog's text renderer or a default span renderer.
49
+ * Unknown segment types use the fallback prop or render content as plain text.
50
+ *
51
+ * @example
52
+ * ```tsx
53
+ * import { XmlRender, XmlRenderProvider } from '@aura/xml-render/react';
54
+ * import { createParser } from '@aura/xml-render';
55
+ * import { registry, catalog } from './xml-config';
56
+ *
57
+ * function RichContent({ text }: { text: string }) {
58
+ * const parser = createParser(registry);
59
+ * const segments = parser.parse(text);
60
+ *
61
+ * return (
62
+ * <XmlRenderProvider catalog={catalog}>
63
+ * <XmlRender segments={segments} />
64
+ * </XmlRenderProvider>
65
+ * );
66
+ * }
67
+ * ```
68
+ *
69
+ * @example With custom fallback
70
+ * ```tsx
71
+ * <XmlRender
72
+ * segments={segments}
73
+ * fallback={(segment, index) => (
74
+ * <div className="unknown-segment">
75
+ * Unknown: {segment.type} - {segment.content}
76
+ * </div>
77
+ * )}
78
+ * />
79
+ * ```
80
+ */
81
+ export function XmlRender({ segments, fallback, catalog: catalogProp, errorFallback, }) {
82
+ // Use provided catalog or get from context
83
+ const contextValue = catalogProp ? null : useXmlRenderContext();
84
+ const catalog = catalogProp ?? contextValue?.catalog;
85
+ if (!catalog) {
86
+ throw new Error("XmlRender requires a catalog prop or must be used within XmlRenderProvider");
87
+ }
88
+ return (_jsx(_Fragment, { children: segments.map((segment, index) => (_jsx(ErrorBoundary, { segmentType: String(segment.type), fallback: errorFallback, children: renderSegmentContent(segment, index, catalog, fallback) }, index))) }));
89
+ }
90
+ //# sourceMappingURL=XmlRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XmlRender.js","sourceRoot":"","sources":["../../src/react/XmlRender.tsx"],"names":[],"mappings":";AASA,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAgBhD;;GAEG;AACH,SAAS,mBAAmB,CAA+B,EACzD,OAAO,GAGR;IACC,OAAO,yBAAO,OAAO,CAAC,OAAO,GAAQ,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAA+B,EACrD,OAAO,GAGR;IACC,wEAAwE;IACxE,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC3C,OAAO,CAAC,IAAI,CACV,kDAAkD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAC1E,CAAC;IACJ,CAAC;IACD,OAAO,yBAAO,OAAO,CAAC,OAAO,GAAQ,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAC3B,OAA6B,EAC7B,KAAa,EACb,OAAuB,EACvB,QAAsE;IAEtE,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAEjC,uBAAuB;IACvB,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;QAC3B,MAAM,YAAY,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;QAC/C,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CACL,KAAC,YAAY,IACX,OAAO,EAAE,OAAuC,EAChD,KAAK,EAAE,KAAK,GACZ,CACH,CAAC;QACJ,CAAC;QACD,OAAO,KAAC,mBAAmB,IAAC,OAAO,EAAE,OAAuC,GAAI,CAAC;IACnF,CAAC;IAED,iCAAiC;IACjC,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,WAA0B,CAAC,CAAC;IACjE,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,KAAC,QAAQ,IAAC,OAAO,EAAE,OAA4C,EAAE,KAAK,EAAE,KAAK,GAAI,CAAC;IAC3F,CAAC;IAED,yCAAyC;IACzC,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,KAAC,eAAe,IAAC,OAAO,EAAE,OAAO,GAAI,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,UAAU,SAAS,CAA+B,EACtD,QAAQ,EACR,QAAQ,EACR,OAAO,EAAE,WAAW,EACpB,aAAa,GACS;IACtB,2CAA2C;IAC3C,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAmB,EAAS,CAAC;IACvE,MAAM,OAAO,GAAG,WAAW,IAAI,YAAY,EAAE,OAAO,CAAC;IAErD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,4EAA4E,CAC7E,CAAC;IACJ,CAAC;IAED,OAAO,CACL,4BACG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAChC,KAAC,aAAa,IAEZ,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EACjC,QAAQ,EAAE,aAAa,YAEtB,oBAAoB,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,IAJnD,KAAK,CAKI,CACjB,CAAC,GACD,CACJ,CAAC;AACJ,CAAC"}