@json-to-office/core-docx 0.27.0 → 0.29.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/visual.d.ts +27 -0
- package/dist/components/visual.d.ts.map +1 -1
- package/dist/core/cached-render.d.ts.map +1 -1
- package/dist/core/flattenVisuals.d.ts +15 -2
- package/dist/core/flattenVisuals.d.ts.map +1 -1
- package/dist/core/generator.d.ts +6 -0
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/core/prerasterizeVisuals.d.ts +44 -0
- package/dist/core/prerasterizeVisuals.d.ts.map +1 -0
- package/dist/core/render.d.ts +5 -0
- package/dist/core/render.d.ts.map +1 -1
- package/dist/index.js +334 -58
- package/dist/index.js.map +1 -1
- package/dist/plugin/createDocumentGenerator.d.ts +6 -0
- package/dist/plugin/createDocumentGenerator.d.ts.map +1 -1
- package/dist/plugin/example/index.js +286 -30
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/plugin/types.d.ts +6 -0
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +7 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/generationContext.d.ts +15 -0
- package/dist/utils/generationContext.d.ts.map +1 -1
- package/dist/utils/imageUtils.d.ts.map +1 -1
- package/dist/utils/promiseLimiter.d.ts +7 -0
- package/dist/utils/promiseLimiter.d.ts.map +1 -0
- package/package.json +3 -3
|
@@ -27,6 +27,12 @@ export interface DocumentGeneratorOptions {
|
|
|
27
27
|
deterministic?: boolean;
|
|
28
28
|
/** Default build timestamp for generated metadata. */
|
|
29
29
|
generatedAt?: string | Date;
|
|
30
|
+
/**
|
|
31
|
+
* Directory that relative asset paths (image `path` props) resolve against.
|
|
32
|
+
* Per-call `options.baseDir` overrides it; defaults to `process.cwd()`
|
|
33
|
+
* when neither is set (#142).
|
|
34
|
+
*/
|
|
35
|
+
baseDir?: string;
|
|
30
36
|
}
|
|
31
37
|
/**
|
|
32
38
|
* Create a document generator with chainable component registration.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createDocumentGenerator.d.ts","sourceRoot":"","sources":["../../src/plugin/createDocumentGenerator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAK7C,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,KAAK,EAEV,wBAAwB,EAOxB,2BAA2B,EAC5B,MAAM,SAAS,CAAC;AAmBjB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,kEAAkE;IAClE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC3C,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,oFAAoF;IACpF,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,2BAA2B,CAAC;IACzC,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"createDocumentGenerator.d.ts","sourceRoot":"","sources":["../../src/plugin/createDocumentGenerator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAK7C,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,KAAK,EAEV,wBAAwB,EAOxB,2BAA2B,EAC5B,MAAM,SAAS,CAAC;AAmBjB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,kEAAkE;IAClE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC3C,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,oFAAoF;IACpF,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,2BAA2B,CAAC;IACzC,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAyoBD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,wBAAwB,CAAC,SAAS,EAAE,CAAC,CAiBvC"}
|
|
@@ -2870,9 +2870,34 @@ import {
|
|
|
2870
2870
|
} from "docx";
|
|
2871
2871
|
|
|
2872
2872
|
// src/utils/imageUtils.ts
|
|
2873
|
-
init_widthUtils();
|
|
2874
2873
|
import { readFileSync } from "fs";
|
|
2875
2874
|
import probe from "probe-image-size";
|
|
2875
|
+
|
|
2876
|
+
// src/utils/generationContext.ts
|
|
2877
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
2878
|
+
import { isAbsolute, resolve } from "path";
|
|
2879
|
+
var generationDateStorage = new AsyncLocalStorage();
|
|
2880
|
+
function runWithGenerationDate(date, callback) {
|
|
2881
|
+
return generationDateStorage.run(date, callback);
|
|
2882
|
+
}
|
|
2883
|
+
function getGenerationDate() {
|
|
2884
|
+
return generationDateStorage.getStore() ?? /* @__PURE__ */ new Date();
|
|
2885
|
+
}
|
|
2886
|
+
var baseDirStorage = new AsyncLocalStorage();
|
|
2887
|
+
function runWithBaseDir(baseDir, callback) {
|
|
2888
|
+
return baseDir === void 0 ? callback() : baseDirStorage.run(resolve(baseDir), callback);
|
|
2889
|
+
}
|
|
2890
|
+
function getBaseDir() {
|
|
2891
|
+
return baseDirStorage.getStore();
|
|
2892
|
+
}
|
|
2893
|
+
function resolveFromBaseDir(filePath) {
|
|
2894
|
+
const base = baseDirStorage.getStore();
|
|
2895
|
+
if (!base || isAbsolute(filePath)) return filePath;
|
|
2896
|
+
return resolve(base, filePath);
|
|
2897
|
+
}
|
|
2898
|
+
|
|
2899
|
+
// src/utils/imageUtils.ts
|
|
2900
|
+
init_widthUtils();
|
|
2876
2901
|
import { ImageRun } from "docx";
|
|
2877
2902
|
function parseWidthValue(width, availableWidthPx) {
|
|
2878
2903
|
if (typeof width === "number") {
|
|
@@ -3048,7 +3073,7 @@ async function getImageBuffer(imagePath) {
|
|
|
3048
3073
|
if (isValidUrl(imagePath)) {
|
|
3049
3074
|
return await downloadImageFromUrl(imagePath);
|
|
3050
3075
|
}
|
|
3051
|
-
return { buffer: readFileSync(imagePath) };
|
|
3076
|
+
return { buffer: readFileSync(resolveFromBaseDir(imagePath)) };
|
|
3052
3077
|
}
|
|
3053
3078
|
async function getImageDimensions(imagePath) {
|
|
3054
3079
|
try {
|
|
@@ -4120,16 +4145,6 @@ function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
|
|
|
4120
4145
|
return runs;
|
|
4121
4146
|
}
|
|
4122
4147
|
|
|
4123
|
-
// src/utils/generationContext.ts
|
|
4124
|
-
import { AsyncLocalStorage } from "async_hooks";
|
|
4125
|
-
var generationDateStorage = new AsyncLocalStorage();
|
|
4126
|
-
function runWithGenerationDate(date, callback) {
|
|
4127
|
-
return generationDateStorage.run(date, callback);
|
|
4128
|
-
}
|
|
4129
|
-
function getGenerationDate() {
|
|
4130
|
-
return generationDateStorage.getStore() ?? /* @__PURE__ */ new Date();
|
|
4131
|
-
}
|
|
4132
|
-
|
|
4133
4148
|
// src/utils/placeholderProcessor.ts
|
|
4134
4149
|
function styledPlaceholderText(text, context) {
|
|
4135
4150
|
return new TextRun2({
|
|
@@ -4476,8 +4491,9 @@ async function renderComponentWithCache(component, theme, themeName, context, by
|
|
|
4476
4491
|
const themeHash = createThemeHash(theme);
|
|
4477
4492
|
const contextKey = context?.section ? `${context.section.currentLayout}:${context.section.columnCount}` : "no-section";
|
|
4478
4493
|
const generationDateKey = getGenerationDate().toISOString();
|
|
4494
|
+
const baseDirKey = getBaseDir() ?? "";
|
|
4479
4495
|
const childrenKey = "children" in component && component.children ? `:children:${JSON.stringify(component.children)}` : "";
|
|
4480
|
-
const cacheKey = `component:${component.name}:${themeHash}:${contextKey}:${generationDateKey}:${componentProps}${childrenKey}`;
|
|
4496
|
+
const cacheKey = `component:${component.name}:${themeHash}:${contextKey}:${generationDateKey}:${baseDirKey}:${componentProps}${childrenKey}`;
|
|
4481
4497
|
const cached = await componentCache.get(cacheKey);
|
|
4482
4498
|
if (cached) {
|
|
4483
4499
|
return cached.result;
|
|
@@ -7130,6 +7146,7 @@ async function renderHighchartsComponent(component, theme, themeName, context) {
|
|
|
7130
7146
|
}
|
|
7131
7147
|
|
|
7132
7148
|
// src/components/visual.ts
|
|
7149
|
+
import { createHash as createHash4 } from "crypto";
|
|
7133
7150
|
import {
|
|
7134
7151
|
clampVisualDpi,
|
|
7135
7152
|
DEFAULT_VISUAL_DPI
|
|
@@ -7172,14 +7189,21 @@ function visualToImageOptions(props) {
|
|
|
7172
7189
|
...props.keepLines !== void 0 && { keepLines: props.keepLines }
|
|
7173
7190
|
};
|
|
7174
7191
|
}
|
|
7175
|
-
|
|
7192
|
+
function visualRasterKey(presentation, dpi, serverUrl) {
|
|
7193
|
+
return createHash4("sha256").update(JSON.stringify({ p: presentation, d: dpi, u: serverUrl ?? null })).digest("hex");
|
|
7194
|
+
}
|
|
7195
|
+
function effectiveVisualServerUrl(props, serviceConfig) {
|
|
7196
|
+
if (serviceConfig?.render) return void 0;
|
|
7197
|
+
return props.serverUrl;
|
|
7198
|
+
}
|
|
7199
|
+
async function rasterizeVisualSlide(presentation, dpi, propsServerUrl, serviceConfig, baseDir) {
|
|
7176
7200
|
if (!isNodeEnvironment()) {
|
|
7177
7201
|
throw new Error(
|
|
7178
7202
|
"Visual rasterization requires a Node.js environment. It is not available in browser environments."
|
|
7179
7203
|
);
|
|
7180
7204
|
}
|
|
7181
7205
|
if (serviceConfig?.render) {
|
|
7182
|
-
return serviceConfig.render({ presentation, dpi });
|
|
7206
|
+
return serviceConfig.render({ presentation, dpi, baseDir });
|
|
7183
7207
|
}
|
|
7184
7208
|
const serverUrl = resolveServiceUrl(
|
|
7185
7209
|
propsServerUrl,
|
|
@@ -7189,7 +7213,7 @@ async function rasterize(presentation, dpi, propsServerUrl, serviceConfig) {
|
|
|
7189
7213
|
const response = await postJsonToService({
|
|
7190
7214
|
url: serverUrl,
|
|
7191
7215
|
path: "/rasterize",
|
|
7192
|
-
body: { presentation, dpi },
|
|
7216
|
+
body: { presentation, dpi, ...baseDir !== void 0 && { baseDir } },
|
|
7193
7217
|
headers: serviceConfig?.headers,
|
|
7194
7218
|
serviceLabel: "PPTX rasterization service",
|
|
7195
7219
|
onUnreachable: (url, cause) => `PPTX rasterization service is not reachable at ${url}. Configure services.pptx with a \`render\` callback or a running \`serverUrl\`.
|
|
@@ -7218,12 +7242,26 @@ async function renderVisualComponent(component, theme, themeName, context) {
|
|
|
7218
7242
|
const dpi = clampVisualDpi(
|
|
7219
7243
|
props.dpi ?? serviceConfig?.dpi ?? DEFAULT_VISUAL_DPI
|
|
7220
7244
|
);
|
|
7221
|
-
const
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
|
|
7245
|
+
const preRasterized = context?.visualRasterResults?.get(
|
|
7246
|
+
visualRasterKey(
|
|
7247
|
+
presentation,
|
|
7248
|
+
dpi,
|
|
7249
|
+
effectiveVisualServerUrl(props, serviceConfig)
|
|
7250
|
+
)
|
|
7226
7251
|
);
|
|
7252
|
+
let result;
|
|
7253
|
+
if (preRasterized) {
|
|
7254
|
+
if (!preRasterized.ok) throw new Error(preRasterized.error);
|
|
7255
|
+
result = preRasterized;
|
|
7256
|
+
} else {
|
|
7257
|
+
result = await rasterizeVisualSlide(
|
|
7258
|
+
presentation,
|
|
7259
|
+
dpi,
|
|
7260
|
+
props.serverUrl,
|
|
7261
|
+
serviceConfig,
|
|
7262
|
+
getBaseDir()
|
|
7263
|
+
);
|
|
7264
|
+
}
|
|
7227
7265
|
return await createImage(
|
|
7228
7266
|
result.base64DataUri,
|
|
7229
7267
|
theme,
|
|
@@ -7285,6 +7323,203 @@ var textSpaceAfterComponent = createComponent({
|
|
|
7285
7323
|
|
|
7286
7324
|
// src/core/render.ts
|
|
7287
7325
|
init_docxImagePositioning();
|
|
7326
|
+
|
|
7327
|
+
// src/core/prerasterizeVisuals.ts
|
|
7328
|
+
import {
|
|
7329
|
+
clampVisualDpi as clampVisualDpi2,
|
|
7330
|
+
DEFAULT_VISUAL_DPI as DEFAULT_VISUAL_DPI2,
|
|
7331
|
+
MAX_RASTERIZE_BATCH_SLIDES
|
|
7332
|
+
} from "@json-to-office/shared";
|
|
7333
|
+
|
|
7334
|
+
// src/utils/promiseLimiter.ts
|
|
7335
|
+
function createLimiter(max) {
|
|
7336
|
+
let active = 0;
|
|
7337
|
+
const queue = [];
|
|
7338
|
+
const release = () => {
|
|
7339
|
+
active--;
|
|
7340
|
+
queue.shift()?.();
|
|
7341
|
+
};
|
|
7342
|
+
return async function limit(fn) {
|
|
7343
|
+
while (active >= max)
|
|
7344
|
+
await new Promise((resolve2) => queue.push(resolve2));
|
|
7345
|
+
active++;
|
|
7346
|
+
try {
|
|
7347
|
+
return await fn();
|
|
7348
|
+
} finally {
|
|
7349
|
+
release();
|
|
7350
|
+
}
|
|
7351
|
+
};
|
|
7352
|
+
}
|
|
7353
|
+
|
|
7354
|
+
// src/core/prerasterizeVisuals.ts
|
|
7355
|
+
var DEFAULT_FALLBACK_CONCURRENCY = 4;
|
|
7356
|
+
var BATCH_TIMEOUT_BASE_MS = 3e4;
|
|
7357
|
+
var BATCH_TIMEOUT_PER_SLIDE_MS = 1e4;
|
|
7358
|
+
function collectVisualProps(root) {
|
|
7359
|
+
const found = [];
|
|
7360
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
7361
|
+
const visit = (node) => {
|
|
7362
|
+
if (!node || typeof node !== "object") return;
|
|
7363
|
+
if (seen.has(node)) return;
|
|
7364
|
+
seen.add(node);
|
|
7365
|
+
if (Array.isArray(node)) {
|
|
7366
|
+
for (const item of node) visit(item);
|
|
7367
|
+
return;
|
|
7368
|
+
}
|
|
7369
|
+
const obj = node;
|
|
7370
|
+
if (typeof obj.name === "string" && obj.enabled === false) return;
|
|
7371
|
+
if (obj.name === "visual" && obj.props && typeof obj.props === "object") {
|
|
7372
|
+
found.push(obj.props);
|
|
7373
|
+
return;
|
|
7374
|
+
}
|
|
7375
|
+
for (const value of Object.values(obj)) visit(value);
|
|
7376
|
+
};
|
|
7377
|
+
visit(root);
|
|
7378
|
+
return found;
|
|
7379
|
+
}
|
|
7380
|
+
function toErrorMessage(error) {
|
|
7381
|
+
return error instanceof Error ? error.message : String(error);
|
|
7382
|
+
}
|
|
7383
|
+
function* chunksOf(items, size) {
|
|
7384
|
+
for (let i = 0; i < items.length; i += size) yield items.slice(i, i + size);
|
|
7385
|
+
}
|
|
7386
|
+
function applyBatchResponse(chunk, response, map) {
|
|
7387
|
+
const results = response?.results;
|
|
7388
|
+
if (!Array.isArray(results) || results.length !== chunk.length) return false;
|
|
7389
|
+
const entries = [];
|
|
7390
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
7391
|
+
const item = results[i];
|
|
7392
|
+
if (item && item.ok === true && typeof item.base64DataUri === "string" && item.base64DataUri.length > 0 && typeof item.width === "number" && typeof item.height === "number") {
|
|
7393
|
+
entries.push([
|
|
7394
|
+
chunk[i].key,
|
|
7395
|
+
{
|
|
7396
|
+
ok: true,
|
|
7397
|
+
base64DataUri: item.base64DataUri,
|
|
7398
|
+
width: item.width,
|
|
7399
|
+
height: item.height
|
|
7400
|
+
}
|
|
7401
|
+
]);
|
|
7402
|
+
} else if (item && item.ok === false && typeof item.error === "string") {
|
|
7403
|
+
entries.push([chunk[i].key, { ok: false, error: item.error }]);
|
|
7404
|
+
} else {
|
|
7405
|
+
return false;
|
|
7406
|
+
}
|
|
7407
|
+
}
|
|
7408
|
+
for (const [key, value] of entries) map.set(key, value);
|
|
7409
|
+
return true;
|
|
7410
|
+
}
|
|
7411
|
+
async function prerasterizeVisuals(root, serviceConfig, options = {}) {
|
|
7412
|
+
const map = /* @__PURE__ */ new Map();
|
|
7413
|
+
if (!isNodeEnvironment() && !serviceConfig?.renderBatch && !serviceConfig?.render) {
|
|
7414
|
+
return map;
|
|
7415
|
+
}
|
|
7416
|
+
const visuals = collectVisualProps(root);
|
|
7417
|
+
if (visuals.length === 0) return map;
|
|
7418
|
+
const targets = /* @__PURE__ */ new Map();
|
|
7419
|
+
for (const props of visuals) {
|
|
7420
|
+
try {
|
|
7421
|
+
const serverUrl2 = effectiveVisualServerUrl(props, serviceConfig);
|
|
7422
|
+
if (serverUrl2 !== void 0) continue;
|
|
7423
|
+
const presentation = buildVisualPresentation(props);
|
|
7424
|
+
const dpi = clampVisualDpi2(
|
|
7425
|
+
props.dpi ?? serviceConfig?.dpi ?? DEFAULT_VISUAL_DPI2
|
|
7426
|
+
);
|
|
7427
|
+
const key = visualRasterKey(presentation, dpi, serverUrl2);
|
|
7428
|
+
if (!targets.has(key)) targets.set(key, { key, presentation, dpi });
|
|
7429
|
+
} catch {
|
|
7430
|
+
continue;
|
|
7431
|
+
}
|
|
7432
|
+
}
|
|
7433
|
+
if (targets.size === 0) return map;
|
|
7434
|
+
const unique = [...targets.values()];
|
|
7435
|
+
const limit = createLimiter(
|
|
7436
|
+
Math.max(1, options.concurrency ?? DEFAULT_FALLBACK_CONCURRENCY)
|
|
7437
|
+
);
|
|
7438
|
+
const rasterizeIndividually = async (chunk) => {
|
|
7439
|
+
await Promise.all(
|
|
7440
|
+
chunk.map(
|
|
7441
|
+
(target) => limit(async () => {
|
|
7442
|
+
try {
|
|
7443
|
+
const result = await rasterizeVisualSlide(
|
|
7444
|
+
target.presentation,
|
|
7445
|
+
target.dpi,
|
|
7446
|
+
void 0,
|
|
7447
|
+
serviceConfig,
|
|
7448
|
+
options.baseDir
|
|
7449
|
+
);
|
|
7450
|
+
map.set(target.key, { ok: true, ...result });
|
|
7451
|
+
} catch (error) {
|
|
7452
|
+
map.set(target.key, { ok: false, error: toErrorMessage(error) });
|
|
7453
|
+
}
|
|
7454
|
+
})
|
|
7455
|
+
)
|
|
7456
|
+
);
|
|
7457
|
+
};
|
|
7458
|
+
if (serviceConfig?.renderBatch) {
|
|
7459
|
+
for (const chunk of chunksOf(unique, MAX_RASTERIZE_BATCH_SLIDES)) {
|
|
7460
|
+
try {
|
|
7461
|
+
const response = await serviceConfig.renderBatch({
|
|
7462
|
+
slides: chunk.map((target) => ({
|
|
7463
|
+
presentation: target.presentation,
|
|
7464
|
+
dpi: target.dpi
|
|
7465
|
+
})),
|
|
7466
|
+
...options.baseDir !== void 0 && { baseDir: options.baseDir }
|
|
7467
|
+
});
|
|
7468
|
+
if (!applyBatchResponse(chunk, response, map)) {
|
|
7469
|
+
throw new Error(
|
|
7470
|
+
"batch rasterizer returned a malformed result (expected index-aligned results[])"
|
|
7471
|
+
);
|
|
7472
|
+
}
|
|
7473
|
+
} catch (error) {
|
|
7474
|
+
if (serviceConfig.render || serviceConfig.serverUrl) {
|
|
7475
|
+
await rasterizeIndividually(chunk);
|
|
7476
|
+
} else {
|
|
7477
|
+
const message = toErrorMessage(error);
|
|
7478
|
+
for (const target of chunk) {
|
|
7479
|
+
map.set(target.key, { ok: false, error: message });
|
|
7480
|
+
}
|
|
7481
|
+
}
|
|
7482
|
+
}
|
|
7483
|
+
}
|
|
7484
|
+
return map;
|
|
7485
|
+
}
|
|
7486
|
+
if (serviceConfig?.render) {
|
|
7487
|
+
await rasterizeIndividually(unique);
|
|
7488
|
+
return map;
|
|
7489
|
+
}
|
|
7490
|
+
const serverUrl = resolveServiceUrl(
|
|
7491
|
+
void 0,
|
|
7492
|
+
serviceConfig?.serverUrl,
|
|
7493
|
+
DEFAULT_RASTERIZE_SERVER_URL
|
|
7494
|
+
);
|
|
7495
|
+
for (const chunk of chunksOf(unique, MAX_RASTERIZE_BATCH_SLIDES)) {
|
|
7496
|
+
let applied = false;
|
|
7497
|
+
try {
|
|
7498
|
+
const response = await postJsonToService({
|
|
7499
|
+
url: serverUrl,
|
|
7500
|
+
path: "/rasterize/batch",
|
|
7501
|
+
body: {
|
|
7502
|
+
slides: chunk.map((target) => ({
|
|
7503
|
+
presentation: target.presentation,
|
|
7504
|
+
dpi: target.dpi
|
|
7505
|
+
})),
|
|
7506
|
+
...options.baseDir !== void 0 && { baseDir: options.baseDir }
|
|
7507
|
+
},
|
|
7508
|
+
headers: serviceConfig?.headers,
|
|
7509
|
+
timeoutMs: BATCH_TIMEOUT_BASE_MS + BATCH_TIMEOUT_PER_SLIDE_MS * chunk.length,
|
|
7510
|
+
serviceLabel: "PPTX batch rasterization service",
|
|
7511
|
+
onUnreachable: (url, cause) => `PPTX rasterization service is not reachable at ${url}. Cause: ${cause}`
|
|
7512
|
+
});
|
|
7513
|
+
applied = applyBatchResponse(chunk, await response.json(), map);
|
|
7514
|
+
} catch {
|
|
7515
|
+
applied = false;
|
|
7516
|
+
}
|
|
7517
|
+
if (!applied) await rasterizeIndividually(chunk);
|
|
7518
|
+
}
|
|
7519
|
+
return map;
|
|
7520
|
+
}
|
|
7521
|
+
|
|
7522
|
+
// src/core/render.ts
|
|
7288
7523
|
function getAlignment3(alignment) {
|
|
7289
7524
|
switch (alignment) {
|
|
7290
7525
|
case "center":
|
|
@@ -7316,10 +7551,13 @@ function coreProperties(metadata) {
|
|
|
7316
7551
|
async function renderDocument(structure, layout, options) {
|
|
7317
7552
|
return runWithGenerationDate(
|
|
7318
7553
|
structure.metadata.date,
|
|
7319
|
-
() =>
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7554
|
+
() => runWithBaseDir(
|
|
7555
|
+
options?.baseDir,
|
|
7556
|
+
() => globalBookmarkRegistry.runScoped(
|
|
7557
|
+
() => globalRevisionIdRegistry.runScoped(
|
|
7558
|
+
() => globalNumberingRegistry.runScoped(
|
|
7559
|
+
() => renderDocumentScoped(structure, layout, options)
|
|
7560
|
+
)
|
|
7323
7561
|
)
|
|
7324
7562
|
)
|
|
7325
7563
|
)
|
|
@@ -7338,6 +7576,21 @@ async function renderDocumentScoped(structure, layout, options) {
|
|
|
7338
7576
|
structure.themeName
|
|
7339
7577
|
);
|
|
7340
7578
|
context.services = options?.services;
|
|
7579
|
+
try {
|
|
7580
|
+
const visualRasterResults = await prerasterizeVisuals(
|
|
7581
|
+
layout.sections,
|
|
7582
|
+
options?.services?.pptx,
|
|
7583
|
+
{ baseDir: getBaseDir() }
|
|
7584
|
+
);
|
|
7585
|
+
if (visualRasterResults.size > 0) {
|
|
7586
|
+
context.visualRasterResults = visualRasterResults;
|
|
7587
|
+
}
|
|
7588
|
+
} catch (error) {
|
|
7589
|
+
console.warn(
|
|
7590
|
+
"[core-docx] Visual pre-rasterization failed; falling back to per-visual rasterization:",
|
|
7591
|
+
error instanceof Error ? error.message : error
|
|
7592
|
+
);
|
|
7593
|
+
}
|
|
7341
7594
|
let sectionBookmarkCounter = 0;
|
|
7342
7595
|
let previousHeader = void 0;
|
|
7343
7596
|
let previousFooter = void 0;
|
|
@@ -8009,7 +8262,8 @@ function createBuilderImpl(state) {
|
|
|
8009
8262
|
fonts: state.fonts,
|
|
8010
8263
|
validation: state.validation,
|
|
8011
8264
|
deterministic: state.deterministic,
|
|
8012
|
-
generatedAt: state.generatedAt
|
|
8265
|
+
generatedAt: state.generatedAt,
|
|
8266
|
+
baseDir: state.baseDir
|
|
8013
8267
|
};
|
|
8014
8268
|
return createBuilderImpl(
|
|
8015
8269
|
newState
|
|
@@ -8108,7 +8362,8 @@ function createBuilderImpl(state) {
|
|
|
8108
8362
|
const layout = applyLayout(structure.sections, modedTheme, themeName);
|
|
8109
8363
|
const generatedDocument = await renderDocument(structure, layout, {
|
|
8110
8364
|
services: state.services,
|
|
8111
|
-
bypassCache: !state.enableCache
|
|
8365
|
+
bypassCache: !state.enableCache,
|
|
8366
|
+
baseDir: options?.baseDir ?? state.baseDir
|
|
8112
8367
|
});
|
|
8113
8368
|
const preservedDefinition = preserveSet ? {
|
|
8114
8369
|
...modedRoot,
|
|
@@ -8238,7 +8493,8 @@ function createDocumentGenerator(options) {
|
|
|
8238
8493
|
fonts: options.fonts,
|
|
8239
8494
|
validation: options.validation,
|
|
8240
8495
|
deterministic: options.deterministic ?? true,
|
|
8241
|
-
generatedAt: options.generatedAt
|
|
8496
|
+
generatedAt: options.generatedAt,
|
|
8497
|
+
baseDir: options.baseDir
|
|
8242
8498
|
};
|
|
8243
8499
|
return createBuilderImpl(initialState);
|
|
8244
8500
|
}
|
|
@@ -8292,7 +8548,7 @@ var WeatherV2PropsSchema = Type3.Object(
|
|
|
8292
8548
|
}
|
|
8293
8549
|
);
|
|
8294
8550
|
async function fetchWeather(city, units) {
|
|
8295
|
-
await new Promise((
|
|
8551
|
+
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
8296
8552
|
const mockData = {
|
|
8297
8553
|
London: {
|
|
8298
8554
|
temperature: units === "imperial" ? 59 : 15,
|
|
@@ -8325,7 +8581,7 @@ async function fetchWeather(city, units) {
|
|
|
8325
8581
|
};
|
|
8326
8582
|
}
|
|
8327
8583
|
async function fetchForecast(city, units, days) {
|
|
8328
|
-
await new Promise((
|
|
8584
|
+
await new Promise((resolve2) => setTimeout(resolve2, 50));
|
|
8329
8585
|
const dayNames = ["Mon", "Tue", "Wed", "Thu", "Fri"];
|
|
8330
8586
|
const base = units === "imperial" ? 65 : 18;
|
|
8331
8587
|
return dayNames.slice(0, days).map((day, i) => ({
|