@meonode/canvas 2.0.2 → 2.0.3
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/cjs/canvas/canvas.helper.js +0 -230
- package/dist/cjs/canvas/canvas.helper.js.map +1 -1
- package/dist/cjs/canvas/chart.canvas.js +70 -144
- package/dist/cjs/canvas/chart.canvas.js.map +1 -1
- package/dist/cjs/canvas/image.canvas.js +2 -2
- package/dist/cjs/canvas/image.canvas.js.map +1 -1
- package/dist/cjs/canvas/layout.canvas.js +6 -6
- package/dist/cjs/canvas/layout.canvas.js.map +1 -1
- package/dist/cjs/canvas/root.canvas.js +23 -117
- package/dist/cjs/canvas/root.canvas.js.map +1 -1
- package/dist/cjs/canvas/text.canvas.js +2 -2
- package/dist/cjs/canvas/text.canvas.js.map +1 -1
- package/dist/cjs/src/canvas/canvas.helper.d.ts +1 -20
- package/dist/cjs/src/canvas/canvas.helper.d.ts.map +1 -1
- package/dist/cjs/src/canvas/canvas.type.d.ts +1 -12
- package/dist/cjs/src/canvas/canvas.type.d.ts.map +1 -1
- package/dist/cjs/src/canvas/chart.canvas.d.ts +1 -1
- package/dist/cjs/src/canvas/chart.canvas.d.ts.map +1 -1
- package/dist/cjs/src/canvas/image.canvas.d.ts +1 -1
- package/dist/cjs/src/canvas/image.canvas.d.ts.map +1 -1
- package/dist/cjs/src/canvas/layout.canvas.d.ts +2 -2
- package/dist/cjs/src/canvas/layout.canvas.d.ts.map +1 -1
- package/dist/cjs/src/canvas/root.canvas.d.ts +3 -2
- package/dist/cjs/src/canvas/root.canvas.d.ts.map +1 -1
- package/dist/cjs/src/canvas/text.canvas.d.ts +1 -1
- package/dist/cjs/src/canvas/text.canvas.d.ts.map +1 -1
- package/dist/cjs/src/worker/comlink.pool.d.ts +30 -0
- package/dist/cjs/src/worker/comlink.pool.d.ts.map +1 -0
- package/dist/cjs/src/worker/comlink.setup.d.ts +4 -0
- package/dist/cjs/src/worker/comlink.setup.d.ts.map +1 -0
- package/dist/cjs/src/worker/worker.types.d.ts +5 -68
- package/dist/cjs/src/worker/worker.types.d.ts.map +1 -1
- package/dist/cjs/worker/comlink.pool.js +164 -0
- package/dist/cjs/worker/comlink.pool.js.map +1 -0
- package/dist/cjs/worker/comlink.setup.js +53 -0
- package/dist/cjs/worker/comlink.setup.js.map +1 -0
- package/dist/cjs/worker/render.worker.js +58 -61
- package/dist/cjs/worker/render.worker.js.map +1 -1
- package/dist/esm/canvas/canvas.helper.js +1 -230
- package/dist/esm/canvas/chart.canvas.js +71 -145
- package/dist/esm/canvas/image.canvas.js +2 -2
- package/dist/esm/canvas/layout.canvas.js +6 -6
- package/dist/esm/canvas/root.canvas.js +23 -116
- package/dist/esm/canvas/text.canvas.js +2 -2
- package/dist/esm/src/canvas/canvas.helper.d.ts +1 -20
- package/dist/esm/src/canvas/canvas.helper.d.ts.map +1 -1
- package/dist/esm/src/canvas/canvas.type.d.ts +1 -12
- package/dist/esm/src/canvas/canvas.type.d.ts.map +1 -1
- package/dist/esm/src/canvas/chart.canvas.d.ts +1 -1
- package/dist/esm/src/canvas/chart.canvas.d.ts.map +1 -1
- package/dist/esm/src/canvas/image.canvas.d.ts +1 -1
- package/dist/esm/src/canvas/image.canvas.d.ts.map +1 -1
- package/dist/esm/src/canvas/layout.canvas.d.ts +2 -2
- package/dist/esm/src/canvas/layout.canvas.d.ts.map +1 -1
- package/dist/esm/src/canvas/root.canvas.d.ts +3 -2
- package/dist/esm/src/canvas/root.canvas.d.ts.map +1 -1
- package/dist/esm/src/canvas/text.canvas.d.ts +1 -1
- package/dist/esm/src/canvas/text.canvas.d.ts.map +1 -1
- package/dist/esm/src/worker/comlink.pool.d.ts +30 -0
- package/dist/esm/src/worker/comlink.pool.d.ts.map +1 -0
- package/dist/esm/src/worker/comlink.setup.d.ts +4 -0
- package/dist/esm/src/worker/comlink.setup.d.ts.map +1 -0
- package/dist/esm/src/worker/worker.types.d.ts +5 -68
- package/dist/esm/src/worker/worker.types.d.ts.map +1 -1
- package/dist/esm/worker/comlink.pool.js +139 -0
- package/dist/esm/worker/comlink.setup.js +30 -0
- package/dist/esm/worker/render.worker.js +38 -60
- package/package.json +2 -1
|
@@ -1,73 +1,70 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var node_worker_threads = require('node:worker_threads');
|
|
4
|
+
require('./comlink.setup.js');
|
|
4
5
|
var root_canvas = require('../canvas/root.canvas.js');
|
|
6
|
+
var Comlink = require('comlink');
|
|
7
|
+
var nodeEndpoint = require('comlink/dist/esm/node-adapter.mjs');
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
function _interopNamespaceDefault(e) {
|
|
10
|
+
var n = Object.create(null);
|
|
11
|
+
if (e) {
|
|
12
|
+
Object.keys(e).forEach(function (k) {
|
|
13
|
+
if (k !== 'default') {
|
|
14
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return e[k]; }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
n.default = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var Comlink__namespace = /*#__PURE__*/_interopNamespaceDefault(Comlink);
|
|
27
|
+
|
|
28
|
+
if (!node_worker_threads.parentPort) {
|
|
20
29
|
throw new Error('[render.worker] Must be run as a worker thread');
|
|
21
30
|
}
|
|
22
31
|
const canvases = new Map();
|
|
23
32
|
let nextCanvasId = 0;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
else if (msg.type === 'call') {
|
|
40
|
-
const canvas = canvases.get(msg.canvasId);
|
|
33
|
+
const api = {
|
|
34
|
+
async render(props) {
|
|
35
|
+
const canvas = await new root_canvas.RootNode(props).render();
|
|
36
|
+
const canvasId = nextCanvasId++;
|
|
37
|
+
canvases.set(canvasId, canvas);
|
|
38
|
+
const result = {
|
|
39
|
+
canvasId,
|
|
40
|
+
buffer: canvas.toBufferSync('png'),
|
|
41
|
+
width: canvas.width,
|
|
42
|
+
height: canvas.height,
|
|
43
|
+
};
|
|
44
|
+
return result;
|
|
45
|
+
},
|
|
46
|
+
async callOnCanvas(canvasId, method, args) {
|
|
47
|
+
const canvas = canvases.get(canvasId);
|
|
41
48
|
if (!canvas) {
|
|
42
|
-
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
try {
|
|
46
|
-
let result;
|
|
47
|
-
switch (msg.method) {
|
|
48
|
-
case 'toBuffer':
|
|
49
|
-
result = await canvas.toBuffer(...msg.args);
|
|
50
|
-
break;
|
|
51
|
-
case 'toURL':
|
|
52
|
-
result = await canvas.toURL(...msg.args);
|
|
53
|
-
break;
|
|
54
|
-
case 'toFile':
|
|
55
|
-
result = await canvas.toFile(...msg.args);
|
|
56
|
-
break;
|
|
57
|
-
case 'toSharp':
|
|
58
|
-
// Sharp instances can't be transferred across threads — serialize to buffer
|
|
59
|
-
result = await canvas.toSharp(...msg.args).toBuffer();
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
reply({ taskId: msg.taskId, result });
|
|
49
|
+
throw new Error(`[render.worker] Canvas ${canvasId} not found`);
|
|
63
50
|
}
|
|
64
|
-
|
|
65
|
-
|
|
51
|
+
switch (method) {
|
|
52
|
+
case 'toBuffer':
|
|
53
|
+
return canvas.toBuffer(...args);
|
|
54
|
+
case 'toURL':
|
|
55
|
+
return canvas.toURL(...args);
|
|
56
|
+
case 'toFile':
|
|
57
|
+
await canvas.toFile(...args);
|
|
58
|
+
return;
|
|
59
|
+
case 'toSharp':
|
|
60
|
+
return await canvas.toSharp(...args).toBuffer();
|
|
61
|
+
default:
|
|
62
|
+
throw new Error(`[render.worker] Unknown method: ${method}`);
|
|
66
63
|
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
},
|
|
65
|
+
releaseCanvas(canvasId) {
|
|
66
|
+
canvases.delete(canvasId);
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
Comlink__namespace.expose(api, nodeEndpoint(node_worker_threads.parentPort));
|
|
73
70
|
//# sourceMappingURL=render.worker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.worker.js","sources":["../../../../../src/worker/render.worker.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"render.worker.js","sources":["../../../../../src/worker/render.worker.ts"],"sourcesContent":["import { parentPort } from 'node:worker_threads'\nimport { Comlink, nodeEndpoint } from '@/worker/comlink.setup.js'\nimport { RootNode } from '@/canvas/root.canvas.js'\nimport type { Canvas } from 'skia-canvas'\nimport type { WorkerAPI, RenderResult } from '@/worker/worker.types.js'\n\nif (!parentPort) {\n throw new Error('[render.worker] Must be run as a worker thread')\n}\n\nconst canvases = new Map<number, Canvas>()\nlet nextCanvasId = 0\n\nconst api: WorkerAPI = {\n async render(props) {\n const canvas = await new RootNode(props).render()\n const canvasId = nextCanvasId++\n canvases.set(canvasId, canvas)\n const result: RenderResult = {\n canvasId,\n buffer: canvas.toBufferSync('png'),\n width: canvas.width,\n height: canvas.height,\n }\n return result\n },\n\n async callOnCanvas(canvasId, method, args) {\n const canvas = canvases.get(canvasId)\n if (!canvas) {\n throw new Error(`[render.worker] Canvas ${canvasId} not found`)\n }\n switch (method) {\n case 'toBuffer':\n return canvas.toBuffer(...(args as [any, any?]))\n case 'toURL':\n return canvas.toURL(...(args as [any, any?]))\n case 'toFile':\n await canvas.toFile(...(args as [string, any?]))\n return\n case 'toSharp':\n return await canvas.toSharp(...(args as [any?])).toBuffer()\n default:\n throw new Error(`[render.worker] Unknown method: ${method}`)\n }\n },\n\n releaseCanvas(canvasId) {\n canvases.delete(canvasId)\n },\n}\n\nComlink.expose(api, nodeEndpoint(parentPort))\n"],"names":["parentPort","RootNode","Comlink"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,IAAI,CAACA,8BAAU,EAAE;AACf,IAAA,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC;AACnE;AAEA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB;AAC1C,IAAI,YAAY,GAAG,CAAC;AAEpB,MAAM,GAAG,GAAc;IACrB,MAAM,MAAM,CAAC,KAAK,EAAA;QAChB,MAAM,MAAM,GAAG,MAAM,IAAIC,oBAAQ,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE;AACjD,QAAA,MAAM,QAAQ,GAAG,YAAY,EAAE;AAC/B,QAAA,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC;AAC9B,QAAA,MAAM,MAAM,GAAiB;YAC3B,QAAQ;AACR,YAAA,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC;YAClC,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,MAAM,CAAC,MAAM;SACtB;AACD,QAAA,OAAO,MAAM;IACf,CAAC;AAED,IAAA,MAAM,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAA;QACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;QACrC,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAA,UAAA,CAAY,CAAC;QACjE;QACA,QAAQ,MAAM;AACZ,YAAA,KAAK,UAAU;AACb,gBAAA,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAI,IAAoB,CAAC;AAClD,YAAA,KAAK,OAAO;AACV,gBAAA,OAAO,MAAM,CAAC,KAAK,CAAC,GAAI,IAAoB,CAAC;AAC/C,YAAA,KAAK,QAAQ;AACX,gBAAA,MAAM,MAAM,CAAC,MAAM,CAAC,GAAI,IAAuB,CAAC;gBAChD;AACF,YAAA,KAAK,SAAS;gBACZ,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,GAAI,IAAe,CAAC,CAAC,QAAQ,EAAE;AAC7D,YAAA;AACE,gBAAA,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,CAAA,CAAE,CAAC;;IAElE,CAAC;AAED,IAAA,aAAa,CAAC,QAAQ,EAAA;AACpB,QAAA,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC3B,CAAC;CACF;AAEDC,kBAAO,CAAC,MAAM,CAAC,GAAG,EAAE,YAAY,CAACF,8BAAU,CAAC,CAAC;;"}
|
|
@@ -209,234 +209,5 @@ function parsePercentage(value, base) {
|
|
|
209
209
|
}
|
|
210
210
|
return 0;
|
|
211
211
|
}
|
|
212
|
-
/**
|
|
213
|
-
* Pre-processes a RootProps descriptor tree on the main thread before postMessage.
|
|
214
|
-
* Executes function props against available data, stores results as serializable fields,
|
|
215
|
-
* then strips remaining functions as a safety net.
|
|
216
|
-
*/
|
|
217
|
-
class WorkerPreProcessor {
|
|
218
|
-
static CHART_COLORS = ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40', '#C9CBCF'];
|
|
219
|
-
static process(props) {
|
|
220
|
-
const cloned = { ...props };
|
|
221
|
-
if (cloned.children) {
|
|
222
|
-
const childArray = Array.isArray(cloned.children) ? cloned.children : [cloned.children];
|
|
223
|
-
cloned.children = childArray.map(child => {
|
|
224
|
-
if (child && typeof child === 'object' && '__type' in child) {
|
|
225
|
-
return this.processDescriptor(child);
|
|
226
|
-
}
|
|
227
|
-
return child;
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
return this.stripNonSerializable(cloned);
|
|
231
|
-
}
|
|
232
|
-
static processDescriptor(desc) {
|
|
233
|
-
if (desc.__type === 'Chart') {
|
|
234
|
-
return this.processChartDescriptor(desc);
|
|
235
|
-
}
|
|
236
|
-
if ('children' in desc && desc.children) {
|
|
237
|
-
return { ...desc, children: desc.children.map(c => this.processDescriptor(c)) };
|
|
238
|
-
}
|
|
239
|
-
return desc;
|
|
240
|
-
}
|
|
241
|
-
static processChartDescriptor(desc) {
|
|
242
|
-
const props = { ...desc.props };
|
|
243
|
-
const options = { ...(props.options || {}) };
|
|
244
|
-
const chartType = props.type;
|
|
245
|
-
const data = props.data;
|
|
246
|
-
// xAxisLabelFormatter
|
|
247
|
-
if (typeof options.xAxisLabelFormatter === 'function' && (chartType === 'bar' || chartType === 'line')) {
|
|
248
|
-
const cartData = data;
|
|
249
|
-
if (cartData.labels) {
|
|
250
|
-
options._preComputedXAxisLabels = cartData.labels.map((label, index) => {
|
|
251
|
-
try {
|
|
252
|
-
return options.xAxisLabelFormatter(label, index);
|
|
253
|
-
}
|
|
254
|
-
catch (err) {
|
|
255
|
-
console.warn(`[WorkerPreProcessor] xAxisLabelFormatter threw for label "${label}" at index ${index}:`, err);
|
|
256
|
-
return label;
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
delete options.xAxisLabelFormatter;
|
|
261
|
-
}
|
|
262
|
-
// yAxisLabelFormatter
|
|
263
|
-
if (typeof options.yAxisLabelFormatter === 'function' && (chartType === 'bar' || chartType === 'line')) {
|
|
264
|
-
const cartData = data;
|
|
265
|
-
const maxValue = Math.max(...cartData.datasets.flatMap((d) => d.data));
|
|
266
|
-
const labels = [];
|
|
267
|
-
for (let i = 0; i <= 5; i++) {
|
|
268
|
-
const value = maxValue - (maxValue / 5) * i;
|
|
269
|
-
try {
|
|
270
|
-
labels.push(options.yAxisLabelFormatter(value));
|
|
271
|
-
}
|
|
272
|
-
catch (err) {
|
|
273
|
-
console.warn(`[WorkerPreProcessor] yAxisLabelFormatter threw for value ${value}:`, err);
|
|
274
|
-
labels.push(String(value));
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
options._preComputedYAxisLabels = labels;
|
|
278
|
-
delete options.yAxisLabelFormatter;
|
|
279
|
-
}
|
|
280
|
-
// renderLegendItem
|
|
281
|
-
if (typeof options.renderLegendItem === 'function') {
|
|
282
|
-
if (chartType === 'bar' || chartType === 'line') {
|
|
283
|
-
const cartData = data;
|
|
284
|
-
options._preComputedLegendItems = cartData.datasets.map((item, index) => {
|
|
285
|
-
const color = item.color || this.generateColor(index);
|
|
286
|
-
try {
|
|
287
|
-
const result = options.renderLegendItem({ item, index, color });
|
|
288
|
-
return this.nodeToDescriptor(result);
|
|
289
|
-
}
|
|
290
|
-
catch (err) {
|
|
291
|
-
console.warn(`[WorkerPreProcessor] renderLegendItem threw at index ${index}:`, err);
|
|
292
|
-
return null;
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
else {
|
|
297
|
-
const pieData = data;
|
|
298
|
-
options._preComputedLegendItems = pieData.map((item, index) => {
|
|
299
|
-
const color = item.color || this.generateColor(index);
|
|
300
|
-
try {
|
|
301
|
-
const result = options.renderLegendItem({ item, index, color });
|
|
302
|
-
return this.nodeToDescriptor(result);
|
|
303
|
-
}
|
|
304
|
-
catch (err) {
|
|
305
|
-
console.warn(`[WorkerPreProcessor] renderLegendItem threw at index ${index}:`, err);
|
|
306
|
-
return null;
|
|
307
|
-
}
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
delete options.renderLegendItem;
|
|
311
|
-
}
|
|
312
|
-
// renderLabelItem
|
|
313
|
-
if (typeof options.renderLabelItem === 'function') {
|
|
314
|
-
if (chartType === 'bar' || chartType === 'line') {
|
|
315
|
-
const cartData = data;
|
|
316
|
-
options._preComputedLabelItems = cartData.labels.map((label, index) => {
|
|
317
|
-
try {
|
|
318
|
-
const result = options.renderLabelItem({ item: label, index });
|
|
319
|
-
return this.nodeToDescriptor(result);
|
|
320
|
-
}
|
|
321
|
-
catch (err) {
|
|
322
|
-
console.warn(`[WorkerPreProcessor] renderLabelItem threw at index ${index}:`, err);
|
|
323
|
-
return null;
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
else {
|
|
328
|
-
const pieData = data;
|
|
329
|
-
options._preComputedLabelItems = pieData.map((item, index) => {
|
|
330
|
-
try {
|
|
331
|
-
const result = options.renderLabelItem({ item, index });
|
|
332
|
-
return this.nodeToDescriptor(result);
|
|
333
|
-
}
|
|
334
|
-
catch (err) {
|
|
335
|
-
console.warn(`[WorkerPreProcessor] renderLabelItem threw at index ${index}:`, err);
|
|
336
|
-
return null;
|
|
337
|
-
}
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
delete options.renderLabelItem;
|
|
341
|
-
}
|
|
342
|
-
// renderValueItem
|
|
343
|
-
if (typeof options.renderValueItem === 'function' && (chartType === 'bar' || chartType === 'line')) {
|
|
344
|
-
const cartData = data;
|
|
345
|
-
options._preComputedValueItems = cartData.datasets.map((dataset, datasetIndex) => dataset.data.map((value, index) => {
|
|
346
|
-
try {
|
|
347
|
-
const result = options.renderValueItem({ item: value, index, datasetIndex });
|
|
348
|
-
return this.nodeToDescriptor(result);
|
|
349
|
-
}
|
|
350
|
-
catch (err) {
|
|
351
|
-
console.warn(`[WorkerPreProcessor] renderValueItem threw at dataset ${datasetIndex}, index ${index}:`, err);
|
|
352
|
-
return null;
|
|
353
|
-
}
|
|
354
|
-
}));
|
|
355
|
-
delete options.renderValueItem;
|
|
356
|
-
}
|
|
357
|
-
props.options = options;
|
|
358
|
-
return { ...desc, props };
|
|
359
|
-
}
|
|
360
|
-
/**
|
|
361
|
-
* Converts a BoxNode instance or CanvasElement to a CanvasElement.
|
|
362
|
-
* Public API functions (Box(), Text(), etc.) already return CanvasElements,
|
|
363
|
-
* but if someone returns an actual class instance, we convert it via initialProps.
|
|
364
|
-
*/
|
|
365
|
-
static nodeToDescriptor(node) {
|
|
366
|
-
if (!node)
|
|
367
|
-
return node;
|
|
368
|
-
// Already a CanvasElement (has __type)
|
|
369
|
-
if (typeof node === 'object' && '__type' in node)
|
|
370
|
-
return node;
|
|
371
|
-
// Class instance (e.g. BoxNode, TextNode, ImageNode) — convert via duck-typing
|
|
372
|
-
if (typeof node === 'object' && node.constructor !== Object) {
|
|
373
|
-
if ('initialProps' in node && 'name' in node) {
|
|
374
|
-
const { children, ...rest } = node.initialProps || {};
|
|
375
|
-
const childArray = Array.isArray(children) ? children : children ? [children] : [];
|
|
376
|
-
const convertedChildren = childArray
|
|
377
|
-
.filter((c) => c)
|
|
378
|
-
.map((c) => this.nodeToDescriptor(c))
|
|
379
|
-
.filter((c) => !!c);
|
|
380
|
-
const name = node.name;
|
|
381
|
-
const type = name === 'TextNode'
|
|
382
|
-
? 'Text'
|
|
383
|
-
: name === 'Row'
|
|
384
|
-
? 'Row'
|
|
385
|
-
: name === 'Image'
|
|
386
|
-
? 'Image'
|
|
387
|
-
: rest.flexDirection === Style.FlexDirection.Column
|
|
388
|
-
? 'Column'
|
|
389
|
-
: 'Box';
|
|
390
|
-
if (type === 'Text') {
|
|
391
|
-
// TextNode stores original text in segments — fall back to joined segment text
|
|
392
|
-
const text = node.segments?.map((s) => s.text).join('') ?? '';
|
|
393
|
-
return { __type: 'Text', text, props: rest };
|
|
394
|
-
}
|
|
395
|
-
if (type === 'Image') {
|
|
396
|
-
return { __type: 'Image', props: rest };
|
|
397
|
-
}
|
|
398
|
-
return {
|
|
399
|
-
__type: type,
|
|
400
|
-
props: rest,
|
|
401
|
-
...(convertedChildren.length > 0 ? { children: convertedChildren } : {}),
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
console.warn('[WorkerPreProcessor] Render function returned an unrecognized class instance. Use descriptor functions (Box(), Text(), etc.) instead.');
|
|
405
|
-
return null;
|
|
406
|
-
}
|
|
407
|
-
return node;
|
|
408
|
-
}
|
|
409
|
-
static generateColor(index) {
|
|
410
|
-
return this.CHART_COLORS[index % this.CHART_COLORS.length];
|
|
411
|
-
}
|
|
412
|
-
static stripNonSerializable(obj) {
|
|
413
|
-
if (obj === null || obj === undefined)
|
|
414
|
-
return obj;
|
|
415
|
-
if (typeof obj === 'function')
|
|
416
|
-
return undefined;
|
|
417
|
-
if (typeof obj === 'symbol')
|
|
418
|
-
return undefined;
|
|
419
|
-
if (typeof obj !== 'object')
|
|
420
|
-
return obj;
|
|
421
|
-
// Preserve binary data types
|
|
422
|
-
if (Buffer.isBuffer(obj))
|
|
423
|
-
return obj;
|
|
424
|
-
if (obj instanceof ArrayBuffer)
|
|
425
|
-
return obj;
|
|
426
|
-
if (ArrayBuffer.isView(obj))
|
|
427
|
-
return obj;
|
|
428
|
-
if (Array.isArray(obj)) {
|
|
429
|
-
return obj.map(item => this.stripNonSerializable(item));
|
|
430
|
-
}
|
|
431
|
-
const result = {};
|
|
432
|
-
for (const key of Object.keys(obj)) {
|
|
433
|
-
const value = obj[key];
|
|
434
|
-
if (typeof value === 'function' || typeof value === 'symbol')
|
|
435
|
-
continue;
|
|
436
|
-
result[key] = this.stripNonSerializable(value);
|
|
437
|
-
}
|
|
438
|
-
return result;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
212
|
|
|
442
|
-
export {
|
|
213
|
+
export { drawBorders, drawRoundedRectPath, parseBorderRadius, parsePercentage };
|