@json-to-office/core-docx 0.14.0 → 0.16.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/components/highcharts.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/visual.d.ts +42 -0
- package/dist/components/visual.d.ts.map +1 -0
- package/dist/core/cached-render.d.ts.map +1 -1
- package/dist/core/content.d.ts.map +1 -1
- package/dist/core/flattenVisuals.d.ts +33 -0
- package/dist/core/flattenVisuals.d.ts.map +1 -0
- package/dist/core/render.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +308 -30
- package/dist/index.js.map +1 -1
- package/dist/plugin/example/index.js +193 -30
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/styles/utils/componentDefaults.d.ts +6 -0
- package/dist/styles/utils/componentDefaults.d.ts.map +1 -1
- package/dist/styles/utils/layoutUtils.d.ts +16 -0
- package/dist/styles/utils/layoutUtils.d.ts.map +1 -1
- package/dist/styles/utils/resolveComponentTree.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +5 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/serviceClient.d.ts +39 -0
- package/dist/utils/serviceClient.d.ts.map +1 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -856,12 +856,20 @@ function getPageDimensions(size) {
|
|
|
856
856
|
}
|
|
857
857
|
return size;
|
|
858
858
|
}
|
|
859
|
-
var PAGE_SIZES, getTableStyle, getDocumentMargins, getPageSetup;
|
|
859
|
+
var resolveTableParagraphSpacing, PAGE_SIZES, getTableStyle, getDocumentMargins, getPageSetup;
|
|
860
860
|
var init_layoutUtils = __esm({
|
|
861
861
|
"src/styles/utils/layoutUtils.ts"() {
|
|
862
862
|
"use strict";
|
|
863
863
|
init_colorUtils();
|
|
864
864
|
init_styleHelpers();
|
|
865
|
+
resolveTableParagraphSpacing = (style) => {
|
|
866
|
+
const lineSpacing = convertLineSpacing(style?.lineSpacing) ?? convertLineSpacing({ type: "single" });
|
|
867
|
+
return {
|
|
868
|
+
before: style?.spacing?.before !== void 0 ? pointsToTwips(style.spacing.before) : 0,
|
|
869
|
+
after: style?.spacing?.after !== void 0 ? pointsToTwips(style.spacing.after) : 0,
|
|
870
|
+
...lineSpacing
|
|
871
|
+
};
|
|
872
|
+
};
|
|
865
873
|
PAGE_SIZES = {
|
|
866
874
|
A4: { width: 11906, height: 16838 },
|
|
867
875
|
A3: { width: 16838, height: 23811 },
|
|
@@ -872,7 +880,10 @@ var init_layoutUtils = __esm({
|
|
|
872
880
|
const themeConfig = resolveTheme(theme, themeName);
|
|
873
881
|
if (themeConfig && themeConfig.styles?.normal) {
|
|
874
882
|
const normalStyle = themeConfig.styles.normal;
|
|
883
|
+
const styles = themeConfig.styles;
|
|
875
884
|
return {
|
|
885
|
+
cellParagraph: resolveTableParagraphSpacing(styles.tableCell),
|
|
886
|
+
headerParagraph: resolveTableParagraphSpacing(styles.tableHeader),
|
|
876
887
|
tableHeader: {
|
|
877
888
|
fill: resolveColor(
|
|
878
889
|
themeConfig.colors?.primary || "#000000",
|
|
@@ -938,6 +949,8 @@ var init_layoutUtils = __esm({
|
|
|
938
949
|
};
|
|
939
950
|
}
|
|
940
951
|
return {
|
|
952
|
+
cellParagraph: resolveTableParagraphSpacing(),
|
|
953
|
+
headerParagraph: resolveTableParagraphSpacing(),
|
|
941
954
|
tableHeader: {
|
|
942
955
|
fill: "000000",
|
|
943
956
|
color: "FFFFFF",
|
|
@@ -1941,7 +1954,8 @@ import {
|
|
|
1941
1954
|
isTableComponent,
|
|
1942
1955
|
isListComponent,
|
|
1943
1956
|
isTocComponent,
|
|
1944
|
-
isHighchartsComponent
|
|
1957
|
+
isHighchartsComponent,
|
|
1958
|
+
isVisualComponent
|
|
1945
1959
|
} from "@json-to-office/shared-docx";
|
|
1946
1960
|
|
|
1947
1961
|
// src/core/generator.ts
|
|
@@ -2037,6 +2051,9 @@ function resolveListProps(props, theme) {
|
|
|
2037
2051
|
function resolveHighchartsProps(props, _theme) {
|
|
2038
2052
|
return props;
|
|
2039
2053
|
}
|
|
2054
|
+
function resolveVisualProps(props, _theme) {
|
|
2055
|
+
return props;
|
|
2056
|
+
}
|
|
2040
2057
|
function getCustomComponentDefaults(theme, componentName) {
|
|
2041
2058
|
const defaults = getComponentDefaults(theme);
|
|
2042
2059
|
return defaults?.[componentName] || {};
|
|
@@ -2066,7 +2083,8 @@ var RESOLVER_MAP = {
|
|
|
2066
2083
|
section: resolveSectionProps,
|
|
2067
2084
|
columns: resolveColumnsProps,
|
|
2068
2085
|
list: resolveListProps,
|
|
2069
|
-
highcharts: resolveHighchartsProps
|
|
2086
|
+
highcharts: resolveHighchartsProps,
|
|
2087
|
+
visual: resolveVisualProps
|
|
2070
2088
|
};
|
|
2071
2089
|
function resolveComponentDefaults(component, theme) {
|
|
2072
2090
|
if (!component.props) return component;
|
|
@@ -4055,7 +4073,7 @@ async function clearComponentCache() {
|
|
|
4055
4073
|
}
|
|
4056
4074
|
}
|
|
4057
4075
|
async function renderComponentWithCache(component, theme, themeName, context, bypassCache = false) {
|
|
4058
|
-
const forceBypassForType = component.name === "toc" || component.name === "section" || componentHasRevision(component);
|
|
4076
|
+
const forceBypassForType = component.name === "toc" || component.name === "section" || component.name === "visual" || componentHasRevision(component);
|
|
4059
4077
|
if (!componentCache) {
|
|
4060
4078
|
initializeComponentCache();
|
|
4061
4079
|
}
|
|
@@ -5119,6 +5137,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
5119
5137
|
children: [
|
|
5120
5138
|
new Paragraph({
|
|
5121
5139
|
...tableConfig.keepInOnePage && { keepNext: true },
|
|
5140
|
+
spacing: tableStyle.headerParagraph,
|
|
5122
5141
|
alignment: getAlignment(horizontalAlignment),
|
|
5123
5142
|
children: cellChildren
|
|
5124
5143
|
})
|
|
@@ -5213,6 +5232,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
5213
5232
|
children: [
|
|
5214
5233
|
new Paragraph({
|
|
5215
5234
|
...tableConfig.keepInOnePage && !isLastRow || isLastRow && tableConfig.keepNext ? { keepNext: true } : {},
|
|
5235
|
+
spacing: tableStyle.cellParagraph,
|
|
5216
5236
|
alignment: AlignmentType2.LEFT,
|
|
5217
5237
|
children: []
|
|
5218
5238
|
})
|
|
@@ -5288,6 +5308,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
5288
5308
|
children: [
|
|
5289
5309
|
new Paragraph({
|
|
5290
5310
|
...tableConfig.keepInOnePage && !isLastRow || isLastRow && tableConfig.keepNext ? { keepNext: true } : {},
|
|
5311
|
+
spacing: tableStyle.cellParagraph,
|
|
5291
5312
|
alignment: getAlignment(horizontalAlignment),
|
|
5292
5313
|
children: cellChildren
|
|
5293
5314
|
})
|
|
@@ -6334,21 +6355,61 @@ function hasNodeBuiltins() {
|
|
|
6334
6355
|
}
|
|
6335
6356
|
}
|
|
6336
6357
|
|
|
6358
|
+
// src/utils/serviceClient.ts
|
|
6359
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
6360
|
+
function resolveServiceUrl(propsUrl, servicesUrl, defaultUrl) {
|
|
6361
|
+
const raw = (propsUrl || servicesUrl || defaultUrl).trim();
|
|
6362
|
+
const withScheme = /^https?:\/\//i.test(raw) ? raw : `http://${raw}`;
|
|
6363
|
+
return withScheme.replace(/\/+$/, "");
|
|
6364
|
+
}
|
|
6365
|
+
async function postJsonToService(opts) {
|
|
6366
|
+
const resolvedHeaders = typeof opts.headers === "function" ? await opts.headers(opts.body) : opts.headers;
|
|
6367
|
+
const headers = {
|
|
6368
|
+
"Content-Type": "application/json",
|
|
6369
|
+
...resolvedHeaders
|
|
6370
|
+
};
|
|
6371
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
6372
|
+
const controller = new AbortController();
|
|
6373
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
6374
|
+
let response;
|
|
6375
|
+
try {
|
|
6376
|
+
response = await fetch(`${opts.url}${opts.path}`, {
|
|
6377
|
+
method: "POST",
|
|
6378
|
+
headers,
|
|
6379
|
+
body: JSON.stringify(opts.body),
|
|
6380
|
+
signal: controller.signal
|
|
6381
|
+
});
|
|
6382
|
+
} catch (error) {
|
|
6383
|
+
if (error?.name === "AbortError") {
|
|
6384
|
+
throw new Error(
|
|
6385
|
+
`${opts.serviceLabel} timed out after ${timeoutMs}ms at ${opts.url}.`
|
|
6386
|
+
);
|
|
6387
|
+
}
|
|
6388
|
+
const cause = error instanceof Error ? error.message : String(error);
|
|
6389
|
+
throw new Error(opts.onUnreachable(opts.url, cause));
|
|
6390
|
+
} finally {
|
|
6391
|
+
clearTimeout(timer);
|
|
6392
|
+
}
|
|
6393
|
+
if (!response.ok) {
|
|
6394
|
+
throw new Error(
|
|
6395
|
+
`${opts.serviceLabel} returned ${response.status}: ${response.statusText}`
|
|
6396
|
+
);
|
|
6397
|
+
}
|
|
6398
|
+
return response;
|
|
6399
|
+
}
|
|
6400
|
+
|
|
6337
6401
|
// src/components/highcharts.ts
|
|
6338
6402
|
var DEFAULT_EXPORT_SERVER_URL = "http://localhost:7801";
|
|
6339
|
-
function getExportServerUrl(propsUrl, servicesUrl) {
|
|
6340
|
-
const raw = propsUrl || servicesUrl || DEFAULT_EXPORT_SERVER_URL;
|
|
6341
|
-
return raw.startsWith("http") ? raw : `http://${raw}`;
|
|
6342
|
-
}
|
|
6343
6403
|
async function generateChart(config, servicesConfig) {
|
|
6344
6404
|
if (!isNodeEnvironment()) {
|
|
6345
6405
|
throw new Error(
|
|
6346
6406
|
"Highcharts export server requires a Node.js environment. Chart generation is not available in browser environments."
|
|
6347
6407
|
);
|
|
6348
6408
|
}
|
|
6349
|
-
const serverUrl =
|
|
6409
|
+
const serverUrl = resolveServiceUrl(
|
|
6350
6410
|
config.serverUrl,
|
|
6351
|
-
servicesConfig?.serverUrl
|
|
6411
|
+
servicesConfig?.serverUrl,
|
|
6412
|
+
DEFAULT_EXPORT_SERVER_URL
|
|
6352
6413
|
);
|
|
6353
6414
|
const requestBody = {
|
|
6354
6415
|
infile: config.options,
|
|
@@ -6356,26 +6417,15 @@ async function generateChart(config, servicesConfig) {
|
|
|
6356
6417
|
b64: true,
|
|
6357
6418
|
scale: config.scale
|
|
6358
6419
|
};
|
|
6359
|
-
const
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
body: JSON.stringify(requestBody)
|
|
6368
|
-
}).catch((error) => {
|
|
6369
|
-
throw new Error(
|
|
6370
|
-
`Highcharts Export Server is not running at ${serverUrl}. Start it with: npx highcharts-export-server --enableServer true
|
|
6371
|
-
Cause: ${error instanceof Error ? error.message : String(error)}`
|
|
6372
|
-
);
|
|
6420
|
+
const response = await postJsonToService({
|
|
6421
|
+
url: serverUrl,
|
|
6422
|
+
path: "/export",
|
|
6423
|
+
body: requestBody,
|
|
6424
|
+
headers: servicesConfig?.headers,
|
|
6425
|
+
serviceLabel: "Highcharts export server",
|
|
6426
|
+
onUnreachable: (url, cause) => `Highcharts Export Server is not running at ${url}. Start it with: npx highcharts-export-server --enableServer true
|
|
6427
|
+
Cause: ${cause}`
|
|
6373
6428
|
});
|
|
6374
|
-
if (!response.ok) {
|
|
6375
|
-
throw new Error(
|
|
6376
|
-
`Highcharts export server returned ${response.status}: ${response.statusText}`
|
|
6377
|
-
);
|
|
6378
|
-
}
|
|
6379
6429
|
const base64Data = await response.text();
|
|
6380
6430
|
const base64DataUri = `data:image/png;base64,${base64Data}`;
|
|
6381
6431
|
const width = config.options.chart.width;
|
|
@@ -6409,6 +6459,116 @@ async function renderHighchartsComponent(component, theme, themeName, context) {
|
|
|
6409
6459
|
return imageParagraphs;
|
|
6410
6460
|
}
|
|
6411
6461
|
|
|
6462
|
+
// src/components/visual.ts
|
|
6463
|
+
import {
|
|
6464
|
+
clampVisualDpi,
|
|
6465
|
+
DEFAULT_VISUAL_DPI
|
|
6466
|
+
} from "@json-to-office/shared";
|
|
6467
|
+
var DEFAULT_RASTERIZE_SERVER_URL = "http://localhost:7802";
|
|
6468
|
+
var PIXELS_PER_INCH = 96;
|
|
6469
|
+
function buildVisualPresentation(props) {
|
|
6470
|
+
const { canvas, elements } = props;
|
|
6471
|
+
const presentationProps = {
|
|
6472
|
+
slideWidth: canvas.width,
|
|
6473
|
+
slideHeight: canvas.height
|
|
6474
|
+
};
|
|
6475
|
+
if (canvas.theme) presentationProps.theme = canvas.theme;
|
|
6476
|
+
const slideProps = {};
|
|
6477
|
+
if (canvas.background) slideProps.background = canvas.background;
|
|
6478
|
+
return {
|
|
6479
|
+
name: "pptx",
|
|
6480
|
+
props: presentationProps,
|
|
6481
|
+
children: [
|
|
6482
|
+
{
|
|
6483
|
+
name: "slide",
|
|
6484
|
+
props: slideProps,
|
|
6485
|
+
children: elements ?? []
|
|
6486
|
+
}
|
|
6487
|
+
]
|
|
6488
|
+
};
|
|
6489
|
+
}
|
|
6490
|
+
function defaultVisualWidthPx(props) {
|
|
6491
|
+
return Math.round(props.canvas.width * PIXELS_PER_INCH);
|
|
6492
|
+
}
|
|
6493
|
+
function visualToImageOptions(props) {
|
|
6494
|
+
return {
|
|
6495
|
+
width: props.width ?? defaultVisualWidthPx(props),
|
|
6496
|
+
...props.height !== void 0 && { height: props.height },
|
|
6497
|
+
alignment: props.alignment ?? "center",
|
|
6498
|
+
...props.caption !== void 0 && { caption: props.caption },
|
|
6499
|
+
...props.spacing !== void 0 && { spacing: props.spacing },
|
|
6500
|
+
...props.floating !== void 0 && { floating: props.floating },
|
|
6501
|
+
...props.keepNext !== void 0 && { keepNext: props.keepNext },
|
|
6502
|
+
...props.keepLines !== void 0 && { keepLines: props.keepLines }
|
|
6503
|
+
};
|
|
6504
|
+
}
|
|
6505
|
+
function visualToImageProps(props, base64DataUri) {
|
|
6506
|
+
return {
|
|
6507
|
+
base64: base64DataUri,
|
|
6508
|
+
...visualToImageOptions(props),
|
|
6509
|
+
...props.alt !== void 0 && { alt: props.alt }
|
|
6510
|
+
};
|
|
6511
|
+
}
|
|
6512
|
+
async function rasterize(presentation, dpi, propsServerUrl, serviceConfig) {
|
|
6513
|
+
if (!isNodeEnvironment()) {
|
|
6514
|
+
throw new Error(
|
|
6515
|
+
"Visual rasterization requires a Node.js environment. It is not available in browser environments."
|
|
6516
|
+
);
|
|
6517
|
+
}
|
|
6518
|
+
if (serviceConfig?.render) {
|
|
6519
|
+
return serviceConfig.render({ presentation, dpi });
|
|
6520
|
+
}
|
|
6521
|
+
const serverUrl = resolveServiceUrl(
|
|
6522
|
+
propsServerUrl,
|
|
6523
|
+
serviceConfig?.serverUrl,
|
|
6524
|
+
DEFAULT_RASTERIZE_SERVER_URL
|
|
6525
|
+
);
|
|
6526
|
+
const response = await postJsonToService({
|
|
6527
|
+
url: serverUrl,
|
|
6528
|
+
path: "/rasterize",
|
|
6529
|
+
body: { presentation, dpi },
|
|
6530
|
+
headers: serviceConfig?.headers,
|
|
6531
|
+
serviceLabel: "PPTX rasterization service",
|
|
6532
|
+
onUnreachable: (url, cause) => `PPTX rasterization service is not reachable at ${url}. Configure services.pptx with a \`render\` callback or a running \`serverUrl\`.
|
|
6533
|
+
Cause: ${cause}`
|
|
6534
|
+
});
|
|
6535
|
+
let result;
|
|
6536
|
+
try {
|
|
6537
|
+
result = await response.json();
|
|
6538
|
+
} catch {
|
|
6539
|
+
throw new Error(
|
|
6540
|
+
"PPTX rasterization service returned a non-JSON response (expected { base64DataUri, width, height })."
|
|
6541
|
+
);
|
|
6542
|
+
}
|
|
6543
|
+
if (!result?.base64DataUri) {
|
|
6544
|
+
throw new Error(
|
|
6545
|
+
"PPTX rasterization service returned a malformed response (missing base64DataUri)."
|
|
6546
|
+
);
|
|
6547
|
+
}
|
|
6548
|
+
return result;
|
|
6549
|
+
}
|
|
6550
|
+
async function renderVisualComponent(component, theme, themeName, context) {
|
|
6551
|
+
if (!isVisualComponent(component)) return [];
|
|
6552
|
+
const props = component.props;
|
|
6553
|
+
const serviceConfig = context?.services?.pptx;
|
|
6554
|
+
const presentation = buildVisualPresentation(props);
|
|
6555
|
+
const dpi = clampVisualDpi(
|
|
6556
|
+
props.dpi ?? serviceConfig?.dpi ?? DEFAULT_VISUAL_DPI
|
|
6557
|
+
);
|
|
6558
|
+
const result = await rasterize(
|
|
6559
|
+
presentation,
|
|
6560
|
+
dpi,
|
|
6561
|
+
props.serverUrl,
|
|
6562
|
+
serviceConfig
|
|
6563
|
+
);
|
|
6564
|
+
return await createImage(
|
|
6565
|
+
result.base64DataUri,
|
|
6566
|
+
theme,
|
|
6567
|
+
themeName,
|
|
6568
|
+
visualToImageOptions(props)
|
|
6569
|
+
);
|
|
6570
|
+
}
|
|
6571
|
+
|
|
6412
6572
|
// src/components/text-space-after.ts
|
|
6413
6573
|
import { Type } from "@sinclair/typebox";
|
|
6414
6574
|
|
|
@@ -6565,7 +6725,7 @@ async function renderDocument(structure, layout, options) {
|
|
|
6565
6725
|
}
|
|
6566
6726
|
});
|
|
6567
6727
|
}
|
|
6568
|
-
async function renderHeaderFooterComponents(components, theme, themeName,
|
|
6728
|
+
async function renderHeaderFooterComponents(components, theme, themeName, context) {
|
|
6569
6729
|
if (!components || components.length === 0) {
|
|
6570
6730
|
return [];
|
|
6571
6731
|
}
|
|
@@ -6697,6 +6857,14 @@ async function renderHeaderFooterComponents(components, theme, themeName, _conte
|
|
|
6697
6857
|
} else if (isTableComponent(component)) {
|
|
6698
6858
|
const tables = await renderTableComponent(component, theme, themeName);
|
|
6699
6859
|
elements.push(...tables);
|
|
6860
|
+
} else if (isVisualComponent(component)) {
|
|
6861
|
+
const visualEls = await renderVisualComponent(
|
|
6862
|
+
component,
|
|
6863
|
+
theme,
|
|
6864
|
+
themeName,
|
|
6865
|
+
context
|
|
6866
|
+
);
|
|
6867
|
+
elements.push(...visualEls);
|
|
6700
6868
|
}
|
|
6701
6869
|
}
|
|
6702
6870
|
return elements;
|
|
@@ -6817,6 +6985,8 @@ async function renderComponent(component, theme, themeName, context) {
|
|
|
6817
6985
|
themeName,
|
|
6818
6986
|
context
|
|
6819
6987
|
);
|
|
6988
|
+
} else if (isVisualComponent(component)) {
|
|
6989
|
+
return await renderVisualComponent(component, theme, themeName, context);
|
|
6820
6990
|
} else if (isSectionComponent(component)) {
|
|
6821
6991
|
return await renderSectionComponent(component, theme, themeName, context);
|
|
6822
6992
|
}
|
|
@@ -7188,6 +7358,112 @@ var DocumentGenerator = {
|
|
|
7188
7358
|
isReportComponentDefinition
|
|
7189
7359
|
};
|
|
7190
7360
|
|
|
7361
|
+
// src/core/flattenVisuals.ts
|
|
7362
|
+
import {
|
|
7363
|
+
clampVisualDpi as clampVisualDpi2,
|
|
7364
|
+
DEFAULT_VISUAL_DPI as DEFAULT_VISUAL_DPI2
|
|
7365
|
+
} from "@json-to-office/shared";
|
|
7366
|
+
var DEFAULT_CONCURRENCY = 4;
|
|
7367
|
+
function createLimiter(max) {
|
|
7368
|
+
let active = 0;
|
|
7369
|
+
const queue = [];
|
|
7370
|
+
const release = () => {
|
|
7371
|
+
active--;
|
|
7372
|
+
queue.shift()?.();
|
|
7373
|
+
};
|
|
7374
|
+
return async function limit(fn) {
|
|
7375
|
+
if (active >= max)
|
|
7376
|
+
await new Promise((resolve2) => queue.push(resolve2));
|
|
7377
|
+
active++;
|
|
7378
|
+
try {
|
|
7379
|
+
return await fn();
|
|
7380
|
+
} finally {
|
|
7381
|
+
release();
|
|
7382
|
+
}
|
|
7383
|
+
};
|
|
7384
|
+
}
|
|
7385
|
+
async function flattenVisuals(doc, options) {
|
|
7386
|
+
const ctx = {
|
|
7387
|
+
rasterize: options.rasterize,
|
|
7388
|
+
dpi: options.dpi,
|
|
7389
|
+
limit: createLimiter(
|
|
7390
|
+
Math.max(1, options.concurrency ?? DEFAULT_CONCURRENCY)
|
|
7391
|
+
)
|
|
7392
|
+
};
|
|
7393
|
+
return await flattenNode(doc, ctx);
|
|
7394
|
+
}
|
|
7395
|
+
async function rasterizeVisual(obj, ctx) {
|
|
7396
|
+
const props = obj.props;
|
|
7397
|
+
const dpi = clampVisualDpi2(props.dpi ?? ctx.dpi ?? DEFAULT_VISUAL_DPI2);
|
|
7398
|
+
const result = await ctx.limit(
|
|
7399
|
+
() => ctx.rasterize({ presentation: buildVisualPresentation(props), dpi })
|
|
7400
|
+
);
|
|
7401
|
+
const image = {
|
|
7402
|
+
name: "image",
|
|
7403
|
+
props: visualToImageProps(props, result.base64DataUri)
|
|
7404
|
+
};
|
|
7405
|
+
if (obj.id !== void 0) image.id = obj.id;
|
|
7406
|
+
if (obj.enabled !== void 0) image.enabled = obj.enabled;
|
|
7407
|
+
return image;
|
|
7408
|
+
}
|
|
7409
|
+
async function flattenNode(node, ctx) {
|
|
7410
|
+
if (Array.isArray(node)) {
|
|
7411
|
+
return Promise.all(node.map((n) => flattenNode(n, ctx)));
|
|
7412
|
+
}
|
|
7413
|
+
if (!node || typeof node !== "object") return node;
|
|
7414
|
+
const obj = node;
|
|
7415
|
+
if (obj.name === "visual" && obj.props && obj.enabled !== false) {
|
|
7416
|
+
return rasterizeVisual(obj, ctx);
|
|
7417
|
+
}
|
|
7418
|
+
const next = { ...obj };
|
|
7419
|
+
if (Array.isArray(obj.children)) {
|
|
7420
|
+
next.children = await flattenNode(obj.children, ctx);
|
|
7421
|
+
}
|
|
7422
|
+
if (obj.props && typeof obj.props === "object") {
|
|
7423
|
+
const props = obj.props;
|
|
7424
|
+
let propsChanged = false;
|
|
7425
|
+
const nextProps = { ...props };
|
|
7426
|
+
for (const key of ["header", "footer"]) {
|
|
7427
|
+
if (Array.isArray(props[key])) {
|
|
7428
|
+
nextProps[key] = await flattenNode(props[key], ctx);
|
|
7429
|
+
propsChanged = true;
|
|
7430
|
+
}
|
|
7431
|
+
}
|
|
7432
|
+
if (Array.isArray(props.columns)) {
|
|
7433
|
+
nextProps.columns = await Promise.all(
|
|
7434
|
+
props.columns.map((col) => flattenColumn(col, ctx))
|
|
7435
|
+
);
|
|
7436
|
+
propsChanged = true;
|
|
7437
|
+
}
|
|
7438
|
+
if (propsChanged) next.props = nextProps;
|
|
7439
|
+
}
|
|
7440
|
+
return next;
|
|
7441
|
+
}
|
|
7442
|
+
async function flattenColumn(col, ctx) {
|
|
7443
|
+
if (!col || typeof col !== "object") return col;
|
|
7444
|
+
const column = col;
|
|
7445
|
+
const nextCol = { ...column };
|
|
7446
|
+
const header = column.header;
|
|
7447
|
+
if (header && typeof header === "object" && "content" in header) {
|
|
7448
|
+
nextCol.header = {
|
|
7449
|
+
...header,
|
|
7450
|
+
content: await flattenNode(header.content, ctx)
|
|
7451
|
+
};
|
|
7452
|
+
}
|
|
7453
|
+
if (Array.isArray(column.cells)) {
|
|
7454
|
+
nextCol.cells = await Promise.all(
|
|
7455
|
+
column.cells.map(async (cell) => {
|
|
7456
|
+
if (cell && typeof cell === "object" && "content" in cell) {
|
|
7457
|
+
const c = cell;
|
|
7458
|
+
return { ...c, content: await flattenNode(c.content, ctx) };
|
|
7459
|
+
}
|
|
7460
|
+
return cell;
|
|
7461
|
+
})
|
|
7462
|
+
);
|
|
7463
|
+
}
|
|
7464
|
+
return nextCol;
|
|
7465
|
+
}
|
|
7466
|
+
|
|
7191
7467
|
// src/utils/warningsDocument.ts
|
|
7192
7468
|
function generateWarningsDocument(warnings) {
|
|
7193
7469
|
if (!warnings || warnings.length === 0) {
|
|
@@ -8007,6 +8283,7 @@ export {
|
|
|
8007
8283
|
examples,
|
|
8008
8284
|
exportPluginSchema,
|
|
8009
8285
|
exportThemeToJson,
|
|
8286
|
+
flattenVisuals,
|
|
8010
8287
|
formatDate,
|
|
8011
8288
|
formatWarningsText,
|
|
8012
8289
|
generateAndSave,
|
|
@@ -8041,6 +8318,7 @@ export {
|
|
|
8041
8318
|
isSectionComponent,
|
|
8042
8319
|
isStatisticComponent,
|
|
8043
8320
|
isTableComponent,
|
|
8321
|
+
isVisualComponent,
|
|
8044
8322
|
loadJsonExample,
|
|
8045
8323
|
loadThemeFromFile,
|
|
8046
8324
|
loadThemeFromJson,
|