@json-render/image 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.
package/dist/index.js ADDED
@@ -0,0 +1,600 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ renderToPng: () => renderToPng,
34
+ renderToSvg: () => renderToSvg,
35
+ schema: () => schema,
36
+ standardComponentDefinitions: () => standardComponentDefinitions,
37
+ standardComponents: () => standardComponents
38
+ });
39
+ module.exports = __toCommonJS(index_exports);
40
+
41
+ // src/schema.ts
42
+ var import_core = require("@json-render/core");
43
+ var schema = (0, import_core.defineSchema)(
44
+ (s) => ({
45
+ spec: s.object({
46
+ root: s.string(),
47
+ elements: s.record(
48
+ s.object({
49
+ type: s.ref("catalog.components"),
50
+ props: s.propsOf("catalog.components"),
51
+ children: s.array(s.string()),
52
+ visible: s.any()
53
+ })
54
+ )
55
+ }),
56
+ catalog: s.object({
57
+ components: s.map({
58
+ props: s.zod(),
59
+ slots: s.array(s.string()),
60
+ description: s.string(),
61
+ example: s.any()
62
+ })
63
+ })
64
+ }),
65
+ {
66
+ defaultRules: [
67
+ "The root element MUST be a Frame component. It defines the image dimensions (width, height) and background.",
68
+ "Frame width and height determine the output image size. Common sizes: 1200x630 (OG image), 1080x1080 (social square), 1920x1080 (banner).",
69
+ "Use Row for horizontal layouts and Column for vertical layouts. Both support gap, align, and justify props.",
70
+ "All text content must use Heading or Text components. Raw strings are not supported.",
71
+ "Image src must be a fully qualified URL. For placeholder images, use https://picsum.photos/{width}/{height}?random={n}.",
72
+ "Satori renders a subset of CSS: flexbox layout, borders, backgrounds, text styling. Absolute positioning is supported via position/top/left/right/bottom.",
73
+ "CRITICAL INTEGRITY CHECK: Before outputting ANY element that references children, you MUST have already output (or will output) each child as its own element. If an element has children: ['a', 'b'], then elements 'a' and 'b' MUST exist."
74
+ ]
75
+ }
76
+ );
77
+
78
+ // src/components/standard.tsx
79
+ var import_jsx_runtime = require("react/jsx-runtime");
80
+ var headingSizes = {
81
+ h1: 48,
82
+ h2: 36,
83
+ h3: 28,
84
+ h4: 22
85
+ };
86
+ var headingWeights = {
87
+ h1: 700,
88
+ h2: 700,
89
+ h3: 600,
90
+ h4: 600
91
+ };
92
+ function cleanStyle(raw) {
93
+ const out = {};
94
+ for (const k in raw) {
95
+ if (raw[k] !== void 0 && raw[k] !== null) {
96
+ out[k] = raw[k];
97
+ }
98
+ }
99
+ return out;
100
+ }
101
+ function FrameComponent({
102
+ element,
103
+ children
104
+ }) {
105
+ const p = element.props;
106
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
107
+ "div",
108
+ {
109
+ style: cleanStyle({
110
+ display: p.display ?? "flex",
111
+ flexDirection: p.flexDirection ?? "column",
112
+ width: p.width,
113
+ height: p.height,
114
+ backgroundColor: p.backgroundColor ?? "white",
115
+ padding: p.padding,
116
+ alignItems: p.alignItems,
117
+ justifyContent: p.justifyContent
118
+ }),
119
+ children
120
+ }
121
+ );
122
+ }
123
+ function BoxComponent({
124
+ element,
125
+ children
126
+ }) {
127
+ const p = element.props;
128
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
129
+ "div",
130
+ {
131
+ style: cleanStyle({
132
+ display: "flex",
133
+ flexDirection: p.flexDirection ?? "column",
134
+ padding: p.padding,
135
+ paddingTop: p.paddingTop,
136
+ paddingBottom: p.paddingBottom,
137
+ paddingLeft: p.paddingLeft,
138
+ paddingRight: p.paddingRight,
139
+ margin: p.margin,
140
+ backgroundColor: p.backgroundColor,
141
+ borderWidth: p.borderWidth,
142
+ borderColor: p.borderColor,
143
+ borderRadius: p.borderRadius,
144
+ borderStyle: p.borderWidth ? "solid" : void 0,
145
+ flex: p.flex,
146
+ width: p.width,
147
+ height: p.height,
148
+ alignItems: p.alignItems,
149
+ justifyContent: p.justifyContent,
150
+ position: p.position,
151
+ top: p.top,
152
+ left: p.left,
153
+ right: p.right,
154
+ bottom: p.bottom,
155
+ overflow: p.overflow
156
+ }),
157
+ children
158
+ }
159
+ );
160
+ }
161
+ function RowComponent({
162
+ element,
163
+ children
164
+ }) {
165
+ const p = element.props;
166
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
167
+ "div",
168
+ {
169
+ style: cleanStyle({
170
+ display: "flex",
171
+ flexDirection: "row",
172
+ gap: p.gap,
173
+ alignItems: p.alignItems,
174
+ justifyContent: p.justifyContent,
175
+ padding: p.padding,
176
+ flex: p.flex,
177
+ flexWrap: p.wrap ? "wrap" : void 0
178
+ }),
179
+ children
180
+ }
181
+ );
182
+ }
183
+ function ColumnComponent({
184
+ element,
185
+ children
186
+ }) {
187
+ const p = element.props;
188
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
189
+ "div",
190
+ {
191
+ style: cleanStyle({
192
+ display: "flex",
193
+ flexDirection: "column",
194
+ gap: p.gap,
195
+ alignItems: p.alignItems,
196
+ justifyContent: p.justifyContent,
197
+ padding: p.padding,
198
+ flex: p.flex
199
+ }),
200
+ children
201
+ }
202
+ );
203
+ }
204
+ function HeadingComponent({
205
+ element
206
+ }) {
207
+ const p = element.props;
208
+ const level = p.level ?? "h2";
209
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
210
+ "div",
211
+ {
212
+ style: cleanStyle({
213
+ display: "flex",
214
+ fontSize: headingSizes[level] ?? 36,
215
+ fontWeight: headingWeights[level] ?? 700,
216
+ color: p.color ?? "black",
217
+ textAlign: p.align ?? "left",
218
+ letterSpacing: p.letterSpacing,
219
+ lineHeight: p.lineHeight ?? 1.2
220
+ }),
221
+ children: p.text
222
+ }
223
+ );
224
+ }
225
+ function TextComponent({
226
+ element
227
+ }) {
228
+ const p = element.props;
229
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
230
+ "div",
231
+ {
232
+ style: cleanStyle({
233
+ display: "flex",
234
+ fontSize: p.fontSize ?? 16,
235
+ color: p.color ?? "black",
236
+ textAlign: p.align ?? "left",
237
+ fontWeight: p.fontWeight === "bold" ? 700 : 400,
238
+ fontStyle: p.fontStyle ?? "normal",
239
+ lineHeight: p.lineHeight ?? 1.4,
240
+ letterSpacing: p.letterSpacing,
241
+ textDecoration: p.textDecoration
242
+ }),
243
+ children: p.text
244
+ }
245
+ );
246
+ }
247
+ function ImageComponent({
248
+ element
249
+ }) {
250
+ const p = element.props;
251
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
252
+ "img",
253
+ {
254
+ src: p.src,
255
+ width: p.width ?? void 0,
256
+ height: p.height ?? void 0,
257
+ style: cleanStyle({
258
+ borderRadius: p.borderRadius,
259
+ objectFit: p.objectFit ?? "contain"
260
+ })
261
+ }
262
+ );
263
+ }
264
+ function DividerComponent({
265
+ element
266
+ }) {
267
+ const p = element.props;
268
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
269
+ "div",
270
+ {
271
+ style: {
272
+ display: "flex",
273
+ width: "100%",
274
+ borderBottom: `${p.thickness ?? 1}px solid ${p.color ?? "#e5e7eb"}`,
275
+ marginTop: p.marginTop ?? 8,
276
+ marginBottom: p.marginBottom ?? 8
277
+ }
278
+ }
279
+ );
280
+ }
281
+ function SpacerComponent({
282
+ element
283
+ }) {
284
+ const p = element.props;
285
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", height: p.height ?? 20 } });
286
+ }
287
+ var standardComponents = {
288
+ Frame: FrameComponent,
289
+ Box: BoxComponent,
290
+ Row: RowComponent,
291
+ Column: ColumnComponent,
292
+ Heading: HeadingComponent,
293
+ Text: TextComponent,
294
+ Image: ImageComponent,
295
+ Divider: DividerComponent,
296
+ Spacer: SpacerComponent
297
+ };
298
+
299
+ // src/render.tsx
300
+ var import_satori = __toESM(require("satori"));
301
+ var import_core2 = require("@json-render/core");
302
+ var import_jsx_runtime2 = require("react/jsx-runtime");
303
+ var noopEmit = () => {
304
+ };
305
+ function renderElement(elementKey, spec, registry, stateModel, repeatItem, repeatIndex, repeatBasePath) {
306
+ const element = spec.elements[elementKey];
307
+ if (!element) return null;
308
+ const ctx = {
309
+ stateModel,
310
+ repeatItem,
311
+ repeatIndex,
312
+ repeatBasePath
313
+ };
314
+ if (element.visible !== void 0) {
315
+ if (!(0, import_core2.evaluateVisibility)(element.visible, ctx)) {
316
+ return null;
317
+ }
318
+ }
319
+ const resolvedProps = (0, import_core2.resolveElementProps)(
320
+ element.props,
321
+ ctx
322
+ );
323
+ const resolvedElement = { ...element, props: resolvedProps };
324
+ const Component = registry[resolvedElement.type];
325
+ if (!Component) return null;
326
+ if (resolvedElement.repeat) {
327
+ const items = (0, import_core2.getByPath)(stateModel, resolvedElement.repeat.statePath) ?? [];
328
+ const fragments = items.map((item, index) => {
329
+ const key = resolvedElement.repeat.key && typeof item === "object" && item !== null ? String(
330
+ item[resolvedElement.repeat.key] ?? index
331
+ ) : String(index);
332
+ const childPath = `${resolvedElement.repeat.statePath}/${index}`;
333
+ const children2 = resolvedElement.children?.map(
334
+ (childKey) => renderElement(
335
+ childKey,
336
+ spec,
337
+ registry,
338
+ stateModel,
339
+ item,
340
+ index,
341
+ childPath
342
+ )
343
+ );
344
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Component, { element: resolvedElement, emit: noopEmit, children: children2 }, key);
345
+ });
346
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fragments });
347
+ }
348
+ const children = resolvedElement.children?.map(
349
+ (childKey) => renderElement(
350
+ childKey,
351
+ spec,
352
+ registry,
353
+ stateModel,
354
+ repeatItem,
355
+ repeatIndex,
356
+ repeatBasePath
357
+ )
358
+ );
359
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Component, { element: resolvedElement, emit: noopEmit, children: children && children.length > 0 ? children : void 0 }, elementKey);
360
+ }
361
+ function getDimensions(spec, options = {}) {
362
+ if (options.width && options.height) {
363
+ return { width: options.width, height: options.height };
364
+ }
365
+ const rootElement = spec.elements[spec.root];
366
+ const props = rootElement?.props;
367
+ return {
368
+ width: options.width ?? props?.width ?? 1200,
369
+ height: options.height ?? props?.height ?? 630
370
+ };
371
+ }
372
+ function buildTree(spec, options = {}) {
373
+ const {
374
+ registry: customRegistry,
375
+ includeStandard = true,
376
+ state = {}
377
+ } = options;
378
+ const mergedState = {
379
+ ...spec.state,
380
+ ...state
381
+ };
382
+ const registry = {
383
+ ...includeStandard ? standardComponents : {},
384
+ ...customRegistry
385
+ };
386
+ const root = renderElement(spec.root, spec, registry, mergedState);
387
+ return root ?? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, {});
388
+ }
389
+ async function renderToSvg(spec, options = {}) {
390
+ const tree = buildTree(spec, options);
391
+ const { width, height } = getDimensions(spec, options);
392
+ return (0, import_satori.default)(tree, {
393
+ width,
394
+ height,
395
+ fonts: options.fonts ?? []
396
+ });
397
+ }
398
+ async function renderToPng(spec, options = {}) {
399
+ const svg = await renderToSvg(spec, options);
400
+ let Resvg;
401
+ try {
402
+ const mod = await import("@resvg/resvg-js");
403
+ Resvg = mod.Resvg;
404
+ } catch {
405
+ throw new Error(
406
+ "@resvg/resvg-js is required for PNG output. Install it with: npm install @resvg/resvg-js"
407
+ );
408
+ }
409
+ const resvg = new Resvg(svg);
410
+ const pngData = resvg.render();
411
+ return pngData.asPng();
412
+ }
413
+
414
+ // src/catalog.ts
415
+ var import_zod = require("zod");
416
+ var standardComponentDefinitions = {
417
+ // ==========================================================================
418
+ // Root
419
+ // ==========================================================================
420
+ Frame: {
421
+ props: import_zod.z.object({
422
+ width: import_zod.z.number(),
423
+ height: import_zod.z.number(),
424
+ backgroundColor: import_zod.z.string().nullable(),
425
+ padding: import_zod.z.number().nullable(),
426
+ display: import_zod.z.enum(["flex", "none"]).nullable(),
427
+ flexDirection: import_zod.z.enum(["row", "column"]).nullable(),
428
+ alignItems: import_zod.z.enum(["flex-start", "center", "flex-end", "stretch"]).nullable(),
429
+ justifyContent: import_zod.z.enum([
430
+ "flex-start",
431
+ "center",
432
+ "flex-end",
433
+ "space-between",
434
+ "space-around"
435
+ ]).nullable()
436
+ }),
437
+ slots: ["default"],
438
+ description: "Root image container. Defines the output image dimensions and background. Must be the root element.",
439
+ example: { width: 1200, height: 630, backgroundColor: "#ffffff" }
440
+ },
441
+ // ==========================================================================
442
+ // Layout Components
443
+ // ==========================================================================
444
+ Box: {
445
+ props: import_zod.z.object({
446
+ padding: import_zod.z.number().nullable(),
447
+ paddingTop: import_zod.z.number().nullable(),
448
+ paddingBottom: import_zod.z.number().nullable(),
449
+ paddingLeft: import_zod.z.number().nullable(),
450
+ paddingRight: import_zod.z.number().nullable(),
451
+ margin: import_zod.z.number().nullable(),
452
+ backgroundColor: import_zod.z.string().nullable(),
453
+ borderWidth: import_zod.z.number().nullable(),
454
+ borderColor: import_zod.z.string().nullable(),
455
+ borderRadius: import_zod.z.number().nullable(),
456
+ flex: import_zod.z.number().nullable(),
457
+ width: import_zod.z.union([import_zod.z.number(), import_zod.z.string()]).nullable(),
458
+ height: import_zod.z.union([import_zod.z.number(), import_zod.z.string()]).nullable(),
459
+ alignItems: import_zod.z.enum(["flex-start", "center", "flex-end", "stretch"]).nullable(),
460
+ justifyContent: import_zod.z.enum([
461
+ "flex-start",
462
+ "center",
463
+ "flex-end",
464
+ "space-between",
465
+ "space-around"
466
+ ]).nullable(),
467
+ flexDirection: import_zod.z.enum(["row", "column"]).nullable(),
468
+ position: import_zod.z.enum(["relative", "absolute"]).nullable(),
469
+ top: import_zod.z.number().nullable(),
470
+ left: import_zod.z.number().nullable(),
471
+ right: import_zod.z.number().nullable(),
472
+ bottom: import_zod.z.number().nullable(),
473
+ overflow: import_zod.z.enum(["visible", "hidden"]).nullable()
474
+ }),
475
+ slots: ["default"],
476
+ description: "Generic container with padding, margin, background, border, and flex alignment. Supports absolute positioning.",
477
+ example: {
478
+ padding: 20,
479
+ backgroundColor: "#f9f9f9",
480
+ borderRadius: 8,
481
+ alignItems: "center"
482
+ }
483
+ },
484
+ Row: {
485
+ props: import_zod.z.object({
486
+ gap: import_zod.z.number().nullable(),
487
+ alignItems: import_zod.z.enum(["flex-start", "center", "flex-end", "stretch"]).nullable(),
488
+ justifyContent: import_zod.z.enum([
489
+ "flex-start",
490
+ "center",
491
+ "flex-end",
492
+ "space-between",
493
+ "space-around"
494
+ ]).nullable(),
495
+ padding: import_zod.z.number().nullable(),
496
+ flex: import_zod.z.number().nullable(),
497
+ wrap: import_zod.z.boolean().nullable()
498
+ }),
499
+ slots: ["default"],
500
+ description: "Horizontal flex layout. Use for placing elements side by side.",
501
+ example: { gap: 10, alignItems: "center" }
502
+ },
503
+ Column: {
504
+ props: import_zod.z.object({
505
+ gap: import_zod.z.number().nullable(),
506
+ alignItems: import_zod.z.enum(["flex-start", "center", "flex-end", "stretch"]).nullable(),
507
+ justifyContent: import_zod.z.enum([
508
+ "flex-start",
509
+ "center",
510
+ "flex-end",
511
+ "space-between",
512
+ "space-around"
513
+ ]).nullable(),
514
+ padding: import_zod.z.number().nullable(),
515
+ flex: import_zod.z.number().nullable()
516
+ }),
517
+ slots: ["default"],
518
+ description: "Vertical flex layout. Use for stacking elements top to bottom.",
519
+ example: { gap: 8, padding: 10 }
520
+ },
521
+ // ==========================================================================
522
+ // Content Components
523
+ // ==========================================================================
524
+ Heading: {
525
+ props: import_zod.z.object({
526
+ text: import_zod.z.string(),
527
+ level: import_zod.z.enum(["h1", "h2", "h3", "h4"]).nullable(),
528
+ color: import_zod.z.string().nullable(),
529
+ align: import_zod.z.enum(["left", "center", "right"]).nullable(),
530
+ letterSpacing: import_zod.z.union([import_zod.z.number(), import_zod.z.string()]).nullable(),
531
+ lineHeight: import_zod.z.number().nullable()
532
+ }),
533
+ slots: [],
534
+ description: "Heading text at various levels. h1 is largest, h4 is smallest.",
535
+ example: { text: "Hello World", level: "h1", color: "#000000" }
536
+ },
537
+ Text: {
538
+ props: import_zod.z.object({
539
+ text: import_zod.z.string(),
540
+ fontSize: import_zod.z.number().nullable(),
541
+ color: import_zod.z.string().nullable(),
542
+ align: import_zod.z.enum(["left", "center", "right"]).nullable(),
543
+ fontWeight: import_zod.z.enum(["normal", "bold"]).nullable(),
544
+ fontStyle: import_zod.z.enum(["normal", "italic"]).nullable(),
545
+ lineHeight: import_zod.z.number().nullable(),
546
+ letterSpacing: import_zod.z.union([import_zod.z.number(), import_zod.z.string()]).nullable(),
547
+ textDecoration: import_zod.z.enum(["none", "underline", "line-through"]).nullable()
548
+ }),
549
+ slots: [],
550
+ description: "Body text with configurable size, color, weight, and alignment.",
551
+ example: { text: "Some content here.", fontSize: 16, color: "#333333" }
552
+ },
553
+ Image: {
554
+ props: import_zod.z.object({
555
+ src: import_zod.z.string(),
556
+ width: import_zod.z.number().nullable(),
557
+ height: import_zod.z.number().nullable(),
558
+ borderRadius: import_zod.z.number().nullable(),
559
+ objectFit: import_zod.z.enum(["contain", "cover", "fill", "none"]).nullable()
560
+ }),
561
+ slots: [],
562
+ description: "Image from a URL. Specify width and/or height to control size. For placeholder images use https://picsum.photos/{width}/{height}?random={n}.",
563
+ example: {
564
+ src: "https://picsum.photos/400/300?random=1",
565
+ width: 400,
566
+ height: 300
567
+ }
568
+ },
569
+ // ==========================================================================
570
+ // Decorative Components
571
+ // ==========================================================================
572
+ Divider: {
573
+ props: import_zod.z.object({
574
+ color: import_zod.z.string().nullable(),
575
+ thickness: import_zod.z.number().nullable(),
576
+ marginTop: import_zod.z.number().nullable(),
577
+ marginBottom: import_zod.z.number().nullable()
578
+ }),
579
+ slots: [],
580
+ description: "Horizontal line separator between content sections.",
581
+ example: { color: "#e5e7eb", thickness: 1 }
582
+ },
583
+ Spacer: {
584
+ props: import_zod.z.object({
585
+ height: import_zod.z.number().nullable()
586
+ }),
587
+ slots: [],
588
+ description: "Empty vertical space between elements.",
589
+ example: { height: 20 }
590
+ }
591
+ };
592
+ // Annotate the CommonJS export names for ESM import in node:
593
+ 0 && (module.exports = {
594
+ renderToPng,
595
+ renderToSvg,
596
+ schema,
597
+ standardComponentDefinitions,
598
+ standardComponents
599
+ });
600
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/schema.ts","../src/components/standard.tsx","../src/render.tsx","../src/catalog.ts"],"sourcesContent":["// Schema\nexport { schema, type ImageSchema, type ImageSpec } from \"./schema\";\n\n// Core types (re-exported for convenience)\nexport type { Spec } from \"@json-render/core\";\n\n// Catalog-aware types\nexport type {\n SetState,\n StateModel,\n ComponentContext,\n ComponentFn,\n Components,\n} from \"./catalog-types\";\n\n// Renderer types\nexport type {\n ComponentRenderProps,\n ComponentRenderer,\n ComponentRegistry,\n} from \"./types\";\n\n// Standard components\nexport { standardComponents } from \"./components\";\n\n// Server-side render functions\nexport { renderToSvg, renderToPng, type RenderOptions } from \"./render\";\n\n// Catalog definitions\nexport {\n standardComponentDefinitions,\n type StandardComponentDefinitions,\n type StandardComponentProps,\n} from \"./catalog\";\n","import { defineSchema } from \"@json-render/core\";\n\n/**\n * The schema for @json-render/image\n *\n * Defines:\n * - Spec: A flat tree of elements with keys, types, props, and children references\n * - Catalog: Components with props schemas\n *\n * Reuses the same { root, elements } spec format as the React and React PDF renderers.\n */\nexport const schema = defineSchema(\n (s) => ({\n spec: s.object({\n root: s.string(),\n elements: s.record(\n s.object({\n type: s.ref(\"catalog.components\"),\n props: s.propsOf(\"catalog.components\"),\n children: s.array(s.string()),\n visible: s.any(),\n }),\n ),\n }),\n\n catalog: s.object({\n components: s.map({\n props: s.zod(),\n slots: s.array(s.string()),\n description: s.string(),\n example: s.any(),\n }),\n }),\n }),\n {\n defaultRules: [\n \"The root element MUST be a Frame component. It defines the image dimensions (width, height) and background.\",\n \"Frame width and height determine the output image size. Common sizes: 1200x630 (OG image), 1080x1080 (social square), 1920x1080 (banner).\",\n \"Use Row for horizontal layouts and Column for vertical layouts. Both support gap, align, and justify props.\",\n \"All text content must use Heading or Text components. Raw strings are not supported.\",\n \"Image src must be a fully qualified URL. For placeholder images, use https://picsum.photos/{width}/{height}?random={n}.\",\n \"Satori renders a subset of CSS: flexbox layout, borders, backgrounds, text styling. Absolute positioning is supported via position/top/left/right/bottom.\",\n \"CRITICAL INTEGRITY CHECK: Before outputting ANY element that references children, you MUST have already output (or will output) each child as its own element. If an element has children: ['a', 'b'], then elements 'a' and 'b' MUST exist.\",\n ],\n },\n);\n\nexport type ImageSchema = typeof schema;\n\nexport type ImageSpec<TCatalog> = typeof schema extends {\n createCatalog: (catalog: TCatalog) => { _specType: infer S };\n}\n ? S\n : never;\n","import React from \"react\";\nimport type { ComponentRenderProps, ComponentRegistry } from \"../types\";\nimport type { StandardComponentProps } from \"../catalog\";\n\nconst headingSizes: Record<string, number> = {\n h1: 48,\n h2: 36,\n h3: 28,\n h4: 22,\n};\n\nconst headingWeights: Record<string, number> = {\n h1: 700,\n h2: 700,\n h3: 600,\n h4: 600,\n};\n\n/**\n * Satori crashes on explicit `undefined` style values (e.g. `padding: undefined`).\n * Strip them so only defined properties are passed.\n */\nfunction cleanStyle(raw: Record<string, unknown>): React.CSSProperties {\n const out: Record<string, unknown> = {};\n for (const k in raw) {\n if (raw[k] !== undefined && raw[k] !== null) {\n out[k] = raw[k];\n }\n }\n return out as React.CSSProperties;\n}\n\n// =============================================================================\n// Root\n// =============================================================================\n\nfunction FrameComponent({\n element,\n children,\n}: ComponentRenderProps<StandardComponentProps<\"Frame\">>) {\n const p = element.props;\n\n return (\n <div\n style={cleanStyle({\n display: p.display ?? \"flex\",\n flexDirection: p.flexDirection ?? \"column\",\n width: p.width,\n height: p.height,\n backgroundColor: p.backgroundColor ?? \"white\",\n padding: p.padding,\n alignItems: p.alignItems,\n justifyContent: p.justifyContent,\n })}\n >\n {children}\n </div>\n );\n}\n\n// =============================================================================\n// Layout Components\n// =============================================================================\n\nfunction BoxComponent({\n element,\n children,\n}: ComponentRenderProps<StandardComponentProps<\"Box\">>) {\n const p = element.props;\n\n return (\n <div\n style={cleanStyle({\n display: \"flex\",\n flexDirection: p.flexDirection ?? \"column\",\n padding: p.padding,\n paddingTop: p.paddingTop,\n paddingBottom: p.paddingBottom,\n paddingLeft: p.paddingLeft,\n paddingRight: p.paddingRight,\n margin: p.margin,\n backgroundColor: p.backgroundColor,\n borderWidth: p.borderWidth,\n borderColor: p.borderColor,\n borderRadius: p.borderRadius,\n borderStyle: p.borderWidth ? \"solid\" : undefined,\n flex: p.flex,\n width: p.width,\n height: p.height,\n alignItems: p.alignItems,\n justifyContent: p.justifyContent,\n position: p.position,\n top: p.top,\n left: p.left,\n right: p.right,\n bottom: p.bottom,\n overflow: p.overflow,\n })}\n >\n {children}\n </div>\n );\n}\n\nfunction RowComponent({\n element,\n children,\n}: ComponentRenderProps<StandardComponentProps<\"Row\">>) {\n const p = element.props;\n\n return (\n <div\n style={cleanStyle({\n display: \"flex\",\n flexDirection: \"row\",\n gap: p.gap,\n alignItems: p.alignItems,\n justifyContent: p.justifyContent,\n padding: p.padding,\n flex: p.flex,\n flexWrap: p.wrap ? \"wrap\" : undefined,\n })}\n >\n {children}\n </div>\n );\n}\n\nfunction ColumnComponent({\n element,\n children,\n}: ComponentRenderProps<StandardComponentProps<\"Column\">>) {\n const p = element.props;\n\n return (\n <div\n style={cleanStyle({\n display: \"flex\",\n flexDirection: \"column\",\n gap: p.gap,\n alignItems: p.alignItems,\n justifyContent: p.justifyContent,\n padding: p.padding,\n flex: p.flex,\n })}\n >\n {children}\n </div>\n );\n}\n\n// =============================================================================\n// Content Components\n// =============================================================================\n\nfunction HeadingComponent({\n element,\n}: ComponentRenderProps<StandardComponentProps<\"Heading\">>) {\n const p = element.props;\n const level = p.level ?? \"h2\";\n\n return (\n <div\n style={cleanStyle({\n display: \"flex\",\n fontSize: headingSizes[level] ?? 36,\n fontWeight: headingWeights[level] ?? 700,\n color: p.color ?? \"black\",\n textAlign: p.align ?? \"left\",\n letterSpacing: p.letterSpacing,\n lineHeight: p.lineHeight ?? 1.2,\n })}\n >\n {p.text}\n </div>\n );\n}\n\nfunction TextComponent({\n element,\n}: ComponentRenderProps<StandardComponentProps<\"Text\">>) {\n const p = element.props;\n\n return (\n <div\n style={cleanStyle({\n display: \"flex\",\n fontSize: p.fontSize ?? 16,\n color: p.color ?? \"black\",\n textAlign: p.align ?? \"left\",\n fontWeight: p.fontWeight === \"bold\" ? 700 : 400,\n fontStyle: p.fontStyle ?? \"normal\",\n lineHeight: p.lineHeight ?? 1.4,\n letterSpacing: p.letterSpacing,\n textDecoration: p.textDecoration,\n })}\n >\n {p.text}\n </div>\n );\n}\n\nfunction ImageComponent({\n element,\n}: ComponentRenderProps<StandardComponentProps<\"Image\">>) {\n const p = element.props;\n\n return (\n <img\n src={p.src}\n width={p.width ?? undefined}\n height={p.height ?? undefined}\n style={cleanStyle({\n borderRadius: p.borderRadius,\n objectFit: p.objectFit ?? \"contain\",\n })}\n />\n );\n}\n\n// =============================================================================\n// Decorative Components\n// =============================================================================\n\nfunction DividerComponent({\n element,\n}: ComponentRenderProps<StandardComponentProps<\"Divider\">>) {\n const p = element.props;\n\n return (\n <div\n style={{\n display: \"flex\",\n width: \"100%\",\n borderBottom: `${p.thickness ?? 1}px solid ${p.color ?? \"#e5e7eb\"}`,\n marginTop: p.marginTop ?? 8,\n marginBottom: p.marginBottom ?? 8,\n }}\n />\n );\n}\n\nfunction SpacerComponent({\n element,\n}: ComponentRenderProps<StandardComponentProps<\"Spacer\">>) {\n const p = element.props;\n\n return <div style={{ display: \"flex\", height: p.height ?? 20 }} />;\n}\n\n// =============================================================================\n// Registry\n// =============================================================================\n\nexport const standardComponents: ComponentRegistry = {\n Frame: FrameComponent,\n Box: BoxComponent,\n Row: RowComponent,\n Column: ColumnComponent,\n Heading: HeadingComponent,\n Text: TextComponent,\n Image: ImageComponent,\n Divider: DividerComponent,\n Spacer: SpacerComponent,\n};\n","import React from \"react\";\nimport satori, { type SatoriOptions } from \"satori\";\nimport type { Spec, UIElement } from \"@json-render/core\";\nimport {\n resolveElementProps,\n evaluateVisibility,\n getByPath,\n type PropResolutionContext,\n} from \"@json-render/core\";\nimport { standardComponents } from \"./components/standard\";\nimport type { ComponentRegistry } from \"./types\";\n\nexport { standardComponents };\n\nexport interface RenderOptions {\n registry?: ComponentRegistry;\n includeStandard?: boolean;\n state?: Record<string, unknown>;\n fonts?: SatoriOptions[\"fonts\"];\n /** Override the Frame width. When omitted, uses the Frame component's width prop. */\n width?: number;\n /** Override the Frame height. When omitted, uses the Frame component's height prop. */\n height?: number;\n}\n\nconst noopEmit = () => {};\n\nfunction renderElement(\n elementKey: string,\n spec: Spec,\n registry: ComponentRegistry,\n stateModel: Record<string, unknown>,\n repeatItem?: unknown,\n repeatIndex?: number,\n repeatBasePath?: string,\n): React.ReactElement | null {\n const element = spec.elements[elementKey];\n if (!element) return null;\n\n const ctx: PropResolutionContext = {\n stateModel,\n repeatItem,\n repeatIndex,\n repeatBasePath,\n };\n\n if (element.visible !== undefined) {\n if (!evaluateVisibility(element.visible, ctx)) {\n return null;\n }\n }\n\n const resolvedProps = resolveElementProps(\n element.props as Record<string, unknown>,\n ctx,\n );\n const resolvedElement: UIElement = { ...element, props: resolvedProps };\n\n const Component = registry[resolvedElement.type];\n if (!Component) return null;\n\n if (resolvedElement.repeat) {\n const items =\n (getByPath(stateModel, resolvedElement.repeat.statePath) as\n | unknown[]\n | undefined) ?? [];\n\n const fragments = items.map((item, index) => {\n const key =\n resolvedElement.repeat!.key && typeof item === \"object\" && item !== null\n ? String(\n (item as Record<string, unknown>)[resolvedElement.repeat!.key!] ??\n index,\n )\n : String(index);\n\n const childPath = `${resolvedElement.repeat!.statePath}/${index}`;\n const children = resolvedElement.children?.map((childKey) =>\n renderElement(\n childKey,\n spec,\n registry,\n stateModel,\n item,\n index,\n childPath,\n ),\n );\n\n return (\n <Component key={key} element={resolvedElement} emit={noopEmit}>\n {children}\n </Component>\n );\n });\n\n return <>{fragments}</>;\n }\n\n const children = resolvedElement.children?.map((childKey) =>\n renderElement(\n childKey,\n spec,\n registry,\n stateModel,\n repeatItem,\n repeatIndex,\n repeatBasePath,\n ),\n );\n\n return (\n <Component key={elementKey} element={resolvedElement} emit={noopEmit}>\n {children && children.length > 0 ? children : undefined}\n </Component>\n );\n}\n\ninterface ImageDimensions {\n width: number;\n height: number;\n}\n\nfunction getDimensions(\n spec: Spec,\n options: RenderOptions = {},\n): ImageDimensions {\n if (options.width && options.height) {\n return { width: options.width, height: options.height };\n }\n\n const rootElement = spec.elements[spec.root];\n const props = rootElement?.props as Record<string, unknown> | undefined;\n\n return {\n width: options.width ?? (props?.width as number) ?? 1200,\n height: options.height ?? (props?.height as number) ?? 630,\n };\n}\n\nfunction buildTree(\n spec: Spec,\n options: RenderOptions = {},\n): React.ReactElement {\n const {\n registry: customRegistry,\n includeStandard = true,\n state = {},\n } = options;\n\n const mergedState: Record<string, unknown> = {\n ...spec.state,\n ...state,\n };\n\n const registry: ComponentRegistry = {\n ...(includeStandard ? standardComponents : {}),\n ...customRegistry,\n };\n\n const root = renderElement(spec.root, spec, registry, mergedState);\n return root ?? <></>;\n}\n\n/**\n * Render a json-render spec to an SVG string.\n *\n * Uses Satori to convert the spec's component tree into SVG.\n * No additional dependencies are needed beyond satori.\n */\nexport async function renderToSvg(\n spec: Spec,\n options: RenderOptions = {},\n): Promise<string> {\n const tree = buildTree(spec, options);\n const { width, height } = getDimensions(spec, options);\n\n return satori(tree as React.ReactNode, {\n width,\n height,\n fonts: options.fonts ?? [],\n });\n}\n\n/**\n * Render a json-render spec to a PNG buffer.\n *\n * Requires `@resvg/resvg-js` to be installed as a peer dependency.\n * The SVG is first generated via Satori, then rasterized to PNG.\n */\nexport async function renderToPng(\n spec: Spec,\n options: RenderOptions = {},\n): Promise<Uint8Array> {\n const svg = await renderToSvg(spec, options);\n\n let Resvg: typeof import(\"@resvg/resvg-js\").Resvg;\n try {\n const mod = await import(\"@resvg/resvg-js\");\n Resvg = mod.Resvg;\n } catch {\n throw new Error(\n \"@resvg/resvg-js is required for PNG output. Install it with: npm install @resvg/resvg-js\",\n );\n }\n\n const resvg = new Resvg(svg);\n const pngData = resvg.render();\n return pngData.asPng();\n}\n","import { z } from \"zod\";\n\n/**\n * Standard component definitions for image catalogs.\n *\n * These define the available image components with their Zod prop schemas.\n * All components render to Satori-compatible JSX (HTML-like elements with\n * inline CSS flexbox styles).\n */\nexport const standardComponentDefinitions = {\n // ==========================================================================\n // Root\n // ==========================================================================\n\n Frame: {\n props: z.object({\n width: z.number(),\n height: z.number(),\n backgroundColor: z.string().nullable(),\n padding: z.number().nullable(),\n display: z.enum([\"flex\", \"none\"]).nullable(),\n flexDirection: z.enum([\"row\", \"column\"]).nullable(),\n alignItems: z\n .enum([\"flex-start\", \"center\", \"flex-end\", \"stretch\"])\n .nullable(),\n justifyContent: z\n .enum([\n \"flex-start\",\n \"center\",\n \"flex-end\",\n \"space-between\",\n \"space-around\",\n ])\n .nullable(),\n }),\n slots: [\"default\"],\n description:\n \"Root image container. Defines the output image dimensions and background. Must be the root element.\",\n example: { width: 1200, height: 630, backgroundColor: \"#ffffff\" },\n },\n\n // ==========================================================================\n // Layout Components\n // ==========================================================================\n\n Box: {\n props: z.object({\n padding: z.number().nullable(),\n paddingTop: z.number().nullable(),\n paddingBottom: z.number().nullable(),\n paddingLeft: z.number().nullable(),\n paddingRight: z.number().nullable(),\n margin: z.number().nullable(),\n backgroundColor: z.string().nullable(),\n borderWidth: z.number().nullable(),\n borderColor: z.string().nullable(),\n borderRadius: z.number().nullable(),\n flex: z.number().nullable(),\n width: z.union([z.number(), z.string()]).nullable(),\n height: z.union([z.number(), z.string()]).nullable(),\n alignItems: z\n .enum([\"flex-start\", \"center\", \"flex-end\", \"stretch\"])\n .nullable(),\n justifyContent: z\n .enum([\n \"flex-start\",\n \"center\",\n \"flex-end\",\n \"space-between\",\n \"space-around\",\n ])\n .nullable(),\n flexDirection: z.enum([\"row\", \"column\"]).nullable(),\n position: z.enum([\"relative\", \"absolute\"]).nullable(),\n top: z.number().nullable(),\n left: z.number().nullable(),\n right: z.number().nullable(),\n bottom: z.number().nullable(),\n overflow: z.enum([\"visible\", \"hidden\"]).nullable(),\n }),\n slots: [\"default\"],\n description:\n \"Generic container with padding, margin, background, border, and flex alignment. Supports absolute positioning.\",\n example: {\n padding: 20,\n backgroundColor: \"#f9f9f9\",\n borderRadius: 8,\n alignItems: \"center\",\n },\n },\n\n Row: {\n props: z.object({\n gap: z.number().nullable(),\n alignItems: z\n .enum([\"flex-start\", \"center\", \"flex-end\", \"stretch\"])\n .nullable(),\n justifyContent: z\n .enum([\n \"flex-start\",\n \"center\",\n \"flex-end\",\n \"space-between\",\n \"space-around\",\n ])\n .nullable(),\n padding: z.number().nullable(),\n flex: z.number().nullable(),\n wrap: z.boolean().nullable(),\n }),\n slots: [\"default\"],\n description:\n \"Horizontal flex layout. Use for placing elements side by side.\",\n example: { gap: 10, alignItems: \"center\" },\n },\n\n Column: {\n props: z.object({\n gap: z.number().nullable(),\n alignItems: z\n .enum([\"flex-start\", \"center\", \"flex-end\", \"stretch\"])\n .nullable(),\n justifyContent: z\n .enum([\n \"flex-start\",\n \"center\",\n \"flex-end\",\n \"space-between\",\n \"space-around\",\n ])\n .nullable(),\n padding: z.number().nullable(),\n flex: z.number().nullable(),\n }),\n slots: [\"default\"],\n description:\n \"Vertical flex layout. Use for stacking elements top to bottom.\",\n example: { gap: 8, padding: 10 },\n },\n\n // ==========================================================================\n // Content Components\n // ==========================================================================\n\n Heading: {\n props: z.object({\n text: z.string(),\n level: z.enum([\"h1\", \"h2\", \"h3\", \"h4\"]).nullable(),\n color: z.string().nullable(),\n align: z.enum([\"left\", \"center\", \"right\"]).nullable(),\n letterSpacing: z.union([z.number(), z.string()]).nullable(),\n lineHeight: z.number().nullable(),\n }),\n slots: [],\n description:\n \"Heading text at various levels. h1 is largest, h4 is smallest.\",\n example: { text: \"Hello World\", level: \"h1\", color: \"#000000\" },\n },\n\n Text: {\n props: z.object({\n text: z.string(),\n fontSize: z.number().nullable(),\n color: z.string().nullable(),\n align: z.enum([\"left\", \"center\", \"right\"]).nullable(),\n fontWeight: z.enum([\"normal\", \"bold\"]).nullable(),\n fontStyle: z.enum([\"normal\", \"italic\"]).nullable(),\n lineHeight: z.number().nullable(),\n letterSpacing: z.union([z.number(), z.string()]).nullable(),\n textDecoration: z.enum([\"none\", \"underline\", \"line-through\"]).nullable(),\n }),\n slots: [],\n description:\n \"Body text with configurable size, color, weight, and alignment.\",\n example: { text: \"Some content here.\", fontSize: 16, color: \"#333333\" },\n },\n\n Image: {\n props: z.object({\n src: z.string(),\n width: z.number().nullable(),\n height: z.number().nullable(),\n borderRadius: z.number().nullable(),\n objectFit: z.enum([\"contain\", \"cover\", \"fill\", \"none\"]).nullable(),\n }),\n slots: [],\n description:\n \"Image from a URL. Specify width and/or height to control size. For placeholder images use https://picsum.photos/{width}/{height}?random={n}.\",\n example: {\n src: \"https://picsum.photos/400/300?random=1\",\n width: 400,\n height: 300,\n },\n },\n\n // ==========================================================================\n // Decorative Components\n // ==========================================================================\n\n Divider: {\n props: z.object({\n color: z.string().nullable(),\n thickness: z.number().nullable(),\n marginTop: z.number().nullable(),\n marginBottom: z.number().nullable(),\n }),\n slots: [],\n description: \"Horizontal line separator between content sections.\",\n example: { color: \"#e5e7eb\", thickness: 1 },\n },\n\n Spacer: {\n props: z.object({\n height: z.number().nullable(),\n }),\n slots: [],\n description: \"Empty vertical space between elements.\",\n example: { height: 20 },\n },\n};\n\nexport type StandardComponentDefinitions = typeof standardComponentDefinitions;\n\nexport type StandardComponentProps<\n K extends keyof StandardComponentDefinitions,\n> = StandardComponentDefinitions[K][\"props\"] extends { _output: infer O }\n ? O\n : z.output<StandardComponentDefinitions[K][\"props\"]>;\n"],"mappings":"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","names":["import_core","import_jsx_runtime","children","satori"]}