abstract-image 11.2.13 → 11.2.17
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/lib/dynamic-image/components.d.ts +2 -0
- package/lib/dynamic-image/components.d.ts.map +1 -0
- package/lib/dynamic-image/components.js +88 -0
- package/lib/dynamic-image/components.js.map +1 -0
- package/lib/dynamic-image/dynamic-image.d.ts +2 -12
- package/lib/dynamic-image/dynamic-image.d.ts.map +1 -1
- package/lib/dynamic-image/dynamic-image.js +17 -172
- package/lib/dynamic-image/dynamic-image.js.map +1 -1
- package/lib/dynamic-image/index.d.ts +1 -0
- package/lib/dynamic-image/index.d.ts.map +1 -1
- package/lib/dynamic-image/index.js +3 -0
- package/lib/dynamic-image/index.js.map +1 -1
- package/lib/dynamic-image/schema.d.ts +236 -0
- package/lib/dynamic-image/schema.d.ts.map +1 -0
- package/lib/dynamic-image/schema.js +239 -0
- package/lib/dynamic-image/schema.js.map +1 -0
- package/lib/dynamic-image/utils.d.ts +2 -0
- package/lib/dynamic-image/utils.d.ts.map +1 -0
- package/lib/dynamic-image/utils.js +56 -0
- package/lib/dynamic-image/utils.js.map +1 -0
- package/package.json +5 -3
- package/src/dynamic-image/components.ts +163 -0
- package/src/dynamic-image/dynamic-image.ts +25 -201
- package/src/dynamic-image/index.ts +1 -0
- package/src/dynamic-image/schema.ts +245 -0
- package/src/dynamic-image/utils.ts +62 -0
- package/lib/dynamic-image/dynamic-image-xsd.d.ts +0 -2
- package/lib/dynamic-image/dynamic-image-xsd.d.ts.map +0 -1
- package/lib/dynamic-image/dynamic-image-xsd.js +0 -188
- package/lib/dynamic-image/dynamic-image-xsd.js.map +0 -1
- package/src/dynamic-image/dynamic-image-xsd.ts +0 -184
- package/src/dynamic-image/dynamic-image-xsd.xml +0 -183
|
@@ -1,219 +1,43 @@
|
|
|
1
|
+
import { render, Schema } from "jsxpression";
|
|
1
2
|
import { AbstractImage } from "../model/abstract-image.js";
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
BinaryImage,
|
|
7
|
-
Component,
|
|
8
|
-
Ellipse,
|
|
9
|
-
Group,
|
|
10
|
-
GrowthDirection,
|
|
11
|
-
Line,
|
|
12
|
-
Polygon,
|
|
13
|
-
PolyLine,
|
|
14
|
-
Rectangle,
|
|
15
|
-
Text,
|
|
16
|
-
TextAlignment,
|
|
17
|
-
} from "../model/component.js";
|
|
18
|
-
import { Point } from "../model/point.js";
|
|
19
|
-
import { xsd } from "./dynamic-image-xsd.js";
|
|
3
|
+
|
|
4
|
+
import { generateDataSchema } from "./utils.js";
|
|
5
|
+
import { createComponents } from "./components.js";
|
|
6
|
+
import { baseSchema } from "./schema.js";
|
|
20
7
|
|
|
21
8
|
export type DynamicImageResult =
|
|
22
9
|
| { readonly type: "Ok"; readonly image: AbstractImage; readonly imageUrls: ReadonlyArray<string> }
|
|
23
10
|
| { readonly type: "Err"; readonly error: DynamicImageError };
|
|
24
11
|
|
|
25
|
-
export type DynamicImageError =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
12
|
+
export type DynamicImageError = {
|
|
13
|
+
type: "RENDER_ERROR";
|
|
14
|
+
message: string;
|
|
15
|
+
cause?: unknown;
|
|
16
|
+
};
|
|
29
17
|
|
|
30
|
-
export function dynamicImage(
|
|
18
|
+
export function dynamicImage(source: string, data: Record<string, unknown>): DynamicImageResult {
|
|
31
19
|
try {
|
|
32
|
-
const
|
|
20
|
+
const imageUrls = Array<string>();
|
|
21
|
+
|
|
22
|
+
const schema: Schema = {
|
|
23
|
+
...baseSchema,
|
|
24
|
+
data: generateDataSchema(data),
|
|
25
|
+
};
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
type: "Err",
|
|
41
|
-
error: {
|
|
42
|
-
type: "XML_PARSE_ERROR",
|
|
43
|
-
message: errorMessage(error),
|
|
44
|
-
cause: error,
|
|
45
|
-
},
|
|
46
|
-
};
|
|
47
|
-
}
|
|
27
|
+
const image = render<AbstractImage>(source, schema, {
|
|
28
|
+
data,
|
|
29
|
+
components: createComponents(imageUrls),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return { type: "Ok", image, imageUrls };
|
|
48
33
|
} catch (error) {
|
|
49
34
|
return {
|
|
50
35
|
type: "Err",
|
|
51
36
|
error: {
|
|
52
|
-
type: "
|
|
53
|
-
message:
|
|
37
|
+
type: "RENDER_ERROR",
|
|
38
|
+
message: error instanceof Error ? error.message : String(error),
|
|
54
39
|
cause: error,
|
|
55
40
|
},
|
|
56
41
|
};
|
|
57
42
|
}
|
|
58
43
|
}
|
|
59
|
-
|
|
60
|
-
function errorMessage(error: unknown): string {
|
|
61
|
-
return error instanceof Error ? error.message : String(error);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function dynamicImageRecursive(el: XmlElement, mutableImageUrls: Array<string>): Component | AbstractImage {
|
|
65
|
-
const children = Array<Component>();
|
|
66
|
-
for (const child of el.children ?? []) {
|
|
67
|
-
if (child.tagName !== undefined) {
|
|
68
|
-
children.push(dynamicImageRecursive(child, mutableImageUrls) as Component);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
switch (el.tagName) {
|
|
73
|
-
case "AbstractImage":
|
|
74
|
-
const size = parsePoint(el.attributes.size);
|
|
75
|
-
return {
|
|
76
|
-
topLeft: parsePoint(el.attributes.topLeft),
|
|
77
|
-
size: { width: size.x, height: size.y },
|
|
78
|
-
backgroundColor: fromString2(el.attributes.backgroundColor ?? "", transparent),
|
|
79
|
-
components: children as Array<Component>,
|
|
80
|
-
} satisfies AbstractImage;
|
|
81
|
-
case "Group":
|
|
82
|
-
return {
|
|
83
|
-
type: "group",
|
|
84
|
-
name: el.attributes.name ?? "",
|
|
85
|
-
children: children,
|
|
86
|
-
} satisfies Group;
|
|
87
|
-
case "Image":
|
|
88
|
-
if (typeof el.attributes.url === "string") {
|
|
89
|
-
mutableImageUrls.push(el.attributes.url);
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
type: "binaryimage",
|
|
93
|
-
topLeft: parsePoint(el.attributes.topLeft),
|
|
94
|
-
bottomRight: parsePoint(el.attributes.bottomRight),
|
|
95
|
-
data: { type: "url", url: el.attributes.url },
|
|
96
|
-
id: el.attributes.id,
|
|
97
|
-
format: "png",
|
|
98
|
-
} satisfies BinaryImage;
|
|
99
|
-
case "Ellipse":
|
|
100
|
-
return {
|
|
101
|
-
type: "ellipse",
|
|
102
|
-
topLeft: parsePoint(el.attributes.topLeft),
|
|
103
|
-
bottomRight: parsePoint(el.attributes.bottomRight),
|
|
104
|
-
fillColor: fromString2(el.attributes.fillColor ?? "", white),
|
|
105
|
-
strokeColor: fromString2(el.attributes.strokeColor ?? "", black),
|
|
106
|
-
id: el.attributes.id,
|
|
107
|
-
strokeDashStyle: {
|
|
108
|
-
dashes: parseNumberArrayString(el.attributes.strokeDashArray),
|
|
109
|
-
offset: el.attributes.strokeDashOffset ? Number(el.attributes.strokeDashOffset) : 0,
|
|
110
|
-
},
|
|
111
|
-
strokeThickness: Number(el.attributes.strokeThickness ?? 1),
|
|
112
|
-
} satisfies Ellipse;
|
|
113
|
-
case "Line":
|
|
114
|
-
return {
|
|
115
|
-
type: "line",
|
|
116
|
-
start: parsePoint(el.attributes.start),
|
|
117
|
-
end: parsePoint(el.attributes.end),
|
|
118
|
-
strokeColor: fromString2(el.attributes.strokeColor ?? "", black),
|
|
119
|
-
id: el.attributes.id,
|
|
120
|
-
strokeDashStyle: {
|
|
121
|
-
dashes: parseNumberArrayString(el.attributes.strokeDashArray),
|
|
122
|
-
offset: el.attributes.strokeDashOffset ? Number(el.attributes.strokeDashOffset) : 0,
|
|
123
|
-
},
|
|
124
|
-
strokeThickness: Number(el.attributes.strokeThickness ?? 1),
|
|
125
|
-
} satisfies Line;
|
|
126
|
-
case "PolyLine":
|
|
127
|
-
return {
|
|
128
|
-
type: "polyline",
|
|
129
|
-
points: parsePointsString(el.attributes.points),
|
|
130
|
-
strokeColor: fromString2(el.attributes.strokeColor ?? "", black),
|
|
131
|
-
id: el.attributes.id,
|
|
132
|
-
strokeDashStyle: {
|
|
133
|
-
dashes: parseNumberArrayString(el.attributes.strokeDashArray),
|
|
134
|
-
offset: el.attributes.strokeDashOffset ? Number(el.attributes.strokeDashOffset) : 0,
|
|
135
|
-
},
|
|
136
|
-
strokeThickness: Number(el.attributes.strokeThickness ?? 1),
|
|
137
|
-
} satisfies PolyLine;
|
|
138
|
-
case "Polygon":
|
|
139
|
-
return {
|
|
140
|
-
type: "polygon",
|
|
141
|
-
points: parsePointsString(el.attributes.points),
|
|
142
|
-
fillColor: fromString2(el.attributes.fillColor ?? "", white),
|
|
143
|
-
strokeColor: fromString2(el.attributes.strokeColor ?? "", black),
|
|
144
|
-
id: el.attributes.id,
|
|
145
|
-
strokeDashStyle: {
|
|
146
|
-
dashes: parseNumberArrayString(el.attributes.strokeDashArray),
|
|
147
|
-
offset: el.attributes.strokeDashOffset ? Number(el.attributes.strokeDashOffset) : 0,
|
|
148
|
-
},
|
|
149
|
-
strokeThickness: Number(el.attributes.strokeThickness ?? 1),
|
|
150
|
-
} satisfies Polygon;
|
|
151
|
-
case "Rectangle":
|
|
152
|
-
return {
|
|
153
|
-
type: "rectangle",
|
|
154
|
-
topLeft: parsePoint(el.attributes.topLeft),
|
|
155
|
-
bottomRight: parsePoint(el.attributes.bottomRight),
|
|
156
|
-
fillColor: fromString2(el.attributes.fillColor ?? "", white),
|
|
157
|
-
radius: el.attributes.radius ? parsePoint(el.attributes.radius) : undefined,
|
|
158
|
-
strokeColor: fromString2(el.attributes.strokeColor ?? "", black),
|
|
159
|
-
id: el.attributes.id,
|
|
160
|
-
strokeDashStyle: {
|
|
161
|
-
dashes: parseNumberArrayString(el.attributes.strokeDashArray),
|
|
162
|
-
offset: el.attributes.strokeDashOffset ? Number(el.attributes.strokeDashOffset) : 0,
|
|
163
|
-
},
|
|
164
|
-
strokeThickness: Number(el.attributes.strokeThickness ?? 1),
|
|
165
|
-
} satisfies Rectangle;
|
|
166
|
-
case "Text":
|
|
167
|
-
return {
|
|
168
|
-
type: "text",
|
|
169
|
-
position: parsePoint(el.attributes.position),
|
|
170
|
-
clockwiseRotationDegrees: el.attributes.clockwiseRotationDegrees
|
|
171
|
-
? Number(el.attributes.clockwiseRotationDegrees)
|
|
172
|
-
: 0,
|
|
173
|
-
textColor: fromString2(el.attributes.textColor ?? "", black),
|
|
174
|
-
strokeColor: fromString2(el.attributes.strokeColor ?? "", transparent),
|
|
175
|
-
text: el.attributes.text?.toString() ?? "",
|
|
176
|
-
id: el.attributes.id,
|
|
177
|
-
fontFamily: el.attributes.fontFamily ?? "",
|
|
178
|
-
fontSize: el.attributes.fontSize ? Number(el.attributes.fontSize ?? 1) : 12,
|
|
179
|
-
strokeThickness: el.attributes.strokeThickness ? Number(el.attributes.strokeThickness) : 2,
|
|
180
|
-
textAlignment: (el.attributes.textAlignment as TextAlignment | undefined) ?? "center",
|
|
181
|
-
verticalGrowthDirection: (el.attributes.verticalGrowthDirection as GrowthDirection | undefined) ?? "down",
|
|
182
|
-
fontWeight: (el.attributes.fontWeight as AbstractFontWeight | undefined) ?? "normal",
|
|
183
|
-
horizontalGrowthDirection: (el.attributes.horizontalGrowthDirection as GrowthDirection | undefined) ?? "right",
|
|
184
|
-
italic: Boolean(el.attributes.italic ?? false),
|
|
185
|
-
} satisfies Text;
|
|
186
|
-
|
|
187
|
-
default:
|
|
188
|
-
throw new Error(`Could not find creator for element with name ${el.tagName}`);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export const parsedXsd = parseXsd(xsd);
|
|
193
|
-
|
|
194
|
-
function parsePoint(pointString: string | number | undefined): Point {
|
|
195
|
-
const [xString, yString] = (typeof pointString === "number" ? pointString.toString() : pointString)?.split(" ") ?? [
|
|
196
|
-
0, 0,
|
|
197
|
-
];
|
|
198
|
-
const [x, y] = [Number(xString ?? 0), Number(yString ?? 0)];
|
|
199
|
-
return { x: Number.isFinite(x) ? x : 0, y: Number.isFinite(y) ? y : 0 };
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
function parsePointsString(numberArrayString: string | number | undefined): Array<Point> {
|
|
203
|
-
return (
|
|
204
|
-
(typeof numberArrayString === "number" ? numberArrayString.toString() : numberArrayString)
|
|
205
|
-
?.split(" ")
|
|
206
|
-
.map((tuple): Point => {
|
|
207
|
-
const [xString, yString] = tuple.split(",");
|
|
208
|
-
return { x: Number(xString ?? 0), y: Number(yString ?? 0) };
|
|
209
|
-
}) ?? []
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function parseNumberArrayString(numberArrayString: string | number | undefined): ReadonlyArray<number> {
|
|
214
|
-
return (
|
|
215
|
-
(typeof numberArrayString === "number" ? numberArrayString.toString() : numberArrayString)
|
|
216
|
-
?.split(",")
|
|
217
|
-
.map(Number) ?? []
|
|
218
|
-
);
|
|
219
|
-
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { Schema } from "jsxpression";
|
|
2
|
+
|
|
3
|
+
export const baseSchema = {
|
|
4
|
+
elements: {
|
|
5
|
+
AbstractImage: {
|
|
6
|
+
description: "Root container — defines the image canvas and its coordinate system.",
|
|
7
|
+
props: {
|
|
8
|
+
width: {
|
|
9
|
+
type: "number",
|
|
10
|
+
required: true,
|
|
11
|
+
description: "Total width of the image canvas (in px).",
|
|
12
|
+
},
|
|
13
|
+
height: {
|
|
14
|
+
type: "number",
|
|
15
|
+
required: true,
|
|
16
|
+
description: "Total height of the image canvas (in px).",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
allowedChildren: ["Image", "Text", "Rectangle", "Ellipse", "Line", "Polyline", "Polygon", "Group"],
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
Group: {
|
|
23
|
+
description: "Groups elements together.",
|
|
24
|
+
props: {},
|
|
25
|
+
allowedChildren: ["Image", "Text", "Rectangle", "Ellipse", "Line", "Polyline", "Polygon", "Group"],
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
Image: {
|
|
29
|
+
description: "Displays a raster image.",
|
|
30
|
+
props: {
|
|
31
|
+
src: {
|
|
32
|
+
type: "string",
|
|
33
|
+
required: true,
|
|
34
|
+
description: "Source of the image (URL or asset ID).",
|
|
35
|
+
},
|
|
36
|
+
x: {
|
|
37
|
+
type: "number",
|
|
38
|
+
description: "X position in pixels.",
|
|
39
|
+
},
|
|
40
|
+
y: {
|
|
41
|
+
type: "number",
|
|
42
|
+
description: "Y position in pixels.",
|
|
43
|
+
},
|
|
44
|
+
width: {
|
|
45
|
+
type: "number",
|
|
46
|
+
description: "Display width in pixels.",
|
|
47
|
+
},
|
|
48
|
+
height: {
|
|
49
|
+
type: "number",
|
|
50
|
+
description: "Display height in pixels.",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
allowedChildren: [],
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
Ellipse: {
|
|
57
|
+
description: "Draws an ellipse using x, y, width, and height.",
|
|
58
|
+
props: {
|
|
59
|
+
x: {
|
|
60
|
+
type: "number",
|
|
61
|
+
description: "X coordinate of the top-left of the ellipse box.",
|
|
62
|
+
},
|
|
63
|
+
y: {
|
|
64
|
+
type: "number",
|
|
65
|
+
description: "Y coordinate of the top-left of the ellipse box.",
|
|
66
|
+
},
|
|
67
|
+
width: {
|
|
68
|
+
type: "number",
|
|
69
|
+
description: "Box width.",
|
|
70
|
+
},
|
|
71
|
+
height: {
|
|
72
|
+
type: "number",
|
|
73
|
+
description: "Box height.",
|
|
74
|
+
},
|
|
75
|
+
stroke: {
|
|
76
|
+
type: "string",
|
|
77
|
+
format: "color",
|
|
78
|
+
description: "Stroke color (CSS color string).",
|
|
79
|
+
},
|
|
80
|
+
strokeWidth: {
|
|
81
|
+
type: "number",
|
|
82
|
+
description: "Stroke width in pixels.",
|
|
83
|
+
},
|
|
84
|
+
fill: {
|
|
85
|
+
type: "string",
|
|
86
|
+
format: "color",
|
|
87
|
+
description: "Fill color (inside the ellipse).",
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
allowedChildren: [],
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
Line: {
|
|
94
|
+
description: "Draws a straight line between two points.",
|
|
95
|
+
props: {
|
|
96
|
+
x1: {
|
|
97
|
+
type: "number",
|
|
98
|
+
description: "X coordinate of the start point.",
|
|
99
|
+
},
|
|
100
|
+
y1: {
|
|
101
|
+
type: "number",
|
|
102
|
+
description: "Y coordinate of the start point.",
|
|
103
|
+
},
|
|
104
|
+
x2: {
|
|
105
|
+
type: "number",
|
|
106
|
+
description: "X coordinate of the end point.",
|
|
107
|
+
},
|
|
108
|
+
y2: {
|
|
109
|
+
type: "number",
|
|
110
|
+
description: "Y coordinate of the end point.",
|
|
111
|
+
},
|
|
112
|
+
stroke: {
|
|
113
|
+
type: "string",
|
|
114
|
+
format: "color",
|
|
115
|
+
description: "Stroke color of the line.",
|
|
116
|
+
},
|
|
117
|
+
strokeWidth: {
|
|
118
|
+
type: "number",
|
|
119
|
+
description: "Width of the stroke in px.",
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
allowedChildren: [],
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
Polyline: {
|
|
126
|
+
description: "A connected set of line segments (open shape).",
|
|
127
|
+
props: {
|
|
128
|
+
points: {
|
|
129
|
+
type: "string",
|
|
130
|
+
required: true,
|
|
131
|
+
description: "List of points: 'x0,y0 x1,y1 x2,y2'.",
|
|
132
|
+
},
|
|
133
|
+
stroke: {
|
|
134
|
+
type: "string",
|
|
135
|
+
format: "color",
|
|
136
|
+
description: "Stroke color.",
|
|
137
|
+
},
|
|
138
|
+
strokeWidth: {
|
|
139
|
+
type: "number",
|
|
140
|
+
description: "Stroke width in px.",
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
allowedChildren: [],
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
Polygon: {
|
|
147
|
+
description: "A closed polygon shape.",
|
|
148
|
+
props: {
|
|
149
|
+
points: {
|
|
150
|
+
type: "string",
|
|
151
|
+
required: true,
|
|
152
|
+
description: "List of vertex points: 'x0,y0 x1,y1 ...'.",
|
|
153
|
+
},
|
|
154
|
+
stroke: {
|
|
155
|
+
type: "string",
|
|
156
|
+
format: "color",
|
|
157
|
+
description: "Stroke color.",
|
|
158
|
+
},
|
|
159
|
+
strokeWidth: {
|
|
160
|
+
type: "number",
|
|
161
|
+
description: "Stroke width in px.",
|
|
162
|
+
},
|
|
163
|
+
fill: {
|
|
164
|
+
type: "string",
|
|
165
|
+
format: "color",
|
|
166
|
+
description: "Fill color of the polygon.",
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
allowedChildren: [],
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
Rectangle: {
|
|
173
|
+
description: "Draws a rectangle, optionally with rounded corners.",
|
|
174
|
+
props: {
|
|
175
|
+
x: {
|
|
176
|
+
type: "number",
|
|
177
|
+
description: "X position of the rectangle (top-left).",
|
|
178
|
+
},
|
|
179
|
+
y: {
|
|
180
|
+
type: "number",
|
|
181
|
+
description: "Y position of the rectangle (top-left).",
|
|
182
|
+
},
|
|
183
|
+
width: {
|
|
184
|
+
type: "number",
|
|
185
|
+
description: "Rectangle width in px.",
|
|
186
|
+
},
|
|
187
|
+
height: {
|
|
188
|
+
type: "number",
|
|
189
|
+
description: "Rectangle height in px.",
|
|
190
|
+
},
|
|
191
|
+
stroke: {
|
|
192
|
+
type: "string",
|
|
193
|
+
format: "color",
|
|
194
|
+
description: "Stroke color.",
|
|
195
|
+
},
|
|
196
|
+
strokeWidth: {
|
|
197
|
+
type: "number",
|
|
198
|
+
description: "Stroke width in px.",
|
|
199
|
+
},
|
|
200
|
+
fill: {
|
|
201
|
+
type: "string",
|
|
202
|
+
format: "color",
|
|
203
|
+
description: "Fill color of the rectangle.",
|
|
204
|
+
},
|
|
205
|
+
radius: {
|
|
206
|
+
type: "number",
|
|
207
|
+
description: "Corner radius in px (uniform).",
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
allowedChildren: [],
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
Text: {
|
|
214
|
+
description: "Renders a text element.",
|
|
215
|
+
props: {
|
|
216
|
+
x: {
|
|
217
|
+
type: "number",
|
|
218
|
+
description: "X position of the text anchor.",
|
|
219
|
+
},
|
|
220
|
+
y: {
|
|
221
|
+
type: "number",
|
|
222
|
+
description: "Y position of the text baseline.",
|
|
223
|
+
},
|
|
224
|
+
fontFamily: {
|
|
225
|
+
type: "string",
|
|
226
|
+
description: "Font family, e.g. 'Inter, system-ui'.",
|
|
227
|
+
},
|
|
228
|
+
fontSize: {
|
|
229
|
+
type: "number",
|
|
230
|
+
description: "Font size in pixels.",
|
|
231
|
+
},
|
|
232
|
+
fontWeight: {
|
|
233
|
+
type: "string",
|
|
234
|
+
description: "Font weight, e.g. 'bold', '700'.",
|
|
235
|
+
},
|
|
236
|
+
fill: {
|
|
237
|
+
type: "string",
|
|
238
|
+
format: "color",
|
|
239
|
+
description: "Fill color (text color).",
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
allowedChildren: [],
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
} as const satisfies Schema;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export function generateDataSchema(data: Record<string, unknown>): Record<string, any> {
|
|
2
|
+
const schema: Record<string, any> = {};
|
|
3
|
+
|
|
4
|
+
for (const [key, value] of Object.entries(data)) {
|
|
5
|
+
schema[key] = inferPropertySchema(value);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
return schema;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function inferPropertySchema(value: unknown): any {
|
|
12
|
+
if (value === null || value === undefined) {
|
|
13
|
+
return {
|
|
14
|
+
type: "string",
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (typeof value === "string") {
|
|
19
|
+
return {
|
|
20
|
+
type: "string",
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (typeof value === "number") {
|
|
25
|
+
return {
|
|
26
|
+
type: "number",
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (typeof value === "boolean") {
|
|
31
|
+
return {
|
|
32
|
+
type: "boolean",
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (typeof value === "function") {
|
|
37
|
+
return {
|
|
38
|
+
type: "function",
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (Array.isArray(value)) {
|
|
43
|
+
const itemSchema = value.length > 0 ? inferPropertySchema(value[0]) : { type: "string" };
|
|
44
|
+
return {
|
|
45
|
+
type: "array",
|
|
46
|
+
shape: itemSchema,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (typeof value === "object") {
|
|
51
|
+
const shape: Record<string, any> = {};
|
|
52
|
+
for (const [k, v] of Object.entries(value)) {
|
|
53
|
+
shape[k] = inferPropertySchema(v);
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
type: "object",
|
|
57
|
+
shape,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return { type: "string" };
|
|
62
|
+
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
export declare const xsd = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n targetNamespace=\"urn:adml\"\n xmlns=\"urn:adml\"\n elementFormDefault=\"qualified\"\n attributeFormDefault=\"unqualified\">\n\n <!-- ========= Root ========= -->\n <xs:element name=\"abstractImage\" type=\"AbstractImage\"/>\n\n <xs:group name=\"Component\">\n <xs:choice>\n <xs:element name=\"image\" type=\"Image\"/>\n <xs:element name=\"ellipse\" type=\"Ellipse\"/>\n <xs:element name=\"line\" type=\"Line\"/>\n <xs:element name=\"polyline\" type=\"PolyLine\"/>\n <xs:element name=\"polygon\" type=\"Polygon\"/>\n <xs:element name=\"rectangle\" type=\"Rectangle\"/>\n <xs:element name=\"text\" type=\"Text\"/>\n <xs:element name=\"group\" type=\"Group\"/>\n </xs:choice>\n </xs:group>\n\n <xs:complexType name=\"AbstractImage\">\n <xs:sequence>\n <xs:element name=\"components\">\n <xs:complexType>\n <xs:sequence>\n <xs:group ref=\"Component\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n </xs:sequence>\n </xs:complexType>\n </xs:element>\n </xs:sequence>\n <xs:attribute name=\"topLeft\" type=\"PointString\" use=\"required\"/>\n <xs:attribute name=\"size\" type=\"SizeString\" use=\"required\"/>\n <xs:attribute name=\"backgroundColor\" type=\"ColorString\" use=\"optional\"/>\n </xs:complexType>\n\n <xs:simpleType name=\"PointString\"><xs:restriction base=\"xs:string\"/></xs:simpleType>\n <xs:simpleType name=\"SizeString\"><xs:restriction base=\"xs:string\"/></xs:simpleType>\n <xs:simpleType name=\"ColorString\"><xs:restriction base=\"xs:string\"/></xs:simpleType>\n <xs:simpleType name=\"PointsString\"><xs:restriction base=\"xs:string\"/></xs:simpleType>\n <xs:simpleType name=\"DashArray\"><xs:restriction base=\"xs:string\"/></xs:simpleType>\n <xs:simpleType name=\"DashOffset\"><xs:restriction base=\"xs:string\"/></xs:simpleType>\n\n <!-- ========= Components ========= -->\n\n <!-- Group -->\n <xs:complexType name=\"Group\">\n <xs:sequence>\n <xs:element name=\"children\">\n <xs:complexType>\n <xs:sequence>\n <xs:group ref=\"Component\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n </xs:sequence>\n </xs:complexType>\n </xs:element>\n </xs:sequence>\n <xs:attribute name=\"name\" type=\"xs:string\" use=\"optional\"/>\n </xs:complexType>\n\n <!-- Image -->\n <xs:complexType name=\"Image\">\n <xs:attribute name=\"url\" type=\"xs:anyURI\" use=\"required\"/>\n <xs:attribute name=\"topLeft\" type=\"PointString\" use=\"required\"/>\n <xs:attribute name=\"bottomRight\" type=\"PointString\" use=\"required\"/>\n <xs:attribute name=\"id\" type=\"xs:string\" use=\"optional\"/>\n </xs:complexType>\n\n <!-- Ellipse -->\n <xs:complexType name=\"Ellipse\">\n <xs:attribute name=\"topLeft\" type=\"PointString\" use=\"required\"/>\n <xs:attribute name=\"bottomRight\" type=\"PointString\" use=\"required\"/>\n <xs:attribute name=\"strokeColor\" type=\"ColorString\" use=\"optional\"/>\n <xs:attribute name=\"strokeThickness\" type=\"xs:double\" use=\"optional\"/>\n <xs:attribute name=\"strokeDashArray\" type=\"DashArray\" use=\"optional\"/> \n <xs:attribute name=\"strokeDashOffset\" type=\"DashOffset\" use=\"optional\"/>\n <xs:attribute name=\"fillColor\" type=\"ColorString\" use=\"optional\"/>\n <xs:attribute name=\"id\" type=\"xs:string\" use=\"optional\"/>\n </xs:complexType>\n\n <!-- Line -->\n <xs:complexType name=\"Line\">\n <xs:attribute name=\"start\" type=\"PointString\" use=\"required\"/>\n <xs:attribute name=\"end\" type=\"PointString\" use=\"required\"/>\n <xs:attribute name=\"strokeColor\" type=\"ColorString\" use=\"optional\"/>\n <xs:attribute name=\"strokeThickness\" type=\"xs:double\" use=\"optional\"/>\n <xs:attribute name=\"strokeDashArray\" type=\"DashArray\" use=\"optional\"/> \n <xs:attribute name=\"strokeDashOffset\" type=\"DashOffset\" use=\"optional\"/>\n <xs:attribute name=\"id\" type=\"xs:string\" use=\"optional\"/>\n </xs:complexType>\n\n <!-- PolyLine -->\n <xs:complexType name=\"PolyLine\">\n <xs:attribute name=\"points\" type=\"PointsString\" use=\"required\"/>\n <xs:attribute name=\"strokeColor\" type=\"ColorString\" use=\"optional\"/>\n <xs:attribute name=\"strokeThickness\" type=\"xs:double\" use=\"optional\"/>\n <xs:attribute name=\"strokeDashArray\" type=\"DashArray\" use=\"optional\"/> \n <xs:attribute name=\"strokeDashOffset\" type=\"DashOffset\" use=\"optional\"/>\n <xs:attribute name=\"id\" type=\"xs:string\" use=\"optional\"/>\n </xs:complexType>\n\n <!-- Polygon -->\n <xs:complexType name=\"Polygon\">\n <xs:attribute name=\"points\" type=\"PointsString\" use=\"required\"/>\n <xs:attribute name=\"strokeColor\" type=\"ColorString\" use=\"optional\"/>\n <xs:attribute name=\"strokeThickness\" type=\"xs:double\" use=\"optional\"/>\n <xs:attribute name=\"strokeDashArray\" type=\"DashArray\" use=\"optional\"/> \n <xs:attribute name=\"strokeDashOffset\" type=\"DashOffset\" use=\"optional\"/>\n <xs:attribute name=\"fillColor\" type=\"ColorString\" use=\"optional\"/>\n <xs:attribute name=\"id\" type=\"xs:string\" use=\"optional\"/>\n </xs:complexType>\n\n <!-- Rectangle -->\n <xs:complexType name=\"Rectangle\">\n <xs:attribute name=\"topLeft\" type=\"PointString\" use=\"required\"/>\n <xs:attribute name=\"bottomRight\" type=\"PointString\" use=\"required\"/>\n <xs:attribute name=\"strokeColor\" type=\"ColorString\" use=\"optional\"/>\n <xs:attribute name=\"strokeThickness\" type=\"xs:double\" use=\"optional\"/>\n <xs:attribute name=\"strokeDashArray\" type=\"DashArray\" use=\"optional\"/> \n <xs:attribute name=\"strokeDashOffset\" type=\"DashOffset\" use=\"optional\"/>\n <xs:attribute name=\"fillColor\" type=\"ColorString\" use=\"optional\"/>\n <xs:attribute name=\"id\" type=\"xs:string\" use=\"optional\"/>\n <xs:attribute name=\"radius\" type=\"PointString\" use=\"optional\"/>\n </xs:complexType>\n\n <!-- Text -->\n <xs:complexType name=\"Text\">\n <xs:attribute name=\"position\" type=\"PointString\" use=\"required\"/>\n <xs:attribute name=\"text\" type=\"xs:string\" use=\"required\"/>\n <xs:attribute name=\"fontFamily\" type=\"xs:string\" use=\"optional\"/>\n <xs:attribute name=\"fontSize\" type=\"xs:double\" use=\"optional\"/>\n <xs:attribute name=\"textColor\" type=\"ColorString\" use=\"optional\"/>\n\t<xs:attribute name=\"fontWeight\" use=\"optional\">\n\t\t<xs:simpleType>\n\t\t<xs:restriction base=\"xs:string\">\n\t\t\t<xs:enumeration value=\"light\"/>\n\t\t\t<xs:enumeration value=\"normal\"/>\n\t\t\t<xs:enumeration value=\"mediumBold\"/>\n\t\t\t<xs:enumeration value=\"bold\"/>\n\t\t\t<xs:enumeration value=\"extraBold\"/>\n\t\t</xs:restriction>\n\t\t</xs:simpleType>\n\t</xs:attribute>\n\t<xs:attribute name=\"clockwiseRotationDegrees\" type=\"xs:double\" use=\"optional\"/>\n\t<xs:attribute name=\"textAlignment\" use=\"optional\">\n\t\t<xs:simpleType>\n\t\t<xs:restriction base=\"xs:string\">\n\t\t\t<xs:enumeration value=\"left\"/>\n\t\t\t<xs:enumeration value=\"center\"/>\n\t\t\t<xs:enumeration value=\"right\"/>\n\t\t</xs:restriction>\n\t\t</xs:simpleType>\n\t</xs:attribute>\n\t<xs:attribute name=\"horizontalGrowthDirection\" use=\"optional\">\n\t\t<xs:simpleType>\n\t\t<xs:restriction base=\"xs:string\">\n\t\t\t<xs:enumeration value=\"up\"/>\n\t\t\t<xs:enumeration value=\"down\"/>\n\t\t\t<xs:enumeration value=\"uniform\"/>\n\t\t\t<xs:enumeration value=\"left\"/>\n\t\t\t<xs:enumeration value=\"right\"/>\n\t\t</xs:restriction>\n\t\t</xs:simpleType>\n\t</xs:attribute>\n\t<xs:attribute name=\"verticalGrowthDirection\" use=\"optional\">\n\t\t<xs:simpleType>\n\t\t<xs:restriction base=\"xs:string\">\n\t\t\t<xs:enumeration value=\"up\"/>\n\t\t\t<xs:enumeration value=\"down\"/>\n\t\t\t<xs:enumeration value=\"uniform\"/>\n\t\t\t<xs:enumeration value=\"left\"/>\n\t\t\t<xs:enumeration value=\"right\"/>\n\t\t</xs:restriction>\n\t\t</xs:simpleType>\n\t</xs:attribute>\n <xs:attribute name=\"strokeThickness\" type=\"xs:double\" use=\"optional\"/>\n <xs:attribute name=\"strokeColor\" type=\"ColorString\" use=\"optional\"/>\n <xs:attribute name=\"italic\" type=\"xs:boolean\" use=\"optional\"/>\n <xs:attribute name=\"id\" type=\"xs:string\" use=\"optional\"/>\n </xs:complexType>\n\n</xs:schema>\n";
|
|
2
|
-
//# sourceMappingURL=dynamic-image-xsd.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-image-xsd.d.ts","sourceRoot":"","sources":["../../src/dynamic-image/dynamic-image-xsd.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,GAAG,w2QAuLf,CAAC"}
|