@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
|
@@ -850,12 +850,20 @@ function getPageDimensions(size) {
|
|
|
850
850
|
}
|
|
851
851
|
return size;
|
|
852
852
|
}
|
|
853
|
-
var PAGE_SIZES, getTableStyle, getDocumentMargins, getPageSetup;
|
|
853
|
+
var resolveTableParagraphSpacing, PAGE_SIZES, getTableStyle, getDocumentMargins, getPageSetup;
|
|
854
854
|
var init_layoutUtils = __esm({
|
|
855
855
|
"src/styles/utils/layoutUtils.ts"() {
|
|
856
856
|
"use strict";
|
|
857
857
|
init_colorUtils();
|
|
858
858
|
init_styleHelpers();
|
|
859
|
+
resolveTableParagraphSpacing = (style) => {
|
|
860
|
+
const lineSpacing = convertLineSpacing(style?.lineSpacing) ?? convertLineSpacing({ type: "single" });
|
|
861
|
+
return {
|
|
862
|
+
before: style?.spacing?.before !== void 0 ? pointsToTwips(style.spacing.before) : 0,
|
|
863
|
+
after: style?.spacing?.after !== void 0 ? pointsToTwips(style.spacing.after) : 0,
|
|
864
|
+
...lineSpacing
|
|
865
|
+
};
|
|
866
|
+
};
|
|
859
867
|
PAGE_SIZES = {
|
|
860
868
|
A4: { width: 11906, height: 16838 },
|
|
861
869
|
A3: { width: 16838, height: 23811 },
|
|
@@ -866,7 +874,10 @@ var init_layoutUtils = __esm({
|
|
|
866
874
|
const themeConfig = resolveTheme(theme, themeName);
|
|
867
875
|
if (themeConfig && themeConfig.styles?.normal) {
|
|
868
876
|
const normalStyle = themeConfig.styles.normal;
|
|
877
|
+
const styles = themeConfig.styles;
|
|
869
878
|
return {
|
|
879
|
+
cellParagraph: resolveTableParagraphSpacing(styles.tableCell),
|
|
880
|
+
headerParagraph: resolveTableParagraphSpacing(styles.tableHeader),
|
|
870
881
|
tableHeader: {
|
|
871
882
|
fill: resolveColor(
|
|
872
883
|
themeConfig.colors?.primary || "#000000",
|
|
@@ -932,6 +943,8 @@ var init_layoutUtils = __esm({
|
|
|
932
943
|
};
|
|
933
944
|
}
|
|
934
945
|
return {
|
|
946
|
+
cellParagraph: resolveTableParagraphSpacing(),
|
|
947
|
+
headerParagraph: resolveTableParagraphSpacing(),
|
|
935
948
|
tableHeader: {
|
|
936
949
|
fill: "000000",
|
|
937
950
|
color: "FFFFFF",
|
|
@@ -2025,7 +2038,8 @@ import {
|
|
|
2025
2038
|
isTableComponent,
|
|
2026
2039
|
isListComponent,
|
|
2027
2040
|
isTocComponent,
|
|
2028
|
-
isHighchartsComponent
|
|
2041
|
+
isHighchartsComponent,
|
|
2042
|
+
isVisualComponent
|
|
2029
2043
|
} from "@json-to-office/shared-docx";
|
|
2030
2044
|
|
|
2031
2045
|
// src/utils/formatters.ts
|
|
@@ -2118,6 +2132,9 @@ function resolveListProps(props, theme) {
|
|
|
2118
2132
|
function resolveHighchartsProps(props, _theme) {
|
|
2119
2133
|
return props;
|
|
2120
2134
|
}
|
|
2135
|
+
function resolveVisualProps(props, _theme) {
|
|
2136
|
+
return props;
|
|
2137
|
+
}
|
|
2121
2138
|
function getCustomComponentDefaults(theme, componentName) {
|
|
2122
2139
|
const defaults = getComponentDefaults(theme);
|
|
2123
2140
|
return defaults?.[componentName] || {};
|
|
@@ -2147,7 +2164,8 @@ var RESOLVER_MAP = {
|
|
|
2147
2164
|
section: resolveSectionProps,
|
|
2148
2165
|
columns: resolveColumnsProps,
|
|
2149
2166
|
list: resolveListProps,
|
|
2150
|
-
highcharts: resolveHighchartsProps
|
|
2167
|
+
highcharts: resolveHighchartsProps,
|
|
2168
|
+
visual: resolveVisualProps
|
|
2151
2169
|
};
|
|
2152
2170
|
function resolveComponentDefaults(component, theme) {
|
|
2153
2171
|
if (!component.props) return component;
|
|
@@ -4128,7 +4146,7 @@ function initializeComponentCache(cache) {
|
|
|
4128
4146
|
}
|
|
4129
4147
|
}
|
|
4130
4148
|
async function renderComponentWithCache(component, theme, themeName, context, bypassCache = false) {
|
|
4131
|
-
const forceBypassForType = component.name === "toc" || component.name === "section" || componentHasRevision(component);
|
|
4149
|
+
const forceBypassForType = component.name === "toc" || component.name === "section" || component.name === "visual" || componentHasRevision(component);
|
|
4132
4150
|
if (!componentCache) {
|
|
4133
4151
|
initializeComponentCache();
|
|
4134
4152
|
}
|
|
@@ -5169,6 +5187,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
5169
5187
|
children: [
|
|
5170
5188
|
new Paragraph({
|
|
5171
5189
|
...tableConfig.keepInOnePage && { keepNext: true },
|
|
5190
|
+
spacing: tableStyle.headerParagraph,
|
|
5172
5191
|
alignment: getAlignment(horizontalAlignment),
|
|
5173
5192
|
children: cellChildren
|
|
5174
5193
|
})
|
|
@@ -5263,6 +5282,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
5263
5282
|
children: [
|
|
5264
5283
|
new Paragraph({
|
|
5265
5284
|
...tableConfig.keepInOnePage && !isLastRow || isLastRow && tableConfig.keepNext ? { keepNext: true } : {},
|
|
5285
|
+
spacing: tableStyle.cellParagraph,
|
|
5266
5286
|
alignment: AlignmentType2.LEFT,
|
|
5267
5287
|
children: []
|
|
5268
5288
|
})
|
|
@@ -5338,6 +5358,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
5338
5358
|
children: [
|
|
5339
5359
|
new Paragraph({
|
|
5340
5360
|
...tableConfig.keepInOnePage && !isLastRow || isLastRow && tableConfig.keepNext ? { keepNext: true } : {},
|
|
5361
|
+
spacing: tableStyle.cellParagraph,
|
|
5341
5362
|
alignment: getAlignment(horizontalAlignment),
|
|
5342
5363
|
children: cellChildren
|
|
5343
5364
|
})
|
|
@@ -6377,21 +6398,61 @@ function isNodeEnvironment() {
|
|
|
6377
6398
|
return typeof process !== "undefined" && process.versions != null && process.versions.node != null && typeof process.versions.node === "string";
|
|
6378
6399
|
}
|
|
6379
6400
|
|
|
6401
|
+
// src/utils/serviceClient.ts
|
|
6402
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
6403
|
+
function resolveServiceUrl(propsUrl, servicesUrl, defaultUrl) {
|
|
6404
|
+
const raw = (propsUrl || servicesUrl || defaultUrl).trim();
|
|
6405
|
+
const withScheme = /^https?:\/\//i.test(raw) ? raw : `http://${raw}`;
|
|
6406
|
+
return withScheme.replace(/\/+$/, "");
|
|
6407
|
+
}
|
|
6408
|
+
async function postJsonToService(opts) {
|
|
6409
|
+
const resolvedHeaders = typeof opts.headers === "function" ? await opts.headers(opts.body) : opts.headers;
|
|
6410
|
+
const headers = {
|
|
6411
|
+
"Content-Type": "application/json",
|
|
6412
|
+
...resolvedHeaders
|
|
6413
|
+
};
|
|
6414
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
6415
|
+
const controller = new AbortController();
|
|
6416
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
6417
|
+
let response;
|
|
6418
|
+
try {
|
|
6419
|
+
response = await fetch(`${opts.url}${opts.path}`, {
|
|
6420
|
+
method: "POST",
|
|
6421
|
+
headers,
|
|
6422
|
+
body: JSON.stringify(opts.body),
|
|
6423
|
+
signal: controller.signal
|
|
6424
|
+
});
|
|
6425
|
+
} catch (error) {
|
|
6426
|
+
if (error?.name === "AbortError") {
|
|
6427
|
+
throw new Error(
|
|
6428
|
+
`${opts.serviceLabel} timed out after ${timeoutMs}ms at ${opts.url}.`
|
|
6429
|
+
);
|
|
6430
|
+
}
|
|
6431
|
+
const cause = error instanceof Error ? error.message : String(error);
|
|
6432
|
+
throw new Error(opts.onUnreachable(opts.url, cause));
|
|
6433
|
+
} finally {
|
|
6434
|
+
clearTimeout(timer);
|
|
6435
|
+
}
|
|
6436
|
+
if (!response.ok) {
|
|
6437
|
+
throw new Error(
|
|
6438
|
+
`${opts.serviceLabel} returned ${response.status}: ${response.statusText}`
|
|
6439
|
+
);
|
|
6440
|
+
}
|
|
6441
|
+
return response;
|
|
6442
|
+
}
|
|
6443
|
+
|
|
6380
6444
|
// src/components/highcharts.ts
|
|
6381
6445
|
var DEFAULT_EXPORT_SERVER_URL = "http://localhost:7801";
|
|
6382
|
-
function getExportServerUrl(propsUrl, servicesUrl) {
|
|
6383
|
-
const raw = propsUrl || servicesUrl || DEFAULT_EXPORT_SERVER_URL;
|
|
6384
|
-
return raw.startsWith("http") ? raw : `http://${raw}`;
|
|
6385
|
-
}
|
|
6386
6446
|
async function generateChart(config, servicesConfig) {
|
|
6387
6447
|
if (!isNodeEnvironment()) {
|
|
6388
6448
|
throw new Error(
|
|
6389
6449
|
"Highcharts export server requires a Node.js environment. Chart generation is not available in browser environments."
|
|
6390
6450
|
);
|
|
6391
6451
|
}
|
|
6392
|
-
const serverUrl =
|
|
6452
|
+
const serverUrl = resolveServiceUrl(
|
|
6393
6453
|
config.serverUrl,
|
|
6394
|
-
servicesConfig?.serverUrl
|
|
6454
|
+
servicesConfig?.serverUrl,
|
|
6455
|
+
DEFAULT_EXPORT_SERVER_URL
|
|
6395
6456
|
);
|
|
6396
6457
|
const requestBody = {
|
|
6397
6458
|
infile: config.options,
|
|
@@ -6399,26 +6460,15 @@ async function generateChart(config, servicesConfig) {
|
|
|
6399
6460
|
b64: true,
|
|
6400
6461
|
scale: config.scale
|
|
6401
6462
|
};
|
|
6402
|
-
const
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
body: JSON.stringify(requestBody)
|
|
6411
|
-
}).catch((error) => {
|
|
6412
|
-
throw new Error(
|
|
6413
|
-
`Highcharts Export Server is not running at ${serverUrl}. Start it with: npx highcharts-export-server --enableServer true
|
|
6414
|
-
Cause: ${error instanceof Error ? error.message : String(error)}`
|
|
6415
|
-
);
|
|
6463
|
+
const response = await postJsonToService({
|
|
6464
|
+
url: serverUrl,
|
|
6465
|
+
path: "/export",
|
|
6466
|
+
body: requestBody,
|
|
6467
|
+
headers: servicesConfig?.headers,
|
|
6468
|
+
serviceLabel: "Highcharts export server",
|
|
6469
|
+
onUnreachable: (url, cause) => `Highcharts Export Server is not running at ${url}. Start it with: npx highcharts-export-server --enableServer true
|
|
6470
|
+
Cause: ${cause}`
|
|
6416
6471
|
});
|
|
6417
|
-
if (!response.ok) {
|
|
6418
|
-
throw new Error(
|
|
6419
|
-
`Highcharts export server returned ${response.status}: ${response.statusText}`
|
|
6420
|
-
);
|
|
6421
|
-
}
|
|
6422
6472
|
const base64Data = await response.text();
|
|
6423
6473
|
const base64DataUri = `data:image/png;base64,${base64Data}`;
|
|
6424
6474
|
const width = config.options.chart.width;
|
|
@@ -6452,6 +6502,109 @@ async function renderHighchartsComponent(component, theme, themeName, context) {
|
|
|
6452
6502
|
return imageParagraphs;
|
|
6453
6503
|
}
|
|
6454
6504
|
|
|
6505
|
+
// src/components/visual.ts
|
|
6506
|
+
import {
|
|
6507
|
+
clampVisualDpi,
|
|
6508
|
+
DEFAULT_VISUAL_DPI
|
|
6509
|
+
} from "@json-to-office/shared";
|
|
6510
|
+
var DEFAULT_RASTERIZE_SERVER_URL = "http://localhost:7802";
|
|
6511
|
+
var PIXELS_PER_INCH = 96;
|
|
6512
|
+
function buildVisualPresentation(props) {
|
|
6513
|
+
const { canvas, elements } = props;
|
|
6514
|
+
const presentationProps = {
|
|
6515
|
+
slideWidth: canvas.width,
|
|
6516
|
+
slideHeight: canvas.height
|
|
6517
|
+
};
|
|
6518
|
+
if (canvas.theme) presentationProps.theme = canvas.theme;
|
|
6519
|
+
const slideProps = {};
|
|
6520
|
+
if (canvas.background) slideProps.background = canvas.background;
|
|
6521
|
+
return {
|
|
6522
|
+
name: "pptx",
|
|
6523
|
+
props: presentationProps,
|
|
6524
|
+
children: [
|
|
6525
|
+
{
|
|
6526
|
+
name: "slide",
|
|
6527
|
+
props: slideProps,
|
|
6528
|
+
children: elements ?? []
|
|
6529
|
+
}
|
|
6530
|
+
]
|
|
6531
|
+
};
|
|
6532
|
+
}
|
|
6533
|
+
function defaultVisualWidthPx(props) {
|
|
6534
|
+
return Math.round(props.canvas.width * PIXELS_PER_INCH);
|
|
6535
|
+
}
|
|
6536
|
+
function visualToImageOptions(props) {
|
|
6537
|
+
return {
|
|
6538
|
+
width: props.width ?? defaultVisualWidthPx(props),
|
|
6539
|
+
...props.height !== void 0 && { height: props.height },
|
|
6540
|
+
alignment: props.alignment ?? "center",
|
|
6541
|
+
...props.caption !== void 0 && { caption: props.caption },
|
|
6542
|
+
...props.spacing !== void 0 && { spacing: props.spacing },
|
|
6543
|
+
...props.floating !== void 0 && { floating: props.floating },
|
|
6544
|
+
...props.keepNext !== void 0 && { keepNext: props.keepNext },
|
|
6545
|
+
...props.keepLines !== void 0 && { keepLines: props.keepLines }
|
|
6546
|
+
};
|
|
6547
|
+
}
|
|
6548
|
+
async function rasterize(presentation, dpi, propsServerUrl, serviceConfig) {
|
|
6549
|
+
if (!isNodeEnvironment()) {
|
|
6550
|
+
throw new Error(
|
|
6551
|
+
"Visual rasterization requires a Node.js environment. It is not available in browser environments."
|
|
6552
|
+
);
|
|
6553
|
+
}
|
|
6554
|
+
if (serviceConfig?.render) {
|
|
6555
|
+
return serviceConfig.render({ presentation, dpi });
|
|
6556
|
+
}
|
|
6557
|
+
const serverUrl = resolveServiceUrl(
|
|
6558
|
+
propsServerUrl,
|
|
6559
|
+
serviceConfig?.serverUrl,
|
|
6560
|
+
DEFAULT_RASTERIZE_SERVER_URL
|
|
6561
|
+
);
|
|
6562
|
+
const response = await postJsonToService({
|
|
6563
|
+
url: serverUrl,
|
|
6564
|
+
path: "/rasterize",
|
|
6565
|
+
body: { presentation, dpi },
|
|
6566
|
+
headers: serviceConfig?.headers,
|
|
6567
|
+
serviceLabel: "PPTX rasterization service",
|
|
6568
|
+
onUnreachable: (url, cause) => `PPTX rasterization service is not reachable at ${url}. Configure services.pptx with a \`render\` callback or a running \`serverUrl\`.
|
|
6569
|
+
Cause: ${cause}`
|
|
6570
|
+
});
|
|
6571
|
+
let result;
|
|
6572
|
+
try {
|
|
6573
|
+
result = await response.json();
|
|
6574
|
+
} catch {
|
|
6575
|
+
throw new Error(
|
|
6576
|
+
"PPTX rasterization service returned a non-JSON response (expected { base64DataUri, width, height })."
|
|
6577
|
+
);
|
|
6578
|
+
}
|
|
6579
|
+
if (!result?.base64DataUri) {
|
|
6580
|
+
throw new Error(
|
|
6581
|
+
"PPTX rasterization service returned a malformed response (missing base64DataUri)."
|
|
6582
|
+
);
|
|
6583
|
+
}
|
|
6584
|
+
return result;
|
|
6585
|
+
}
|
|
6586
|
+
async function renderVisualComponent(component, theme, themeName, context) {
|
|
6587
|
+
if (!isVisualComponent(component)) return [];
|
|
6588
|
+
const props = component.props;
|
|
6589
|
+
const serviceConfig = context?.services?.pptx;
|
|
6590
|
+
const presentation = buildVisualPresentation(props);
|
|
6591
|
+
const dpi = clampVisualDpi(
|
|
6592
|
+
props.dpi ?? serviceConfig?.dpi ?? DEFAULT_VISUAL_DPI
|
|
6593
|
+
);
|
|
6594
|
+
const result = await rasterize(
|
|
6595
|
+
presentation,
|
|
6596
|
+
dpi,
|
|
6597
|
+
props.serverUrl,
|
|
6598
|
+
serviceConfig
|
|
6599
|
+
);
|
|
6600
|
+
return await createImage(
|
|
6601
|
+
result.base64DataUri,
|
|
6602
|
+
theme,
|
|
6603
|
+
themeName,
|
|
6604
|
+
visualToImageOptions(props)
|
|
6605
|
+
);
|
|
6606
|
+
}
|
|
6607
|
+
|
|
6455
6608
|
// src/components/text-space-after.ts
|
|
6456
6609
|
import { Type as Type2 } from "@sinclair/typebox";
|
|
6457
6610
|
|
|
@@ -6608,7 +6761,7 @@ async function renderDocument(structure, layout, options) {
|
|
|
6608
6761
|
}
|
|
6609
6762
|
});
|
|
6610
6763
|
}
|
|
6611
|
-
async function renderHeaderFooterComponents(components, theme, themeName,
|
|
6764
|
+
async function renderHeaderFooterComponents(components, theme, themeName, context) {
|
|
6612
6765
|
if (!components || components.length === 0) {
|
|
6613
6766
|
return [];
|
|
6614
6767
|
}
|
|
@@ -6740,6 +6893,14 @@ async function renderHeaderFooterComponents(components, theme, themeName, _conte
|
|
|
6740
6893
|
} else if (isTableComponent(component)) {
|
|
6741
6894
|
const tables = await renderTableComponent(component, theme, themeName);
|
|
6742
6895
|
elements.push(...tables);
|
|
6896
|
+
} else if (isVisualComponent(component)) {
|
|
6897
|
+
const visualEls = await renderVisualComponent(
|
|
6898
|
+
component,
|
|
6899
|
+
theme,
|
|
6900
|
+
themeName,
|
|
6901
|
+
context
|
|
6902
|
+
);
|
|
6903
|
+
elements.push(...visualEls);
|
|
6743
6904
|
}
|
|
6744
6905
|
}
|
|
6745
6906
|
return elements;
|
|
@@ -6860,6 +7021,8 @@ async function renderComponent(component, theme, themeName, context) {
|
|
|
6860
7021
|
themeName,
|
|
6861
7022
|
context
|
|
6862
7023
|
);
|
|
7024
|
+
} else if (isVisualComponent(component)) {
|
|
7025
|
+
return await renderVisualComponent(component, theme, themeName, context);
|
|
6863
7026
|
} else if (isSectionComponent(component)) {
|
|
6864
7027
|
return await renderSectionComponent(component, theme, themeName, context);
|
|
6865
7028
|
}
|