@extend-ai/react-docx 0.7.0-alpha.2 → 0.7.0-alpha.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/docx_wasm_bg.wasm +0 -0
- package/dist/index.cjs +723 -346
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +721 -346
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2178,16 +2178,17 @@ function shouldAllowStoredPageCountReduction(options) {
|
|
|
2178
2178
|
if (targetPageCount >= estimatedPageCount) {
|
|
2179
2179
|
return true;
|
|
2180
2180
|
}
|
|
2181
|
+
const renderedBreakHintPageCount = Number.isFinite(
|
|
2182
|
+
options.renderedBreakHintPageCount
|
|
2183
|
+
) ? Math.max(1, Math.round(options.renderedBreakHintPageCount)) : void 0;
|
|
2184
|
+
const renderedBreakHintsSupportTarget = options.hasLastRenderedPageBreakHints === true && renderedBreakHintPageCount !== void 0 && targetPageCount >= renderedBreakHintPageCount;
|
|
2181
2185
|
if (options.hasMeasuredBodyFooterOverlap === true) {
|
|
2182
|
-
return
|
|
2186
|
+
return renderedBreakHintsSupportTarget;
|
|
2183
2187
|
}
|
|
2184
2188
|
if (options.hasLastRenderedPageBreakHints !== true) {
|
|
2185
2189
|
return true;
|
|
2186
2190
|
}
|
|
2187
|
-
|
|
2188
|
-
options.renderedBreakHintPageCount
|
|
2189
|
-
) ? Math.max(1, Math.round(options.renderedBreakHintPageCount)) : void 0;
|
|
2190
|
-
return renderedBreakHintPageCount !== void 0 && targetPageCount >= renderedBreakHintPageCount;
|
|
2191
|
+
return renderedBreakHintsSupportTarget;
|
|
2191
2192
|
}
|
|
2192
2193
|
function shouldLatchMeasuredBodyFooterOverlap(options) {
|
|
2193
2194
|
if (options.measuredBodyFooterOverlap !== true) {
|
|
@@ -3297,6 +3298,423 @@ function sliceLayoutToLineRange(layout, startLineIndex, endLineIndex) {
|
|
|
3297
3298
|
};
|
|
3298
3299
|
}
|
|
3299
3300
|
|
|
3301
|
+
// src/content-signature.ts
|
|
3302
|
+
var FNV_OFFSET_BASIS = 2166136261;
|
|
3303
|
+
var FNV_PRIME = 16777619;
|
|
3304
|
+
var LONG_STRING_SAMPLE_LENGTH = 64;
|
|
3305
|
+
var LONG_STRING_THRESHOLD = 256;
|
|
3306
|
+
function fnv1aAppend(hash, text) {
|
|
3307
|
+
let next = hash;
|
|
3308
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
3309
|
+
next ^= text.charCodeAt(index);
|
|
3310
|
+
next = Math.imul(next, FNV_PRIME);
|
|
3311
|
+
}
|
|
3312
|
+
return next >>> 0;
|
|
3313
|
+
}
|
|
3314
|
+
function fnv1aAppendString(hash, value) {
|
|
3315
|
+
if (value.length <= LONG_STRING_THRESHOLD) {
|
|
3316
|
+
return fnv1aAppend(fnv1aAppend(hash, `${value.length}:`), value);
|
|
3317
|
+
}
|
|
3318
|
+
const head = value.slice(0, LONG_STRING_SAMPLE_LENGTH);
|
|
3319
|
+
const middleIndex = Math.floor(value.length / 2);
|
|
3320
|
+
const middle = value.slice(
|
|
3321
|
+
middleIndex,
|
|
3322
|
+
middleIndex + LONG_STRING_SAMPLE_LENGTH
|
|
3323
|
+
);
|
|
3324
|
+
const tail = value.slice(value.length - LONG_STRING_SAMPLE_LENGTH);
|
|
3325
|
+
let next = fnv1aAppend(hash, `${value.length}:`);
|
|
3326
|
+
next = fnv1aAppend(next, head);
|
|
3327
|
+
next = fnv1aAppend(next, middle);
|
|
3328
|
+
return fnv1aAppend(next, tail);
|
|
3329
|
+
}
|
|
3330
|
+
function fnv1aAppendValue(hash, value) {
|
|
3331
|
+
if (value === null) {
|
|
3332
|
+
return fnv1aAppend(hash, "~n");
|
|
3333
|
+
}
|
|
3334
|
+
switch (typeof value) {
|
|
3335
|
+
case "undefined":
|
|
3336
|
+
return fnv1aAppend(hash, "~u");
|
|
3337
|
+
case "string":
|
|
3338
|
+
return fnv1aAppendString(fnv1aAppend(hash, "~s"), value);
|
|
3339
|
+
case "number":
|
|
3340
|
+
return fnv1aAppend(hash, `~#${value}`);
|
|
3341
|
+
case "boolean":
|
|
3342
|
+
return fnv1aAppend(hash, value ? "~t" : "~f");
|
|
3343
|
+
case "object":
|
|
3344
|
+
break;
|
|
3345
|
+
default:
|
|
3346
|
+
return fnv1aAppend(hash, "~x");
|
|
3347
|
+
}
|
|
3348
|
+
if (Array.isArray(value)) {
|
|
3349
|
+
let next2 = fnv1aAppend(hash, `~a${value.length}`);
|
|
3350
|
+
for (const entry of value) {
|
|
3351
|
+
next2 = fnv1aAppendValue(next2, entry);
|
|
3352
|
+
}
|
|
3353
|
+
return next2;
|
|
3354
|
+
}
|
|
3355
|
+
if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
|
|
3356
|
+
const byteLength = value instanceof ArrayBuffer ? value.byteLength : value.byteLength;
|
|
3357
|
+
return fnv1aAppend(hash, `~b${byteLength}`);
|
|
3358
|
+
}
|
|
3359
|
+
let next = fnv1aAppend(hash, "~o");
|
|
3360
|
+
for (const key of Object.keys(value)) {
|
|
3361
|
+
const entry = value[key];
|
|
3362
|
+
if (entry === void 0) {
|
|
3363
|
+
continue;
|
|
3364
|
+
}
|
|
3365
|
+
next = fnv1aAppend(next, key);
|
|
3366
|
+
next = fnv1aAppendValue(next, entry);
|
|
3367
|
+
}
|
|
3368
|
+
return next;
|
|
3369
|
+
}
|
|
3370
|
+
function contentHash(value) {
|
|
3371
|
+
return fnv1aAppendValue(FNV_OFFSET_BASIS, value).toString(36);
|
|
3372
|
+
}
|
|
3373
|
+
var nodeSignatureCache = /* @__PURE__ */ new WeakMap();
|
|
3374
|
+
function docNodeContentSignature(node) {
|
|
3375
|
+
if (typeof node !== "object" || node === null) {
|
|
3376
|
+
return contentHash(node);
|
|
3377
|
+
}
|
|
3378
|
+
const cached = nodeSignatureCache.get(node);
|
|
3379
|
+
if (cached !== void 0) {
|
|
3380
|
+
return cached;
|
|
3381
|
+
}
|
|
3382
|
+
const signature = contentHash(node);
|
|
3383
|
+
nodeSignatureCache.set(node, signature);
|
|
3384
|
+
return signature;
|
|
3385
|
+
}
|
|
3386
|
+
var metadataSignatureCache = /* @__PURE__ */ new WeakMap();
|
|
3387
|
+
function docModelThumbnailMetadataSignature(metadata) {
|
|
3388
|
+
const cached = metadataSignatureCache.get(metadata);
|
|
3389
|
+
if (cached !== void 0) {
|
|
3390
|
+
return cached;
|
|
3391
|
+
}
|
|
3392
|
+
const relevant = metadata;
|
|
3393
|
+
let hash = FNV_OFFSET_BASIS;
|
|
3394
|
+
hash = fnv1aAppendValue(hash, relevant.sections);
|
|
3395
|
+
hash = fnv1aAppendValue(hash, relevant.headerSections);
|
|
3396
|
+
hash = fnv1aAppendValue(hash, relevant.footerSections);
|
|
3397
|
+
hash = fnv1aAppendValue(hash, relevant.numberingDefinitions);
|
|
3398
|
+
hash = fnv1aAppendValue(hash, relevant.footnotes);
|
|
3399
|
+
hash = fnv1aAppendValue(hash, relevant.endnotes);
|
|
3400
|
+
hash = fnv1aAppendValue(hash, relevant.documentBackgroundColor);
|
|
3401
|
+
hash = fnv1aAppendValue(hash, relevant.compatibility);
|
|
3402
|
+
const signature = (hash >>> 0).toString(36);
|
|
3403
|
+
metadataSignatureCache.set(metadata, signature);
|
|
3404
|
+
return signature;
|
|
3405
|
+
}
|
|
3406
|
+
|
|
3407
|
+
// src/thumbnail-raster.ts
|
|
3408
|
+
var DOCX_THUMBNAIL_EXCLUDE_ATTRIBUTE = "data-docx-thumbnail-exclude";
|
|
3409
|
+
var THUMBNAIL_EXCLUDED_CLONE_SELECTOR = [
|
|
3410
|
+
`[${DOCX_THUMBNAIL_EXCLUDE_ATTRIBUTE}="true"]`,
|
|
3411
|
+
"textarea",
|
|
3412
|
+
'[data-image-resize-handle="true"]',
|
|
3413
|
+
'[data-docx-table-move-handle="true"]'
|
|
3414
|
+
].join(",");
|
|
3415
|
+
var THUMBNAIL_IMAGE_DOWNSCALE_MIN_DATA_URI_LENGTH = 32768;
|
|
3416
|
+
var THUMBNAIL_IMAGE_DOWNSCALE_MAX_DIMENSION_PX = 512;
|
|
3417
|
+
var THUMBNAIL_IMAGE_JPEG_QUALITY = 0.78;
|
|
3418
|
+
function thumbnailSvgDataUri(svg) {
|
|
3419
|
+
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
|
3420
|
+
}
|
|
3421
|
+
function thumbnailImageSourceQualifiesForDownscale(src) {
|
|
3422
|
+
return src.length >= THUMBNAIL_IMAGE_DOWNSCALE_MIN_DATA_URI_LENGTH && src.startsWith("data:image/") && !src.startsWith("data:image/svg");
|
|
3423
|
+
}
|
|
3424
|
+
async function loadThumbnailImage(src) {
|
|
3425
|
+
const image = new Image();
|
|
3426
|
+
image.decoding = "async";
|
|
3427
|
+
const loaded = new Promise((resolve, reject) => {
|
|
3428
|
+
image.onload = () => resolve(image);
|
|
3429
|
+
image.onerror = () => {
|
|
3430
|
+
reject(new Error("Failed to decode DOCX thumbnail image."));
|
|
3431
|
+
};
|
|
3432
|
+
});
|
|
3433
|
+
image.src = src;
|
|
3434
|
+
if (typeof image.decode === "function") {
|
|
3435
|
+
try {
|
|
3436
|
+
await image.decode();
|
|
3437
|
+
return image;
|
|
3438
|
+
} catch {
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
return loaded;
|
|
3442
|
+
}
|
|
3443
|
+
var downscaledThumbnailImageCache = /* @__PURE__ */ new Map();
|
|
3444
|
+
async function downscaleThumbnailImageDataUri(src) {
|
|
3445
|
+
if (typeof document === "undefined") {
|
|
3446
|
+
return void 0;
|
|
3447
|
+
}
|
|
3448
|
+
const image = await loadThumbnailImage(src);
|
|
3449
|
+
const naturalWidth = image.naturalWidth || image.width;
|
|
3450
|
+
const naturalHeight = image.naturalHeight || image.height;
|
|
3451
|
+
if (!naturalWidth || !naturalHeight) {
|
|
3452
|
+
return void 0;
|
|
3453
|
+
}
|
|
3454
|
+
const scale = THUMBNAIL_IMAGE_DOWNSCALE_MAX_DIMENSION_PX / Math.max(naturalWidth, naturalHeight);
|
|
3455
|
+
if (scale >= 1) {
|
|
3456
|
+
return void 0;
|
|
3457
|
+
}
|
|
3458
|
+
const canvas = document.createElement("canvas");
|
|
3459
|
+
canvas.width = Math.max(1, Math.round(naturalWidth * scale));
|
|
3460
|
+
canvas.height = Math.max(1, Math.round(naturalHeight * scale));
|
|
3461
|
+
const context = canvas.getContext("2d");
|
|
3462
|
+
if (!context) {
|
|
3463
|
+
return void 0;
|
|
3464
|
+
}
|
|
3465
|
+
context.imageSmoothingEnabled = true;
|
|
3466
|
+
context.imageSmoothingQuality = "high";
|
|
3467
|
+
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
3468
|
+
const sourceIsJpeg = src.startsWith("data:image/jpeg") || src.startsWith("data:image/jpg");
|
|
3469
|
+
const downscaled = sourceIsJpeg ? canvas.toDataURL("image/jpeg", THUMBNAIL_IMAGE_JPEG_QUALITY) : canvas.toDataURL("image/png");
|
|
3470
|
+
return downscaled.length < src.length ? downscaled : void 0;
|
|
3471
|
+
}
|
|
3472
|
+
function getDownscaledThumbnailImageDataUri(src) {
|
|
3473
|
+
const cached = downscaledThumbnailImageCache.get(src);
|
|
3474
|
+
if (cached) {
|
|
3475
|
+
return cached;
|
|
3476
|
+
}
|
|
3477
|
+
const pending = downscaleThumbnailImageDataUri(src).catch(() => void 0);
|
|
3478
|
+
downscaledThumbnailImageCache.set(src, pending);
|
|
3479
|
+
return pending;
|
|
3480
|
+
}
|
|
3481
|
+
async function buildDocxThumbnailSvgMarkup(params) {
|
|
3482
|
+
const { pageElement, sourceWidthPx, sourceHeightPx, widthPx, heightPx } = params;
|
|
3483
|
+
const clone = pageElement.cloneNode(true);
|
|
3484
|
+
clone.querySelectorAll(THUMBNAIL_EXCLUDED_CLONE_SELECTOR).forEach((excluded) => {
|
|
3485
|
+
excluded.remove();
|
|
3486
|
+
});
|
|
3487
|
+
const cloneImages = Array.from(clone.querySelectorAll("img"));
|
|
3488
|
+
await Promise.all(
|
|
3489
|
+
cloneImages.map(async (cloneImage) => {
|
|
3490
|
+
const src = cloneImage.getAttribute("src");
|
|
3491
|
+
if (!src || !thumbnailImageSourceQualifiesForDownscale(src)) {
|
|
3492
|
+
return;
|
|
3493
|
+
}
|
|
3494
|
+
const downscaled = await getDownscaledThumbnailImageDataUri(src);
|
|
3495
|
+
if (downscaled) {
|
|
3496
|
+
cloneImage.setAttribute("src", downscaled);
|
|
3497
|
+
}
|
|
3498
|
+
})
|
|
3499
|
+
);
|
|
3500
|
+
const scaleX = widthPx / sourceWidthPx;
|
|
3501
|
+
const scaleY = heightPx / sourceHeightPx;
|
|
3502
|
+
const serializedPage = new XMLSerializer().serializeToString(clone);
|
|
3503
|
+
return `
|
|
3504
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="${widthPx}" height="${heightPx}" viewBox="0 0 ${widthPx} ${heightPx}">
|
|
3505
|
+
<foreignObject x="0" y="0" width="100%" height="100%">
|
|
3506
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style="width:${widthPx}px;height:${heightPx}px;overflow:hidden;">
|
|
3507
|
+
<div style="width:${sourceWidthPx}px;height:${sourceHeightPx}px;transform-origin:top left;transform:scale(${scaleX}, ${scaleY});">
|
|
3508
|
+
${serializedPage}
|
|
3509
|
+
</div>
|
|
3510
|
+
</div>
|
|
3511
|
+
</foreignObject>
|
|
3512
|
+
</svg>
|
|
3513
|
+
`;
|
|
3514
|
+
}
|
|
3515
|
+
async function rasterizeDocxThumbnailSurface(params) {
|
|
3516
|
+
if (typeof window === "undefined" || typeof XMLSerializer === "undefined") {
|
|
3517
|
+
throw new Error("DOCX thumbnails require a browser environment.");
|
|
3518
|
+
}
|
|
3519
|
+
const safeSourceWidthPx = Math.max(1, Math.round(params.sourceWidthPx));
|
|
3520
|
+
const safeSourceHeightPx = Math.max(1, Math.round(params.sourceHeightPx));
|
|
3521
|
+
const svgMarkup = await buildDocxThumbnailSvgMarkup({
|
|
3522
|
+
pageElement: params.pageElement,
|
|
3523
|
+
sourceWidthPx: safeSourceWidthPx,
|
|
3524
|
+
sourceHeightPx: safeSourceHeightPx,
|
|
3525
|
+
widthPx: params.widthPx,
|
|
3526
|
+
heightPx: params.heightPx
|
|
3527
|
+
});
|
|
3528
|
+
const image = await loadThumbnailImage(thumbnailSvgDataUri(svgMarkup));
|
|
3529
|
+
const surface = document.createElement("canvas");
|
|
3530
|
+
surface.width = Math.max(1, Math.round(params.pixelWidthPx));
|
|
3531
|
+
surface.height = Math.max(1, Math.round(params.pixelHeightPx));
|
|
3532
|
+
const context = surface.getContext("2d");
|
|
3533
|
+
if (!context) {
|
|
3534
|
+
throw new Error("2D canvas context is unavailable for DOCX thumbnails.");
|
|
3535
|
+
}
|
|
3536
|
+
context.imageSmoothingEnabled = true;
|
|
3537
|
+
context.imageSmoothingQuality = "high";
|
|
3538
|
+
context.drawImage(image, 0, 0, surface.width, surface.height);
|
|
3539
|
+
return surface;
|
|
3540
|
+
}
|
|
3541
|
+
function blitDocxThumbnailSurface(surface, canvas, resolution) {
|
|
3542
|
+
canvas.width = Math.max(1, Math.round(resolution.pixelWidthPx));
|
|
3543
|
+
canvas.height = Math.max(1, Math.round(resolution.pixelHeightPx));
|
|
3544
|
+
canvas.style.width = `${Math.max(1, Math.round(resolution.widthPx))}px`;
|
|
3545
|
+
canvas.style.height = `${Math.max(1, Math.round(resolution.heightPx))}px`;
|
|
3546
|
+
const context = canvas.getContext("2d");
|
|
3547
|
+
if (!context) {
|
|
3548
|
+
throw new Error("2D canvas context is unavailable for DOCX thumbnails.");
|
|
3549
|
+
}
|
|
3550
|
+
context.setTransform(1, 0, 0, 1, 0, 0);
|
|
3551
|
+
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
3552
|
+
context.drawImage(surface, 0, 0, canvas.width, canvas.height);
|
|
3553
|
+
}
|
|
3554
|
+
var DocxThumbnailSurfaceCache = class {
|
|
3555
|
+
constructor(maxEntries) {
|
|
3556
|
+
this.maxEntries = maxEntries;
|
|
3557
|
+
}
|
|
3558
|
+
entries = /* @__PURE__ */ new Map();
|
|
3559
|
+
get size() {
|
|
3560
|
+
return this.entries.size;
|
|
3561
|
+
}
|
|
3562
|
+
get(key) {
|
|
3563
|
+
const value = this.entries.get(key);
|
|
3564
|
+
if (value === void 0) {
|
|
3565
|
+
return void 0;
|
|
3566
|
+
}
|
|
3567
|
+
this.entries.delete(key);
|
|
3568
|
+
this.entries.set(key, value);
|
|
3569
|
+
return value;
|
|
3570
|
+
}
|
|
3571
|
+
set(key, value) {
|
|
3572
|
+
this.entries.delete(key);
|
|
3573
|
+
this.entries.set(key, value);
|
|
3574
|
+
while (this.entries.size > this.maxEntries) {
|
|
3575
|
+
const oldestKey = this.entries.keys().next().value;
|
|
3576
|
+
if (oldestKey === void 0) {
|
|
3577
|
+
break;
|
|
3578
|
+
}
|
|
3579
|
+
this.entries.delete(oldestKey);
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
clear() {
|
|
3583
|
+
this.entries.clear();
|
|
3584
|
+
}
|
|
3585
|
+
};
|
|
3586
|
+
var IDLE_TASK_TIMEOUT_MS = 300;
|
|
3587
|
+
function defaultScheduleTask(callback) {
|
|
3588
|
+
const idleWindow = typeof window === "undefined" ? void 0 : window;
|
|
3589
|
+
if (!idleWindow || typeof idleWindow.requestIdleCallback !== "function") {
|
|
3590
|
+
setTimeout(callback, 16);
|
|
3591
|
+
return;
|
|
3592
|
+
}
|
|
3593
|
+
let invoked = false;
|
|
3594
|
+
const runOnce = () => {
|
|
3595
|
+
if (invoked) {
|
|
3596
|
+
return;
|
|
3597
|
+
}
|
|
3598
|
+
invoked = true;
|
|
3599
|
+
callback();
|
|
3600
|
+
};
|
|
3601
|
+
const idleHandle = idleWindow.requestIdleCallback(runOnce, {
|
|
3602
|
+
timeout: IDLE_TASK_TIMEOUT_MS
|
|
3603
|
+
});
|
|
3604
|
+
setTimeout(() => {
|
|
3605
|
+
if (invoked) {
|
|
3606
|
+
return;
|
|
3607
|
+
}
|
|
3608
|
+
if (typeof idleWindow.cancelIdleCallback === "function") {
|
|
3609
|
+
idleWindow.cancelIdleCallback(idleHandle);
|
|
3610
|
+
}
|
|
3611
|
+
runOnce();
|
|
3612
|
+
}, IDLE_TASK_TIMEOUT_MS + 50);
|
|
3613
|
+
}
|
|
3614
|
+
function defaultScheduleDelayed(callback, delayMs) {
|
|
3615
|
+
setTimeout(callback, delayMs);
|
|
3616
|
+
}
|
|
3617
|
+
var SerialIdleTaskQueue = class {
|
|
3618
|
+
pending = [];
|
|
3619
|
+
lastRunAtByKey = /* @__PURE__ */ new Map();
|
|
3620
|
+
scheduleTask;
|
|
3621
|
+
scheduleDelayed;
|
|
3622
|
+
minTaskIntervalMs;
|
|
3623
|
+
now;
|
|
3624
|
+
pumpScheduled = false;
|
|
3625
|
+
running = false;
|
|
3626
|
+
constructor(options) {
|
|
3627
|
+
this.scheduleTask = options?.scheduleTask ?? defaultScheduleTask;
|
|
3628
|
+
this.scheduleDelayed = options?.scheduleDelayed ?? defaultScheduleDelayed;
|
|
3629
|
+
this.minTaskIntervalMs = Math.max(0, options?.minTaskIntervalMs ?? 0);
|
|
3630
|
+
this.now = options?.now ?? (() => Date.now());
|
|
3631
|
+
}
|
|
3632
|
+
get pendingCount() {
|
|
3633
|
+
return this.pending.length;
|
|
3634
|
+
}
|
|
3635
|
+
enqueue(key, run) {
|
|
3636
|
+
return new Promise((resolve) => {
|
|
3637
|
+
const existing = this.pending.find((entry) => entry.key === key);
|
|
3638
|
+
if (existing) {
|
|
3639
|
+
existing.run = run;
|
|
3640
|
+
existing.resolvers.push(resolve);
|
|
3641
|
+
} else {
|
|
3642
|
+
this.pending.push({ key, run, resolvers: [resolve] });
|
|
3643
|
+
}
|
|
3644
|
+
this.schedulePump();
|
|
3645
|
+
});
|
|
3646
|
+
}
|
|
3647
|
+
/** Drops all queued tasks, resolving their waiters without running them. */
|
|
3648
|
+
clear() {
|
|
3649
|
+
const dropped = this.pending.splice(0, this.pending.length);
|
|
3650
|
+
this.lastRunAtByKey.clear();
|
|
3651
|
+
dropped.forEach((entry) => {
|
|
3652
|
+
entry.resolvers.forEach((resolveEntry) => {
|
|
3653
|
+
resolveEntry();
|
|
3654
|
+
});
|
|
3655
|
+
});
|
|
3656
|
+
}
|
|
3657
|
+
schedulePump() {
|
|
3658
|
+
if (this.pumpScheduled || this.running || this.pending.length === 0) {
|
|
3659
|
+
return;
|
|
3660
|
+
}
|
|
3661
|
+
this.pumpScheduled = true;
|
|
3662
|
+
this.scheduleTask(() => {
|
|
3663
|
+
this.pumpScheduled = false;
|
|
3664
|
+
void this.runNext();
|
|
3665
|
+
});
|
|
3666
|
+
}
|
|
3667
|
+
takeNextEligibleEntry() {
|
|
3668
|
+
if (this.pending.length === 0) {
|
|
3669
|
+
return void 0;
|
|
3670
|
+
}
|
|
3671
|
+
const now = this.now();
|
|
3672
|
+
let earliestWaitMs;
|
|
3673
|
+
for (let index = 0; index < this.pending.length; index += 1) {
|
|
3674
|
+
const candidate = this.pending[index];
|
|
3675
|
+
if (!candidate) {
|
|
3676
|
+
continue;
|
|
3677
|
+
}
|
|
3678
|
+
const lastRunAt = this.lastRunAtByKey.get(candidate.key);
|
|
3679
|
+
const waitMs = lastRunAt === void 0 ? 0 : lastRunAt + this.minTaskIntervalMs - now;
|
|
3680
|
+
if (waitMs <= 0) {
|
|
3681
|
+
this.pending.splice(index, 1);
|
|
3682
|
+
return { entry: candidate };
|
|
3683
|
+
}
|
|
3684
|
+
earliestWaitMs = earliestWaitMs === void 0 ? waitMs : Math.min(earliestWaitMs, waitMs);
|
|
3685
|
+
}
|
|
3686
|
+
return earliestWaitMs === void 0 ? void 0 : { retryDelayMs: earliestWaitMs };
|
|
3687
|
+
}
|
|
3688
|
+
async runNext() {
|
|
3689
|
+
if (this.running) {
|
|
3690
|
+
return;
|
|
3691
|
+
}
|
|
3692
|
+
const next = this.takeNextEligibleEntry();
|
|
3693
|
+
if (!next) {
|
|
3694
|
+
return;
|
|
3695
|
+
}
|
|
3696
|
+
if (!("entry" in next)) {
|
|
3697
|
+
this.scheduleDelayed(() => {
|
|
3698
|
+
this.schedulePump();
|
|
3699
|
+
}, next.retryDelayMs);
|
|
3700
|
+
return;
|
|
3701
|
+
}
|
|
3702
|
+
this.running = true;
|
|
3703
|
+
const { entry } = next;
|
|
3704
|
+
try {
|
|
3705
|
+
await entry.run();
|
|
3706
|
+
} catch {
|
|
3707
|
+
} finally {
|
|
3708
|
+
this.lastRunAtByKey.set(entry.key, this.now());
|
|
3709
|
+
this.running = false;
|
|
3710
|
+
entry.resolvers.forEach((resolveEntry) => {
|
|
3711
|
+
resolveEntry();
|
|
3712
|
+
});
|
|
3713
|
+
this.schedulePump();
|
|
3714
|
+
}
|
|
3715
|
+
}
|
|
3716
|
+
};
|
|
3717
|
+
|
|
3300
3718
|
// src/editor.tsx
|
|
3301
3719
|
import { Fragment as Fragment2, jsx, jsxs } from "react/jsx-runtime";
|
|
3302
3720
|
var HIGHLIGHT_TO_CSS = {
|
|
@@ -3393,6 +3811,9 @@ var DEFAULT_PARAGRAPH_LINE_MULTIPLE = 1;
|
|
|
3393
3811
|
var WORD_SINGLE_LINE_AUTO_SCALE = 0.88;
|
|
3394
3812
|
var WORD_SINGLE_LINE_AUTO_SCALE_SANS = 0.9;
|
|
3395
3813
|
var WORD_SINGLE_LINE_AUTO_SCALE_SERIF = 1.08;
|
|
3814
|
+
var WORD_EMPTY_PARAGRAPH_LINE_SCALE = 1.21;
|
|
3815
|
+
var WORD_EMPTY_PARAGRAPH_LINE_SCALE_SERIF = 1.15;
|
|
3816
|
+
var WORD_EMPTY_PARAGRAPH_LINE_SCALE_SANS = 1.15;
|
|
3396
3817
|
var WORD_AUTO_LINE_SCALE_BLEND_END_MULTIPLE = 1.08;
|
|
3397
3818
|
var MIN_AUTO_LINE_MULTIPLE = 0.1;
|
|
3398
3819
|
var MIN_PARAGRAPH_LINE_HEIGHT_PX = 14;
|
|
@@ -3437,7 +3858,6 @@ var TEXT_MEASURE_CACHE_MAX_ENTRIES = 12e3;
|
|
|
3437
3858
|
var DEFAULT_TAB_STOP_PX = 48;
|
|
3438
3859
|
var TAB_LEADER_ZONE_GAP_PX = 20;
|
|
3439
3860
|
var EMPTY_PARAGRAPH_EXTRA_HEIGHT_PX = 0;
|
|
3440
|
-
var LEADING_COVER_SPACER_EXTRA_HEIGHT_PX = 2;
|
|
3441
3861
|
var PARAGRAPH_SEGMENT_TOP_BLEED_PX = 22;
|
|
3442
3862
|
var PARAGRAPH_SEGMENT_DESCENDER_BLEED_PX = 6;
|
|
3443
3863
|
var PARAGRAPH_SEGMENT_VISUAL_SAFETY_PX = 24;
|
|
@@ -5957,19 +6377,6 @@ function floatingTextBoxVisibleTextFromImage(image) {
|
|
|
5957
6377
|
const normalized = normalizeFloatingTextBoxComparisonText(text);
|
|
5958
6378
|
return normalized.length > 0 ? normalized : void 0;
|
|
5959
6379
|
}
|
|
5960
|
-
function absoluteFloatingTextBearingTextBoxFootprintPx(image) {
|
|
5961
|
-
const floating = image.floating;
|
|
5962
|
-
if (!shouldRenderAbsoluteFloatingImage(image) || !floating || image.syntheticTextBox !== true || syntheticTextBoxContainsPictureLayer(image) || !floatingTextBoxVisibleTextFromImage(image)) {
|
|
5963
|
-
return 0;
|
|
5964
|
-
}
|
|
5965
|
-
const imageHeightPx = Number.isFinite(image.heightPx) && image.heightPx > 0 ? Math.round(image.heightPx) : Number.isFinite(image.widthPx) && image.widthPx > 0 ? Math.round(image.widthPx) : MIN_PARAGRAPH_LINE_HEIGHT_PX;
|
|
5966
|
-
const distTPx = Math.max(0, Math.round(floating.distTPx ?? 0));
|
|
5967
|
-
const distBPx = Math.max(0, Math.round(floating.distBPx ?? 0));
|
|
5968
|
-
return Math.max(
|
|
5969
|
-
MIN_PARAGRAPH_LINE_HEIGHT_PX,
|
|
5970
|
-
imageHeightPx + distTPx + distBPx
|
|
5971
|
-
);
|
|
5972
|
-
}
|
|
5973
6380
|
function paragraphVisibleTextIsOnlyAbsoluteFloatingTextBoxContent(paragraph) {
|
|
5974
6381
|
if (!paragraphHasVisibleText2(paragraph) || paragraphHasFormField2(paragraph)) {
|
|
5975
6382
|
return false;
|
|
@@ -6002,29 +6409,9 @@ function paragraphHasOnlyWhitespaceText(paragraph) {
|
|
|
6002
6409
|
return child.text.replace(/[\s\u00a0]+/g, "").length === 0;
|
|
6003
6410
|
});
|
|
6004
6411
|
}
|
|
6005
|
-
function paragraphHasActiveNumbering(paragraph) {
|
|
6006
|
-
const numbering = paragraph.style?.numbering;
|
|
6007
|
-
return Boolean(
|
|
6008
|
-
numbering && Number.isFinite(numbering.numId) && Math.round(numbering.numId) > 0
|
|
6009
|
-
);
|
|
6010
|
-
}
|
|
6011
6412
|
function paragraphContainsSectionBreakProperties(paragraph) {
|
|
6012
6413
|
return /<w:sectPr\b/i.test(paragraph.sourceXml ?? "");
|
|
6013
6414
|
}
|
|
6014
|
-
function paragraphTextBearingAbsoluteFloatingTextBoxFootprintPx(paragraph) {
|
|
6015
|
-
if (paragraphHasVisibleText2(paragraph) || paragraphHasFormField2(paragraph) || paragraphContainsSectionBreakProperties(paragraph)) {
|
|
6016
|
-
return 0;
|
|
6017
|
-
}
|
|
6018
|
-
return paragraph.children.reduce((largest, child) => {
|
|
6019
|
-
if (child.type !== "image") {
|
|
6020
|
-
return largest;
|
|
6021
|
-
}
|
|
6022
|
-
return Math.max(
|
|
6023
|
-
largest,
|
|
6024
|
-
absoluteFloatingTextBearingTextBoxFootprintPx(child)
|
|
6025
|
-
);
|
|
6026
|
-
}, 0);
|
|
6027
|
-
}
|
|
6028
6415
|
function paragraphAbsoluteFloatingAnchorsDependOnParagraphFlow(paragraph) {
|
|
6029
6416
|
return paragraph.children.some((child) => {
|
|
6030
6417
|
if (child.type !== "image" || !shouldRenderAbsoluteFloatingImage(child) || child.syntheticTextBox !== true || !floatingTextBoxVisibleTextFromImage(child) || child.floating?.behindDocument !== true) {
|
|
@@ -6116,21 +6503,6 @@ function paragraphParticipatesInLeadingCoverLayout(model, nodeIndex, pageContent
|
|
|
6116
6503
|
}
|
|
6117
6504
|
return sawLikelyCoverArtAnchor;
|
|
6118
6505
|
}
|
|
6119
|
-
function paragraphLikelyFullPageCoverFootprintPx(model, nodeIndex, paragraph, pageContentWidthPx, pageContentHeightPx) {
|
|
6120
|
-
if (!paragraphParticipatesInLeadingCoverLayout(
|
|
6121
|
-
model,
|
|
6122
|
-
nodeIndex,
|
|
6123
|
-
pageContentWidthPx,
|
|
6124
|
-
pageContentHeightPx
|
|
6125
|
-
) || !paragraphIsLikelyFullPageCoverArtAnchor(
|
|
6126
|
-
paragraph,
|
|
6127
|
-
pageContentWidthPx,
|
|
6128
|
-
pageContentHeightPx
|
|
6129
|
-
)) {
|
|
6130
|
-
return 0;
|
|
6131
|
-
}
|
|
6132
|
-
return Math.max(1, Math.round(pageContentHeightPx));
|
|
6133
|
-
}
|
|
6134
6506
|
function fullPageCoverImageRenderKey(nodeIndex, childIndex) {
|
|
6135
6507
|
return `${nodeIndex}:${childIndex}`;
|
|
6136
6508
|
}
|
|
@@ -6169,71 +6541,6 @@ function fullPageCoverAbsoluteFloatingImageStyle(image, layout, options) {
|
|
|
6169
6541
|
zIndex: floating?.behindDocument === true ? 0 : normalizedZIndex
|
|
6170
6542
|
};
|
|
6171
6543
|
}
|
|
6172
|
-
function paragraphActsAsLeadingCoverLayoutSpacer(model, nodeIndex, paragraph, pageContentWidthPx, pageContentHeightPx) {
|
|
6173
|
-
if (nodeIndex <= 0 || !paragraphHasOnlyWhitespaceText(paragraph) || paragraphHasExplicitPageBreak2(paragraph)) {
|
|
6174
|
-
return false;
|
|
6175
|
-
}
|
|
6176
|
-
if (paragraphHasActiveNumbering(paragraph)) {
|
|
6177
|
-
return false;
|
|
6178
|
-
}
|
|
6179
|
-
return paragraphParticipatesInLeadingCoverLayout(
|
|
6180
|
-
model,
|
|
6181
|
-
nodeIndex,
|
|
6182
|
-
pageContentWidthPx,
|
|
6183
|
-
pageContentHeightPx
|
|
6184
|
-
);
|
|
6185
|
-
}
|
|
6186
|
-
function paragraphActsAsLeadingCoverLayoutPreambleSpacer(model, nodeIndex, paragraph, pageContentWidthPx, pageContentHeightPx) {
|
|
6187
|
-
if (!paragraphHasOnlyWhitespaceText(paragraph) || paragraphHasExplicitPageBreak2(paragraph) || paragraphHasActiveNumbering(paragraph)) {
|
|
6188
|
-
return false;
|
|
6189
|
-
}
|
|
6190
|
-
const nextNode = model.nodes[nodeIndex + 1];
|
|
6191
|
-
if (!nextNode || nextNode.type !== "paragraph") {
|
|
6192
|
-
return false;
|
|
6193
|
-
}
|
|
6194
|
-
if (!paragraphParticipatesInLeadingCoverLayout(
|
|
6195
|
-
model,
|
|
6196
|
-
nodeIndex + 1,
|
|
6197
|
-
pageContentWidthPx,
|
|
6198
|
-
pageContentHeightPx
|
|
6199
|
-
)) {
|
|
6200
|
-
return false;
|
|
6201
|
-
}
|
|
6202
|
-
for (let probeIndex = nodeIndex - 1; probeIndex >= 0; probeIndex -= 1) {
|
|
6203
|
-
const previousNode = model.nodes[probeIndex];
|
|
6204
|
-
if (!previousNode || previousNode.type !== "paragraph") {
|
|
6205
|
-
return false;
|
|
6206
|
-
}
|
|
6207
|
-
if (paragraphHasOnlyWhitespaceText(previousNode)) {
|
|
6208
|
-
continue;
|
|
6209
|
-
}
|
|
6210
|
-
if (paragraphHasAbsoluteFloatingImage(previousNode)) {
|
|
6211
|
-
return false;
|
|
6212
|
-
}
|
|
6213
|
-
return !paragraphIsLikelyFullPageCoverArtAnchor(
|
|
6214
|
-
previousNode,
|
|
6215
|
-
pageContentWidthPx,
|
|
6216
|
-
pageContentHeightPx
|
|
6217
|
-
);
|
|
6218
|
-
}
|
|
6219
|
-
return true;
|
|
6220
|
-
}
|
|
6221
|
-
function paragraphStartsNewPageAfterLeadingCoverLayout(model, nodeIndex, paragraph, pageContentWidthPx, pageContentHeightPx) {
|
|
6222
|
-
if (nodeIndex <= 0 || !paragraphStartsNormalFlowContent(paragraph) || paragraphHasExplicitPageBreak2(paragraph) || paragraphHasPageBreakBefore2(paragraph)) {
|
|
6223
|
-
return false;
|
|
6224
|
-
}
|
|
6225
|
-
const previousNode = model.nodes[nodeIndex - 1];
|
|
6226
|
-
if (!previousNode || previousNode.type !== "paragraph") {
|
|
6227
|
-
return false;
|
|
6228
|
-
}
|
|
6229
|
-
return paragraphActsAsLeadingCoverLayoutSpacer(
|
|
6230
|
-
model,
|
|
6231
|
-
nodeIndex - 1,
|
|
6232
|
-
previousNode,
|
|
6233
|
-
pageContentWidthPx,
|
|
6234
|
-
pageContentHeightPx
|
|
6235
|
-
);
|
|
6236
|
-
}
|
|
6237
6544
|
function paragraphLooksLikeCheckboxChoiceRow(paragraph) {
|
|
6238
6545
|
if (paragraph.children.some((child) => child.type === "image")) {
|
|
6239
6546
|
return false;
|
|
@@ -6751,7 +7058,8 @@ function buildParagraphPretextLayoutSource(paragraph, options) {
|
|
|
6751
7058
|
let combinedText = "";
|
|
6752
7059
|
const paragraphBaseFontPx = paragraphBaseFontSizePx(paragraph);
|
|
6753
7060
|
const tabStopPositionsPx = options?.expandTabsForLayout ? resolveParagraphTabStopsPx(paragraph) : [];
|
|
6754
|
-
const
|
|
7061
|
+
const usesCheckboxRowTabFallback = paragraphLooksLikeCheckboxChoiceRow(paragraph);
|
|
7062
|
+
const fallbackTabWidthPx = usesCheckboxRowTabFallback ? checkboxChoiceRowTabWidthPx(paragraph) : DEFAULT_TAB_STOP_PX;
|
|
6755
7063
|
let approximateLineWidthPx = 0;
|
|
6756
7064
|
let lastTextStyle = firstRunStyle(paragraph);
|
|
6757
7065
|
for (let childIndex = 0; childIndex < paragraph.children.length; childIndex += 1) {
|
|
@@ -6817,7 +7125,8 @@ function buildParagraphPretextLayoutSource(paragraph, options) {
|
|
|
6817
7125
|
const tabWidthPx = resolveTabSpacerWidthPx(
|
|
6818
7126
|
tabStopPositionsPx,
|
|
6819
7127
|
approximateLineWidthPx,
|
|
6820
|
-
fallbackTabWidthPx
|
|
7128
|
+
fallbackTabWidthPx,
|
|
7129
|
+
usesCheckboxRowTabFallback
|
|
6821
7130
|
);
|
|
6822
7131
|
const spacerText = buildParagraphPretextTabSpacerText(
|
|
6823
7132
|
tabWidthPx,
|
|
@@ -7566,10 +7875,14 @@ function updateEstimatedLineWidthPxForText(currentLineWidthPx, text, style) {
|
|
|
7566
7875
|
const trailingSegment = segments[segments.length - 1] ?? "";
|
|
7567
7876
|
return estimateTextAdvanceWidthPx(trailingSegment, style);
|
|
7568
7877
|
}
|
|
7569
|
-
function resolveTabSpacerWidthPx(tabStopPositionsPx, currentLineWidthPx, fallbackWidthPx) {
|
|
7878
|
+
function resolveTabSpacerWidthPx(tabStopPositionsPx, currentLineWidthPx, fallbackWidthPx, fixedFallback = false) {
|
|
7570
7879
|
const safeFallback = Math.max(12, Math.round(fallbackWidthPx));
|
|
7571
7880
|
if (tabStopPositionsPx.length === 0) {
|
|
7572
|
-
|
|
7881
|
+
if (fixedFallback) {
|
|
7882
|
+
return safeFallback;
|
|
7883
|
+
}
|
|
7884
|
+
const nextStop2 = (Math.floor((currentLineWidthPx + 0.5) / safeFallback) + 1) * safeFallback;
|
|
7885
|
+
return Math.max(2, Math.round(nextStop2 - currentLineWidthPx));
|
|
7573
7886
|
}
|
|
7574
7887
|
const nextStop = tabStopPositionsPx.find(
|
|
7575
7888
|
(stop) => stop > currentLineWidthPx + 0.5
|
|
@@ -8322,7 +8635,23 @@ function singleLineAutoScaleForFontFamily(fontFamily) {
|
|
|
8322
8635
|
}
|
|
8323
8636
|
return WORD_SINGLE_LINE_AUTO_SCALE;
|
|
8324
8637
|
}
|
|
8638
|
+
function emptyParagraphLineScaleForFontFamily(fontFamily) {
|
|
8639
|
+
const normalized = normalizeFontFamilyToken(fontFamily) ?? fontFamily?.toLowerCase();
|
|
8640
|
+
if (!normalized) {
|
|
8641
|
+
return WORD_EMPTY_PARAGRAPH_LINE_SCALE;
|
|
8642
|
+
}
|
|
8643
|
+
if (normalized === "times roman" || normalized === "times new roman" || normalized === "cambria" || normalized === "garamond" || normalized === "georgia" || normalized === "book antiqua" || normalized === "palatino linotype") {
|
|
8644
|
+
return WORD_EMPTY_PARAGRAPH_LINE_SCALE_SERIF;
|
|
8645
|
+
}
|
|
8646
|
+
if (normalized === "arial") {
|
|
8647
|
+
return WORD_EMPTY_PARAGRAPH_LINE_SCALE_SANS;
|
|
8648
|
+
}
|
|
8649
|
+
return WORD_EMPTY_PARAGRAPH_LINE_SCALE;
|
|
8650
|
+
}
|
|
8325
8651
|
function resolveParagraphSingleLineAutoScale(paragraph, fontFamily) {
|
|
8652
|
+
if (paragraphHasOnlyWhitespaceText(paragraph)) {
|
|
8653
|
+
return emptyParagraphLineScaleForFontFamily(fontFamily);
|
|
8654
|
+
}
|
|
8326
8655
|
const baseScale = singleLineAutoScaleForFontFamily(fontFamily);
|
|
8327
8656
|
return paragraphHasCheckboxFormField(paragraph) ? Math.max(1.08, baseScale) : baseScale;
|
|
8328
8657
|
}
|
|
@@ -9037,36 +9366,6 @@ function resolveMaxPretextLineRangeEndIndexThatFits(layout, startLineIndex, maxE
|
|
|
9037
9366
|
}
|
|
9038
9367
|
return bestEnd;
|
|
9039
9368
|
}
|
|
9040
|
-
function estimateAbsoluteFloatingImageFootprintPx(paragraph, image) {
|
|
9041
|
-
if (!shouldRenderAbsoluteFloatingImage(image)) {
|
|
9042
|
-
return 0;
|
|
9043
|
-
}
|
|
9044
|
-
const floating = image.floating;
|
|
9045
|
-
if (!floating) {
|
|
9046
|
-
return 0;
|
|
9047
|
-
}
|
|
9048
|
-
const wrapType = (floating.wrapType ?? "none").trim().toLowerCase();
|
|
9049
|
-
if (wrapType !== "none") {
|
|
9050
|
-
return 0;
|
|
9051
|
-
}
|
|
9052
|
-
const behavesAsTextBearingFloatingTextBox = image.syntheticTextBox && !syntheticTextBoxContainsPictureLayer(image) && Boolean(floatingTextBoxVisibleTextFromImage(image));
|
|
9053
|
-
if (behavesAsTextBearingFloatingTextBox) {
|
|
9054
|
-
if (paragraphHasVisibleText2(paragraph) || paragraphHasFormField2(paragraph) || paragraphContainsSectionBreakProperties(paragraph)) {
|
|
9055
|
-
return 0;
|
|
9056
|
-
}
|
|
9057
|
-
const imageHeightPx = Number.isFinite(image.heightPx) && image.heightPx > 0 ? Math.round(image.heightPx) : Number.isFinite(image.widthPx) && image.widthPx > 0 ? Math.round(image.widthPx) : MIN_PARAGRAPH_LINE_HEIGHT_PX;
|
|
9058
|
-
const distTPx = Math.max(0, Math.round(floating.distTPx ?? 0));
|
|
9059
|
-
const distBPx = Math.max(0, Math.round(floating.distBPx ?? 0));
|
|
9060
|
-
return Math.max(
|
|
9061
|
-
MIN_PARAGRAPH_LINE_HEIGHT_PX,
|
|
9062
|
-
imageHeightPx + distTPx + distBPx
|
|
9063
|
-
);
|
|
9064
|
-
}
|
|
9065
|
-
if (floating.behindDocument) {
|
|
9066
|
-
return 0;
|
|
9067
|
-
}
|
|
9068
|
-
return 0;
|
|
9069
|
-
}
|
|
9070
9369
|
function resolveAutoLineSpacingMultiple(lineTwips, fallbackMultiple) {
|
|
9071
9370
|
if (!Number.isFinite(lineTwips)) {
|
|
9072
9371
|
return Math.max(MIN_AUTO_LINE_MULTIPLE, fallbackMultiple);
|
|
@@ -9164,8 +9463,15 @@ function estimateParagraphLineHeightPx(paragraph, docGridLinePitchPx, disableDoc
|
|
|
9164
9463
|
docGridMinimumLineHeightPx ?? 0
|
|
9165
9464
|
);
|
|
9166
9465
|
}
|
|
9167
|
-
const
|
|
9168
|
-
|
|
9466
|
+
const resolvedAutoMultiple = resolveAutoLineSpacingMultiple(
|
|
9467
|
+
lineTwips,
|
|
9468
|
+
defaultLineMultiple
|
|
9469
|
+
);
|
|
9470
|
+
const multiple = paragraphHasOnlyWhitespaceText(paragraph) ? Math.max(
|
|
9471
|
+
MIN_AUTO_LINE_MULTIPLE,
|
|
9472
|
+
Number((resolvedAutoMultiple * singleLineScale).toFixed(3))
|
|
9473
|
+
) : calibrateAutoLineSpacingMultiple(
|
|
9474
|
+
resolvedAutoMultiple,
|
|
9169
9475
|
baseFontFamily,
|
|
9170
9476
|
singleLineScale
|
|
9171
9477
|
);
|
|
@@ -9242,19 +9548,6 @@ function estimateParagraphHeightPx(paragraph, availableWidthPx, numberingDefinit
|
|
|
9242
9548
|
estimateWrappedFloatingImageFootprintPx(paragraph, child)
|
|
9243
9549
|
);
|
|
9244
9550
|
}, 0);
|
|
9245
|
-
const absoluteFloatingImageHeightPx = paragraph.children.reduce(
|
|
9246
|
-
(largest, child) => {
|
|
9247
|
-
if (child.type !== "image") {
|
|
9248
|
-
return largest;
|
|
9249
|
-
}
|
|
9250
|
-
return Math.max(
|
|
9251
|
-
largest,
|
|
9252
|
-
estimateAbsoluteFloatingImageFootprintPx(paragraph, child)
|
|
9253
|
-
);
|
|
9254
|
-
},
|
|
9255
|
-
0
|
|
9256
|
-
);
|
|
9257
|
-
const effectiveAbsoluteFloatingImageHeightPx = collapsibleAbsoluteFloatingAnchorOnlyParagraph || decorativeBehindTextAnchorOnlyParagraph ? 0 : absoluteFloatingImageHeightPx;
|
|
9258
9551
|
const emptyParagraphHeightPx = decorativeBehindTextAnchorOnlyParagraph ? 0 : paragraphIsEffectivelyEmpty(paragraph) ? lineHeightPx + EMPTY_PARAGRAPH_EXTRA_HEIGHT_PX : 0;
|
|
9259
9552
|
const topBorderInsetPx = paragraphBorderInsetPx(
|
|
9260
9553
|
paragraph.style?.borders?.top
|
|
@@ -9274,7 +9567,6 @@ function estimateParagraphHeightPx(paragraph, availableWidthPx, numberingDefinit
|
|
|
9274
9567
|
textFlowHeightPx,
|
|
9275
9568
|
inlineImageHeightPx,
|
|
9276
9569
|
wrappedFloatingImageHeightPx,
|
|
9277
|
-
effectiveAbsoluteFloatingImageHeightPx,
|
|
9278
9570
|
emptyParagraphHeightPx
|
|
9279
9571
|
);
|
|
9280
9572
|
if (excludeWrappedFloatingImageFootprint && paragraph.children.some((c) => c.type === "image")) {
|
|
@@ -10535,6 +10827,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
|
|
|
10535
10827
|
let previousParagraphAfterPx = 0;
|
|
10536
10828
|
let currentMetricsIndex = 0;
|
|
10537
10829
|
let currentSectionPageFlowOriginPx = 0;
|
|
10830
|
+
let committedKeepNextChainEndNodeIndex = -1;
|
|
10538
10831
|
let currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
|
|
10539
10832
|
0,
|
|
10540
10833
|
metricsBySection[0]
|
|
@@ -10593,31 +10886,10 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
|
|
|
10593
10886
|
previousParagraphAfterPx = 0;
|
|
10594
10887
|
continue;
|
|
10595
10888
|
}
|
|
10596
|
-
if (node.type === "paragraph" && paragraphActsAsLeadingCoverLayoutPreambleSpacer(
|
|
10597
|
-
model,
|
|
10598
|
-
nodeIndex,
|
|
10599
|
-
node,
|
|
10600
|
-
nodeMetrics.pageContentWidthPx,
|
|
10601
|
-
nodeMetrics.pageContentHeightPx
|
|
10602
|
-
)) {
|
|
10603
|
-
previousParagraphAfterPx = 0;
|
|
10604
|
-
continue;
|
|
10605
|
-
}
|
|
10606
10889
|
if (node.type === "paragraph" && paragraphActsAsTrailingRenderedPageBreakSpacer(model, nodeIndex, node)) {
|
|
10607
10890
|
previousParagraphAfterPx = 0;
|
|
10608
10891
|
continue;
|
|
10609
10892
|
}
|
|
10610
|
-
if (node.type === "paragraph" && paragraphActsAsLeadingCoverLayoutOverlay(
|
|
10611
|
-
model,
|
|
10612
|
-
nodeIndex,
|
|
10613
|
-
node,
|
|
10614
|
-
nodeMetrics.pageContentWidthPx,
|
|
10615
|
-
nodeMetrics.pageContentHeightPx
|
|
10616
|
-
)) {
|
|
10617
|
-
currentPageSegments.push({ nodeIndex });
|
|
10618
|
-
previousParagraphAfterPx = 0;
|
|
10619
|
-
continue;
|
|
10620
|
-
}
|
|
10621
10893
|
if (node.type === "paragraph" && paragraphActsAsDecorativeBehindTextBackgroundOverlay(node)) {
|
|
10622
10894
|
currentPageSegments.push({ nodeIndex });
|
|
10623
10895
|
previousParagraphAfterPx = 0;
|
|
@@ -10627,22 +10899,6 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
|
|
|
10627
10899
|
continue;
|
|
10628
10900
|
}
|
|
10629
10901
|
if (node.type === "paragraph") {
|
|
10630
|
-
if (paragraphStartsNewPageAfterLeadingCoverLayout(
|
|
10631
|
-
model,
|
|
10632
|
-
nodeIndex,
|
|
10633
|
-
node,
|
|
10634
|
-
nodeMetrics.pageContentWidthPx,
|
|
10635
|
-
nodeMetrics.pageContentHeightPx
|
|
10636
|
-
) && currentPageSegments.length > 0) {
|
|
10637
|
-
startNextPage();
|
|
10638
|
-
pageConsumedHeightPx = 0;
|
|
10639
|
-
previousParagraphAfterPx = 0;
|
|
10640
|
-
currentSectionPageFlowOriginPx = 0;
|
|
10641
|
-
currentPageContentHeightPx = resolveMetricsPageContentHeightPx(
|
|
10642
|
-
currentPageIndex,
|
|
10643
|
-
nodeMetrics
|
|
10644
|
-
);
|
|
10645
|
-
}
|
|
10646
10902
|
if (paragraphHasPageBreakBefore2(node) && currentPageSegments.length > 0) {
|
|
10647
10903
|
startNextPage();
|
|
10648
10904
|
pageConsumedHeightPx = 0;
|
|
@@ -10726,18 +10982,12 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
|
|
|
10726
10982
|
1,
|
|
10727
10983
|
estimatedOrMeasuredHeightPx - directBeforeSpacingPx - directAfterSpacingPx + beforeSpacingPx + afterSpacingPx
|
|
10728
10984
|
);
|
|
10729
|
-
const
|
|
10730
|
-
model,
|
|
10731
|
-
nodeIndex,
|
|
10732
|
-
node,
|
|
10733
|
-
nodeMetrics.pageContentWidthPx,
|
|
10734
|
-
nodeMetrics.pageContentHeightPx
|
|
10735
|
-
);
|
|
10736
|
-
const paragraphTooTallForSinglePage = Math.max(rawNodeHeightPx, coverFootprintPx) > nodeMetrics.pageContentHeightPx + PAGE_OVERFLOW_TOLERANCE_PX;
|
|
10985
|
+
const paragraphTooTallForSinglePage = rawNodeHeightPx > nodeMetrics.pageContentHeightPx + PAGE_OVERFLOW_TOLERANCE_PX;
|
|
10737
10986
|
const keepLinesOverflowSplit = node.style?.keepLines === true && paragraphTooTallForSinglePage;
|
|
10738
10987
|
const keepNextOverflowSplit = node.style?.keepNext === true && paragraphTooTallForSinglePage;
|
|
10739
10988
|
const forceOverflowSplit = keepLinesOverflowSplit || keepNextOverflowSplit;
|
|
10740
|
-
|
|
10989
|
+
const nodeIsWithinCommittedKeepNextChain = nodeIndex <= committedKeepNextChainEndNodeIndex;
|
|
10990
|
+
if (forceOverflowSplit && !nodeIsWithinCommittedKeepNextChain && pageConsumedHeightPx > 0 && currentPageSegments.length > 0) {
|
|
10741
10991
|
startNextPage();
|
|
10742
10992
|
pageConsumedHeightPx = 0;
|
|
10743
10993
|
previousParagraphAfterPx = 0;
|
|
@@ -10750,7 +11000,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
|
|
|
10750
11000
|
const collapsedMarginPx = pageConsumedHeightPx > 0 ? Math.min(previousParagraphAfterPx, beforeSpacingPx) : 0;
|
|
10751
11001
|
const collapsedNodeHeightPx = Math.max(
|
|
10752
11002
|
1,
|
|
10753
|
-
|
|
11003
|
+
rawNodeHeightPx - collapsedMarginPx
|
|
10754
11004
|
);
|
|
10755
11005
|
const paragraphSupportsPretextSegmentRendering = Boolean(
|
|
10756
11006
|
paragraphPretextSourceForSegmentRendering
|
|
@@ -10776,7 +11026,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
|
|
|
10776
11026
|
}
|
|
10777
11027
|
const collapsedNodeHeightPxAdjusted = Math.max(
|
|
10778
11028
|
1,
|
|
10779
|
-
|
|
11029
|
+
rawNodeHeightPx - collapsedMarginPx
|
|
10780
11030
|
);
|
|
10781
11031
|
const paragraphPretextLineCount = paragraphContainsExplicitLineBreakText(node) || paragraphContainsTabCharacter(node) ? resolveParagraphPretextLayoutForSegmentRendering()?.lineCount : void 0;
|
|
10782
11032
|
const supportsImageParagraphLineSplit = paragraphHasImage2(node) && paragraphSupportsPretextSegmentRendering;
|
|
@@ -11000,7 +11250,8 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
|
|
|
11000
11250
|
continue;
|
|
11001
11251
|
}
|
|
11002
11252
|
let requiredHeightPx = collapsedNodeHeightPxAdjusted;
|
|
11003
|
-
|
|
11253
|
+
let keepNextChainEndNodeIndex = -1;
|
|
11254
|
+
if (node.style?.keepNext === true && !nodeIsWithinCommittedKeepNextChain && paragraphHasVisibleText2(node)) {
|
|
11004
11255
|
let chainCursor = nodeIndex;
|
|
11005
11256
|
let chainPreviousParagraphAfterPx = afterSpacingPx;
|
|
11006
11257
|
while (chainCursor < model.nodes.length - 1) {
|
|
@@ -11060,6 +11311,7 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
|
|
|
11060
11311
|
);
|
|
11061
11312
|
chainPreviousParagraphAfterPx = nextAfterSpacingPx;
|
|
11062
11313
|
}
|
|
11314
|
+
keepNextChainEndNodeIndex = chainCursor;
|
|
11063
11315
|
}
|
|
11064
11316
|
const remainingHeightPx = currentPageContentHeightPx - pageConsumedHeightPx;
|
|
11065
11317
|
const canKeepTrailingSectionTailOnCurrentPage = shouldKeepTrailingSectionTailOnCurrentPage(
|
|
@@ -11101,11 +11353,11 @@ function buildDocumentPageNodeSegments(model, pageContentHeightPx, pageContentWi
|
|
|
11101
11353
|
nodeMetrics
|
|
11102
11354
|
);
|
|
11103
11355
|
}
|
|
11356
|
+
if (pageConsumedHeightPx === 0 && keepNextChainEndNodeIndex > nodeIndex) {
|
|
11357
|
+
committedKeepNextChainEndNodeIndex = keepNextChainEndNodeIndex;
|
|
11358
|
+
}
|
|
11104
11359
|
currentPageSegments.push({ nodeIndex });
|
|
11105
|
-
const effectiveNodeHeightPx =
|
|
11106
|
-
pageConsumedHeightPx > 0 ? collapsedNodeHeightPx : rawNodeHeightPx,
|
|
11107
|
-
coverFootprintPx
|
|
11108
|
-
);
|
|
11360
|
+
const effectiveNodeHeightPx = pageConsumedHeightPx > 0 ? collapsedNodeHeightPx : rawNodeHeightPx;
|
|
11109
11361
|
pageConsumedHeightPx += effectiveNodeHeightPx;
|
|
11110
11362
|
previousParagraphAfterPx = afterSpacingPx;
|
|
11111
11363
|
continue;
|
|
@@ -11912,11 +12164,15 @@ function paragraphLineHeight(paragraph, docGridLinePitchPx, disableDocGridSnap =
|
|
|
11912
12164
|
disableDocGridSnap
|
|
11913
12165
|
)}px`;
|
|
11914
12166
|
}
|
|
11915
|
-
const
|
|
11916
|
-
|
|
11917
|
-
|
|
11918
|
-
|
|
11919
|
-
|
|
12167
|
+
const resolvedAutoMultiple = resolveAutoLineSpacingMultiple(
|
|
12168
|
+
lineTwips,
|
|
12169
|
+
DEFAULT_PARAGRAPH_LINE_MULTIPLE
|
|
12170
|
+
);
|
|
12171
|
+
const lineMultiple = paragraphHasOnlyWhitespaceText(paragraph) ? Math.max(
|
|
12172
|
+
MIN_AUTO_LINE_MULTIPLE,
|
|
12173
|
+
Number((resolvedAutoMultiple * singleLineScale).toFixed(3))
|
|
12174
|
+
) : calibrateAutoLineSpacingMultiple(
|
|
12175
|
+
resolvedAutoMultiple,
|
|
11920
12176
|
baseFontFamily,
|
|
11921
12177
|
singleLineScale
|
|
11922
12178
|
);
|
|
@@ -12260,8 +12516,7 @@ function paragraphBlockStyle(paragraph, numberingDefinitions, headingStyles, doc
|
|
|
12260
12516
|
const suppressIndentForFloatingAnchorOnlyParagraph = paragraphIsFloatingImageAnchorOnly(paragraph);
|
|
12261
12517
|
const suppressStackingContextForBehindTextAnchorOnlyParagraph = paragraphIsBehindTextAbsoluteFloatingImageAnchorOnly(paragraph);
|
|
12262
12518
|
const suppressFlowFootprintForBehindTextAnchorOnlyParagraph = paragraphActsAsDecorativeBehindTextBackgroundOverlay(paragraph);
|
|
12263
|
-
const
|
|
12264
|
-
const reservedMinHeightPx = suppressFlowFootprintForBehindTextAnchorOnlyParagraph ? void 0 : textBearingAbsoluteFloatingTextBoxFootprintPx > 0 ? textBearingAbsoluteFloatingTextBoxFootprintPx : paragraphIsEffectivelyEmpty(paragraph) ? estimateParagraphLineHeightPx(
|
|
12519
|
+
const reservedMinHeightPx = suppressFlowFootprintForBehindTextAnchorOnlyParagraph ? void 0 : paragraphIsEffectivelyEmpty(paragraph) ? estimateParagraphLineHeightPx(
|
|
12265
12520
|
paragraph,
|
|
12266
12521
|
docGridLinePitchPx,
|
|
12267
12522
|
disableDocGridSnap
|
|
@@ -14019,7 +14274,8 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
|
|
|
14019
14274
|
const resolveNextTabWidthPx = () => resolveTabSpacerWidthPx(
|
|
14020
14275
|
tabStopPositionsPx,
|
|
14021
14276
|
approximateLineWidthPx,
|
|
14022
|
-
fallbackTabWidthPx
|
|
14277
|
+
fallbackTabWidthPx,
|
|
14278
|
+
checkboxChoiceRow
|
|
14023
14279
|
);
|
|
14024
14280
|
const appendPlainTextWithSoftBreakControl = (target, keySeed, text, style, measureStyle) => {
|
|
14025
14281
|
const shouldControlSoftBreakStretch = paragraph.style?.align === "justify" && text.includes("\n");
|
|
@@ -22097,12 +22353,32 @@ function ensureDocxViewerPageSurfaceRegistry(editor) {
|
|
|
22097
22353
|
if (!registry) {
|
|
22098
22354
|
registry = {
|
|
22099
22355
|
pageElements: /* @__PURE__ */ new Map(),
|
|
22356
|
+
pageContentKeys: /* @__PURE__ */ new Map(),
|
|
22100
22357
|
listeners: /* @__PURE__ */ new Set()
|
|
22101
22358
|
};
|
|
22102
22359
|
docxViewerPageSurfaceRegistryByEditor.set(owner, registry);
|
|
22103
22360
|
}
|
|
22104
22361
|
return registry;
|
|
22105
22362
|
}
|
|
22363
|
+
function syncDocxViewerPageSurfaceContentKeys(editor, contentKeysByPage) {
|
|
22364
|
+
const registry = ensureDocxViewerPageSurfaceRegistry(editor);
|
|
22365
|
+
let changed = false;
|
|
22366
|
+
contentKeysByPage.forEach((contentKey, pageIndex) => {
|
|
22367
|
+
if (registry.pageContentKeys.get(pageIndex) !== contentKey) {
|
|
22368
|
+
registry.pageContentKeys.set(pageIndex, contentKey);
|
|
22369
|
+
changed = true;
|
|
22370
|
+
}
|
|
22371
|
+
});
|
|
22372
|
+
registry.pageContentKeys.forEach((_, pageIndex) => {
|
|
22373
|
+
if (pageIndex >= contentKeysByPage.length) {
|
|
22374
|
+
registry.pageContentKeys.delete(pageIndex);
|
|
22375
|
+
changed = true;
|
|
22376
|
+
}
|
|
22377
|
+
});
|
|
22378
|
+
if (changed) {
|
|
22379
|
+
notifyDocxViewerPageSurfaceSubscribers(registry);
|
|
22380
|
+
}
|
|
22381
|
+
}
|
|
22106
22382
|
function subscribeDocxViewerPageSurfaces(editor, listener) {
|
|
22107
22383
|
const registry = ensureDocxViewerPageSurfaceRegistry(editor);
|
|
22108
22384
|
registry.listeners.add(listener);
|
|
@@ -22166,62 +22442,8 @@ function resolveDocxViewerPageSurfaceSize(element, fallbackWidthPx, fallbackHeig
|
|
|
22166
22442
|
heightPx: Math.max(1, Math.round(fallbackHeightPx))
|
|
22167
22443
|
};
|
|
22168
22444
|
}
|
|
22169
|
-
|
|
22170
|
-
|
|
22171
|
-
throw new Error("DOCX thumbnails require a browser environment.");
|
|
22172
|
-
}
|
|
22173
|
-
const {
|
|
22174
|
-
pageElement,
|
|
22175
|
-
sourceWidthPx,
|
|
22176
|
-
sourceHeightPx,
|
|
22177
|
-
canvas,
|
|
22178
|
-
widthPx,
|
|
22179
|
-
heightPx,
|
|
22180
|
-
pixelWidthPx,
|
|
22181
|
-
pixelHeightPx
|
|
22182
|
-
} = params;
|
|
22183
|
-
const safeSourceWidthPx = Math.max(1, Math.round(sourceWidthPx));
|
|
22184
|
-
const safeSourceHeightPx = Math.max(1, Math.round(sourceHeightPx));
|
|
22185
|
-
const scaleX = widthPx / safeSourceWidthPx;
|
|
22186
|
-
const scaleY = heightPx / safeSourceHeightPx;
|
|
22187
|
-
const serializedPage = new XMLSerializer().serializeToString(
|
|
22188
|
-
pageElement.cloneNode(true)
|
|
22189
|
-
);
|
|
22190
|
-
const svgMarkup = `
|
|
22191
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="${widthPx}" height="${heightPx}" viewBox="0 0 ${widthPx} ${heightPx}">
|
|
22192
|
-
<foreignObject x="0" y="0" width="100%" height="100%">
|
|
22193
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="width:${widthPx}px;height:${heightPx}px;overflow:hidden;">
|
|
22194
|
-
<div style="width:${safeSourceWidthPx}px;height:${safeSourceHeightPx}px;transform-origin:top left;transform:scale(${scaleX}, ${scaleY});">
|
|
22195
|
-
${serializedPage}
|
|
22196
|
-
</div>
|
|
22197
|
-
</div>
|
|
22198
|
-
</foreignObject>
|
|
22199
|
-
</svg>
|
|
22200
|
-
`;
|
|
22201
|
-
const svgDataUrl = svgDataUri(svgMarkup);
|
|
22202
|
-
const image = await new Promise((resolve, reject) => {
|
|
22203
|
-
const nextImage = new Image();
|
|
22204
|
-
nextImage.decoding = "async";
|
|
22205
|
-
nextImage.onload = () => resolve(nextImage);
|
|
22206
|
-
nextImage.onerror = () => {
|
|
22207
|
-
reject(new Error("Failed to rasterize DOCX page thumbnail."));
|
|
22208
|
-
};
|
|
22209
|
-
nextImage.src = svgDataUrl;
|
|
22210
|
-
});
|
|
22211
|
-
canvas.width = Math.max(1, Math.round(pixelWidthPx));
|
|
22212
|
-
canvas.height = Math.max(1, Math.round(pixelHeightPx));
|
|
22213
|
-
canvas.style.width = `${Math.max(1, Math.round(widthPx))}px`;
|
|
22214
|
-
canvas.style.height = `${Math.max(1, Math.round(heightPx))}px`;
|
|
22215
|
-
const context = canvas.getContext("2d");
|
|
22216
|
-
if (!context) {
|
|
22217
|
-
throw new Error("2D canvas context is unavailable for DOCX thumbnails.");
|
|
22218
|
-
}
|
|
22219
|
-
context.setTransform(1, 0, 0, 1, 0, 0);
|
|
22220
|
-
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
22221
|
-
context.imageSmoothingEnabled = true;
|
|
22222
|
-
context.imageSmoothingQuality = "high";
|
|
22223
|
-
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
22224
|
-
}
|
|
22445
|
+
var DOCX_THUMBNAIL_SURFACE_CACHE_MAX_ENTRIES = 32;
|
|
22446
|
+
var DOCX_THUMBNAIL_MIN_RASTER_INTERVAL_MS = 200;
|
|
22225
22447
|
function resolveDocxPageThumbnailResolution(options) {
|
|
22226
22448
|
const safeSourceWidthPx = Math.max(1, Math.round(options.sourceWidthPx));
|
|
22227
22449
|
const safeSourceHeightPx = Math.max(1, Math.round(options.sourceHeightPx));
|
|
@@ -22295,8 +22517,51 @@ function useDocxPageThumbnails(editor, options = {}) {
|
|
|
22295
22517
|
},
|
|
22296
22518
|
[]
|
|
22297
22519
|
);
|
|
22520
|
+
const thumbnailSurfaceCacheRef = React.useRef(void 0);
|
|
22521
|
+
const thumbnailRasterQueueRef = React.useRef(void 0);
|
|
22522
|
+
const lastPaintedThumbnailKeyByCanvasRef = React.useRef(
|
|
22523
|
+
/* @__PURE__ */ new WeakMap()
|
|
22524
|
+
);
|
|
22525
|
+
const ensureThumbnailSurfaceCache = React.useCallback(() => {
|
|
22526
|
+
if (!thumbnailSurfaceCacheRef.current) {
|
|
22527
|
+
thumbnailSurfaceCacheRef.current = new DocxThumbnailSurfaceCache(
|
|
22528
|
+
DOCX_THUMBNAIL_SURFACE_CACHE_MAX_ENTRIES
|
|
22529
|
+
);
|
|
22530
|
+
}
|
|
22531
|
+
return thumbnailSurfaceCacheRef.current;
|
|
22532
|
+
}, []);
|
|
22533
|
+
const ensureThumbnailRasterQueue = React.useCallback(() => {
|
|
22534
|
+
if (!thumbnailRasterQueueRef.current) {
|
|
22535
|
+
thumbnailRasterQueueRef.current = new SerialIdleTaskQueue({
|
|
22536
|
+
minTaskIntervalMs: DOCX_THUMBNAIL_MIN_RASTER_INTERVAL_MS
|
|
22537
|
+
});
|
|
22538
|
+
}
|
|
22539
|
+
return thumbnailRasterQueueRef.current;
|
|
22540
|
+
}, []);
|
|
22541
|
+
React.useEffect(() => {
|
|
22542
|
+
thumbnailSurfaceCacheRef.current?.clear();
|
|
22543
|
+
thumbnailRasterQueueRef.current?.clear();
|
|
22544
|
+
lastPaintedThumbnailKeyByCanvasRef.current = /* @__PURE__ */ new WeakMap();
|
|
22545
|
+
}, [editor.documentLoadNonce, pageSurfaceRegistryOwner]);
|
|
22546
|
+
const thumbnailResolutionOptionsKey = React.useMemo(() => {
|
|
22547
|
+
const bounds = options.resolution;
|
|
22548
|
+
const boundsKey = typeof bounds === "number" ? `n${bounds}` : bounds ? `b${bounds.maxWidth ?? ""}x${bounds.maxHeight ?? ""}` : "";
|
|
22549
|
+
return `${boundsKey}|${options.maxWidthPx ?? ""}|${options.maxHeightPx ?? ""}|${options.pixelRatio ?? ""}`;
|
|
22550
|
+
}, [
|
|
22551
|
+
options.maxHeightPx,
|
|
22552
|
+
options.maxWidthPx,
|
|
22553
|
+
options.pixelRatio,
|
|
22554
|
+
options.resolution
|
|
22555
|
+
]);
|
|
22556
|
+
const thumbnailSkipKeyForPage = React.useCallback(
|
|
22557
|
+
(pageIndex) => {
|
|
22558
|
+
const contentKey = pageSurfaceRegistry.pageContentKeys.get(pageIndex);
|
|
22559
|
+
return contentKey === void 0 ? void 0 : `${contentKey}|${editor.documentTheme}|${thumbnailResolutionOptionsKey}`;
|
|
22560
|
+
},
|
|
22561
|
+
[editor.documentTheme, pageSurfaceRegistry, thumbnailResolutionOptionsKey]
|
|
22562
|
+
);
|
|
22298
22563
|
const renderPageThumbnailToCanvas = React.useCallback(
|
|
22299
|
-
async (pageIndex, canvas) => {
|
|
22564
|
+
async (pageIndex, canvas, renderOptions) => {
|
|
22300
22565
|
if (options.disabled) {
|
|
22301
22566
|
return;
|
|
22302
22567
|
}
|
|
@@ -22304,63 +22569,101 @@ function useDocxPageThumbnails(editor, options = {}) {
|
|
|
22304
22569
|
if (!targetCanvas) {
|
|
22305
22570
|
return;
|
|
22306
22571
|
}
|
|
22307
|
-
const pageElement =
|
|
22572
|
+
const pageElement = pageSurfaceRegistry.pageElements.get(pageIndex);
|
|
22308
22573
|
if (!pageElement || !pageElement.isConnected) {
|
|
22309
22574
|
updatePageThumbnailState(pageIndex, "unavailable");
|
|
22310
22575
|
return;
|
|
22311
22576
|
}
|
|
22312
|
-
const
|
|
22313
|
-
|
|
22314
|
-
|
|
22315
|
-
|
|
22316
|
-
|
|
22317
|
-
|
|
22318
|
-
sourceWidthPx: sourceSize.widthPx,
|
|
22319
|
-
sourceHeightPx: sourceSize.heightPx,
|
|
22320
|
-
resolution: options.resolution,
|
|
22321
|
-
maxWidthPx: options.maxWidthPx,
|
|
22322
|
-
maxHeightPx: options.maxHeightPx,
|
|
22323
|
-
pixelRatio: options.pixelRatio
|
|
22324
|
-
});
|
|
22577
|
+
const force = renderOptions?.force === true;
|
|
22578
|
+
const lastPaintedKey = lastPaintedThumbnailKeyByCanvasRef.current.get(targetCanvas);
|
|
22579
|
+
if (!force && lastPaintedKey !== void 0 && lastPaintedKey === thumbnailSkipKeyForPage(pageIndex)) {
|
|
22580
|
+
updatePageThumbnailState(pageIndex, "ready");
|
|
22581
|
+
return;
|
|
22582
|
+
}
|
|
22325
22583
|
updatePageThumbnailState(pageIndex, "rendering");
|
|
22326
|
-
|
|
22327
|
-
|
|
22328
|
-
|
|
22584
|
+
await ensureThumbnailRasterQueue().enqueue(targetCanvas, async () => {
|
|
22585
|
+
const livePageElement = pageSurfaceRegistry.pageElements.get(pageIndex);
|
|
22586
|
+
if (!livePageElement || !livePageElement.isConnected) {
|
|
22587
|
+
updatePageThumbnailState(pageIndex, "unavailable");
|
|
22588
|
+
return;
|
|
22589
|
+
}
|
|
22590
|
+
const runSkipKey = thumbnailSkipKeyForPage(pageIndex);
|
|
22591
|
+
const sourceSize = resolveDocxViewerPageSurfaceSize(
|
|
22592
|
+
livePageElement,
|
|
22593
|
+
fallbackLayout.pageWidthPx,
|
|
22594
|
+
fallbackLayout.pageHeightPx
|
|
22595
|
+
);
|
|
22596
|
+
const resolution = resolveDocxPageThumbnailResolution({
|
|
22329
22597
|
sourceWidthPx: sourceSize.widthPx,
|
|
22330
22598
|
sourceHeightPx: sourceSize.heightPx,
|
|
22331
|
-
|
|
22332
|
-
|
|
22333
|
-
|
|
22334
|
-
|
|
22335
|
-
pixelHeightPx: resolution.pixelHeightPx
|
|
22599
|
+
resolution: options.resolution,
|
|
22600
|
+
maxWidthPx: options.maxWidthPx,
|
|
22601
|
+
maxHeightPx: options.maxHeightPx,
|
|
22602
|
+
pixelRatio: options.pixelRatio
|
|
22336
22603
|
});
|
|
22337
|
-
|
|
22338
|
-
|
|
22339
|
-
|
|
22340
|
-
|
|
22341
|
-
|
|
22342
|
-
|
|
22343
|
-
|
|
22344
|
-
|
|
22604
|
+
const surfaceKey = runSkipKey === void 0 ? void 0 : `${runSkipKey}|${sourceSize.widthPx}x${sourceSize.heightPx}|${resolution.pixelWidthPx}x${resolution.pixelHeightPx}`;
|
|
22605
|
+
const surfaceCache = ensureThumbnailSurfaceCache();
|
|
22606
|
+
try {
|
|
22607
|
+
let surface = !force && surfaceKey !== void 0 ? surfaceCache.get(surfaceKey) : void 0;
|
|
22608
|
+
if (!surface) {
|
|
22609
|
+
surface = await rasterizeDocxThumbnailSurface({
|
|
22610
|
+
pageElement: livePageElement,
|
|
22611
|
+
sourceWidthPx: sourceSize.widthPx,
|
|
22612
|
+
sourceHeightPx: sourceSize.heightPx,
|
|
22613
|
+
widthPx: resolution.widthPx,
|
|
22614
|
+
heightPx: resolution.heightPx,
|
|
22615
|
+
pixelWidthPx: resolution.pixelWidthPx,
|
|
22616
|
+
pixelHeightPx: resolution.pixelHeightPx
|
|
22617
|
+
});
|
|
22618
|
+
if (surfaceKey !== void 0) {
|
|
22619
|
+
surfaceCache.set(surfaceKey, surface);
|
|
22620
|
+
}
|
|
22621
|
+
}
|
|
22622
|
+
blitDocxThumbnailSurface(surface, targetCanvas, resolution);
|
|
22623
|
+
if (runSkipKey !== void 0) {
|
|
22624
|
+
lastPaintedThumbnailKeyByCanvasRef.current.set(
|
|
22625
|
+
targetCanvas,
|
|
22626
|
+
runSkipKey
|
|
22627
|
+
);
|
|
22628
|
+
}
|
|
22629
|
+
updatePageThumbnailState(pageIndex, "ready");
|
|
22630
|
+
} catch (error) {
|
|
22631
|
+
updatePageThumbnailState(
|
|
22632
|
+
pageIndex,
|
|
22633
|
+
"error",
|
|
22634
|
+
error instanceof Error ? error : new Error("Failed to render DOCX page thumbnail.")
|
|
22635
|
+
);
|
|
22636
|
+
}
|
|
22637
|
+
});
|
|
22345
22638
|
},
|
|
22346
22639
|
[
|
|
22640
|
+
ensureThumbnailRasterQueue,
|
|
22641
|
+
ensureThumbnailSurfaceCache,
|
|
22347
22642
|
fallbackLayout.pageHeightPx,
|
|
22348
22643
|
fallbackLayout.pageWidthPx,
|
|
22349
|
-
mountedPageElements,
|
|
22350
22644
|
options.disabled,
|
|
22351
22645
|
options.resolution,
|
|
22352
22646
|
options.maxHeightPx,
|
|
22353
22647
|
options.maxWidthPx,
|
|
22354
22648
|
options.pixelRatio,
|
|
22649
|
+
pageSurfaceRegistry,
|
|
22650
|
+
thumbnailSkipKeyForPage,
|
|
22355
22651
|
updatePageThumbnailState
|
|
22356
22652
|
]
|
|
22357
22653
|
);
|
|
22358
|
-
const
|
|
22359
|
-
|
|
22360
|
-
|
|
22361
|
-
|
|
22362
|
-
|
|
22363
|
-
|
|
22654
|
+
const requestAttachedThumbnailRenders = React.useCallback(
|
|
22655
|
+
async (renderOptions) => {
|
|
22656
|
+
const tasks = [...attachedCanvasByPageRef.current.keys()].map(
|
|
22657
|
+
(pageIndex) => renderPageThumbnailToCanvas(pageIndex, void 0, renderOptions)
|
|
22658
|
+
);
|
|
22659
|
+
await Promise.all(tasks);
|
|
22660
|
+
},
|
|
22661
|
+
[renderPageThumbnailToCanvas]
|
|
22662
|
+
);
|
|
22663
|
+
const rerenderAttachedThumbnails = React.useCallback(
|
|
22664
|
+
async () => requestAttachedThumbnailRenders({ force: true }),
|
|
22665
|
+
[requestAttachedThumbnailRenders]
|
|
22666
|
+
);
|
|
22364
22667
|
const renderPageThumbnailToCanvasRef = React.useRef(
|
|
22365
22668
|
renderPageThumbnailToCanvas
|
|
22366
22669
|
);
|
|
@@ -22372,7 +22675,7 @@ function useDocxPageThumbnails(editor, options = {}) {
|
|
|
22372
22675
|
renderToCanvasCallbacksRef.current.clear();
|
|
22373
22676
|
}, [pageSurfaceRegistryOwner]);
|
|
22374
22677
|
React.useEffect(() => {
|
|
22375
|
-
void
|
|
22678
|
+
void requestAttachedThumbnailRenders();
|
|
22376
22679
|
}, [
|
|
22377
22680
|
editor.documentLoadNonce,
|
|
22378
22681
|
editor.documentTheme,
|
|
@@ -22383,7 +22686,7 @@ function useDocxPageThumbnails(editor, options = {}) {
|
|
|
22383
22686
|
options.maxHeightPx,
|
|
22384
22687
|
options.maxWidthPx,
|
|
22385
22688
|
options.pixelRatio,
|
|
22386
|
-
|
|
22689
|
+
requestAttachedThumbnailRenders
|
|
22387
22690
|
]);
|
|
22388
22691
|
const thumbnails = React.useMemo(() => {
|
|
22389
22692
|
const totalPages = Math.max(1, editor.totalPages);
|
|
@@ -24773,6 +25076,42 @@ function DocxEditorViewer({
|
|
|
24773
25076
|
pageNodeSegmentsByPage,
|
|
24774
25077
|
primarySectionPropertiesXml
|
|
24775
25078
|
]);
|
|
25079
|
+
const pageThumbnailContentKeysByPage = React.useMemo(() => {
|
|
25080
|
+
const metadataSignature = docModelThumbnailMetadataSignature(
|
|
25081
|
+
editor.model.metadata
|
|
25082
|
+
);
|
|
25083
|
+
return pageNodeSegmentsByPage.map((pageSegments, pageIndex) => {
|
|
25084
|
+
const sectionInfo = pageSectionInfoByIndex[pageIndex];
|
|
25085
|
+
let nodeSignatures = "";
|
|
25086
|
+
for (const segment of pageSegments) {
|
|
25087
|
+
nodeSignatures += docNodeContentSignature(
|
|
25088
|
+
editor.model.nodes[segment.nodeIndex]
|
|
25089
|
+
);
|
|
25090
|
+
nodeSignatures += ",";
|
|
25091
|
+
}
|
|
25092
|
+
return [
|
|
25093
|
+
editor.documentLoadNonce,
|
|
25094
|
+
trackedChangesEnabled ? "tc1" : "tc0",
|
|
25095
|
+
metadataSignature,
|
|
25096
|
+
sectionInfo ? `${sectionInfo.sectionIndex}.${sectionInfo.pageNumber}` : "s?",
|
|
25097
|
+
pageNodeSegmentIdentityKeysByPage[pageIndex] ?? "",
|
|
25098
|
+
nodeSignatures
|
|
25099
|
+
].join("|");
|
|
25100
|
+
});
|
|
25101
|
+
}, [
|
|
25102
|
+
editor.documentLoadNonce,
|
|
25103
|
+
editor.model,
|
|
25104
|
+
pageNodeSegmentIdentityKeysByPage,
|
|
25105
|
+
pageNodeSegmentsByPage,
|
|
25106
|
+
pageSectionInfoByIndex,
|
|
25107
|
+
trackedChangesEnabled
|
|
25108
|
+
]);
|
|
25109
|
+
React.useEffect(() => {
|
|
25110
|
+
syncDocxViewerPageSurfaceContentKeys(
|
|
25111
|
+
editor,
|
|
25112
|
+
pageThumbnailContentKeysByPage
|
|
25113
|
+
);
|
|
25114
|
+
}, [pageSurfaceRegistryOwner, pageThumbnailContentKeysByPage]);
|
|
24776
25115
|
const resolveStyleRefFieldValueForPage = React.useMemo(() => {
|
|
24777
25116
|
const valueCache = /* @__PURE__ */ new Map();
|
|
24778
25117
|
const nodes = editor.model.nodes;
|
|
@@ -32489,6 +32828,7 @@ function DocxEditorViewer({
|
|
|
32489
32828
|
"span",
|
|
32490
32829
|
{
|
|
32491
32830
|
contentEditable: false,
|
|
32831
|
+
...{ [DOCX_THUMBNAIL_EXCLUDE_ATTRIBUTE]: "true" },
|
|
32492
32832
|
style: {
|
|
32493
32833
|
position: "absolute",
|
|
32494
32834
|
left: rect.left,
|
|
@@ -32511,6 +32851,7 @@ function DocxEditorViewer({
|
|
|
32511
32851
|
"span",
|
|
32512
32852
|
{
|
|
32513
32853
|
contentEditable: false,
|
|
32854
|
+
...{ [DOCX_THUMBNAIL_EXCLUDE_ATTRIBUTE]: "true" },
|
|
32514
32855
|
style: {
|
|
32515
32856
|
position: "absolute",
|
|
32516
32857
|
left: caretRect.left,
|
|
@@ -35714,13 +36055,6 @@ function DocxEditorViewer({
|
|
|
35714
36055
|
options?.pageFlowForeignExclusions ?? []
|
|
35715
36056
|
)
|
|
35716
36057
|
);
|
|
35717
|
-
const leadingCoverLayoutSpacer = paragraphActsAsLeadingCoverLayoutSpacer(
|
|
35718
|
-
editor.model,
|
|
35719
|
-
nodeIndex,
|
|
35720
|
-
node,
|
|
35721
|
-
paragraphContentWidthPx,
|
|
35722
|
-
resolvedPageLayout.pageHeightPx - resolvedPageLayout.marginsPx.top - resolvedPageLayout.marginsPx.bottom
|
|
35723
|
-
);
|
|
35724
36058
|
const beforeSpacingPx = effectiveParagraphBeforeSpacingPx(
|
|
35725
36059
|
editor.model,
|
|
35726
36060
|
nodeIndex,
|
|
@@ -35779,9 +36113,6 @@ function DocxEditorViewer({
|
|
|
35779
36113
|
lineHeight: 0,
|
|
35780
36114
|
overflow: "visible"
|
|
35781
36115
|
} : requiresPageAbsoluteContext ? { position: "static" } : requiresLocalAbsoluteContext ? { position: "relative" } : hasDualWrappedFloatingImage ? { position: "relative" } : void 0,
|
|
35782
|
-
...leadingCoverLayoutSpacer ? {
|
|
35783
|
-
minHeight: `${estimateParagraphLineHeightPx(node, nodeDocGridLinePitchPx) + EMPTY_PARAGRAPH_EXTRA_HEIGHT_PX + LEADING_COVER_SPACER_EXTRA_HEIGHT_PX}px`
|
|
35784
|
-
} : void 0,
|
|
35785
36116
|
// Carry the paragraph's run font on the editable host so text typed into
|
|
35786
36117
|
// it (which is a bare, not-yet-committed text node, not a styled run
|
|
35787
36118
|
// span) renders in the same font the committed run will use — i.e. the
|
|
@@ -36816,6 +37147,22 @@ ${currentText.slice(end)}`;
|
|
|
36816
37147
|
const rowSpanValue = cell.style?.rowSpan && cell.style.rowSpan > 1 ? cell.style.rowSpan : 1;
|
|
36817
37148
|
const colSpan = colSpanValue > 1 ? colSpanValue : void 0;
|
|
36818
37149
|
const rowSpan = rowSpanValue > 1 ? rowSpanValue : void 0;
|
|
37150
|
+
const exactRowSpanRows = node.rows.slice(
|
|
37151
|
+
rowIndex,
|
|
37152
|
+
rowIndex + rowSpanValue
|
|
37153
|
+
);
|
|
37154
|
+
const exactRowSpanClipHeightPx = exactRowSpanRows.length > 0 && exactRowSpanRows.every((spannedRow, rowOffset) => {
|
|
37155
|
+
const spannedHeightPx = rowHeightsPx[rowIndex + rowOffset];
|
|
37156
|
+
return spannedRow.style?.heightRule === "exact" && Number.isFinite(spannedHeightPx) && spannedHeightPx > 0;
|
|
37157
|
+
}) ? exactRowSpanRows.reduce(
|
|
37158
|
+
(sum, _spannedRow, rowOffset) => sum + Math.max(
|
|
37159
|
+
MIN_PARAGRAPH_LINE_HEIGHT_PX,
|
|
37160
|
+
Math.round(
|
|
37161
|
+
rowHeightsPx[rowIndex + rowOffset]
|
|
37162
|
+
)
|
|
37163
|
+
),
|
|
37164
|
+
0
|
|
37165
|
+
) : void 0;
|
|
36819
37166
|
const startColumnIndex = columnCursor;
|
|
36820
37167
|
const boundaryColumnIndex = startColumnIndex + colSpanValue - 1;
|
|
36821
37168
|
columnCursor += colSpanValue;
|
|
@@ -37934,12 +38281,11 @@ ${currentText.slice(end)}`;
|
|
|
37934
38281
|
style: {
|
|
37935
38282
|
display: "grid",
|
|
37936
38283
|
gap: 0,
|
|
37937
|
-
//
|
|
37938
|
-
//
|
|
37939
|
-
//
|
|
37940
|
-
|
|
37941
|
-
|
|
37942
|
-
maxHeight: resolvedRowHeightStyle.height,
|
|
38284
|
+
// Without the clip the row balloons to fit
|
|
38285
|
+
// content (height on a <tr>/<td> is only
|
|
38286
|
+
// ever a minimum).
|
|
38287
|
+
...exactRowSpanClipHeightPx !== void 0 && !isSlicedRow ? {
|
|
38288
|
+
maxHeight: `${exactRowSpanClipHeightPx}px`,
|
|
37943
38289
|
overflow: "hidden"
|
|
37944
38290
|
} : void 0
|
|
37945
38291
|
},
|
|
@@ -39726,11 +40072,27 @@ ${currentText.slice(end)}`;
|
|
|
39726
40072
|
currentGroup.segments.push(segment);
|
|
39727
40073
|
return;
|
|
39728
40074
|
}
|
|
40075
|
+
if (currentGroup && parseSectionStartType(
|
|
40076
|
+
documentSections[currentSectionIndex]?.sectionPropertiesXml
|
|
40077
|
+
) === "nextcolumn") {
|
|
40078
|
+
const previousColumns = sectionColumnsBySectionIndex[currentGroup.sectionIndex];
|
|
40079
|
+
const nextColumns = sectionColumnsBySectionIndex[currentSectionIndex];
|
|
40080
|
+
const sameGeometry = previousColumns && nextColumns && previousColumns.count === nextColumns.count && Math.abs(
|
|
40081
|
+
previousColumns.gapPx - nextColumns.gapPx
|
|
40082
|
+
) <= 2 && JSON.stringify(previousColumns.widthsPx ?? null) === JSON.stringify(nextColumns.widthsPx ?? null);
|
|
40083
|
+
if (sameGeometry) {
|
|
40084
|
+
currentGroup.segments.push(segment);
|
|
40085
|
+
return;
|
|
40086
|
+
}
|
|
40087
|
+
}
|
|
39729
40088
|
sectionGroups.push({
|
|
39730
40089
|
sectionIndex: currentSectionIndex,
|
|
39731
40090
|
segments: [segment]
|
|
39732
40091
|
});
|
|
39733
40092
|
});
|
|
40093
|
+
if (typeof window !== "undefined" && window.__docxDebugGroups) {
|
|
40094
|
+
console.log("[groups]", pageIndex, JSON.stringify(sectionGroups.map((g) => ({ s: g.sectionIndex, n: g.segments.map((x) => x.nodeIndex) }))));
|
|
40095
|
+
}
|
|
39734
40096
|
return sectionGroups.map((group, groupIndex) => {
|
|
39735
40097
|
const sectionColumns = sectionColumnsBySectionIndex[group.sectionIndex];
|
|
39736
40098
|
const isLastGroupOnPage = groupIndex === sectionGroups.length - 1;
|
|
@@ -39899,7 +40261,7 @@ ${currentText.slice(end)}`;
|
|
|
39899
40261
|
(editor.model.metadata.sections ?? []).filter(
|
|
39900
40262
|
(candidate) => parseSectionStartType(
|
|
39901
40263
|
candidate.sectionPropertiesXml
|
|
39902
|
-
) === "
|
|
40264
|
+
) === "nextcolumn"
|
|
39903
40265
|
).map(
|
|
39904
40266
|
(candidate) => Math.max(
|
|
39905
40267
|
0,
|
|
@@ -41809,6 +42171,7 @@ function collectDocxEstimatedOverflowBreakStartNodeIndexes(model, hardBreakStart
|
|
|
41809
42171
|
let pageConsumedHeightPx = 0;
|
|
41810
42172
|
let previousParagraphAfterPx = 0;
|
|
41811
42173
|
let currentMetricsIndex = 0;
|
|
42174
|
+
let committedKeepNextChainEndNodeIndex = -1;
|
|
41812
42175
|
const suppressSpacingBeforeAfterPageBreak = options?.suppressSpacingBeforeAfterPageBreak ?? false;
|
|
41813
42176
|
let currentPageContentHeightPx = metricsBySection[0]?.pageContentHeightPx ?? fallbackMetrics.pageContentHeightPx;
|
|
41814
42177
|
for (let nodeIndex = 0; nodeIndex < model.nodes.length; nodeIndex += 1) {
|
|
@@ -41846,7 +42209,8 @@ function collectDocxEstimatedOverflowBreakStartNodeIndexes(model, hardBreakStart
|
|
|
41846
42209
|
const collapsedMarginPx = node.type === "paragraph" && pageConsumedHeightPx > 0 ? Math.min(previousParagraphAfterPx, nodeBeforeSpacingPx) : 0;
|
|
41847
42210
|
const collapsedNodeHeightPx = Math.max(1, rawNodeHeightPx - collapsedMarginPx);
|
|
41848
42211
|
let requiredHeightPx = collapsedNodeHeightPx;
|
|
41849
|
-
|
|
42212
|
+
let keepNextChainEndNodeIndex = -1;
|
|
42213
|
+
if (node.type === "paragraph" && node.style?.keepNext === true && nodeIndex > committedKeepNextChainEndNodeIndex && callbacks.paragraphHasVisibleText(node)) {
|
|
41850
42214
|
let chainCursor = nodeIndex;
|
|
41851
42215
|
let chainPreviousParagraphAfterPx = paragraphAfterSpacingPx2(node);
|
|
41852
42216
|
while (chainCursor < model.nodes.length - 1) {
|
|
@@ -41904,6 +42268,7 @@ function collectDocxEstimatedOverflowBreakStartNodeIndexes(model, hardBreakStart
|
|
|
41904
42268
|
);
|
|
41905
42269
|
chainPreviousParagraphAfterPx = paragraphAfterSpacingPx2(nextChainNode);
|
|
41906
42270
|
}
|
|
42271
|
+
keepNextChainEndNodeIndex = chainCursor;
|
|
41907
42272
|
}
|
|
41908
42273
|
const remainingHeightPx = currentPageContentHeightPx - pageConsumedHeightPx;
|
|
41909
42274
|
if (pageConsumedHeightPx > 0 && requiredHeightPx > remainingHeightPx + pageOverflowTolerancePx) {
|
|
@@ -41912,6 +42277,9 @@ function collectDocxEstimatedOverflowBreakStartNodeIndexes(model, hardBreakStart
|
|
|
41912
42277
|
previousParagraphAfterPx = 0;
|
|
41913
42278
|
currentPageContentHeightPx = nodeMetrics.pageContentHeightPx;
|
|
41914
42279
|
}
|
|
42280
|
+
if (pageConsumedHeightPx === 0 && keepNextChainEndNodeIndex > nodeIndex) {
|
|
42281
|
+
committedKeepNextChainEndNodeIndex = keepNextChainEndNodeIndex;
|
|
42282
|
+
}
|
|
41915
42283
|
const effectiveNodeHeightPx = pageConsumedHeightPx > 0 ? collapsedNodeHeightPx : rawNodeHeightPx;
|
|
41916
42284
|
pageConsumedHeightPx += effectiveNodeHeightPx;
|
|
41917
42285
|
previousParagraphAfterPx = node.type === "paragraph" ? paragraphAfterSpacingPx2(node) : 0;
|
|
@@ -41963,6 +42331,7 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
|
|
|
41963
42331
|
let pageConsumedHeightPx = 0;
|
|
41964
42332
|
let previousParagraphAfterPx = 0;
|
|
41965
42333
|
let currentMetricsIndex = 0;
|
|
42334
|
+
let committedKeepNextChainEndNodeIndex = -1;
|
|
41966
42335
|
let currentPageContentHeightPx = resolvePageContentHeightPx(
|
|
41967
42336
|
0,
|
|
41968
42337
|
metricsBySection[0]?.pageContentHeightPx ?? fallbackMetrics.pageContentHeightPx
|
|
@@ -42026,7 +42395,8 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
|
|
|
42026
42395
|
const keepLinesOverflowSplit = node.style?.keepLines === true && paragraphTooTallForSinglePage;
|
|
42027
42396
|
const keepNextOverflowSplit = node.style?.keepNext === true && paragraphTooTallForSinglePage;
|
|
42028
42397
|
const forceOverflowSplit = keepLinesOverflowSplit || keepNextOverflowSplit;
|
|
42029
|
-
|
|
42398
|
+
const nodeIsWithinCommittedKeepNextChain = nodeIndex <= committedKeepNextChainEndNodeIndex;
|
|
42399
|
+
if (forceOverflowSplit && !nodeIsWithinCommittedKeepNextChain && pageConsumedHeightPx > 0 && currentPageSegments.length > 0) {
|
|
42030
42400
|
startNextPage();
|
|
42031
42401
|
pageConsumedHeightPx = 0;
|
|
42032
42402
|
previousParagraphAfterPx = 0;
|
|
@@ -42176,7 +42546,8 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
|
|
|
42176
42546
|
continue;
|
|
42177
42547
|
}
|
|
42178
42548
|
let requiredHeightPx = collapsedNodeHeightPx;
|
|
42179
|
-
|
|
42549
|
+
let keepNextChainEndNodeIndex = -1;
|
|
42550
|
+
if (node.style?.keepNext === true && !nodeIsWithinCommittedKeepNextChain && callbacks.paragraphHasVisibleText(node)) {
|
|
42180
42551
|
let chainCursor = nodeIndex;
|
|
42181
42552
|
let chainPreviousParagraphAfterPx = afterSpacingPx;
|
|
42182
42553
|
while (chainCursor < model.nodes.length - 1) {
|
|
@@ -42234,6 +42605,7 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
|
|
|
42234
42605
|
);
|
|
42235
42606
|
chainPreviousParagraphAfterPx = paragraphAfterSpacingPx2(nextChainNode);
|
|
42236
42607
|
}
|
|
42608
|
+
keepNextChainEndNodeIndex = chainCursor;
|
|
42237
42609
|
}
|
|
42238
42610
|
const remainingHeightPx = currentPageContentHeightPx - pageConsumedHeightPx;
|
|
42239
42611
|
if (pageConsumedHeightPx > 0 && requiredHeightPx > remainingHeightPx + pageOverflowTolerancePx) {
|
|
@@ -42245,6 +42617,9 @@ function buildDocumentPageNodeSegments2(model, pageContentHeightPx, pageContentW
|
|
|
42245
42617
|
nodeMetrics.pageContentHeightPx
|
|
42246
42618
|
);
|
|
42247
42619
|
}
|
|
42620
|
+
if (pageConsumedHeightPx === 0 && keepNextChainEndNodeIndex > nodeIndex) {
|
|
42621
|
+
committedKeepNextChainEndNodeIndex = keepNextChainEndNodeIndex;
|
|
42622
|
+
}
|
|
42248
42623
|
currentPageSegments.push({ nodeIndex });
|
|
42249
42624
|
const effectiveNodeHeightPx = pageConsumedHeightPx > 0 ? collapsedNodeHeightPx : rawNodeHeightPx;
|
|
42250
42625
|
pageConsumedHeightPx += effectiveNodeHeightPx;
|