@extend-ai/react-docx 0.8.3 → 0.9.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/README.md +43 -0
- package/dist/docx_wasm_bg.wasm +0 -0
- package/dist/index.cjs +1565 -980
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +134 -7
- package/dist/index.d.ts +134 -7
- package/dist/index.js +1557 -975
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
|
|
28
28
|
// src/index.tsx
|
|
29
29
|
import * as React2 from "react";
|
|
30
|
+
import { flushSync as flushSync2 } from "react-dom";
|
|
30
31
|
|
|
31
32
|
// ../layout-engine/src/index.ts
|
|
32
33
|
var DEFAULT_OPTIONS = {
|
|
@@ -445,529 +446,6 @@ async function importDocxBuffer(buffer, options = {}) {
|
|
|
445
446
|
return result;
|
|
446
447
|
}
|
|
447
448
|
|
|
448
|
-
// src/section-layout.ts
|
|
449
|
-
var DEFAULT_DOC_PAGE_WIDTH = 900;
|
|
450
|
-
var DEFAULT_DOC_PAGE_HEIGHT = 1200;
|
|
451
|
-
var DEFAULT_DOC_PAGE_MARGIN = 56;
|
|
452
|
-
var TWIPS_PER_PIXEL = 15;
|
|
453
|
-
var DEFAULT_DOCUMENT_LAYOUT = {
|
|
454
|
-
pageWidthPx: DEFAULT_DOC_PAGE_WIDTH,
|
|
455
|
-
pageHeightPx: DEFAULT_DOC_PAGE_HEIGHT,
|
|
456
|
-
marginsPx: {
|
|
457
|
-
top: DEFAULT_DOC_PAGE_MARGIN,
|
|
458
|
-
right: DEFAULT_DOC_PAGE_MARGIN,
|
|
459
|
-
bottom: DEFAULT_DOC_PAGE_MARGIN,
|
|
460
|
-
left: DEFAULT_DOC_PAGE_MARGIN
|
|
461
|
-
},
|
|
462
|
-
headerDistancePx: DEFAULT_DOC_PAGE_MARGIN,
|
|
463
|
-
footerDistancePx: DEFAULT_DOC_PAGE_MARGIN,
|
|
464
|
-
docGridLinePitchPx: void 0
|
|
465
|
-
};
|
|
466
|
-
function pageMarginPaddingStyle(marginsPx) {
|
|
467
|
-
return {
|
|
468
|
-
paddingTop: marginsPx.top,
|
|
469
|
-
paddingRight: marginsPx.right,
|
|
470
|
-
paddingBottom: marginsPx.bottom,
|
|
471
|
-
paddingLeft: marginsPx.left
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
function twipsToPixels(twips) {
|
|
475
|
-
if (!Number.isFinite(twips)) {
|
|
476
|
-
return void 0;
|
|
477
|
-
}
|
|
478
|
-
return Math.max(0, Math.round(twips / TWIPS_PER_PIXEL));
|
|
479
|
-
}
|
|
480
|
-
function readTwipsAttribute(tagXml, attribute) {
|
|
481
|
-
if (!tagXml) {
|
|
482
|
-
return void 0;
|
|
483
|
-
}
|
|
484
|
-
const match = tagXml.match(new RegExp(`${attribute}="(\\d+)"`, "i"));
|
|
485
|
-
if (!match?.[1]) {
|
|
486
|
-
return void 0;
|
|
487
|
-
}
|
|
488
|
-
const parsed = Number(match[1]);
|
|
489
|
-
return Number.isFinite(parsed) ? parsed : void 0;
|
|
490
|
-
}
|
|
491
|
-
function readStringAttribute(tagXml, attribute) {
|
|
492
|
-
if (!tagXml) {
|
|
493
|
-
return void 0;
|
|
494
|
-
}
|
|
495
|
-
return tagXml.match(new RegExp(`${attribute}="([^"]+)"`, "i"))?.[1];
|
|
496
|
-
}
|
|
497
|
-
function resolvePageSizeForOrientation(params) {
|
|
498
|
-
const normalizedOrientation = params.orientation?.trim().toLowerCase();
|
|
499
|
-
const widthPx = Math.max(1, params.widthPx);
|
|
500
|
-
const heightPx = Math.max(1, params.heightPx);
|
|
501
|
-
if (normalizedOrientation === "landscape" && widthPx < heightPx) {
|
|
502
|
-
return { widthPx: heightPx, heightPx: widthPx };
|
|
503
|
-
}
|
|
504
|
-
if (normalizedOrientation === "portrait" && widthPx > heightPx) {
|
|
505
|
-
return { widthPx: heightPx, heightPx: widthPx };
|
|
506
|
-
}
|
|
507
|
-
return { widthPx, heightPx };
|
|
508
|
-
}
|
|
509
|
-
function normalizeHexColor(value) {
|
|
510
|
-
if (!value) {
|
|
511
|
-
return void 0;
|
|
512
|
-
}
|
|
513
|
-
const normalized = value.trim();
|
|
514
|
-
if (!normalized || normalized.toLowerCase() === "auto") {
|
|
515
|
-
return void 0;
|
|
516
|
-
}
|
|
517
|
-
if (/^[0-9a-fA-F]{6}$/.test(normalized)) {
|
|
518
|
-
return `#${normalized}`;
|
|
519
|
-
}
|
|
520
|
-
if (/^#[0-9a-fA-F]{6}$/.test(normalized)) {
|
|
521
|
-
return normalized;
|
|
522
|
-
}
|
|
523
|
-
return void 0;
|
|
524
|
-
}
|
|
525
|
-
function borderTypeToCssStyle(rawType) {
|
|
526
|
-
const value = rawType?.trim().toLowerCase();
|
|
527
|
-
if (!value || value === "none" || value === "nil") {
|
|
528
|
-
return void 0;
|
|
529
|
-
}
|
|
530
|
-
if (value === "double") {
|
|
531
|
-
return "double";
|
|
532
|
-
}
|
|
533
|
-
if (value === "dashed" || value === "dashsmallgap" || value === "dotdash" || value === "dotdotdash") {
|
|
534
|
-
return "dashed";
|
|
535
|
-
}
|
|
536
|
-
if (value === "dotted") {
|
|
537
|
-
return "dotted";
|
|
538
|
-
}
|
|
539
|
-
return "solid";
|
|
540
|
-
}
|
|
541
|
-
function pointsToPixels(points) {
|
|
542
|
-
if (!Number.isFinite(points)) {
|
|
543
|
-
return void 0;
|
|
544
|
-
}
|
|
545
|
-
return Math.max(0, Math.round(points * (96 / 72)));
|
|
546
|
-
}
|
|
547
|
-
function parseSectionPageBorderEdge(sectionPropertiesXml, edge) {
|
|
548
|
-
if (!sectionPropertiesXml) {
|
|
549
|
-
return void 0;
|
|
550
|
-
}
|
|
551
|
-
const bordersXml = sectionPropertiesXml.match(
|
|
552
|
-
/<w:pgBorders\b[\s\S]*?<\/w:pgBorders>/i
|
|
553
|
-
)?.[0];
|
|
554
|
-
if (!bordersXml) {
|
|
555
|
-
return void 0;
|
|
556
|
-
}
|
|
557
|
-
const edgeTag = bordersXml.match(new RegExp(`<w:${edge}\\b[^>]*/?>`, "i"))?.[0];
|
|
558
|
-
if (!edgeTag) {
|
|
559
|
-
return void 0;
|
|
560
|
-
}
|
|
561
|
-
const cssStyle = borderTypeToCssStyle(readStringAttribute(edgeTag, "w:val"));
|
|
562
|
-
if (!cssStyle) {
|
|
563
|
-
return void 0;
|
|
564
|
-
}
|
|
565
|
-
const sizeEighthPt = Number(readStringAttribute(edgeTag, "w:sz"));
|
|
566
|
-
const widthPx = Number.isFinite(sizeEighthPt) && sizeEighthPt > 0 ? Math.max(0.5, Number((sizeEighthPt / 6).toFixed(2))) : 1;
|
|
567
|
-
const color = normalizeHexColor(readStringAttribute(edgeTag, "w:color")) ?? "#000000";
|
|
568
|
-
const offsetPoints = Number(readStringAttribute(edgeTag, "w:space"));
|
|
569
|
-
return {
|
|
570
|
-
cssBorder: `${widthPx}px ${cssStyle} ${color}`,
|
|
571
|
-
offsetPx: pointsToPixels(offsetPoints) ?? 0,
|
|
572
|
-
shadow: readStringAttribute(edgeTag, "w:shadow")?.trim().toLowerCase() === "1" || readStringAttribute(edgeTag, "w:shadow")?.trim().toLowerCase() === "true"
|
|
573
|
-
};
|
|
574
|
-
}
|
|
575
|
-
function parseSectionPageBorders(sectionPropertiesXml) {
|
|
576
|
-
if (!sectionPropertiesXml || !/<w:pgBorders\b/i.test(sectionPropertiesXml)) {
|
|
577
|
-
return void 0;
|
|
578
|
-
}
|
|
579
|
-
const borders = {
|
|
580
|
-
top: parseSectionPageBorderEdge(sectionPropertiesXml, "top"),
|
|
581
|
-
right: parseSectionPageBorderEdge(sectionPropertiesXml, "right"),
|
|
582
|
-
bottom: parseSectionPageBorderEdge(sectionPropertiesXml, "bottom"),
|
|
583
|
-
left: parseSectionPageBorderEdge(sectionPropertiesXml, "left")
|
|
584
|
-
};
|
|
585
|
-
return borders.top || borders.right || borders.bottom || borders.left ? borders : void 0;
|
|
586
|
-
}
|
|
587
|
-
function parseSectionLayout(sectionPropertiesXml) {
|
|
588
|
-
if (!sectionPropertiesXml) {
|
|
589
|
-
return DEFAULT_DOCUMENT_LAYOUT;
|
|
590
|
-
}
|
|
591
|
-
const pageSizeTag = sectionPropertiesXml.match(/<w:pgSz\b[^>]*>/i)?.[0];
|
|
592
|
-
const pageMarginTag = sectionPropertiesXml.match(/<w:pgMar\b[^>]*>/i)?.[0];
|
|
593
|
-
const docGridTag = sectionPropertiesXml.match(/<w:docGrid\b[^>]*\/?>/i)?.[0];
|
|
594
|
-
const rawPageWidthPx = twipsToPixels(readTwipsAttribute(pageSizeTag, "w:w")) ?? DEFAULT_DOCUMENT_LAYOUT.pageWidthPx;
|
|
595
|
-
const rawPageHeightPx = twipsToPixels(readTwipsAttribute(pageSizeTag, "w:h")) ?? DEFAULT_DOCUMENT_LAYOUT.pageHeightPx;
|
|
596
|
-
const pageSize = resolvePageSizeForOrientation({
|
|
597
|
-
widthPx: rawPageWidthPx,
|
|
598
|
-
heightPx: rawPageHeightPx,
|
|
599
|
-
orientation: readStringAttribute(pageSizeTag, "w:orient")
|
|
600
|
-
});
|
|
601
|
-
const topMarginPx = twipsToPixels(readTwipsAttribute(pageMarginTag, "w:top")) ?? DEFAULT_DOCUMENT_LAYOUT.marginsPx.top;
|
|
602
|
-
const rightMarginPx = twipsToPixels(readTwipsAttribute(pageMarginTag, "w:right")) ?? DEFAULT_DOCUMENT_LAYOUT.marginsPx.right;
|
|
603
|
-
const bottomMarginPx = twipsToPixels(readTwipsAttribute(pageMarginTag, "w:bottom")) ?? DEFAULT_DOCUMENT_LAYOUT.marginsPx.bottom;
|
|
604
|
-
const leftMarginPx = twipsToPixels(readTwipsAttribute(pageMarginTag, "w:left")) ?? DEFAULT_DOCUMENT_LAYOUT.marginsPx.left;
|
|
605
|
-
const headerDistancePx = twipsToPixels(readTwipsAttribute(pageMarginTag, "w:header")) ?? DEFAULT_DOCUMENT_LAYOUT.headerDistancePx;
|
|
606
|
-
const footerDistancePx = twipsToPixels(readTwipsAttribute(pageMarginTag, "w:footer")) ?? DEFAULT_DOCUMENT_LAYOUT.footerDistancePx;
|
|
607
|
-
const docGridType = readStringAttribute(docGridTag, "w:type")?.toLowerCase();
|
|
608
|
-
const docGridLinePitchPx = docGridType === "lines" || docGridType === "linesandchars" || docGridType === "snaptochars" ? twipsToPixels(readTwipsAttribute(docGridTag, "w:linePitch")) ?? DEFAULT_DOCUMENT_LAYOUT.docGridLinePitchPx : DEFAULT_DOCUMENT_LAYOUT.docGridLinePitchPx;
|
|
609
|
-
return {
|
|
610
|
-
pageWidthPx: pageSize.widthPx,
|
|
611
|
-
pageHeightPx: pageSize.heightPx,
|
|
612
|
-
marginsPx: {
|
|
613
|
-
top: topMarginPx,
|
|
614
|
-
right: rightMarginPx,
|
|
615
|
-
bottom: bottomMarginPx,
|
|
616
|
-
left: leftMarginPx
|
|
617
|
-
},
|
|
618
|
-
headerDistancePx,
|
|
619
|
-
footerDistancePx,
|
|
620
|
-
docGridLinePitchPx
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
function resolveDocumentSectionPropertiesXml(model) {
|
|
624
|
-
return model.metadata.sections?.[0]?.sectionPropertiesXml ?? model.metadata.sectionPropertiesXml;
|
|
625
|
-
}
|
|
626
|
-
function resolveDocumentLayout(model) {
|
|
627
|
-
return parseSectionLayout(resolveDocumentSectionPropertiesXml(model));
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
// src/image-render.ts
|
|
631
|
-
import { encode as encodePng } from "fast-png";
|
|
632
|
-
import UTIFModule from "utif";
|
|
633
|
-
var TIFF_CONTENT_TYPES = /* @__PURE__ */ new Set(["image/tiff", "image/tif"]);
|
|
634
|
-
var PLACEHOLDER_FALLBACK_CONTENT_TYPES = /* @__PURE__ */ new Set([
|
|
635
|
-
"image/x-emf",
|
|
636
|
-
"image/emf",
|
|
637
|
-
"image/x-wmf",
|
|
638
|
-
"image/wmf"
|
|
639
|
-
]);
|
|
640
|
-
var TIFF_DATA_URI_PREFIXES = ["data:image/tiff", "data:image/tif"];
|
|
641
|
-
var EMF_DATA_URI_PREFIXES = ["data:image/emf", "data:image/x-emf"];
|
|
642
|
-
var WMF_DATA_URI_PREFIXES = ["data:image/wmf", "data:image/x-wmf"];
|
|
643
|
-
var UTIF = UTIFModule;
|
|
644
|
-
var convertedTiffSrcCache = /* @__PURE__ */ new Map();
|
|
645
|
-
function normalizeImageContentType(image) {
|
|
646
|
-
return image.contentType?.trim().toLowerCase();
|
|
647
|
-
}
|
|
648
|
-
function normalizeImageSrc(image) {
|
|
649
|
-
return image.src?.trim();
|
|
650
|
-
}
|
|
651
|
-
function imageHasTiffContent(image) {
|
|
652
|
-
const contentType = normalizeImageContentType(image);
|
|
653
|
-
if (contentType && TIFF_CONTENT_TYPES.has(contentType)) {
|
|
654
|
-
return true;
|
|
655
|
-
}
|
|
656
|
-
const src = normalizeImageSrc(image)?.toLowerCase();
|
|
657
|
-
return Boolean(src && TIFF_DATA_URI_PREFIXES.some((prefix) => src.startsWith(prefix)));
|
|
658
|
-
}
|
|
659
|
-
function imageHasMetafileContent(image) {
|
|
660
|
-
const contentType = normalizeImageContentType(image);
|
|
661
|
-
if (contentType && PLACEHOLDER_FALLBACK_CONTENT_TYPES.has(contentType)) {
|
|
662
|
-
return true;
|
|
663
|
-
}
|
|
664
|
-
const src = normalizeImageSrc(image)?.toLowerCase();
|
|
665
|
-
return Boolean(
|
|
666
|
-
src && (EMF_DATA_URI_PREFIXES.some((prefix) => src.startsWith(prefix)) || WMF_DATA_URI_PREFIXES.some((prefix) => src.startsWith(prefix)))
|
|
667
|
-
);
|
|
668
|
-
}
|
|
669
|
-
function imageUsesEmfContent(image) {
|
|
670
|
-
const contentType = normalizeImageContentType(image);
|
|
671
|
-
if (contentType === "image/x-emf" || contentType === "image/emf") {
|
|
672
|
-
return true;
|
|
673
|
-
}
|
|
674
|
-
const src = normalizeImageSrc(image)?.toLowerCase();
|
|
675
|
-
return Boolean(src && EMF_DATA_URI_PREFIXES.some((prefix) => src.startsWith(prefix)));
|
|
676
|
-
}
|
|
677
|
-
function imageUsesWmfContent(image) {
|
|
678
|
-
const contentType = normalizeImageContentType(image);
|
|
679
|
-
if (contentType === "image/x-wmf" || contentType === "image/wmf") {
|
|
680
|
-
return true;
|
|
681
|
-
}
|
|
682
|
-
const src = normalizeImageSrc(image)?.toLowerCase();
|
|
683
|
-
return Boolean(src && WMF_DATA_URI_PREFIXES.some((prefix) => src.startsWith(prefix)));
|
|
684
|
-
}
|
|
685
|
-
function imageUsesPlaceholderFallback(image) {
|
|
686
|
-
return imageHasMetafileContent(image);
|
|
687
|
-
}
|
|
688
|
-
function unsupportedImageFallbackLabel(image, widthPx, heightPx) {
|
|
689
|
-
const isSmallIcon = (widthPx ?? 0) <= 56 && (heightPx ?? 0) <= 56;
|
|
690
|
-
if (imageUsesEmfContent(image)) {
|
|
691
|
-
return isSmallIcon ? "e" : "EMF";
|
|
692
|
-
}
|
|
693
|
-
if (imageUsesWmfContent(image)) {
|
|
694
|
-
return isSmallIcon ? "w" : "WMF";
|
|
695
|
-
}
|
|
696
|
-
return isSmallIcon ? "e" : "TIFF";
|
|
697
|
-
}
|
|
698
|
-
function dataUriToBytes(dataUri) {
|
|
699
|
-
const match = dataUri.match(/^data:([^;]+);base64,(.+)$/i);
|
|
700
|
-
if (!match) {
|
|
701
|
-
return void 0;
|
|
702
|
-
}
|
|
703
|
-
const [, , base64] = match;
|
|
704
|
-
if (typeof Buffer !== "undefined") {
|
|
705
|
-
return new Uint8Array(Buffer.from(base64, "base64"));
|
|
706
|
-
}
|
|
707
|
-
if (typeof atob !== "function") {
|
|
708
|
-
return void 0;
|
|
709
|
-
}
|
|
710
|
-
const binary = atob(base64);
|
|
711
|
-
const bytes = new Uint8Array(binary.length);
|
|
712
|
-
for (let index = 0; index < binary.length; index += 1) {
|
|
713
|
-
bytes[index] = binary.charCodeAt(index);
|
|
714
|
-
}
|
|
715
|
-
return bytes;
|
|
716
|
-
}
|
|
717
|
-
function bytesToBase64(bytes) {
|
|
718
|
-
if (typeof Buffer !== "undefined") {
|
|
719
|
-
return Buffer.from(bytes).toString("base64");
|
|
720
|
-
}
|
|
721
|
-
if (typeof btoa !== "function") {
|
|
722
|
-
return void 0;
|
|
723
|
-
}
|
|
724
|
-
let binary = "";
|
|
725
|
-
const chunkSize = 32768;
|
|
726
|
-
for (let index = 0; index < bytes.byteLength; index += chunkSize) {
|
|
727
|
-
const chunk = bytes.subarray(index, index + chunkSize);
|
|
728
|
-
binary += String.fromCharCode(...chunk);
|
|
729
|
-
}
|
|
730
|
-
return btoa(binary);
|
|
731
|
-
}
|
|
732
|
-
function toArrayBuffer(bytes) {
|
|
733
|
-
const { buffer, byteOffset, byteLength } = bytes;
|
|
734
|
-
if (byteOffset === 0 && byteLength === buffer.byteLength) {
|
|
735
|
-
return buffer;
|
|
736
|
-
}
|
|
737
|
-
return buffer.slice(byteOffset, byteOffset + byteLength);
|
|
738
|
-
}
|
|
739
|
-
function resolveTiffBytes(image) {
|
|
740
|
-
if (image.data?.byteLength) {
|
|
741
|
-
return image.data;
|
|
742
|
-
}
|
|
743
|
-
const src = normalizeImageSrc(image);
|
|
744
|
-
return src ? dataUriToBytes(src) : void 0;
|
|
745
|
-
}
|
|
746
|
-
function selectPrimaryTiffPage(ifds) {
|
|
747
|
-
if (ifds.length === 0) {
|
|
748
|
-
return void 0;
|
|
749
|
-
}
|
|
750
|
-
let candidates = ifds;
|
|
751
|
-
if (Array.isArray(ifds[0]?.subIFD) && ifds[0].subIFD.length > 0) {
|
|
752
|
-
candidates = candidates.concat(ifds[0].subIFD);
|
|
753
|
-
}
|
|
754
|
-
let best;
|
|
755
|
-
let maxArea = -1;
|
|
756
|
-
for (const candidate of candidates) {
|
|
757
|
-
const width = candidate.width ?? candidate.t256 ?? 0;
|
|
758
|
-
const height = candidate.height ?? candidate.t257 ?? 0;
|
|
759
|
-
if (!width || !height) {
|
|
760
|
-
continue;
|
|
761
|
-
}
|
|
762
|
-
const area = width * height;
|
|
763
|
-
if (best === void 0 || area > maxArea) {
|
|
764
|
-
best = candidate;
|
|
765
|
-
maxArea = area;
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
return best ?? ifds[0];
|
|
769
|
-
}
|
|
770
|
-
function convertTiffToPngDataUri(bytes) {
|
|
771
|
-
const tiffBuffer = toArrayBuffer(bytes);
|
|
772
|
-
const ifds = UTIF.decode(tiffBuffer);
|
|
773
|
-
const page = selectPrimaryTiffPage(ifds);
|
|
774
|
-
if (!page) {
|
|
775
|
-
return void 0;
|
|
776
|
-
}
|
|
777
|
-
UTIF.decodeImage(tiffBuffer, page, ifds);
|
|
778
|
-
const width = page.width ?? page.t256 ?? 0;
|
|
779
|
-
const height = page.height ?? page.t257 ?? 0;
|
|
780
|
-
const rgba = UTIF.toRGBA8(page);
|
|
781
|
-
if (!width || !height || rgba.byteLength !== width * height * 4) {
|
|
782
|
-
return void 0;
|
|
783
|
-
}
|
|
784
|
-
const pngBytes = encodePng({
|
|
785
|
-
width,
|
|
786
|
-
height,
|
|
787
|
-
data: rgba,
|
|
788
|
-
channels: 4,
|
|
789
|
-
depth: 8
|
|
790
|
-
});
|
|
791
|
-
const base64 = bytesToBase64(pngBytes);
|
|
792
|
-
return base64 ? `data:image/png;base64,${base64}` : void 0;
|
|
793
|
-
}
|
|
794
|
-
function resolveRenderableImageSource(image) {
|
|
795
|
-
const src = normalizeImageSrc(image);
|
|
796
|
-
if (!src) {
|
|
797
|
-
return void 0;
|
|
798
|
-
}
|
|
799
|
-
if (imageHasMetafileContent(image)) {
|
|
800
|
-
return void 0;
|
|
801
|
-
}
|
|
802
|
-
if (!imageHasTiffContent(image)) {
|
|
803
|
-
return src;
|
|
804
|
-
}
|
|
805
|
-
const cached = convertedTiffSrcCache.get(src);
|
|
806
|
-
if (cached !== void 0 || convertedTiffSrcCache.has(src)) {
|
|
807
|
-
return cached;
|
|
808
|
-
}
|
|
809
|
-
let converted;
|
|
810
|
-
try {
|
|
811
|
-
const bytes = resolveTiffBytes(image);
|
|
812
|
-
if (bytes) {
|
|
813
|
-
converted = convertTiffToPngDataUri(bytes);
|
|
814
|
-
}
|
|
815
|
-
} catch {
|
|
816
|
-
converted = void 0;
|
|
817
|
-
}
|
|
818
|
-
convertedTiffSrcCache.set(src, converted);
|
|
819
|
-
return converted;
|
|
820
|
-
}
|
|
821
|
-
function subscribeRenderableImageSourceUpdates(listener) {
|
|
822
|
-
void listener;
|
|
823
|
-
return () => {
|
|
824
|
-
};
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
// src/script-fonts.ts
|
|
828
|
-
var EAST_ASIA_SCRIPT_RE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Bopomofo}\p{Script=Yi}]/u;
|
|
829
|
-
var COMPLEX_SCRIPT_RE = /[\p{Script=Arabic}\p{Script=Hebrew}\p{Script=Syriac}\p{Script=Thaana}\p{Script=Nko}\p{Script=Samaritan}\p{Script=Mandaic}\p{Script=Devanagari}\p{Script=Bengali}\p{Script=Gurmukhi}\p{Script=Gujarati}\p{Script=Oriya}\p{Script=Tamil}\p{Script=Telugu}\p{Script=Kannada}\p{Script=Malayalam}\p{Script=Sinhala}\p{Script=Thai}\p{Script=Lao}\p{Script=Tibetan}\p{Script=Myanmar}\p{Script=Khmer}]/u;
|
|
830
|
-
var NEUTRAL_OR_CONTINUATION_RE = /[\p{Mark}\p{Separator}\p{Punctuation}\u200c\u200d\ufe00-\ufe0f]/u;
|
|
831
|
-
var EAST_ASIA_LANGUAGE_RE = /^(?:ja|ko|zh)(?:-|$)/i;
|
|
832
|
-
var COMPLEX_SCRIPT_LANGUAGE_RE = /^(?:ar|ckb|dv|fa|he|hi|ks|ku|pa-arab|ps|sd|syr|ug|ur|yi)(?:-|$)/i;
|
|
833
|
-
function normalizeFamily(value) {
|
|
834
|
-
const normalized = value?.trim();
|
|
835
|
-
return normalized || void 0;
|
|
836
|
-
}
|
|
837
|
-
function normalizedFamilyKey(value) {
|
|
838
|
-
return normalizeFamily(value)?.replace(/^['"]+|['"]+$/g, "").toLowerCase();
|
|
839
|
-
}
|
|
840
|
-
function hasLegacyFontFamilyOverride(style) {
|
|
841
|
-
const current = normalizedFamilyKey(style?.fontFamily);
|
|
842
|
-
const imported = normalizedFamilyKey(style?.sourceFontFamily);
|
|
843
|
-
if (!current) {
|
|
844
|
-
return false;
|
|
845
|
-
}
|
|
846
|
-
if (imported) {
|
|
847
|
-
return current !== imported;
|
|
848
|
-
}
|
|
849
|
-
return !(normalizeFamily(style?.fontFamilyAscii) || normalizeFamily(style?.fontFamilyHAnsi) || normalizeFamily(style?.fontFamilyEastAsia) || normalizeFamily(style?.fontFamilyCs) || normalizeFamily(style?.fontThemeAscii) || normalizeFamily(style?.fontThemeHAnsi) || normalizeFamily(style?.fontThemeEastAsia) || normalizeFamily(style?.fontThemeCs));
|
|
850
|
-
}
|
|
851
|
-
function normalizedFontHint(style) {
|
|
852
|
-
return style?.fontHint?.trim().replace(/[-_\s]/g, "").toLowerCase() ?? "";
|
|
853
|
-
}
|
|
854
|
-
function neutralScript(style) {
|
|
855
|
-
const hint = normalizedFontHint(style);
|
|
856
|
-
if (hint === "eastasia") {
|
|
857
|
-
return "eastAsia";
|
|
858
|
-
}
|
|
859
|
-
if (hint === "cs" || hint === "complexscript" || hint === "bidi") {
|
|
860
|
-
return "complexScript";
|
|
861
|
-
}
|
|
862
|
-
if (style?.rightToLeft || COMPLEX_SCRIPT_LANGUAGE_RE.test(style?.languageBidi?.trim() ?? "")) {
|
|
863
|
-
return "complexScript";
|
|
864
|
-
}
|
|
865
|
-
if (EAST_ASIA_LANGUAGE_RE.test(style?.languageEastAsia?.trim() ?? "")) {
|
|
866
|
-
return "eastAsia";
|
|
867
|
-
}
|
|
868
|
-
return "highAnsi";
|
|
869
|
-
}
|
|
870
|
-
function classifyDocxFontScript(value, style) {
|
|
871
|
-
const character = Array.from(value)[0];
|
|
872
|
-
if (!character) {
|
|
873
|
-
return void 0;
|
|
874
|
-
}
|
|
875
|
-
if (style?.complexScript === true || style?.rightToLeft === true && style?.complexScript !== false) {
|
|
876
|
-
return "complexScript";
|
|
877
|
-
}
|
|
878
|
-
const codePoint = character.codePointAt(0) ?? 0;
|
|
879
|
-
if (codePoint <= 127) {
|
|
880
|
-
return "ascii";
|
|
881
|
-
}
|
|
882
|
-
if (EAST_ASIA_SCRIPT_RE.test(character) || codePoint >= 12288 && codePoint <= 12351 || codePoint >= 65280 && codePoint <= 65519) {
|
|
883
|
-
return "eastAsia";
|
|
884
|
-
}
|
|
885
|
-
if (COMPLEX_SCRIPT_RE.test(character)) {
|
|
886
|
-
return "complexScript";
|
|
887
|
-
}
|
|
888
|
-
if (NEUTRAL_OR_CONTINUATION_RE.test(character)) {
|
|
889
|
-
return void 0;
|
|
890
|
-
}
|
|
891
|
-
return "highAnsi";
|
|
892
|
-
}
|
|
893
|
-
function resolveDocxScriptFontFamily(style, script) {
|
|
894
|
-
const legacyFamily = normalizeFamily(style?.fontFamily);
|
|
895
|
-
if (hasLegacyFontFamilyOverride(style)) {
|
|
896
|
-
return legacyFamily;
|
|
897
|
-
}
|
|
898
|
-
switch (script) {
|
|
899
|
-
case "ascii":
|
|
900
|
-
return normalizeFamily(style?.resolvedFontFamilyAscii) ?? normalizeFamily(style?.fontFamilyAscii) ?? normalizeFamily(style?.resolvedFontFamilyHAnsi) ?? normalizeFamily(style?.fontFamilyHAnsi) ?? legacyFamily;
|
|
901
|
-
case "highAnsi":
|
|
902
|
-
return normalizeFamily(style?.resolvedFontFamilyHAnsi) ?? normalizeFamily(style?.fontFamilyHAnsi) ?? normalizeFamily(style?.resolvedFontFamilyAscii) ?? normalizeFamily(style?.fontFamilyAscii) ?? legacyFamily;
|
|
903
|
-
case "eastAsia":
|
|
904
|
-
return normalizeFamily(style?.resolvedFontFamilyEastAsia) ?? normalizeFamily(style?.fontFamilyEastAsia) ?? normalizeFamily(style?.resolvedFontFamilyHAnsi) ?? normalizeFamily(style?.fontFamilyHAnsi) ?? normalizeFamily(style?.resolvedFontFamilyAscii) ?? normalizeFamily(style?.fontFamilyAscii) ?? legacyFamily;
|
|
905
|
-
case "complexScript":
|
|
906
|
-
return normalizeFamily(style?.resolvedFontFamilyCs) ?? normalizeFamily(style?.fontFamilyCs) ?? normalizeFamily(style?.resolvedFontFamilyHAnsi) ?? normalizeFamily(style?.fontFamilyHAnsi) ?? normalizeFamily(style?.resolvedFontFamilyAscii) ?? normalizeFamily(style?.fontFamilyAscii) ?? legacyFamily;
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
function segmentTextByDocxScriptFont(text, style) {
|
|
910
|
-
if (!text) {
|
|
911
|
-
return [];
|
|
912
|
-
}
|
|
913
|
-
const tokens = [];
|
|
914
|
-
let offset = 0;
|
|
915
|
-
for (const character of text) {
|
|
916
|
-
const startOffset = offset;
|
|
917
|
-
offset += character.length;
|
|
918
|
-
tokens.push({
|
|
919
|
-
text: character,
|
|
920
|
-
startOffset,
|
|
921
|
-
endOffset: offset,
|
|
922
|
-
script: classifyDocxFontScript(character, style)
|
|
923
|
-
});
|
|
924
|
-
}
|
|
925
|
-
const fallbackScript = neutralScript(style);
|
|
926
|
-
const nextStrongScript = new Array(
|
|
927
|
-
tokens.length
|
|
928
|
-
);
|
|
929
|
-
let nextScript;
|
|
930
|
-
for (let index = tokens.length - 1; index >= 0; index -= 1) {
|
|
931
|
-
nextStrongScript[index] = nextScript;
|
|
932
|
-
if (tokens[index]?.script) {
|
|
933
|
-
nextScript = tokens[index]?.script;
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
let previousScript;
|
|
937
|
-
for (let index = 0; index < tokens.length; index += 1) {
|
|
938
|
-
const token = tokens[index];
|
|
939
|
-
if (!token) {
|
|
940
|
-
continue;
|
|
941
|
-
}
|
|
942
|
-
token.script = token.script ?? previousScript ?? nextStrongScript[index] ?? fallbackScript;
|
|
943
|
-
previousScript = token.script;
|
|
944
|
-
}
|
|
945
|
-
const segments = [];
|
|
946
|
-
for (const token of tokens) {
|
|
947
|
-
const script = token.script ?? fallbackScript;
|
|
948
|
-
const fontFamily = resolveDocxScriptFontFamily(style, script);
|
|
949
|
-
const previous = segments[segments.length - 1];
|
|
950
|
-
if (previous && normalizedFamilyKey(previous.fontFamily) === normalizedFamilyKey(fontFamily)) {
|
|
951
|
-
previous.text += token.text;
|
|
952
|
-
previous.endOffset = token.endOffset;
|
|
953
|
-
continue;
|
|
954
|
-
}
|
|
955
|
-
segments.push({
|
|
956
|
-
text: token.text,
|
|
957
|
-
startOffset: token.startOffset,
|
|
958
|
-
endOffset: token.endOffset,
|
|
959
|
-
script,
|
|
960
|
-
fontFamily
|
|
961
|
-
});
|
|
962
|
-
}
|
|
963
|
-
return segments;
|
|
964
|
-
}
|
|
965
|
-
function resolveDocxTextFontFamily(text, style) {
|
|
966
|
-
return segmentTextByDocxScriptFont(text, style).find(
|
|
967
|
-
(segment) => segment.fontFamily
|
|
968
|
-
)?.fontFamily ?? normalizeFamily(style?.fontFamily);
|
|
969
|
-
}
|
|
970
|
-
|
|
971
449
|
// src/editor.tsx
|
|
972
450
|
import * as React from "react";
|
|
973
451
|
import { flushSync } from "react-dom";
|
|
@@ -3515,450 +2993,973 @@ function applyTextEditingIntent(text, selectionStart, selectionEnd, intent) {
|
|
|
3515
2993
|
return void 0;
|
|
3516
2994
|
}
|
|
3517
2995
|
}
|
|
3518
|
-
function shouldCoalesceTextCommit(previous, next, windowMs = 1e3) {
|
|
3519
|
-
return Boolean(
|
|
3520
|
-
previous && previous.key === next.key && next.at >= previous.at && next.at - previous.at <= windowMs && previous.caretAfter === next.caretBefore
|
|
3521
|
-
);
|
|
2996
|
+
function shouldCoalesceTextCommit(previous, next, windowMs = 1e3) {
|
|
2997
|
+
return Boolean(
|
|
2998
|
+
previous && previous.key === next.key && next.at >= previous.at && next.at - previous.at <= windowMs && previous.caretAfter === next.caretBefore
|
|
2999
|
+
);
|
|
3000
|
+
}
|
|
3001
|
+
function mergeCellParagraphTexts(paragraphTexts, boundaryParagraphIndex) {
|
|
3002
|
+
if (boundaryParagraphIndex <= 0 || boundaryParagraphIndex >= paragraphTexts.length) {
|
|
3003
|
+
return void 0;
|
|
3004
|
+
}
|
|
3005
|
+
const mergedTexts = [
|
|
3006
|
+
...paragraphTexts.slice(0, boundaryParagraphIndex - 1),
|
|
3007
|
+
`${paragraphTexts[boundaryParagraphIndex - 1]}${paragraphTexts[boundaryParagraphIndex]}`,
|
|
3008
|
+
...paragraphTexts.slice(boundaryParagraphIndex + 1)
|
|
3009
|
+
];
|
|
3010
|
+
const cellText = mergedTexts.join("\n");
|
|
3011
|
+
let caretGlobalOffset = 0;
|
|
3012
|
+
for (let index = 0; index < boundaryParagraphIndex - 1; index += 1) {
|
|
3013
|
+
caretGlobalOffset += paragraphTexts[index].length + 1;
|
|
3014
|
+
}
|
|
3015
|
+
caretGlobalOffset += paragraphTexts[boundaryParagraphIndex - 1].length;
|
|
3016
|
+
const parts = cellText.split("\n");
|
|
3017
|
+
let remaining = caretGlobalOffset;
|
|
3018
|
+
let caretParagraphIndex = 0;
|
|
3019
|
+
while (caretParagraphIndex < parts.length - 1 && remaining > parts[caretParagraphIndex].length) {
|
|
3020
|
+
remaining -= parts[caretParagraphIndex].length + 1;
|
|
3021
|
+
caretParagraphIndex += 1;
|
|
3022
|
+
}
|
|
3023
|
+
return {
|
|
3024
|
+
cellText,
|
|
3025
|
+
caretParagraphIndex,
|
|
3026
|
+
caretOffset: Math.max(0, Math.min(remaining, parts[caretParagraphIndex].length))
|
|
3027
|
+
};
|
|
3028
|
+
}
|
|
3029
|
+
|
|
3030
|
+
// src/pagination-breaks.ts
|
|
3031
|
+
var PAGE_BREAK_XML_PATTERN = /<w:br\b[^>]*w:type="page"[^>]*\/?>/i;
|
|
3032
|
+
var PAGE_BREAK_BEFORE_XML_PATTERN = /<w:pageBreakBefore\b[^>]*\/?>/i;
|
|
3033
|
+
var tableExplicitPageBreakInfoBySourceXml = /* @__PURE__ */ new Map();
|
|
3034
|
+
function isOnOffTagEnabled(tagXml) {
|
|
3035
|
+
if (!tagXml) {
|
|
3036
|
+
return false;
|
|
3037
|
+
}
|
|
3038
|
+
const valueMatch = tagXml.match(/\bw:val="([^"]+)"/i)?.[1]?.trim().toLowerCase();
|
|
3039
|
+
if (!valueMatch) {
|
|
3040
|
+
return true;
|
|
3041
|
+
}
|
|
3042
|
+
return !["0", "false", "off", "no"].includes(valueMatch);
|
|
3043
|
+
}
|
|
3044
|
+
function paragraphHasExplicitPageBreak(paragraph) {
|
|
3045
|
+
const sourceXml = paragraph.sourceXml ?? "";
|
|
3046
|
+
return sourceXml.length > 0 && PAGE_BREAK_XML_PATTERN.test(sourceXml);
|
|
3047
|
+
}
|
|
3048
|
+
function paragraphHasPageBreakBefore(paragraph) {
|
|
3049
|
+
if (paragraph.style?.pageBreakBefore === true) {
|
|
3050
|
+
return true;
|
|
3051
|
+
}
|
|
3052
|
+
const sourceXml = paragraph.sourceXml ?? "";
|
|
3053
|
+
if (!sourceXml) {
|
|
3054
|
+
return false;
|
|
3055
|
+
}
|
|
3056
|
+
return isOnOffTagEnabled(sourceXml.match(PAGE_BREAK_BEFORE_XML_PATTERN)?.[0]);
|
|
3057
|
+
}
|
|
3058
|
+
function paragraphHasVisibleText(paragraph) {
|
|
3059
|
+
return paragraph.children.some(
|
|
3060
|
+
(child) => child.type === "text" && child.text.trim().length > 0 || child.type === "form-field" && (child.value ?? "").trim().length > 0
|
|
3061
|
+
);
|
|
3062
|
+
}
|
|
3063
|
+
function paragraphHasImage(paragraph) {
|
|
3064
|
+
return paragraph.children.some((child) => child.type === "image");
|
|
3065
|
+
}
|
|
3066
|
+
function paragraphHasFormField(paragraph) {
|
|
3067
|
+
return paragraph.children.some((child) => child.type === "form-field");
|
|
3068
|
+
}
|
|
3069
|
+
function paragraphIsOnlyExplicitPageBreak(paragraph) {
|
|
3070
|
+
return paragraphHasExplicitPageBreak(paragraph) && !paragraphHasVisibleText(paragraph) && !paragraphHasImage(paragraph) && !paragraphHasFormField(paragraph);
|
|
3071
|
+
}
|
|
3072
|
+
function tableCellDirectParagraphs(nodeContent) {
|
|
3073
|
+
return nodeContent.filter((entry) => entry.type === "paragraph");
|
|
3074
|
+
}
|
|
3075
|
+
function tableRowHasSubstantiveContentOutsideBreakOnlyParagraphs(row) {
|
|
3076
|
+
return row.cells.some(
|
|
3077
|
+
(cell) => tableCellDirectParagraphs(cell.nodes).some((paragraph) => {
|
|
3078
|
+
if (paragraphIsOnlyExplicitPageBreak(paragraph)) {
|
|
3079
|
+
return false;
|
|
3080
|
+
}
|
|
3081
|
+
return paragraphHasVisibleText(paragraph) || paragraphHasImage(paragraph) || paragraphHasFormField(paragraph) || paragraphHasExplicitPageBreak(paragraph);
|
|
3082
|
+
})
|
|
3083
|
+
);
|
|
3084
|
+
}
|
|
3085
|
+
function tableRowSubstantiveCellIndexes(row) {
|
|
3086
|
+
const indexes = [];
|
|
3087
|
+
row.cells.forEach((cell, cellIndex) => {
|
|
3088
|
+
const substantive = tableCellDirectParagraphs(cell.nodes).some((paragraph) => {
|
|
3089
|
+
if (paragraphIsOnlyExplicitPageBreak(paragraph)) {
|
|
3090
|
+
return false;
|
|
3091
|
+
}
|
|
3092
|
+
return paragraphHasVisibleText(paragraph) || paragraphHasImage(paragraph) || paragraphHasFormField(paragraph) || paragraphHasExplicitPageBreak(paragraph);
|
|
3093
|
+
});
|
|
3094
|
+
if (substantive) {
|
|
3095
|
+
indexes.push(cellIndex);
|
|
3096
|
+
}
|
|
3097
|
+
});
|
|
3098
|
+
return indexes;
|
|
3099
|
+
}
|
|
3100
|
+
function tableRowUsesTrailingSignatureCellBreakPattern(table, row) {
|
|
3101
|
+
if (table.rows.length !== 1 || row.cells.length < 4) {
|
|
3102
|
+
return false;
|
|
3103
|
+
}
|
|
3104
|
+
const substantiveIndexes = tableRowSubstantiveCellIndexes(row);
|
|
3105
|
+
return substantiveIndexes.length === 1 && substantiveIndexes[0] >= row.cells.length - 1;
|
|
3106
|
+
}
|
|
3107
|
+
function collectTableExplicitPageBreakInfo(table) {
|
|
3108
|
+
const sourceXml = table.sourceXml ?? "";
|
|
3109
|
+
if (sourceXml) {
|
|
3110
|
+
const cached = tableExplicitPageBreakInfoBySourceXml.get(sourceXml);
|
|
3111
|
+
if (cached) {
|
|
3112
|
+
return cached;
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
const startRowIndexes = /* @__PURE__ */ new Set();
|
|
3116
|
+
let breakAfterTable = false;
|
|
3117
|
+
table.rows.forEach((row, rowIndex) => {
|
|
3118
|
+
let rowBreakTarget;
|
|
3119
|
+
row.cells.forEach((cell) => {
|
|
3120
|
+
tableCellDirectParagraphs(cell.nodes).forEach((paragraph) => {
|
|
3121
|
+
if (!paragraphHasExplicitPageBreak(paragraph)) {
|
|
3122
|
+
return;
|
|
3123
|
+
}
|
|
3124
|
+
if (paragraphIsOnlyExplicitPageBreak(paragraph) && rowIndex === 0 && tableRowHasSubstantiveContentOutsideBreakOnlyParagraphs(row) && !tableRowUsesTrailingSignatureCellBreakPattern(table, row)) {
|
|
3125
|
+
return;
|
|
3126
|
+
}
|
|
3127
|
+
const breakTarget = paragraphIsOnlyExplicitPageBreak(paragraph) ? rowIndex : rowIndex + 1;
|
|
3128
|
+
if (rowBreakTarget === void 0 || breakTarget < rowBreakTarget) {
|
|
3129
|
+
rowBreakTarget = breakTarget;
|
|
3130
|
+
}
|
|
3131
|
+
});
|
|
3132
|
+
});
|
|
3133
|
+
if (rowBreakTarget === void 0) {
|
|
3134
|
+
return;
|
|
3135
|
+
}
|
|
3136
|
+
if (rowBreakTarget >= table.rows.length) {
|
|
3137
|
+
breakAfterTable = true;
|
|
3138
|
+
return;
|
|
3139
|
+
}
|
|
3140
|
+
startRowIndexes.add(Math.max(0, rowBreakTarget));
|
|
3141
|
+
});
|
|
3142
|
+
const info = {
|
|
3143
|
+
startRowIndexes: [...startRowIndexes].sort((left, right) => left - right),
|
|
3144
|
+
breakAfterTable
|
|
3145
|
+
};
|
|
3146
|
+
if (sourceXml) {
|
|
3147
|
+
tableExplicitPageBreakInfoBySourceXml.set(sourceXml, info);
|
|
3148
|
+
}
|
|
3149
|
+
return info;
|
|
3150
|
+
}
|
|
3151
|
+
function collectTopLevelExplicitPageBreakStartNodeIndexes(nodes) {
|
|
3152
|
+
const breaks = /* @__PURE__ */ new Set();
|
|
3153
|
+
for (let nodeIndex = 0; nodeIndex < nodes.length; nodeIndex += 1) {
|
|
3154
|
+
const node = nodes[nodeIndex];
|
|
3155
|
+
const hasNextNode = nodeIndex + 1 < nodes.length;
|
|
3156
|
+
if (node.type === "paragraph") {
|
|
3157
|
+
if (paragraphHasPageBreakBefore(node)) {
|
|
3158
|
+
breaks.add(nodeIndex);
|
|
3159
|
+
}
|
|
3160
|
+
if (hasNextNode && paragraphHasExplicitPageBreak(node)) {
|
|
3161
|
+
breaks.add(nodeIndex + 1);
|
|
3162
|
+
}
|
|
3163
|
+
continue;
|
|
3164
|
+
}
|
|
3165
|
+
const tableBreakInfo = collectTableExplicitPageBreakInfo(node);
|
|
3166
|
+
if (tableBreakInfo.startRowIndexes.includes(0) && nodeIndex > 0) {
|
|
3167
|
+
breaks.add(nodeIndex);
|
|
3168
|
+
}
|
|
3169
|
+
if (hasNextNode && tableBreakInfo.breakAfterTable) {
|
|
3170
|
+
breaks.add(nodeIndex + 1);
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3173
|
+
for (const breakIndex of [...breaks]) {
|
|
3174
|
+
if (breakIndex <= 0 || breakIndex >= nodes.length) {
|
|
3175
|
+
breaks.delete(breakIndex);
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
return breaks;
|
|
3179
|
+
}
|
|
3180
|
+
|
|
3181
|
+
// src/page-count-reconciliation.ts
|
|
3182
|
+
var PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS = 10;
|
|
3183
|
+
function shouldAllowStoredPageCountReduction(options) {
|
|
3184
|
+
const estimatedPageCount = Math.max(
|
|
3185
|
+
1,
|
|
3186
|
+
Math.round(options.estimatedPageCount)
|
|
3187
|
+
);
|
|
3188
|
+
const targetPageCount = Math.max(1, Math.round(options.targetPageCount));
|
|
3189
|
+
if (targetPageCount >= estimatedPageCount) {
|
|
3190
|
+
return true;
|
|
3191
|
+
}
|
|
3192
|
+
const renderedBreakHintPageCount = Number.isFinite(
|
|
3193
|
+
options.renderedBreakHintPageCount
|
|
3194
|
+
) ? Math.max(1, Math.round(options.renderedBreakHintPageCount)) : void 0;
|
|
3195
|
+
const renderedBreakHintsSupportTarget = options.hasLastRenderedPageBreakHints === true && renderedBreakHintPageCount !== void 0 && targetPageCount >= renderedBreakHintPageCount;
|
|
3196
|
+
if (options.hasMeasuredBodyFooterOverlap === true) {
|
|
3197
|
+
return renderedBreakHintsSupportTarget;
|
|
3198
|
+
}
|
|
3199
|
+
if (options.hasLastRenderedPageBreakHints !== true) {
|
|
3200
|
+
return true;
|
|
3201
|
+
}
|
|
3202
|
+
return renderedBreakHintsSupportTarget;
|
|
3203
|
+
}
|
|
3204
|
+
function shouldLatchMeasuredBodyFooterOverlap(options) {
|
|
3205
|
+
if (options.measuredBodyFooterOverlap !== true) {
|
|
3206
|
+
return false;
|
|
3207
|
+
}
|
|
3208
|
+
const targetPageCount = Number.isFinite(options.targetPageCount) ? Math.max(1, Math.round(options.targetPageCount)) : void 0;
|
|
3209
|
+
if (targetPageCount === void 0) {
|
|
3210
|
+
return false;
|
|
3211
|
+
}
|
|
3212
|
+
const pageCount = Math.max(1, Math.round(options.pageCount));
|
|
3213
|
+
return pageCount <= targetPageCount;
|
|
3214
|
+
}
|
|
3215
|
+
function resolveMeasuredBodyFooterOverlapLatchState(options) {
|
|
3216
|
+
const shouldConsiderMeasuredBodyFooterOverlap = shouldLatchMeasuredBodyFooterOverlap({
|
|
3217
|
+
pageCount: options.pageCount,
|
|
3218
|
+
targetPageCount: options.targetPageCount,
|
|
3219
|
+
measuredBodyFooterOverlap: options.overlappingPageIndexes.length > 0
|
|
3220
|
+
});
|
|
3221
|
+
if (!shouldConsiderMeasuredBodyFooterOverlap) {
|
|
3222
|
+
return {
|
|
3223
|
+
signature: void 0,
|
|
3224
|
+
consecutivePasses: 0,
|
|
3225
|
+
shouldLatch: false
|
|
3226
|
+
};
|
|
3227
|
+
}
|
|
3228
|
+
const signature = options.overlappingPageIndexes.map((pageIndex) => `${pageIndex}`).join("|");
|
|
3229
|
+
const consecutivePasses = signature === options.previousSignature ? Math.max(0, Math.round(options.previousConsecutivePasses ?? 0)) + 1 : 1;
|
|
3230
|
+
const stabilityThreshold = Math.max(
|
|
3231
|
+
1,
|
|
3232
|
+
Math.round(options.stabilityThreshold ?? 1)
|
|
3233
|
+
);
|
|
3234
|
+
return {
|
|
3235
|
+
signature,
|
|
3236
|
+
consecutivePasses,
|
|
3237
|
+
shouldLatch: consecutivePasses >= stabilityThreshold
|
|
3238
|
+
};
|
|
3239
|
+
}
|
|
3240
|
+
function createEstimatedPagesBuildMemo(build) {
|
|
3241
|
+
const entries = [];
|
|
3242
|
+
return (measuredTableRowHeightsByNodeIndex, measuredPageContentHeightsPxByPageIndex, strictLastRenderedParagraphStartBreaks) => {
|
|
3243
|
+
const cached = entries.find(
|
|
3244
|
+
(entry) => entry.measuredTableRowHeightsByNodeIndex === measuredTableRowHeightsByNodeIndex && entry.measuredPageContentHeightsPxByPageIndex === measuredPageContentHeightsPxByPageIndex && entry.strictLastRenderedParagraphStartBreaks === strictLastRenderedParagraphStartBreaks
|
|
3245
|
+
);
|
|
3246
|
+
if (cached) {
|
|
3247
|
+
return cached.pages;
|
|
3248
|
+
}
|
|
3249
|
+
const pages = build(
|
|
3250
|
+
measuredTableRowHeightsByNodeIndex,
|
|
3251
|
+
measuredPageContentHeightsPxByPageIndex,
|
|
3252
|
+
strictLastRenderedParagraphStartBreaks
|
|
3253
|
+
);
|
|
3254
|
+
entries.push({
|
|
3255
|
+
measuredTableRowHeightsByNodeIndex,
|
|
3256
|
+
measuredPageContentHeightsPxByPageIndex,
|
|
3257
|
+
strictLastRenderedParagraphStartBreaks,
|
|
3258
|
+
pages
|
|
3259
|
+
});
|
|
3260
|
+
return pages;
|
|
3261
|
+
};
|
|
3262
|
+
}
|
|
3263
|
+
function resolveMeasuredSplitParagraphPageComparison(options) {
|
|
3264
|
+
if (options.canUndo || options.canRedo || !options.hasMeasuredPageContentHeights) {
|
|
3265
|
+
return {
|
|
3266
|
+
pages: options.measuredEstimatedPages,
|
|
3267
|
+
usedPureEstimatedPages: false
|
|
3268
|
+
};
|
|
3269
|
+
}
|
|
3270
|
+
const measuredPagesAreOnlySplitParagraphs = options.measuredEstimatedPages.length > 0 && options.measuredEstimatedPages.every(
|
|
3271
|
+
options.pageContainsOnlySplitParagraphSegments
|
|
3272
|
+
);
|
|
3273
|
+
if (!measuredPagesAreOnlySplitParagraphs) {
|
|
3274
|
+
return {
|
|
3275
|
+
pages: options.measuredEstimatedPages,
|
|
3276
|
+
usedPureEstimatedPages: false
|
|
3277
|
+
};
|
|
3278
|
+
}
|
|
3279
|
+
const pureEstimatedPages = options.buildPureEstimatedPages();
|
|
3280
|
+
const purePagesAreOnlySplitParagraphs = pureEstimatedPages.length > 0 && pureEstimatedPages.every(options.pageContainsOnlySplitParagraphSegments);
|
|
3281
|
+
if (purePagesAreOnlySplitParagraphs && pureEstimatedPages.length < options.measuredEstimatedPages.length) {
|
|
3282
|
+
return { pages: pureEstimatedPages, usedPureEstimatedPages: true };
|
|
3283
|
+
}
|
|
3284
|
+
return {
|
|
3285
|
+
pages: options.measuredEstimatedPages,
|
|
3286
|
+
usedPureEstimatedPages: false
|
|
3287
|
+
};
|
|
3288
|
+
}
|
|
3289
|
+
function isBetterCandidate(candidate, incumbent, targetPageCount) {
|
|
3290
|
+
const candidateDifference = Math.abs(candidate.pageCount - targetPageCount);
|
|
3291
|
+
const incumbentDifference = Math.abs(incumbent.pageCount - targetPageCount);
|
|
3292
|
+
if (candidateDifference !== incumbentDifference) {
|
|
3293
|
+
return candidateDifference < incumbentDifference;
|
|
3294
|
+
}
|
|
3295
|
+
const candidateScaleDelta = Math.abs(candidate.scale - 1);
|
|
3296
|
+
const incumbentScaleDelta = Math.abs(incumbent.scale - 1);
|
|
3297
|
+
if (candidateScaleDelta !== incumbentScaleDelta) {
|
|
3298
|
+
return candidateScaleDelta < incumbentScaleDelta;
|
|
3299
|
+
}
|
|
3300
|
+
return candidate.pageCount === targetPageCount && incumbent.pageCount !== targetPageCount;
|
|
3301
|
+
}
|
|
3302
|
+
function reconcilePageCountCandidateToTargetCountByScalingHeight(options) {
|
|
3303
|
+
const {
|
|
3304
|
+
initialPages,
|
|
3305
|
+
targetPageCount,
|
|
3306
|
+
buildPagesAtScale,
|
|
3307
|
+
maxDifference = 3,
|
|
3308
|
+
scales: customScales
|
|
3309
|
+
} = options;
|
|
3310
|
+
const safeTargetPageCount = Math.max(1, Math.round(targetPageCount));
|
|
3311
|
+
const initialPageCount = initialPages.length;
|
|
3312
|
+
const initialDifference = Math.abs(initialPageCount - safeTargetPageCount);
|
|
3313
|
+
if (initialDifference === 0 || initialDifference > maxDifference) {
|
|
3314
|
+
return {
|
|
3315
|
+
pageCount: initialPageCount,
|
|
3316
|
+
pages: initialPages,
|
|
3317
|
+
scale: 1
|
|
3318
|
+
};
|
|
3319
|
+
}
|
|
3320
|
+
const bestCandidate = {
|
|
3321
|
+
pageCount: initialPageCount,
|
|
3322
|
+
pages: initialPages,
|
|
3323
|
+
scale: 1
|
|
3324
|
+
};
|
|
3325
|
+
let selectedCandidate = bestCandidate;
|
|
3326
|
+
const needMorePages = initialPageCount < safeTargetPageCount;
|
|
3327
|
+
const scales = customScales && customScales.length > 0 ? customScales : needMorePages ? [
|
|
3328
|
+
0.98,
|
|
3329
|
+
0.96,
|
|
3330
|
+
0.94,
|
|
3331
|
+
0.92,
|
|
3332
|
+
0.9,
|
|
3333
|
+
0.88,
|
|
3334
|
+
0.86,
|
|
3335
|
+
0.84,
|
|
3336
|
+
0.82,
|
|
3337
|
+
0.8,
|
|
3338
|
+
0.78,
|
|
3339
|
+
0.76,
|
|
3340
|
+
0.74,
|
|
3341
|
+
0.72,
|
|
3342
|
+
0.7,
|
|
3343
|
+
0.68,
|
|
3344
|
+
0.66,
|
|
3345
|
+
0.64,
|
|
3346
|
+
0.62,
|
|
3347
|
+
0.6,
|
|
3348
|
+
0.58,
|
|
3349
|
+
0.56,
|
|
3350
|
+
0.54,
|
|
3351
|
+
0.52,
|
|
3352
|
+
0.5,
|
|
3353
|
+
0.48,
|
|
3354
|
+
0.46,
|
|
3355
|
+
0.44,
|
|
3356
|
+
0.42,
|
|
3357
|
+
0.4,
|
|
3358
|
+
0.38,
|
|
3359
|
+
0.36,
|
|
3360
|
+
0.34,
|
|
3361
|
+
0.32,
|
|
3362
|
+
0.3,
|
|
3363
|
+
0.28,
|
|
3364
|
+
0.26,
|
|
3365
|
+
0.24,
|
|
3366
|
+
0.22,
|
|
3367
|
+
0.2
|
|
3368
|
+
] : [
|
|
3369
|
+
1.02,
|
|
3370
|
+
1.04,
|
|
3371
|
+
1.06,
|
|
3372
|
+
1.08,
|
|
3373
|
+
1.1,
|
|
3374
|
+
1.12,
|
|
3375
|
+
1.14,
|
|
3376
|
+
1.16,
|
|
3377
|
+
1.18,
|
|
3378
|
+
1.2,
|
|
3379
|
+
1.22,
|
|
3380
|
+
1.24,
|
|
3381
|
+
1.26,
|
|
3382
|
+
1.28,
|
|
3383
|
+
1.3
|
|
3384
|
+
];
|
|
3385
|
+
const buildCandidateAtScale = (scale) => {
|
|
3386
|
+
const pages = buildPagesAtScale(scale);
|
|
3387
|
+
return {
|
|
3388
|
+
pageCount: pages.length,
|
|
3389
|
+
pages,
|
|
3390
|
+
scale
|
|
3391
|
+
};
|
|
3392
|
+
};
|
|
3393
|
+
const refineExactTargetCandidate = (lowerScale, upperScale) => {
|
|
3394
|
+
let bestExactCandidate;
|
|
3395
|
+
const interval = upperScale - lowerScale;
|
|
3396
|
+
if (!Number.isFinite(interval) || Math.abs(interval) < 1e-4) {
|
|
3397
|
+
return selectedCandidate;
|
|
3398
|
+
}
|
|
3399
|
+
for (let step = 1; step <= PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS; step += 1) {
|
|
3400
|
+
const scale = lowerScale + interval * step / PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS;
|
|
3401
|
+
const candidate = buildCandidateAtScale(scale);
|
|
3402
|
+
if (isBetterCandidate(candidate, selectedCandidate, safeTargetPageCount)) {
|
|
3403
|
+
selectedCandidate = candidate;
|
|
3404
|
+
}
|
|
3405
|
+
if (candidate.pageCount === safeTargetPageCount && (bestExactCandidate === void 0 || isBetterCandidate(
|
|
3406
|
+
candidate,
|
|
3407
|
+
bestExactCandidate,
|
|
3408
|
+
safeTargetPageCount
|
|
3409
|
+
))) {
|
|
3410
|
+
bestExactCandidate = candidate;
|
|
3411
|
+
}
|
|
3412
|
+
}
|
|
3413
|
+
return bestExactCandidate ?? selectedCandidate;
|
|
3414
|
+
};
|
|
3415
|
+
let previousScale = 1;
|
|
3416
|
+
let previousPageCount = initialPageCount;
|
|
3417
|
+
for (const scale of scales) {
|
|
3418
|
+
const candidate = buildCandidateAtScale(scale);
|
|
3419
|
+
if (isBetterCandidate(candidate, selectedCandidate, safeTargetPageCount)) {
|
|
3420
|
+
selectedCandidate = candidate;
|
|
3421
|
+
}
|
|
3422
|
+
if (candidate.pageCount === safeTargetPageCount) {
|
|
3423
|
+
const crossedIntoExactTarget = needMorePages ? previousPageCount < safeTargetPageCount : previousPageCount > safeTargetPageCount;
|
|
3424
|
+
if (crossedIntoExactTarget) {
|
|
3425
|
+
return refineExactTargetCandidate(previousScale, scale);
|
|
3426
|
+
}
|
|
3427
|
+
return candidate;
|
|
3428
|
+
}
|
|
3429
|
+
previousScale = scale;
|
|
3430
|
+
previousPageCount = candidate.pageCount;
|
|
3431
|
+
}
|
|
3432
|
+
if (!needMorePages && selectedCandidate.pageCount !== safeTargetPageCount) {
|
|
3433
|
+
return {
|
|
3434
|
+
pageCount: initialPageCount,
|
|
3435
|
+
pages: initialPages,
|
|
3436
|
+
scale: 1
|
|
3437
|
+
};
|
|
3438
|
+
}
|
|
3439
|
+
return selectedCandidate;
|
|
3440
|
+
}
|
|
3441
|
+
|
|
3442
|
+
// src/section-layout.ts
|
|
3443
|
+
var DEFAULT_DOC_PAGE_WIDTH = 900;
|
|
3444
|
+
var DEFAULT_DOC_PAGE_HEIGHT = 1200;
|
|
3445
|
+
var DEFAULT_DOC_PAGE_MARGIN = 56;
|
|
3446
|
+
var TWIPS_PER_PIXEL = 15;
|
|
3447
|
+
var DEFAULT_DOCUMENT_LAYOUT = {
|
|
3448
|
+
pageWidthPx: DEFAULT_DOC_PAGE_WIDTH,
|
|
3449
|
+
pageHeightPx: DEFAULT_DOC_PAGE_HEIGHT,
|
|
3450
|
+
marginsPx: {
|
|
3451
|
+
top: DEFAULT_DOC_PAGE_MARGIN,
|
|
3452
|
+
right: DEFAULT_DOC_PAGE_MARGIN,
|
|
3453
|
+
bottom: DEFAULT_DOC_PAGE_MARGIN,
|
|
3454
|
+
left: DEFAULT_DOC_PAGE_MARGIN
|
|
3455
|
+
},
|
|
3456
|
+
headerDistancePx: DEFAULT_DOC_PAGE_MARGIN,
|
|
3457
|
+
footerDistancePx: DEFAULT_DOC_PAGE_MARGIN,
|
|
3458
|
+
docGridLinePitchPx: void 0
|
|
3459
|
+
};
|
|
3460
|
+
function pageMarginPaddingStyle(marginsPx) {
|
|
3461
|
+
return {
|
|
3462
|
+
paddingTop: marginsPx.top,
|
|
3463
|
+
paddingRight: marginsPx.right,
|
|
3464
|
+
paddingBottom: marginsPx.bottom,
|
|
3465
|
+
paddingLeft: marginsPx.left
|
|
3466
|
+
};
|
|
3467
|
+
}
|
|
3468
|
+
function twipsToPixels(twips) {
|
|
3469
|
+
if (!Number.isFinite(twips)) {
|
|
3470
|
+
return void 0;
|
|
3471
|
+
}
|
|
3472
|
+
return Math.max(0, Math.round(twips / TWIPS_PER_PIXEL));
|
|
3473
|
+
}
|
|
3474
|
+
function readTwipsAttribute(tagXml, attribute) {
|
|
3475
|
+
if (!tagXml) {
|
|
3476
|
+
return void 0;
|
|
3477
|
+
}
|
|
3478
|
+
const match = tagXml.match(new RegExp(`${attribute}="(\\d+)"`, "i"));
|
|
3479
|
+
if (!match?.[1]) {
|
|
3480
|
+
return void 0;
|
|
3481
|
+
}
|
|
3482
|
+
const parsed = Number(match[1]);
|
|
3483
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
3484
|
+
}
|
|
3485
|
+
function readStringAttribute(tagXml, attribute) {
|
|
3486
|
+
if (!tagXml) {
|
|
3487
|
+
return void 0;
|
|
3488
|
+
}
|
|
3489
|
+
return tagXml.match(new RegExp(`${attribute}="([^"]+)"`, "i"))?.[1];
|
|
3490
|
+
}
|
|
3491
|
+
function resolvePageSizeForOrientation(params) {
|
|
3492
|
+
const normalizedOrientation = params.orientation?.trim().toLowerCase();
|
|
3493
|
+
const widthPx = Math.max(1, params.widthPx);
|
|
3494
|
+
const heightPx = Math.max(1, params.heightPx);
|
|
3495
|
+
if (normalizedOrientation === "landscape" && widthPx < heightPx) {
|
|
3496
|
+
return { widthPx: heightPx, heightPx: widthPx };
|
|
3497
|
+
}
|
|
3498
|
+
if (normalizedOrientation === "portrait" && widthPx > heightPx) {
|
|
3499
|
+
return { widthPx: heightPx, heightPx: widthPx };
|
|
3500
|
+
}
|
|
3501
|
+
return { widthPx, heightPx };
|
|
3502
|
+
}
|
|
3503
|
+
function normalizeHexColor(value) {
|
|
3504
|
+
if (!value) {
|
|
3505
|
+
return void 0;
|
|
3506
|
+
}
|
|
3507
|
+
const normalized = value.trim();
|
|
3508
|
+
if (!normalized || normalized.toLowerCase() === "auto") {
|
|
3509
|
+
return void 0;
|
|
3510
|
+
}
|
|
3511
|
+
if (/^[0-9a-fA-F]{6}$/.test(normalized)) {
|
|
3512
|
+
return `#${normalized}`;
|
|
3513
|
+
}
|
|
3514
|
+
if (/^#[0-9a-fA-F]{6}$/.test(normalized)) {
|
|
3515
|
+
return normalized;
|
|
3516
|
+
}
|
|
3517
|
+
return void 0;
|
|
3522
3518
|
}
|
|
3523
|
-
function
|
|
3524
|
-
|
|
3519
|
+
function borderTypeToCssStyle(rawType) {
|
|
3520
|
+
const value = rawType?.trim().toLowerCase();
|
|
3521
|
+
if (!value || value === "none" || value === "nil") {
|
|
3525
3522
|
return void 0;
|
|
3526
3523
|
}
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
`${paragraphTexts[boundaryParagraphIndex - 1]}${paragraphTexts[boundaryParagraphIndex]}`,
|
|
3530
|
-
...paragraphTexts.slice(boundaryParagraphIndex + 1)
|
|
3531
|
-
];
|
|
3532
|
-
const cellText = mergedTexts.join("\n");
|
|
3533
|
-
let caretGlobalOffset = 0;
|
|
3534
|
-
for (let index = 0; index < boundaryParagraphIndex - 1; index += 1) {
|
|
3535
|
-
caretGlobalOffset += paragraphTexts[index].length + 1;
|
|
3524
|
+
if (value === "double") {
|
|
3525
|
+
return "double";
|
|
3536
3526
|
}
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3527
|
+
if (value === "dashed" || value === "dashsmallgap" || value === "dotdash" || value === "dotdotdash") {
|
|
3528
|
+
return "dashed";
|
|
3529
|
+
}
|
|
3530
|
+
if (value === "dotted") {
|
|
3531
|
+
return "dotted";
|
|
3532
|
+
}
|
|
3533
|
+
return "solid";
|
|
3534
|
+
}
|
|
3535
|
+
function pointsToPixels(points) {
|
|
3536
|
+
if (!Number.isFinite(points)) {
|
|
3537
|
+
return void 0;
|
|
3538
|
+
}
|
|
3539
|
+
return Math.max(0, Math.round(points * (96 / 72)));
|
|
3540
|
+
}
|
|
3541
|
+
function parseSectionPageBorderEdge(sectionPropertiesXml, edge) {
|
|
3542
|
+
if (!sectionPropertiesXml) {
|
|
3543
|
+
return void 0;
|
|
3544
|
+
}
|
|
3545
|
+
const bordersXml = sectionPropertiesXml.match(
|
|
3546
|
+
/<w:pgBorders\b[\s\S]*?<\/w:pgBorders>/i
|
|
3547
|
+
)?.[0];
|
|
3548
|
+
if (!bordersXml) {
|
|
3549
|
+
return void 0;
|
|
3550
|
+
}
|
|
3551
|
+
const edgeTag = bordersXml.match(new RegExp(`<w:${edge}\\b[^>]*/?>`, "i"))?.[0];
|
|
3552
|
+
if (!edgeTag) {
|
|
3553
|
+
return void 0;
|
|
3554
|
+
}
|
|
3555
|
+
const cssStyle = borderTypeToCssStyle(readStringAttribute(edgeTag, "w:val"));
|
|
3556
|
+
if (!cssStyle) {
|
|
3557
|
+
return void 0;
|
|
3544
3558
|
}
|
|
3559
|
+
const sizeEighthPt = Number(readStringAttribute(edgeTag, "w:sz"));
|
|
3560
|
+
const widthPx = Number.isFinite(sizeEighthPt) && sizeEighthPt > 0 ? Math.max(0.5, Number((sizeEighthPt / 6).toFixed(2))) : 1;
|
|
3561
|
+
const color = normalizeHexColor(readStringAttribute(edgeTag, "w:color")) ?? "#000000";
|
|
3562
|
+
const offsetPoints = Number(readStringAttribute(edgeTag, "w:space"));
|
|
3545
3563
|
return {
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3564
|
+
cssBorder: `${widthPx}px ${cssStyle} ${color}`,
|
|
3565
|
+
offsetPx: pointsToPixels(offsetPoints) ?? 0,
|
|
3566
|
+
shadow: readStringAttribute(edgeTag, "w:shadow")?.trim().toLowerCase() === "1" || readStringAttribute(edgeTag, "w:shadow")?.trim().toLowerCase() === "true"
|
|
3549
3567
|
};
|
|
3550
3568
|
}
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
var PAGE_BREAK_BEFORE_XML_PATTERN = /<w:pageBreakBefore\b[^>]*\/?>/i;
|
|
3555
|
-
var tableExplicitPageBreakInfoBySourceXml = /* @__PURE__ */ new Map();
|
|
3556
|
-
function isOnOffTagEnabled(tagXml) {
|
|
3557
|
-
if (!tagXml) {
|
|
3558
|
-
return false;
|
|
3569
|
+
function parseSectionPageBorders(sectionPropertiesXml) {
|
|
3570
|
+
if (!sectionPropertiesXml || !/<w:pgBorders\b/i.test(sectionPropertiesXml)) {
|
|
3571
|
+
return void 0;
|
|
3559
3572
|
}
|
|
3560
|
-
const
|
|
3561
|
-
|
|
3562
|
-
|
|
3573
|
+
const borders = {
|
|
3574
|
+
top: parseSectionPageBorderEdge(sectionPropertiesXml, "top"),
|
|
3575
|
+
right: parseSectionPageBorderEdge(sectionPropertiesXml, "right"),
|
|
3576
|
+
bottom: parseSectionPageBorderEdge(sectionPropertiesXml, "bottom"),
|
|
3577
|
+
left: parseSectionPageBorderEdge(sectionPropertiesXml, "left")
|
|
3578
|
+
};
|
|
3579
|
+
return borders.top || borders.right || borders.bottom || borders.left ? borders : void 0;
|
|
3580
|
+
}
|
|
3581
|
+
function parseSectionLayout(sectionPropertiesXml) {
|
|
3582
|
+
if (!sectionPropertiesXml) {
|
|
3583
|
+
return DEFAULT_DOCUMENT_LAYOUT;
|
|
3563
3584
|
}
|
|
3564
|
-
|
|
3585
|
+
const pageSizeTag = sectionPropertiesXml.match(/<w:pgSz\b[^>]*>/i)?.[0];
|
|
3586
|
+
const pageMarginTag = sectionPropertiesXml.match(/<w:pgMar\b[^>]*>/i)?.[0];
|
|
3587
|
+
const docGridTag = sectionPropertiesXml.match(/<w:docGrid\b[^>]*\/?>/i)?.[0];
|
|
3588
|
+
const rawPageWidthPx = twipsToPixels(readTwipsAttribute(pageSizeTag, "w:w")) ?? DEFAULT_DOCUMENT_LAYOUT.pageWidthPx;
|
|
3589
|
+
const rawPageHeightPx = twipsToPixels(readTwipsAttribute(pageSizeTag, "w:h")) ?? DEFAULT_DOCUMENT_LAYOUT.pageHeightPx;
|
|
3590
|
+
const pageSize = resolvePageSizeForOrientation({
|
|
3591
|
+
widthPx: rawPageWidthPx,
|
|
3592
|
+
heightPx: rawPageHeightPx,
|
|
3593
|
+
orientation: readStringAttribute(pageSizeTag, "w:orient")
|
|
3594
|
+
});
|
|
3595
|
+
const topMarginPx = twipsToPixels(readTwipsAttribute(pageMarginTag, "w:top")) ?? DEFAULT_DOCUMENT_LAYOUT.marginsPx.top;
|
|
3596
|
+
const rightMarginPx = twipsToPixels(readTwipsAttribute(pageMarginTag, "w:right")) ?? DEFAULT_DOCUMENT_LAYOUT.marginsPx.right;
|
|
3597
|
+
const bottomMarginPx = twipsToPixels(readTwipsAttribute(pageMarginTag, "w:bottom")) ?? DEFAULT_DOCUMENT_LAYOUT.marginsPx.bottom;
|
|
3598
|
+
const leftMarginPx = twipsToPixels(readTwipsAttribute(pageMarginTag, "w:left")) ?? DEFAULT_DOCUMENT_LAYOUT.marginsPx.left;
|
|
3599
|
+
const headerDistancePx = twipsToPixels(readTwipsAttribute(pageMarginTag, "w:header")) ?? DEFAULT_DOCUMENT_LAYOUT.headerDistancePx;
|
|
3600
|
+
const footerDistancePx = twipsToPixels(readTwipsAttribute(pageMarginTag, "w:footer")) ?? DEFAULT_DOCUMENT_LAYOUT.footerDistancePx;
|
|
3601
|
+
const docGridType = readStringAttribute(docGridTag, "w:type")?.toLowerCase();
|
|
3602
|
+
const docGridLinePitchPx = docGridType === "lines" || docGridType === "linesandchars" || docGridType === "snaptochars" ? twipsToPixels(readTwipsAttribute(docGridTag, "w:linePitch")) ?? DEFAULT_DOCUMENT_LAYOUT.docGridLinePitchPx : DEFAULT_DOCUMENT_LAYOUT.docGridLinePitchPx;
|
|
3603
|
+
return {
|
|
3604
|
+
pageWidthPx: pageSize.widthPx,
|
|
3605
|
+
pageHeightPx: pageSize.heightPx,
|
|
3606
|
+
marginsPx: {
|
|
3607
|
+
top: topMarginPx,
|
|
3608
|
+
right: rightMarginPx,
|
|
3609
|
+
bottom: bottomMarginPx,
|
|
3610
|
+
left: leftMarginPx
|
|
3611
|
+
},
|
|
3612
|
+
headerDistancePx,
|
|
3613
|
+
footerDistancePx,
|
|
3614
|
+
docGridLinePitchPx
|
|
3615
|
+
};
|
|
3565
3616
|
}
|
|
3566
|
-
function
|
|
3567
|
-
|
|
3568
|
-
return sourceXml.length > 0 && PAGE_BREAK_XML_PATTERN.test(sourceXml);
|
|
3617
|
+
function resolveDocumentSectionPropertiesXml(model) {
|
|
3618
|
+
return model.metadata.sections?.[0]?.sectionPropertiesXml ?? model.metadata.sectionPropertiesXml;
|
|
3569
3619
|
}
|
|
3570
|
-
function
|
|
3571
|
-
|
|
3620
|
+
function resolveDocumentLayout(model) {
|
|
3621
|
+
return parseSectionLayout(resolveDocumentSectionPropertiesXml(model));
|
|
3622
|
+
}
|
|
3623
|
+
|
|
3624
|
+
// src/image-render.ts
|
|
3625
|
+
import { encode as encodePng } from "fast-png";
|
|
3626
|
+
import UTIFModule from "utif";
|
|
3627
|
+
var TIFF_CONTENT_TYPES = /* @__PURE__ */ new Set(["image/tiff", "image/tif"]);
|
|
3628
|
+
var PLACEHOLDER_FALLBACK_CONTENT_TYPES = /* @__PURE__ */ new Set([
|
|
3629
|
+
"image/x-emf",
|
|
3630
|
+
"image/emf",
|
|
3631
|
+
"image/x-wmf",
|
|
3632
|
+
"image/wmf"
|
|
3633
|
+
]);
|
|
3634
|
+
var TIFF_DATA_URI_PREFIXES = ["data:image/tiff", "data:image/tif"];
|
|
3635
|
+
var EMF_DATA_URI_PREFIXES = ["data:image/emf", "data:image/x-emf"];
|
|
3636
|
+
var WMF_DATA_URI_PREFIXES = ["data:image/wmf", "data:image/x-wmf"];
|
|
3637
|
+
var UTIF = UTIFModule;
|
|
3638
|
+
var convertedTiffSrcCache = /* @__PURE__ */ new Map();
|
|
3639
|
+
function normalizeImageContentType(image) {
|
|
3640
|
+
return image.contentType?.trim().toLowerCase();
|
|
3641
|
+
}
|
|
3642
|
+
function normalizeImageSrc(image) {
|
|
3643
|
+
return image.src?.trim();
|
|
3644
|
+
}
|
|
3645
|
+
function imageHasTiffContent(image) {
|
|
3646
|
+
const contentType = normalizeImageContentType(image);
|
|
3647
|
+
if (contentType && TIFF_CONTENT_TYPES.has(contentType)) {
|
|
3572
3648
|
return true;
|
|
3573
3649
|
}
|
|
3574
|
-
const
|
|
3575
|
-
|
|
3576
|
-
return false;
|
|
3577
|
-
}
|
|
3578
|
-
return isOnOffTagEnabled(sourceXml.match(PAGE_BREAK_BEFORE_XML_PATTERN)?.[0]);
|
|
3650
|
+
const src = normalizeImageSrc(image)?.toLowerCase();
|
|
3651
|
+
return Boolean(src && TIFF_DATA_URI_PREFIXES.some((prefix) => src.startsWith(prefix)));
|
|
3579
3652
|
}
|
|
3580
|
-
function
|
|
3581
|
-
|
|
3582
|
-
|
|
3653
|
+
function imageHasMetafileContent(image) {
|
|
3654
|
+
const contentType = normalizeImageContentType(image);
|
|
3655
|
+
if (contentType && PLACEHOLDER_FALLBACK_CONTENT_TYPES.has(contentType)) {
|
|
3656
|
+
return true;
|
|
3657
|
+
}
|
|
3658
|
+
const src = normalizeImageSrc(image)?.toLowerCase();
|
|
3659
|
+
return Boolean(
|
|
3660
|
+
src && (EMF_DATA_URI_PREFIXES.some((prefix) => src.startsWith(prefix)) || WMF_DATA_URI_PREFIXES.some((prefix) => src.startsWith(prefix)))
|
|
3583
3661
|
);
|
|
3584
3662
|
}
|
|
3585
|
-
function
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3663
|
+
function imageUsesEmfContent(image) {
|
|
3664
|
+
const contentType = normalizeImageContentType(image);
|
|
3665
|
+
if (contentType === "image/x-emf" || contentType === "image/emf") {
|
|
3666
|
+
return true;
|
|
3667
|
+
}
|
|
3668
|
+
const src = normalizeImageSrc(image)?.toLowerCase();
|
|
3669
|
+
return Boolean(src && EMF_DATA_URI_PREFIXES.some((prefix) => src.startsWith(prefix)));
|
|
3590
3670
|
}
|
|
3591
|
-
function
|
|
3592
|
-
|
|
3671
|
+
function imageUsesWmfContent(image) {
|
|
3672
|
+
const contentType = normalizeImageContentType(image);
|
|
3673
|
+
if (contentType === "image/x-wmf" || contentType === "image/wmf") {
|
|
3674
|
+
return true;
|
|
3675
|
+
}
|
|
3676
|
+
const src = normalizeImageSrc(image)?.toLowerCase();
|
|
3677
|
+
return Boolean(src && WMF_DATA_URI_PREFIXES.some((prefix) => src.startsWith(prefix)));
|
|
3593
3678
|
}
|
|
3594
|
-
function
|
|
3595
|
-
return
|
|
3679
|
+
function imageUsesPlaceholderFallback(image) {
|
|
3680
|
+
return imageHasMetafileContent(image);
|
|
3596
3681
|
}
|
|
3597
|
-
function
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3682
|
+
function unsupportedImageFallbackLabel(image, widthPx, heightPx) {
|
|
3683
|
+
const isSmallIcon = (widthPx ?? 0) <= 56 && (heightPx ?? 0) <= 56;
|
|
3684
|
+
if (imageUsesEmfContent(image)) {
|
|
3685
|
+
return isSmallIcon ? "e" : "EMF";
|
|
3686
|
+
}
|
|
3687
|
+
if (imageUsesWmfContent(image)) {
|
|
3688
|
+
return isSmallIcon ? "w" : "WMF";
|
|
3689
|
+
}
|
|
3690
|
+
return isSmallIcon ? "e" : "TIFF";
|
|
3606
3691
|
}
|
|
3607
|
-
function
|
|
3608
|
-
const
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3692
|
+
function dataUriToBytes(dataUri) {
|
|
3693
|
+
const match = dataUri.match(/^data:([^;]+);base64,(.+)$/i);
|
|
3694
|
+
if (!match) {
|
|
3695
|
+
return void 0;
|
|
3696
|
+
}
|
|
3697
|
+
const [, , base64] = match;
|
|
3698
|
+
if (typeof Buffer !== "undefined") {
|
|
3699
|
+
return new Uint8Array(Buffer.from(base64, "base64"));
|
|
3700
|
+
}
|
|
3701
|
+
if (typeof atob !== "function") {
|
|
3702
|
+
return void 0;
|
|
3703
|
+
}
|
|
3704
|
+
const binary = atob(base64);
|
|
3705
|
+
const bytes = new Uint8Array(binary.length);
|
|
3706
|
+
for (let index = 0; index < binary.length; index += 1) {
|
|
3707
|
+
bytes[index] = binary.charCodeAt(index);
|
|
3708
|
+
}
|
|
3709
|
+
return bytes;
|
|
3621
3710
|
}
|
|
3622
|
-
function
|
|
3623
|
-
if (
|
|
3624
|
-
return
|
|
3711
|
+
function bytesToBase64(bytes) {
|
|
3712
|
+
if (typeof Buffer !== "undefined") {
|
|
3713
|
+
return Buffer.from(bytes).toString("base64");
|
|
3625
3714
|
}
|
|
3626
|
-
|
|
3627
|
-
|
|
3715
|
+
if (typeof btoa !== "function") {
|
|
3716
|
+
return void 0;
|
|
3717
|
+
}
|
|
3718
|
+
let binary = "";
|
|
3719
|
+
const chunkSize = 32768;
|
|
3720
|
+
for (let index = 0; index < bytes.byteLength; index += chunkSize) {
|
|
3721
|
+
const chunk = bytes.subarray(index, index + chunkSize);
|
|
3722
|
+
binary += String.fromCharCode(...chunk);
|
|
3723
|
+
}
|
|
3724
|
+
return btoa(binary);
|
|
3628
3725
|
}
|
|
3629
|
-
function
|
|
3630
|
-
const
|
|
3631
|
-
if (
|
|
3632
|
-
|
|
3633
|
-
if (cached) {
|
|
3634
|
-
return cached;
|
|
3635
|
-
}
|
|
3726
|
+
function toArrayBuffer(bytes) {
|
|
3727
|
+
const { buffer, byteOffset, byteLength } = bytes;
|
|
3728
|
+
if (byteOffset === 0 && byteLength === buffer.byteLength) {
|
|
3729
|
+
return buffer;
|
|
3636
3730
|
}
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
tableCellDirectParagraphs(cell.nodes).forEach((paragraph) => {
|
|
3643
|
-
if (!paragraphHasExplicitPageBreak(paragraph)) {
|
|
3644
|
-
return;
|
|
3645
|
-
}
|
|
3646
|
-
if (paragraphIsOnlyExplicitPageBreak(paragraph) && rowIndex === 0 && tableRowHasSubstantiveContentOutsideBreakOnlyParagraphs(row) && !tableRowUsesTrailingSignatureCellBreakPattern(table, row)) {
|
|
3647
|
-
return;
|
|
3648
|
-
}
|
|
3649
|
-
const breakTarget = paragraphIsOnlyExplicitPageBreak(paragraph) ? rowIndex : rowIndex + 1;
|
|
3650
|
-
if (rowBreakTarget === void 0 || breakTarget < rowBreakTarget) {
|
|
3651
|
-
rowBreakTarget = breakTarget;
|
|
3652
|
-
}
|
|
3653
|
-
});
|
|
3654
|
-
});
|
|
3655
|
-
if (rowBreakTarget === void 0) {
|
|
3656
|
-
return;
|
|
3657
|
-
}
|
|
3658
|
-
if (rowBreakTarget >= table.rows.length) {
|
|
3659
|
-
breakAfterTable = true;
|
|
3660
|
-
return;
|
|
3661
|
-
}
|
|
3662
|
-
startRowIndexes.add(Math.max(0, rowBreakTarget));
|
|
3663
|
-
});
|
|
3664
|
-
const info = {
|
|
3665
|
-
startRowIndexes: [...startRowIndexes].sort((left, right) => left - right),
|
|
3666
|
-
breakAfterTable
|
|
3667
|
-
};
|
|
3668
|
-
if (sourceXml) {
|
|
3669
|
-
tableExplicitPageBreakInfoBySourceXml.set(sourceXml, info);
|
|
3731
|
+
return buffer.slice(byteOffset, byteOffset + byteLength);
|
|
3732
|
+
}
|
|
3733
|
+
function resolveTiffBytes(image) {
|
|
3734
|
+
if (image.data?.byteLength) {
|
|
3735
|
+
return image.data;
|
|
3670
3736
|
}
|
|
3671
|
-
|
|
3737
|
+
const src = normalizeImageSrc(image);
|
|
3738
|
+
return src ? dataUriToBytes(src) : void 0;
|
|
3672
3739
|
}
|
|
3673
|
-
function
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3740
|
+
function selectPrimaryTiffPage(ifds) {
|
|
3741
|
+
if (ifds.length === 0) {
|
|
3742
|
+
return void 0;
|
|
3743
|
+
}
|
|
3744
|
+
let candidates = ifds;
|
|
3745
|
+
if (Array.isArray(ifds[0]?.subIFD) && ifds[0].subIFD.length > 0) {
|
|
3746
|
+
candidates = candidates.concat(ifds[0].subIFD);
|
|
3747
|
+
}
|
|
3748
|
+
let best;
|
|
3749
|
+
let maxArea = -1;
|
|
3750
|
+
for (const candidate of candidates) {
|
|
3751
|
+
const width = candidate.width ?? candidate.t256 ?? 0;
|
|
3752
|
+
const height = candidate.height ?? candidate.t257 ?? 0;
|
|
3753
|
+
if (!width || !height) {
|
|
3685
3754
|
continue;
|
|
3686
3755
|
}
|
|
3687
|
-
const
|
|
3688
|
-
if (
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
if (hasNextNode && tableBreakInfo.breakAfterTable) {
|
|
3692
|
-
breaks.add(nodeIndex + 1);
|
|
3756
|
+
const area = width * height;
|
|
3757
|
+
if (best === void 0 || area > maxArea) {
|
|
3758
|
+
best = candidate;
|
|
3759
|
+
maxArea = area;
|
|
3693
3760
|
}
|
|
3694
3761
|
}
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3762
|
+
return best ?? ifds[0];
|
|
3763
|
+
}
|
|
3764
|
+
function convertTiffToPngDataUri(bytes) {
|
|
3765
|
+
const tiffBuffer = toArrayBuffer(bytes);
|
|
3766
|
+
const ifds = UTIF.decode(tiffBuffer);
|
|
3767
|
+
const page = selectPrimaryTiffPage(ifds);
|
|
3768
|
+
if (!page) {
|
|
3769
|
+
return void 0;
|
|
3699
3770
|
}
|
|
3700
|
-
|
|
3771
|
+
UTIF.decodeImage(tiffBuffer, page, ifds);
|
|
3772
|
+
const width = page.width ?? page.t256 ?? 0;
|
|
3773
|
+
const height = page.height ?? page.t257 ?? 0;
|
|
3774
|
+
const rgba = UTIF.toRGBA8(page);
|
|
3775
|
+
if (!width || !height || rgba.byteLength !== width * height * 4) {
|
|
3776
|
+
return void 0;
|
|
3777
|
+
}
|
|
3778
|
+
const pngBytes = encodePng({
|
|
3779
|
+
width,
|
|
3780
|
+
height,
|
|
3781
|
+
data: rgba,
|
|
3782
|
+
channels: 4,
|
|
3783
|
+
depth: 8
|
|
3784
|
+
});
|
|
3785
|
+
const base64 = bytesToBase64(pngBytes);
|
|
3786
|
+
return base64 ? `data:image/png;base64,${base64}` : void 0;
|
|
3701
3787
|
}
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
const estimatedPageCount = Math.max(
|
|
3707
|
-
1,
|
|
3708
|
-
Math.round(options.estimatedPageCount)
|
|
3709
|
-
);
|
|
3710
|
-
const targetPageCount = Math.max(1, Math.round(options.targetPageCount));
|
|
3711
|
-
if (targetPageCount >= estimatedPageCount) {
|
|
3712
|
-
return true;
|
|
3788
|
+
function resolveRenderableImageSource(image) {
|
|
3789
|
+
const src = normalizeImageSrc(image);
|
|
3790
|
+
if (!src) {
|
|
3791
|
+
return void 0;
|
|
3713
3792
|
}
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
) ? Math.max(1, Math.round(options.renderedBreakHintPageCount)) : void 0;
|
|
3717
|
-
const renderedBreakHintsSupportTarget = options.hasLastRenderedPageBreakHints === true && renderedBreakHintPageCount !== void 0 && targetPageCount >= renderedBreakHintPageCount;
|
|
3718
|
-
if (options.hasMeasuredBodyFooterOverlap === true) {
|
|
3719
|
-
return renderedBreakHintsSupportTarget;
|
|
3793
|
+
if (imageHasMetafileContent(image)) {
|
|
3794
|
+
return void 0;
|
|
3720
3795
|
}
|
|
3721
|
-
if (
|
|
3722
|
-
return
|
|
3796
|
+
if (!imageHasTiffContent(image)) {
|
|
3797
|
+
return src;
|
|
3723
3798
|
}
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
if (options.measuredBodyFooterOverlap !== true) {
|
|
3728
|
-
return false;
|
|
3799
|
+
const cached = convertedTiffSrcCache.get(src);
|
|
3800
|
+
if (cached !== void 0 || convertedTiffSrcCache.has(src)) {
|
|
3801
|
+
return cached;
|
|
3729
3802
|
}
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3803
|
+
let converted;
|
|
3804
|
+
try {
|
|
3805
|
+
const bytes = resolveTiffBytes(image);
|
|
3806
|
+
if (bytes) {
|
|
3807
|
+
converted = convertTiffToPngDataUri(bytes);
|
|
3808
|
+
}
|
|
3809
|
+
} catch {
|
|
3810
|
+
converted = void 0;
|
|
3733
3811
|
}
|
|
3734
|
-
|
|
3735
|
-
return
|
|
3812
|
+
convertedTiffSrcCache.set(src, converted);
|
|
3813
|
+
return converted;
|
|
3736
3814
|
}
|
|
3737
|
-
function
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
targetPageCount: options.targetPageCount,
|
|
3741
|
-
measuredBodyFooterOverlap: options.overlappingPageIndexes.length > 0
|
|
3742
|
-
});
|
|
3743
|
-
if (!shouldConsiderMeasuredBodyFooterOverlap) {
|
|
3744
|
-
return {
|
|
3745
|
-
signature: void 0,
|
|
3746
|
-
consecutivePasses: 0,
|
|
3747
|
-
shouldLatch: false
|
|
3748
|
-
};
|
|
3749
|
-
}
|
|
3750
|
-
const signature = options.overlappingPageIndexes.map((pageIndex) => `${pageIndex}`).join("|");
|
|
3751
|
-
const consecutivePasses = signature === options.previousSignature ? Math.max(0, Math.round(options.previousConsecutivePasses ?? 0)) + 1 : 1;
|
|
3752
|
-
const stabilityThreshold = Math.max(
|
|
3753
|
-
1,
|
|
3754
|
-
Math.round(options.stabilityThreshold ?? 1)
|
|
3755
|
-
);
|
|
3756
|
-
return {
|
|
3757
|
-
signature,
|
|
3758
|
-
consecutivePasses,
|
|
3759
|
-
shouldLatch: consecutivePasses >= stabilityThreshold
|
|
3815
|
+
function subscribeRenderableImageSourceUpdates(listener) {
|
|
3816
|
+
void listener;
|
|
3817
|
+
return () => {
|
|
3760
3818
|
};
|
|
3761
3819
|
}
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3820
|
+
|
|
3821
|
+
// src/script-fonts.ts
|
|
3822
|
+
var EAST_ASIA_SCRIPT_RE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Bopomofo}\p{Script=Yi}]/u;
|
|
3823
|
+
var COMPLEX_SCRIPT_RE = /[\p{Script=Arabic}\p{Script=Hebrew}\p{Script=Syriac}\p{Script=Thaana}\p{Script=Nko}\p{Script=Samaritan}\p{Script=Mandaic}\p{Script=Devanagari}\p{Script=Bengali}\p{Script=Gurmukhi}\p{Script=Gujarati}\p{Script=Oriya}\p{Script=Tamil}\p{Script=Telugu}\p{Script=Kannada}\p{Script=Malayalam}\p{Script=Sinhala}\p{Script=Thai}\p{Script=Lao}\p{Script=Tibetan}\p{Script=Myanmar}\p{Script=Khmer}]/u;
|
|
3824
|
+
var NEUTRAL_OR_CONTINUATION_RE = /[\p{Mark}\p{Separator}\p{Punctuation}\u200c\u200d\ufe00-\ufe0f]/u;
|
|
3825
|
+
var EAST_ASIA_LANGUAGE_RE = /^(?:ja|ko|zh)(?:-|$)/i;
|
|
3826
|
+
var COMPLEX_SCRIPT_LANGUAGE_RE = /^(?:ar|ckb|dv|fa|he|hi|ks|ku|pa-arab|ps|sd|syr|ug|ur|yi)(?:-|$)/i;
|
|
3827
|
+
function normalizeFamily(value) {
|
|
3828
|
+
const normalized = value?.trim();
|
|
3829
|
+
return normalized || void 0;
|
|
3830
|
+
}
|
|
3831
|
+
function normalizedFamilyKey(value) {
|
|
3832
|
+
return normalizeFamily(value)?.replace(/^['"]+|['"]+$/g, "").toLowerCase();
|
|
3833
|
+
}
|
|
3834
|
+
function hasLegacyFontFamilyOverride(style) {
|
|
3835
|
+
const current = normalizedFamilyKey(style?.fontFamily);
|
|
3836
|
+
const imported = normalizedFamilyKey(style?.sourceFontFamily);
|
|
3837
|
+
if (!current) {
|
|
3838
|
+
return false;
|
|
3839
|
+
}
|
|
3840
|
+
if (imported) {
|
|
3841
|
+
return current !== imported;
|
|
3842
|
+
}
|
|
3843
|
+
return !(normalizeFamily(style?.fontFamilyAscii) || normalizeFamily(style?.fontFamilyHAnsi) || normalizeFamily(style?.fontFamilyEastAsia) || normalizeFamily(style?.fontFamilyCs) || normalizeFamily(style?.fontThemeAscii) || normalizeFamily(style?.fontThemeHAnsi) || normalizeFamily(style?.fontThemeEastAsia) || normalizeFamily(style?.fontThemeCs));
|
|
3844
|
+
}
|
|
3845
|
+
function normalizedFontHint(style) {
|
|
3846
|
+
return style?.fontHint?.trim().replace(/[-_\s]/g, "").toLowerCase() ?? "";
|
|
3784
3847
|
}
|
|
3785
|
-
function
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
usedPureEstimatedPages: false
|
|
3790
|
-
};
|
|
3848
|
+
function neutralScript(style) {
|
|
3849
|
+
const hint = normalizedFontHint(style);
|
|
3850
|
+
if (hint === "eastasia") {
|
|
3851
|
+
return "eastAsia";
|
|
3791
3852
|
}
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
);
|
|
3795
|
-
if (!measuredPagesAreOnlySplitParagraphs) {
|
|
3796
|
-
return {
|
|
3797
|
-
pages: options.measuredEstimatedPages,
|
|
3798
|
-
usedPureEstimatedPages: false
|
|
3799
|
-
};
|
|
3853
|
+
if (hint === "cs" || hint === "complexscript" || hint === "bidi") {
|
|
3854
|
+
return "complexScript";
|
|
3800
3855
|
}
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
if (purePagesAreOnlySplitParagraphs && pureEstimatedPages.length < options.measuredEstimatedPages.length) {
|
|
3804
|
-
return { pages: pureEstimatedPages, usedPureEstimatedPages: true };
|
|
3856
|
+
if (style?.rightToLeft || COMPLEX_SCRIPT_LANGUAGE_RE.test(style?.languageBidi?.trim() ?? "")) {
|
|
3857
|
+
return "complexScript";
|
|
3805
3858
|
}
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3859
|
+
if (EAST_ASIA_LANGUAGE_RE.test(style?.languageEastAsia?.trim() ?? "")) {
|
|
3860
|
+
return "eastAsia";
|
|
3861
|
+
}
|
|
3862
|
+
return "highAnsi";
|
|
3810
3863
|
}
|
|
3811
|
-
function
|
|
3812
|
-
const
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
return candidateDifference < incumbentDifference;
|
|
3864
|
+
function classifyDocxFontScript(value, style) {
|
|
3865
|
+
const character = Array.from(value)[0];
|
|
3866
|
+
if (!character) {
|
|
3867
|
+
return void 0;
|
|
3816
3868
|
}
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
if (candidateScaleDelta !== incumbentScaleDelta) {
|
|
3820
|
-
return candidateScaleDelta < incumbentScaleDelta;
|
|
3869
|
+
if (style?.complexScript === true || style?.rightToLeft === true && style?.complexScript !== false) {
|
|
3870
|
+
return "complexScript";
|
|
3821
3871
|
}
|
|
3822
|
-
|
|
3872
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
3873
|
+
if (codePoint <= 127) {
|
|
3874
|
+
return "ascii";
|
|
3875
|
+
}
|
|
3876
|
+
if (EAST_ASIA_SCRIPT_RE.test(character) || codePoint >= 12288 && codePoint <= 12351 || codePoint >= 65280 && codePoint <= 65519) {
|
|
3877
|
+
return "eastAsia";
|
|
3878
|
+
}
|
|
3879
|
+
if (COMPLEX_SCRIPT_RE.test(character)) {
|
|
3880
|
+
return "complexScript";
|
|
3881
|
+
}
|
|
3882
|
+
if (NEUTRAL_OR_CONTINUATION_RE.test(character)) {
|
|
3883
|
+
return void 0;
|
|
3884
|
+
}
|
|
3885
|
+
return "highAnsi";
|
|
3823
3886
|
}
|
|
3824
|
-
function
|
|
3825
|
-
const
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
buildPagesAtScale,
|
|
3829
|
-
maxDifference = 3,
|
|
3830
|
-
scales: customScales
|
|
3831
|
-
} = options;
|
|
3832
|
-
const safeTargetPageCount = Math.max(1, Math.round(targetPageCount));
|
|
3833
|
-
const initialPageCount = initialPages.length;
|
|
3834
|
-
const initialDifference = Math.abs(initialPageCount - safeTargetPageCount);
|
|
3835
|
-
if (initialDifference === 0 || initialDifference > maxDifference) {
|
|
3836
|
-
return {
|
|
3837
|
-
pageCount: initialPageCount,
|
|
3838
|
-
pages: initialPages,
|
|
3839
|
-
scale: 1
|
|
3840
|
-
};
|
|
3887
|
+
function resolveDocxScriptFontFamily(style, script) {
|
|
3888
|
+
const legacyFamily = normalizeFamily(style?.fontFamily);
|
|
3889
|
+
if (hasLegacyFontFamilyOverride(style)) {
|
|
3890
|
+
return legacyFamily;
|
|
3841
3891
|
}
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
0.42,
|
|
3879
|
-
0.4,
|
|
3880
|
-
0.38,
|
|
3881
|
-
0.36,
|
|
3882
|
-
0.34,
|
|
3883
|
-
0.32,
|
|
3884
|
-
0.3,
|
|
3885
|
-
0.28,
|
|
3886
|
-
0.26,
|
|
3887
|
-
0.24,
|
|
3888
|
-
0.22,
|
|
3889
|
-
0.2
|
|
3890
|
-
] : [
|
|
3891
|
-
1.02,
|
|
3892
|
-
1.04,
|
|
3893
|
-
1.06,
|
|
3894
|
-
1.08,
|
|
3895
|
-
1.1,
|
|
3896
|
-
1.12,
|
|
3897
|
-
1.14,
|
|
3898
|
-
1.16,
|
|
3899
|
-
1.18,
|
|
3900
|
-
1.2,
|
|
3901
|
-
1.22,
|
|
3902
|
-
1.24,
|
|
3903
|
-
1.26,
|
|
3904
|
-
1.28,
|
|
3905
|
-
1.3
|
|
3906
|
-
];
|
|
3907
|
-
const buildCandidateAtScale = (scale) => {
|
|
3908
|
-
const pages = buildPagesAtScale(scale);
|
|
3909
|
-
return {
|
|
3910
|
-
pageCount: pages.length,
|
|
3911
|
-
pages,
|
|
3912
|
-
scale
|
|
3913
|
-
};
|
|
3914
|
-
};
|
|
3915
|
-
const refineExactTargetCandidate = (lowerScale, upperScale) => {
|
|
3916
|
-
let bestExactCandidate;
|
|
3917
|
-
const interval = upperScale - lowerScale;
|
|
3918
|
-
if (!Number.isFinite(interval) || Math.abs(interval) < 1e-4) {
|
|
3919
|
-
return selectedCandidate;
|
|
3920
|
-
}
|
|
3921
|
-
for (let step = 1; step <= PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS; step += 1) {
|
|
3922
|
-
const scale = lowerScale + interval * step / PAGE_COUNT_RECONCILIATION_REFINEMENT_STEPS;
|
|
3923
|
-
const candidate = buildCandidateAtScale(scale);
|
|
3924
|
-
if (isBetterCandidate(candidate, selectedCandidate, safeTargetPageCount)) {
|
|
3925
|
-
selectedCandidate = candidate;
|
|
3926
|
-
}
|
|
3927
|
-
if (candidate.pageCount === safeTargetPageCount && (bestExactCandidate === void 0 || isBetterCandidate(
|
|
3928
|
-
candidate,
|
|
3929
|
-
bestExactCandidate,
|
|
3930
|
-
safeTargetPageCount
|
|
3931
|
-
))) {
|
|
3932
|
-
bestExactCandidate = candidate;
|
|
3933
|
-
}
|
|
3934
|
-
}
|
|
3935
|
-
return bestExactCandidate ?? selectedCandidate;
|
|
3936
|
-
};
|
|
3937
|
-
let previousScale = 1;
|
|
3938
|
-
let previousPageCount = initialPageCount;
|
|
3939
|
-
for (const scale of scales) {
|
|
3940
|
-
const candidate = buildCandidateAtScale(scale);
|
|
3941
|
-
if (isBetterCandidate(candidate, selectedCandidate, safeTargetPageCount)) {
|
|
3942
|
-
selectedCandidate = candidate;
|
|
3892
|
+
switch (script) {
|
|
3893
|
+
case "ascii":
|
|
3894
|
+
return normalizeFamily(style?.resolvedFontFamilyAscii) ?? normalizeFamily(style?.fontFamilyAscii) ?? normalizeFamily(style?.resolvedFontFamilyHAnsi) ?? normalizeFamily(style?.fontFamilyHAnsi) ?? legacyFamily;
|
|
3895
|
+
case "highAnsi":
|
|
3896
|
+
return normalizeFamily(style?.resolvedFontFamilyHAnsi) ?? normalizeFamily(style?.fontFamilyHAnsi) ?? normalizeFamily(style?.resolvedFontFamilyAscii) ?? normalizeFamily(style?.fontFamilyAscii) ?? legacyFamily;
|
|
3897
|
+
case "eastAsia":
|
|
3898
|
+
return normalizeFamily(style?.resolvedFontFamilyEastAsia) ?? normalizeFamily(style?.fontFamilyEastAsia) ?? normalizeFamily(style?.resolvedFontFamilyHAnsi) ?? normalizeFamily(style?.fontFamilyHAnsi) ?? normalizeFamily(style?.resolvedFontFamilyAscii) ?? normalizeFamily(style?.fontFamilyAscii) ?? legacyFamily;
|
|
3899
|
+
case "complexScript":
|
|
3900
|
+
return normalizeFamily(style?.resolvedFontFamilyCs) ?? normalizeFamily(style?.fontFamilyCs) ?? normalizeFamily(style?.resolvedFontFamilyHAnsi) ?? normalizeFamily(style?.fontFamilyHAnsi) ?? normalizeFamily(style?.resolvedFontFamilyAscii) ?? normalizeFamily(style?.fontFamilyAscii) ?? legacyFamily;
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
function segmentTextByDocxScriptFont(text, style) {
|
|
3904
|
+
if (!text) {
|
|
3905
|
+
return [];
|
|
3906
|
+
}
|
|
3907
|
+
const tokens = [];
|
|
3908
|
+
let offset = 0;
|
|
3909
|
+
for (const character of text) {
|
|
3910
|
+
const startOffset = offset;
|
|
3911
|
+
offset += character.length;
|
|
3912
|
+
tokens.push({
|
|
3913
|
+
text: character,
|
|
3914
|
+
startOffset,
|
|
3915
|
+
endOffset: offset,
|
|
3916
|
+
script: classifyDocxFontScript(character, style)
|
|
3917
|
+
});
|
|
3918
|
+
}
|
|
3919
|
+
const fallbackScript = neutralScript(style);
|
|
3920
|
+
const nextStrongScript = new Array(
|
|
3921
|
+
tokens.length
|
|
3922
|
+
);
|
|
3923
|
+
let nextScript;
|
|
3924
|
+
for (let index = tokens.length - 1; index >= 0; index -= 1) {
|
|
3925
|
+
nextStrongScript[index] = nextScript;
|
|
3926
|
+
if (tokens[index]?.script) {
|
|
3927
|
+
nextScript = tokens[index]?.script;
|
|
3943
3928
|
}
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3929
|
+
}
|
|
3930
|
+
let previousScript;
|
|
3931
|
+
for (let index = 0; index < tokens.length; index += 1) {
|
|
3932
|
+
const token = tokens[index];
|
|
3933
|
+
if (!token) {
|
|
3934
|
+
continue;
|
|
3950
3935
|
}
|
|
3951
|
-
|
|
3952
|
-
|
|
3936
|
+
token.script = token.script ?? previousScript ?? nextStrongScript[index] ?? fallbackScript;
|
|
3937
|
+
previousScript = token.script;
|
|
3953
3938
|
}
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3939
|
+
const segments = [];
|
|
3940
|
+
for (const token of tokens) {
|
|
3941
|
+
const script = token.script ?? fallbackScript;
|
|
3942
|
+
const fontFamily = resolveDocxScriptFontFamily(style, script);
|
|
3943
|
+
const previous = segments[segments.length - 1];
|
|
3944
|
+
if (previous && normalizedFamilyKey(previous.fontFamily) === normalizedFamilyKey(fontFamily)) {
|
|
3945
|
+
previous.text += token.text;
|
|
3946
|
+
previous.endOffset = token.endOffset;
|
|
3947
|
+
continue;
|
|
3948
|
+
}
|
|
3949
|
+
segments.push({
|
|
3950
|
+
text: token.text,
|
|
3951
|
+
startOffset: token.startOffset,
|
|
3952
|
+
endOffset: token.endOffset,
|
|
3953
|
+
script,
|
|
3954
|
+
fontFamily
|
|
3955
|
+
});
|
|
3960
3956
|
}
|
|
3961
|
-
return
|
|
3957
|
+
return segments;
|
|
3958
|
+
}
|
|
3959
|
+
function resolveDocxTextFontFamily(text, style) {
|
|
3960
|
+
return segmentTextByDocxScriptFont(text, style).find(
|
|
3961
|
+
(segment) => segment.fontFamily
|
|
3962
|
+
)?.fontFamily ?? normalizeFamily(style?.fontFamily);
|
|
3962
3963
|
}
|
|
3963
3964
|
|
|
3964
3965
|
// src/editor-transaction-state.ts
|
|
@@ -5826,7 +5827,7 @@ var SerialIdleTaskQueue = class {
|
|
|
5826
5827
|
if (this.pending.length === 0) {
|
|
5827
5828
|
return void 0;
|
|
5828
5829
|
}
|
|
5829
|
-
const
|
|
5830
|
+
const now2 = this.now();
|
|
5830
5831
|
let earliestWaitMs;
|
|
5831
5832
|
let bestIndex = -1;
|
|
5832
5833
|
let bestEntry;
|
|
@@ -5836,7 +5837,7 @@ var SerialIdleTaskQueue = class {
|
|
|
5836
5837
|
continue;
|
|
5837
5838
|
}
|
|
5838
5839
|
const lastRunAt = this.lastRunAtByKey.get(candidate.key);
|
|
5839
|
-
const waitMs = lastRunAt === void 0 ? 0 : lastRunAt + this.minTaskIntervalMs -
|
|
5840
|
+
const waitMs = lastRunAt === void 0 ? 0 : lastRunAt + this.minTaskIntervalMs - now2;
|
|
5840
5841
|
if (waitMs <= 0) {
|
|
5841
5842
|
if (!bestEntry || candidate.priority < bestEntry.priority || candidate.priority === bestEntry.priority && candidate.sequence < bestEntry.sequence) {
|
|
5842
5843
|
bestEntry = candidate;
|
|
@@ -22277,11 +22278,16 @@ function useDocxEditor(options = {}) {
|
|
|
22277
22278
|
const starterTemplateRef = React.useRef(
|
|
22278
22279
|
cloneDocModelWithBlockIds(options.starterModel ?? defaultStarterModel)
|
|
22279
22280
|
);
|
|
22281
|
+
const initialModelRef = React.useRef(
|
|
22282
|
+
cloneDocModelWithBlockIds(
|
|
22283
|
+
options.document?.model ?? starterTemplateRef.current
|
|
22284
|
+
)
|
|
22285
|
+
);
|
|
22280
22286
|
const [editorState, dispatchCanonicalEditorState] = React.useReducer(
|
|
22281
22287
|
reduceDocxEditorState,
|
|
22282
|
-
|
|
22283
|
-
(
|
|
22284
|
-
model: cloneDocModelWithBlockIds(
|
|
22288
|
+
initialModelRef.current,
|
|
22289
|
+
(initialModel) => ({
|
|
22290
|
+
model: cloneDocModelWithBlockIds(initialModel),
|
|
22285
22291
|
selection: {
|
|
22286
22292
|
kind: "paragraph",
|
|
22287
22293
|
nodeIndex: 0
|
|
@@ -22367,7 +22373,7 @@ function useDocxEditor(options = {}) {
|
|
|
22367
22373
|
},
|
|
22368
22374
|
[applyCanonicalEditorStateAction]
|
|
22369
22375
|
);
|
|
22370
|
-
const [basePackage, setBasePackage] = React.useState();
|
|
22376
|
+
const [basePackage, setBasePackage] = React.useState(options.document?.package);
|
|
22371
22377
|
const [documentLoadNonce, setDocumentLoadNonce] = React.useState(0);
|
|
22372
22378
|
const documentLoadNonceRef = React.useRef(0);
|
|
22373
22379
|
const advanceDocumentLoadNonce = React.useCallback(() => {
|
|
@@ -22375,11 +22381,11 @@ function useDocxEditor(options = {}) {
|
|
|
22375
22381
|
setDocumentLoadNonce(documentLoadNonceRef.current);
|
|
22376
22382
|
}, []);
|
|
22377
22383
|
const [fileName, setFileName] = React.useState(
|
|
22378
|
-
options.initialFileName ?? "(new document)"
|
|
22384
|
+
options.initialFileName ?? options.document?.fileName ?? "(new document)"
|
|
22379
22385
|
);
|
|
22380
22386
|
const [selectedFormFieldLocation, setSelectedFormFieldLocation] = React.useState();
|
|
22381
22387
|
const [status, setStatus] = React.useState(
|
|
22382
|
-
options.initialStatus ?? "Ready"
|
|
22388
|
+
options.initialStatus ?? (options.document?.fileName ? `Loaded ${options.document.fileName}` : "Ready")
|
|
22383
22389
|
);
|
|
22384
22390
|
const [importError, setImportError] = React.useState();
|
|
22385
22391
|
const [isImporting, setIsImporting] = React.useState(false);
|
|
@@ -22796,6 +22802,16 @@ function useDocxEditor(options = {}) {
|
|
|
22796
22802
|
unloadEmbeddedFonts();
|
|
22797
22803
|
};
|
|
22798
22804
|
}, [unloadEmbeddedFonts]);
|
|
22805
|
+
React.useEffect(() => {
|
|
22806
|
+
if (!options.document || options.loadEmbeddedFonts === false || options.document.embeddedFontsLoaded) {
|
|
22807
|
+
return;
|
|
22808
|
+
}
|
|
22809
|
+
void loadEmbeddedFontsFromPackage(options.document.package);
|
|
22810
|
+
}, [
|
|
22811
|
+
loadEmbeddedFontsFromPackage,
|
|
22812
|
+
options.document,
|
|
22813
|
+
options.loadEmbeddedFonts
|
|
22814
|
+
]);
|
|
22799
22815
|
const dispatchEditorTransaction = React.useCallback(
|
|
22800
22816
|
(resolver) => {
|
|
22801
22817
|
const currentState = canonicalEditorStateRef.current;
|
|
@@ -26182,7 +26198,7 @@ function useDocxEditor(options = {}) {
|
|
|
26182
26198
|
);
|
|
26183
26199
|
const commitParagraphTextAtRange = React.useCallback(
|
|
26184
26200
|
(location, text, caret, options2) => {
|
|
26185
|
-
const
|
|
26201
|
+
const now2 = Date.now();
|
|
26186
26202
|
return dispatchEditorTransaction((current) => {
|
|
26187
26203
|
const paragraph = getParagraphAtLocation(
|
|
26188
26204
|
current.model,
|
|
@@ -26199,9 +26215,9 @@ function useDocxEditor(options = {}) {
|
|
|
26199
26215
|
const coalesce = options2?.coalesceKey !== void 0 && shouldCoalesceTextCommit(textCommitBurstRef.current, {
|
|
26200
26216
|
key: options2.coalesceKey,
|
|
26201
26217
|
caretBefore: insertionOffset,
|
|
26202
|
-
at:
|
|
26218
|
+
at: now2
|
|
26203
26219
|
});
|
|
26204
|
-
textCommitBurstRef.current = options2?.coalesceKey !== void 0 ? { key: options2.coalesceKey, caretAfter: caret.end, at:
|
|
26220
|
+
textCommitBurstRef.current = options2?.coalesceKey !== void 0 ? { key: options2.coalesceKey, caretAfter: caret.end, at: now2 } : void 0;
|
|
26205
26221
|
return {
|
|
26206
26222
|
model: nextModel,
|
|
26207
26223
|
selection: selectionFromTextRangeLocation(location),
|
|
@@ -26982,7 +26998,7 @@ function DocxDetachedThumbnailPageSurface({
|
|
|
26982
26998
|
{
|
|
26983
26999
|
editor,
|
|
26984
27000
|
mode: "read-only",
|
|
26985
|
-
|
|
27001
|
+
pageIndexes: [pageIndex],
|
|
26986
27002
|
pageVirtualization: { enabled: false },
|
|
26987
27003
|
showTrackedChanges: editor.showTrackedChanges,
|
|
26988
27004
|
showComments: editor.showComments,
|
|
@@ -26999,6 +27015,7 @@ var DocxDetachedThumbnailSurfaceRenderer = class {
|
|
|
26999
27015
|
root;
|
|
27000
27016
|
activePageIndex;
|
|
27001
27017
|
activeRenderKey;
|
|
27018
|
+
rootGeneration = 0;
|
|
27002
27019
|
async renderPageSurface(params) {
|
|
27003
27020
|
if (typeof document === "undefined" || typeof window === "undefined") {
|
|
27004
27021
|
return void 0;
|
|
@@ -27024,16 +27041,24 @@ var DocxDetachedThumbnailSurfaceRenderer = class {
|
|
|
27024
27041
|
return this.waitForPageSurface(registry, pageIndex);
|
|
27025
27042
|
}
|
|
27026
27043
|
clear() {
|
|
27027
|
-
|
|
27028
|
-
|
|
27029
|
-
|
|
27030
|
-
|
|
27031
|
-
if (this.host?.parentNode) {
|
|
27032
|
-
this.host.parentNode.removeChild(this.host);
|
|
27033
|
-
}
|
|
27044
|
+
const root = this.root;
|
|
27045
|
+
const host = this.host;
|
|
27046
|
+
this.rootGeneration += 1;
|
|
27047
|
+
this.root = void 0;
|
|
27034
27048
|
this.host = void 0;
|
|
27035
27049
|
this.activePageIndex = void 0;
|
|
27036
27050
|
this.activeRenderKey = void 0;
|
|
27051
|
+
const dispose = () => {
|
|
27052
|
+
root?.unmount();
|
|
27053
|
+
if (host?.parentNode) {
|
|
27054
|
+
host.parentNode.removeChild(host);
|
|
27055
|
+
}
|
|
27056
|
+
};
|
|
27057
|
+
if (root && typeof window !== "undefined") {
|
|
27058
|
+
window.setTimeout(dispose, 0);
|
|
27059
|
+
} else {
|
|
27060
|
+
dispose();
|
|
27061
|
+
}
|
|
27037
27062
|
}
|
|
27038
27063
|
async ensureRoot() {
|
|
27039
27064
|
if (this.root) {
|
|
@@ -27042,6 +27067,7 @@ var DocxDetachedThumbnailSurfaceRenderer = class {
|
|
|
27042
27067
|
if (typeof document === "undefined") {
|
|
27043
27068
|
return;
|
|
27044
27069
|
}
|
|
27070
|
+
const generation = this.rootGeneration;
|
|
27045
27071
|
const host = document.createElement("div");
|
|
27046
27072
|
host.setAttribute("data-docx-thumbnail-detached-renderer", "true");
|
|
27047
27073
|
Object.assign(host.style, {
|
|
@@ -27058,6 +27084,12 @@ var DocxDetachedThumbnailSurfaceRenderer = class {
|
|
|
27058
27084
|
document.body.appendChild(host);
|
|
27059
27085
|
this.host = host;
|
|
27060
27086
|
const { createRoot } = await import("react-dom/client");
|
|
27087
|
+
if (generation !== this.rootGeneration) {
|
|
27088
|
+
if (host.parentNode) {
|
|
27089
|
+
host.parentNode.removeChild(host);
|
|
27090
|
+
}
|
|
27091
|
+
return;
|
|
27092
|
+
}
|
|
27061
27093
|
this.root = createRoot(host);
|
|
27062
27094
|
}
|
|
27063
27095
|
async waitForPageSurface(registry, pageIndex) {
|
|
@@ -27195,6 +27227,7 @@ function useDocxPageThumbnails(editor, options = {}) {
|
|
|
27195
27227
|
const nextThumbnailCanvasQueueIdRef = React.useRef(0);
|
|
27196
27228
|
const queuedPrefetchThumbnailKeysRef = React.useRef(/* @__PURE__ */ new Set());
|
|
27197
27229
|
const thumbnailMinRasterIntervalMs = normalizeDocxThumbnailMinRasterIntervalMs(options.minRasterIntervalMs);
|
|
27230
|
+
const defaultThumbnailScheduling = options.scheduling ?? "idle";
|
|
27198
27231
|
const ensureThumbnailSurfaceCache = React.useCallback(() => {
|
|
27199
27232
|
if (!thumbnailSurfaceCacheRef.current) {
|
|
27200
27233
|
thumbnailSurfaceCacheRef.current = new DocxThumbnailSurfaceCache(
|
|
@@ -27275,20 +27308,43 @@ function useDocxPageThumbnails(editor, options = {}) {
|
|
|
27275
27308
|
[editor.documentTheme, pageSurfaceRegistry, thumbnailResolutionOptionsKey]
|
|
27276
27309
|
);
|
|
27277
27310
|
const totalThumbnailPages = Math.max(1, editor.totalPages);
|
|
27278
|
-
const
|
|
27279
|
-
() => normalizeDocxThumbnailPageIndexes(
|
|
27280
|
-
options.
|
|
27311
|
+
const hardThumbnailPageIndexes = React.useMemo(
|
|
27312
|
+
() => options.pageIndexes === void 0 ? void 0 : normalizeDocxThumbnailPageIndexes(
|
|
27313
|
+
options.pageIndexes,
|
|
27281
27314
|
totalThumbnailPages
|
|
27282
27315
|
),
|
|
27283
|
-
[options.
|
|
27316
|
+
[options.pageIndexes, totalThumbnailPages]
|
|
27284
27317
|
);
|
|
27285
|
-
const
|
|
27286
|
-
() =>
|
|
27318
|
+
const hardThumbnailPageIndexSet = React.useMemo(
|
|
27319
|
+
() => hardThumbnailPageIndexes ? new Set(hardThumbnailPageIndexes) : void 0,
|
|
27320
|
+
[hardThumbnailPageIndexes]
|
|
27321
|
+
);
|
|
27322
|
+
const visibleThumbnailPageIndexes = React.useMemo(() => {
|
|
27323
|
+
const normalized = normalizeDocxThumbnailPageIndexes(
|
|
27324
|
+
options.renderWindow?.visiblePageIndexes,
|
|
27325
|
+
totalThumbnailPages
|
|
27326
|
+
);
|
|
27327
|
+
return hardThumbnailPageIndexSet ? normalized.filter(
|
|
27328
|
+
(pageIndex) => hardThumbnailPageIndexSet.has(pageIndex)
|
|
27329
|
+
) : normalized;
|
|
27330
|
+
}, [
|
|
27331
|
+
hardThumbnailPageIndexSet,
|
|
27332
|
+
options.renderWindow?.visiblePageIndexes,
|
|
27333
|
+
totalThumbnailPages
|
|
27334
|
+
]);
|
|
27335
|
+
const prefetchThumbnailPageIndexes = React.useMemo(() => {
|
|
27336
|
+
const normalized = normalizeDocxThumbnailPageIndexes(
|
|
27287
27337
|
options.renderWindow?.prefetchPageIndexes,
|
|
27288
27338
|
totalThumbnailPages
|
|
27289
|
-
)
|
|
27290
|
-
|
|
27291
|
-
|
|
27339
|
+
);
|
|
27340
|
+
return hardThumbnailPageIndexSet ? normalized.filter(
|
|
27341
|
+
(pageIndex) => hardThumbnailPageIndexSet.has(pageIndex)
|
|
27342
|
+
) : normalized;
|
|
27343
|
+
}, [
|
|
27344
|
+
hardThumbnailPageIndexSet,
|
|
27345
|
+
options.renderWindow?.prefetchPageIndexes,
|
|
27346
|
+
totalThumbnailPages
|
|
27347
|
+
]);
|
|
27292
27348
|
const visibleThumbnailPageIndexesKey = docxThumbnailPageIndexesKey(
|
|
27293
27349
|
visibleThumbnailPageIndexes
|
|
27294
27350
|
);
|
|
@@ -27445,6 +27501,10 @@ function useDocxPageThumbnails(editor, options = {}) {
|
|
|
27445
27501
|
await paintIntoTarget();
|
|
27446
27502
|
return;
|
|
27447
27503
|
}
|
|
27504
|
+
if ((renderOptions?.scheduling ?? defaultThumbnailScheduling) === "immediate") {
|
|
27505
|
+
await paintIntoTarget();
|
|
27506
|
+
return;
|
|
27507
|
+
}
|
|
27448
27508
|
await ensureThumbnailRasterQueue().enqueue(
|
|
27449
27509
|
thumbnailQueueKeyForCanvas(targetCanvas),
|
|
27450
27510
|
paintIntoTarget,
|
|
@@ -27458,6 +27518,7 @@ function useDocxPageThumbnails(editor, options = {}) {
|
|
|
27458
27518
|
},
|
|
27459
27519
|
[
|
|
27460
27520
|
ensureThumbnailRasterQueue,
|
|
27521
|
+
defaultThumbnailScheduling,
|
|
27461
27522
|
options.disabled,
|
|
27462
27523
|
pageSurfaceRegistry,
|
|
27463
27524
|
renderPageThumbnailSurface,
|
|
@@ -27579,7 +27640,8 @@ function useDocxPageThumbnails(editor, options = {}) {
|
|
|
27579
27640
|
]);
|
|
27580
27641
|
const thumbnailGeometryItems = React.useMemo(() => {
|
|
27581
27642
|
const totalPages = Math.max(1, editor.totalPages);
|
|
27582
|
-
|
|
27643
|
+
const geometryPageIndexes = hardThumbnailPageIndexes ?? Array.from({ length: totalPages }, (_, pageIndex) => pageIndex);
|
|
27644
|
+
return geometryPageIndexes.map((pageIndex) => {
|
|
27583
27645
|
const pageElement = mountedPageElements.get(pageIndex);
|
|
27584
27646
|
const sourceSize = pageElement && pageElement.isConnected ? resolveDocxViewerPageSurfaceSize(
|
|
27585
27647
|
pageElement,
|
|
@@ -27633,8 +27695,11 @@ function useDocxPageThumbnails(editor, options = {}) {
|
|
|
27633
27695
|
return nextCanvasRef;
|
|
27634
27696
|
})(),
|
|
27635
27697
|
renderToCanvas: renderToCanvasCallbacksRef.current.get(pageIndex) ?? (() => {
|
|
27636
|
-
const nextRenderToCanvas = async (canvas) => {
|
|
27637
|
-
await renderPageThumbnailToCanvasRef.current(pageIndex, canvas
|
|
27698
|
+
const nextRenderToCanvas = async (canvas, renderOptions) => {
|
|
27699
|
+
await renderPageThumbnailToCanvasRef.current(pageIndex, canvas, {
|
|
27700
|
+
force: renderOptions?.force,
|
|
27701
|
+
scheduling: renderOptions?.scheduling
|
|
27702
|
+
});
|
|
27638
27703
|
};
|
|
27639
27704
|
renderToCanvasCallbacksRef.current.set(
|
|
27640
27705
|
pageIndex,
|
|
@@ -27660,6 +27725,7 @@ function useDocxPageThumbnails(editor, options = {}) {
|
|
|
27660
27725
|
options.maxHeightPx,
|
|
27661
27726
|
options.maxWidthPx,
|
|
27662
27727
|
options.pixelRatio,
|
|
27728
|
+
hardThumbnailPageIndexes,
|
|
27663
27729
|
pageSurfaceRegistry,
|
|
27664
27730
|
thumbnailQueueKeyForCanvas
|
|
27665
27731
|
]);
|
|
@@ -27680,7 +27746,9 @@ function useDocxPageThumbnails(editor, options = {}) {
|
|
|
27680
27746
|
if (!canvas || options.disabled) {
|
|
27681
27747
|
return false;
|
|
27682
27748
|
}
|
|
27683
|
-
const thumbnail = thumbnails
|
|
27749
|
+
const thumbnail = thumbnails.find(
|
|
27750
|
+
(candidate) => candidate.pageIndex === pageIndex
|
|
27751
|
+
);
|
|
27684
27752
|
if (!thumbnail) {
|
|
27685
27753
|
return false;
|
|
27686
27754
|
}
|
|
@@ -28818,6 +28886,7 @@ function DocxEditorViewer({
|
|
|
28818
28886
|
loadingState,
|
|
28819
28887
|
pageVirtualization,
|
|
28820
28888
|
visiblePageRange,
|
|
28889
|
+
pageIndexes,
|
|
28821
28890
|
onPageCountChange,
|
|
28822
28891
|
onRequestPageReveal,
|
|
28823
28892
|
headingStyles,
|
|
@@ -28969,16 +29038,16 @@ function DocxEditorViewer({
|
|
|
28969
29038
|
const [embeddedTableColumnWidths, setEmbeddedTableColumnWidths] = React.useState({});
|
|
28970
29039
|
const handleRepeatedFormFieldClick = React.useCallback(
|
|
28971
29040
|
(location) => {
|
|
28972
|
-
const
|
|
29041
|
+
const now2 = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
28973
29042
|
const key = formFieldLocationKey(location);
|
|
28974
29043
|
const previousClick = lastFormFieldClickRef.current;
|
|
28975
|
-
if (previousClick && previousClick.key === key &&
|
|
29044
|
+
if (previousClick && previousClick.key === key && now2 - previousClick.time <= 350) {
|
|
28976
29045
|
lastFormFieldClickRef.current = void 0;
|
|
28977
29046
|
editor.selectFormField(location);
|
|
28978
29047
|
onFormFieldDoubleClick?.(location);
|
|
28979
29048
|
return true;
|
|
28980
29049
|
}
|
|
28981
|
-
lastFormFieldClickRef.current = { key, time:
|
|
29050
|
+
lastFormFieldClickRef.current = { key, time: now2 };
|
|
28982
29051
|
return false;
|
|
28983
29052
|
},
|
|
28984
29053
|
[editor.selectFormField, formFieldLocationKey, onFormFieldDoubleClick]
|
|
@@ -30250,6 +30319,13 @@ function DocxEditorViewer({
|
|
|
30250
30319
|
};
|
|
30251
30320
|
}, [editor.model.nodes, pageNodeSegmentsByPage]);
|
|
30252
30321
|
const pageCount = pageNodeSegmentsByPage.length;
|
|
30322
|
+
const requestedPageIndexes = React.useMemo(
|
|
30323
|
+
() => normalizeDocxThumbnailPageIndexes(pageIndexes, pageCount).sort(
|
|
30324
|
+
(left, right) => left - right
|
|
30325
|
+
),
|
|
30326
|
+
[pageCount, pageIndexes]
|
|
30327
|
+
);
|
|
30328
|
+
const hasRequestedPageIndexes = pageIndexes !== void 0;
|
|
30253
30329
|
const hasLargeTableLayoutSurface = React.useMemo(() => {
|
|
30254
30330
|
let tableParagraphCount = 0;
|
|
30255
30331
|
let tableCellCount = 0;
|
|
@@ -30344,7 +30420,7 @@ function DocxEditorViewer({
|
|
|
30344
30420
|
)
|
|
30345
30421
|
)
|
|
30346
30422
|
) : 0;
|
|
30347
|
-
const hasExternalVisiblePageRange = Number.isFinite(Number(visiblePageRange?.startPageIndex)) || Number.isFinite(Number(visiblePageRange?.endPageIndex));
|
|
30423
|
+
const hasExternalVisiblePageRange = hasRequestedPageIndexes || Number.isFinite(Number(visiblePageRange?.startPageIndex)) || Number.isFinite(Number(visiblePageRange?.endPageIndex));
|
|
30348
30424
|
const [deferInternalPageVirtualization, setDeferInternalPageVirtualization] = React.useState(false);
|
|
30349
30425
|
const [internalVirtualScrollElement, setInternalVirtualScrollElement] = React.useState(null);
|
|
30350
30426
|
const [virtualizerMeasurementScale, setVirtualizerMeasurementScale] = React.useState(1);
|
|
@@ -30927,9 +31003,12 @@ function DocxEditorViewer({
|
|
|
30927
31003
|
const initialPremeasurePageLimit = hasLargeTableLayoutSurface ? Math.min(2, INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT) : INITIAL_PAGINATION_PREMEASURE_PAGE_LIMIT;
|
|
30928
31004
|
const initialPremeasureEndPageIndex = hasExternalVisiblePageRange ? normalizedVisiblePageRange.endPageIndex : Math.min(pageCount - 1, initialPremeasurePageLimit - 1);
|
|
30929
31005
|
const measureAllPagesBeforeInitialReveal = hideDocumentUntilPaginationSettled && pageCount > 0 && initialPremeasureStartPageIndex === 0 && initialPremeasureEndPageIndex >= pageCount - 1;
|
|
30930
|
-
const visiblePageStartIndex = measureAllPagesBeforeInitialReveal ? 0 : hideDocumentUntilPaginationSettled ? initialPremeasureStartPageIndex : normalizedVisiblePageRange.startPageIndex;
|
|
30931
|
-
const visiblePageEndIndex = measureAllPagesBeforeInitialReveal ? pageCount - 1 : hideDocumentUntilPaginationSettled ? initialPremeasureEndPageIndex : normalizedVisiblePageRange.endPageIndex;
|
|
31006
|
+
const visiblePageStartIndex = hasRequestedPageIndexes ? requestedPageIndexes[0] ?? 0 : measureAllPagesBeforeInitialReveal ? 0 : hideDocumentUntilPaginationSettled ? initialPremeasureStartPageIndex : normalizedVisiblePageRange.startPageIndex;
|
|
31007
|
+
const visiblePageEndIndex = hasRequestedPageIndexes ? requestedPageIndexes[requestedPageIndexes.length - 1] ?? -1 : measureAllPagesBeforeInitialReveal ? pageCount - 1 : hideDocumentUntilPaginationSettled ? initialPremeasureEndPageIndex : normalizedVisiblePageRange.endPageIndex;
|
|
30932
31008
|
const visiblePageIndexes = React.useMemo(() => {
|
|
31009
|
+
if (hasRequestedPageIndexes) {
|
|
31010
|
+
return requestedPageIndexes;
|
|
31011
|
+
}
|
|
30933
31012
|
if (pageCount <= 0 || visiblePageEndIndex < visiblePageStartIndex) {
|
|
30934
31013
|
return [];
|
|
30935
31014
|
}
|
|
@@ -30938,7 +31017,13 @@ function DocxEditorViewer({
|
|
|
30938
31017
|
indexes.push(pageIndex);
|
|
30939
31018
|
}
|
|
30940
31019
|
return indexes;
|
|
30941
|
-
}, [
|
|
31020
|
+
}, [
|
|
31021
|
+
hasRequestedPageIndexes,
|
|
31022
|
+
pageCount,
|
|
31023
|
+
requestedPageIndexes,
|
|
31024
|
+
visiblePageEndIndex,
|
|
31025
|
+
visiblePageStartIndex
|
|
31026
|
+
]);
|
|
30942
31027
|
const pageStackVirtualSpacers = React.useMemo(() => {
|
|
30943
31028
|
const pageWrapperWidthPxForIndex = (pageIndex) => {
|
|
30944
31029
|
const pageLayout = pageSectionInfoByIndex[pageIndex]?.layout ?? documentLayout;
|
|
@@ -31368,9 +31453,14 @@ function DocxEditorViewer({
|
|
|
31368
31453
|
]);
|
|
31369
31454
|
const isPageVisible = React.useCallback(
|
|
31370
31455
|
(pageIndex) => {
|
|
31371
|
-
return pageIndex >= visiblePageStartIndex && pageIndex <= visiblePageEndIndex;
|
|
31456
|
+
return hasRequestedPageIndexes ? requestedPageIndexes.includes(pageIndex) : pageIndex >= visiblePageStartIndex && pageIndex <= visiblePageEndIndex;
|
|
31372
31457
|
},
|
|
31373
|
-
[
|
|
31458
|
+
[
|
|
31459
|
+
hasRequestedPageIndexes,
|
|
31460
|
+
requestedPageIndexes,
|
|
31461
|
+
visiblePageEndIndex,
|
|
31462
|
+
visiblePageStartIndex
|
|
31463
|
+
]
|
|
31374
31464
|
);
|
|
31375
31465
|
const requestPageReveal = React.useCallback(
|
|
31376
31466
|
(targetPageIndex) => {
|
|
@@ -47921,6 +48011,223 @@ ${currentText.slice(end)}`;
|
|
|
47921
48011
|
);
|
|
47922
48012
|
}
|
|
47923
48013
|
|
|
48014
|
+
// src/parsed-docx.ts
|
|
48015
|
+
function now() {
|
|
48016
|
+
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
48017
|
+
}
|
|
48018
|
+
function xmlAttribute3(xml, name) {
|
|
48019
|
+
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
48020
|
+
return xml.match(new RegExp(`${escapedName}="([^"]*)"`, "i"))?.[1];
|
|
48021
|
+
}
|
|
48022
|
+
function relationshipPartName(partName) {
|
|
48023
|
+
const segments = partName.split("/");
|
|
48024
|
+
const name = segments.pop() ?? partName;
|
|
48025
|
+
const directory = segments.join("/");
|
|
48026
|
+
return directory ? `${directory}/_rels/${name}.rels` : `_rels/${name}.rels`;
|
|
48027
|
+
}
|
|
48028
|
+
function resolveRelativePartName(basePartName, target) {
|
|
48029
|
+
if (/^[a-z]+:/i.test(target)) {
|
|
48030
|
+
return target;
|
|
48031
|
+
}
|
|
48032
|
+
if (target.startsWith("/")) {
|
|
48033
|
+
return target.replace(/^\/+/, "");
|
|
48034
|
+
}
|
|
48035
|
+
const segments = basePartName.replace(/^\/+/, "").split("/");
|
|
48036
|
+
segments.pop();
|
|
48037
|
+
target.split("/").forEach((segment) => {
|
|
48038
|
+
if (!segment || segment === ".") {
|
|
48039
|
+
return;
|
|
48040
|
+
}
|
|
48041
|
+
if (segment === "..") {
|
|
48042
|
+
segments.pop();
|
|
48043
|
+
return;
|
|
48044
|
+
}
|
|
48045
|
+
segments.push(segment);
|
|
48046
|
+
});
|
|
48047
|
+
return segments.join("/");
|
|
48048
|
+
}
|
|
48049
|
+
function parseRelationships(pkg, partName) {
|
|
48050
|
+
const relationships = /* @__PURE__ */ new Map();
|
|
48051
|
+
const xml = pkg.parts.get(relationshipPartName(partName))?.content;
|
|
48052
|
+
if (!xml) {
|
|
48053
|
+
return relationships;
|
|
48054
|
+
}
|
|
48055
|
+
const pattern = /<Relationship\b[^>]*Id="([^"]+)"[^>]*Target="([^"]+)"[^>]*\/?>/gi;
|
|
48056
|
+
let match;
|
|
48057
|
+
while (match = pattern.exec(xml)) {
|
|
48058
|
+
const id = match[1]?.trim();
|
|
48059
|
+
const target = match[2]?.trim();
|
|
48060
|
+
if (id && target) {
|
|
48061
|
+
relationships.set(id, resolveRelativePartName(partName, target));
|
|
48062
|
+
}
|
|
48063
|
+
}
|
|
48064
|
+
return relationships;
|
|
48065
|
+
}
|
|
48066
|
+
function deobfuscateFontData(data, key) {
|
|
48067
|
+
const output = Uint8Array.from(data);
|
|
48068
|
+
const normalizedKey = (key ?? "").replace(/[{}-]/g, "");
|
|
48069
|
+
if (/^[0-9a-f]{32}$/i.test(normalizedKey)) {
|
|
48070
|
+
const keyBytes = Uint8Array.from(
|
|
48071
|
+
normalizedKey.match(/../g)?.map((pair) => Number.parseInt(pair, 16)) ?? []
|
|
48072
|
+
).reverse();
|
|
48073
|
+
const length = Math.min(32, output.length);
|
|
48074
|
+
for (let index = 0; index < length; index += 1) {
|
|
48075
|
+
output[index] ^= keyBytes[index % keyBytes.length] ?? 0;
|
|
48076
|
+
}
|
|
48077
|
+
}
|
|
48078
|
+
return output.buffer.slice(
|
|
48079
|
+
output.byteOffset,
|
|
48080
|
+
output.byteOffset + output.byteLength
|
|
48081
|
+
);
|
|
48082
|
+
}
|
|
48083
|
+
function embeddedFontDescriptors(pkg) {
|
|
48084
|
+
const partName = "word/fontTable.xml";
|
|
48085
|
+
const xml = pkg.parts.get(partName)?.content;
|
|
48086
|
+
if (!xml) {
|
|
48087
|
+
return [];
|
|
48088
|
+
}
|
|
48089
|
+
const relationships = parseRelationships(pkg, partName);
|
|
48090
|
+
const descriptors = [];
|
|
48091
|
+
const fontPattern = /<w:font\b[^>]*w:name="([^"]+)"[^>]*>([\s\S]*?)<\/w:font>/gi;
|
|
48092
|
+
const variants = [
|
|
48093
|
+
{ tag: "embedRegular", style: "normal", weight: "400" },
|
|
48094
|
+
{ tag: "embedBold", style: "normal", weight: "700" },
|
|
48095
|
+
{ tag: "embedItalic", style: "italic", weight: "400" },
|
|
48096
|
+
{ tag: "embedBoldItalic", style: "italic", weight: "700" }
|
|
48097
|
+
];
|
|
48098
|
+
let fontMatch;
|
|
48099
|
+
while (fontMatch = fontPattern.exec(xml)) {
|
|
48100
|
+
const family = fontMatch[1]?.trim();
|
|
48101
|
+
const fontXml = fontMatch[2] ?? "";
|
|
48102
|
+
if (!family) {
|
|
48103
|
+
continue;
|
|
48104
|
+
}
|
|
48105
|
+
variants.forEach((variant) => {
|
|
48106
|
+
const tagXml = fontXml.match(new RegExp(`<w:${variant.tag}\\b[^>]*\\/?>`, "i"))?.[0] ?? "";
|
|
48107
|
+
const relationshipId = xmlAttribute3(tagXml, "r:id");
|
|
48108
|
+
const resolvedPartName = relationshipId ? relationships.get(relationshipId) : void 0;
|
|
48109
|
+
const data = resolvedPartName ? pkg.binaryAssets.get(resolvedPartName) : void 0;
|
|
48110
|
+
if (!data) {
|
|
48111
|
+
return;
|
|
48112
|
+
}
|
|
48113
|
+
descriptors.push({
|
|
48114
|
+
family,
|
|
48115
|
+
style: variant.style,
|
|
48116
|
+
weight: variant.weight,
|
|
48117
|
+
source: deobfuscateFontData(data, xmlAttribute3(tagXml, "w:fontKey"))
|
|
48118
|
+
});
|
|
48119
|
+
});
|
|
48120
|
+
}
|
|
48121
|
+
return descriptors;
|
|
48122
|
+
}
|
|
48123
|
+
async function sourceToArrayBuffer(source) {
|
|
48124
|
+
if (source instanceof ArrayBuffer) {
|
|
48125
|
+
return source;
|
|
48126
|
+
}
|
|
48127
|
+
if (ArrayBuffer.isView(source)) {
|
|
48128
|
+
return source.buffer.slice(
|
|
48129
|
+
source.byteOffset,
|
|
48130
|
+
source.byteOffset + source.byteLength
|
|
48131
|
+
);
|
|
48132
|
+
}
|
|
48133
|
+
return source.arrayBuffer();
|
|
48134
|
+
}
|
|
48135
|
+
async function parseDocxForViewer(source, options = {}) {
|
|
48136
|
+
const startedAt = now();
|
|
48137
|
+
const readStartedAt = now();
|
|
48138
|
+
const buffer = await sourceToArrayBuffer(source);
|
|
48139
|
+
const readFinishedAt = now();
|
|
48140
|
+
const importResult = await importDocxBuffer(buffer, {
|
|
48141
|
+
signal: options.signal,
|
|
48142
|
+
transferBuffer: options.transferBuffer,
|
|
48143
|
+
useWorker: options.useWorker
|
|
48144
|
+
});
|
|
48145
|
+
const importFinishedAt = now();
|
|
48146
|
+
let faces = [];
|
|
48147
|
+
let fontLoadingMs = 0;
|
|
48148
|
+
let fontLoadingComplete = false;
|
|
48149
|
+
let fontLoadPromise;
|
|
48150
|
+
const dispose = () => {
|
|
48151
|
+
if (typeof document !== "undefined" && "fonts" in document) {
|
|
48152
|
+
faces.forEach((face) => {
|
|
48153
|
+
try {
|
|
48154
|
+
document.fonts.delete(face);
|
|
48155
|
+
} catch {
|
|
48156
|
+
}
|
|
48157
|
+
});
|
|
48158
|
+
}
|
|
48159
|
+
faces = [];
|
|
48160
|
+
};
|
|
48161
|
+
const loadEmbeddedFonts = () => {
|
|
48162
|
+
if (fontLoadPromise) {
|
|
48163
|
+
return fontLoadPromise;
|
|
48164
|
+
}
|
|
48165
|
+
fontLoadPromise = (async () => {
|
|
48166
|
+
if (typeof document === "undefined" || !("fonts" in document) || typeof FontFace === "undefined") {
|
|
48167
|
+
fontLoadingComplete = true;
|
|
48168
|
+
return;
|
|
48169
|
+
}
|
|
48170
|
+
const fontStartedAt = now();
|
|
48171
|
+
const loaded = (await Promise.all(
|
|
48172
|
+
embeddedFontDescriptors(importResult.package).map(
|
|
48173
|
+
async (descriptor) => {
|
|
48174
|
+
try {
|
|
48175
|
+
const face = new FontFace(
|
|
48176
|
+
descriptor.family,
|
|
48177
|
+
descriptor.source,
|
|
48178
|
+
{
|
|
48179
|
+
style: descriptor.style,
|
|
48180
|
+
weight: descriptor.weight
|
|
48181
|
+
}
|
|
48182
|
+
);
|
|
48183
|
+
await face.load();
|
|
48184
|
+
return face;
|
|
48185
|
+
} catch {
|
|
48186
|
+
return void 0;
|
|
48187
|
+
}
|
|
48188
|
+
}
|
|
48189
|
+
)
|
|
48190
|
+
)).filter((face) => Boolean(face));
|
|
48191
|
+
loaded.forEach((face) => document.fonts.add(face));
|
|
48192
|
+
faces = loaded;
|
|
48193
|
+
try {
|
|
48194
|
+
await document.fonts.ready;
|
|
48195
|
+
} catch {
|
|
48196
|
+
}
|
|
48197
|
+
fontLoadingMs += now() - fontStartedAt;
|
|
48198
|
+
fontLoadingComplete = true;
|
|
48199
|
+
})();
|
|
48200
|
+
return fontLoadPromise;
|
|
48201
|
+
};
|
|
48202
|
+
if (options.loadEmbeddedFonts !== false && options.loadEmbeddedFonts !== "defer") {
|
|
48203
|
+
await loadEmbeddedFonts();
|
|
48204
|
+
}
|
|
48205
|
+
const nonFontTotalMs = importFinishedAt - startedAt;
|
|
48206
|
+
const timings = {
|
|
48207
|
+
fileReadMs: readFinishedAt - readStartedAt,
|
|
48208
|
+
parseMs: importResult.timings?.parseMs ?? importFinishedAt - readFinishedAt,
|
|
48209
|
+
modelConstructionMs: importResult.timings?.buildModelMs ?? 0,
|
|
48210
|
+
get fontLoadingMs() {
|
|
48211
|
+
return fontLoadingMs;
|
|
48212
|
+
},
|
|
48213
|
+
get totalMs() {
|
|
48214
|
+
return nonFontTotalMs + fontLoadingMs;
|
|
48215
|
+
}
|
|
48216
|
+
};
|
|
48217
|
+
return {
|
|
48218
|
+
model: importResult.model,
|
|
48219
|
+
package: importResult.package,
|
|
48220
|
+
source: importResult.source,
|
|
48221
|
+
fileName: options.fileName ?? (typeof File !== "undefined" && source instanceof File ? source.name : void 0),
|
|
48222
|
+
timings,
|
|
48223
|
+
get embeddedFontsLoaded() {
|
|
48224
|
+
return fontLoadingComplete;
|
|
48225
|
+
},
|
|
48226
|
+
loadEmbeddedFonts,
|
|
48227
|
+
dispose
|
|
48228
|
+
};
|
|
48229
|
+
}
|
|
48230
|
+
|
|
47924
48231
|
// ../layout-core/src/pagination.ts
|
|
47925
48232
|
var TWIPS_PER_PIXEL2 = 15;
|
|
47926
48233
|
var PAGE_BREAK_XML_PATTERN3 = /<w:br\b[^>]*w:type="page"[^>]*\/?>/i;
|
|
@@ -49701,6 +50008,9 @@ function renderBlock(block) {
|
|
|
49701
50008
|
function ReactDocxViewer({
|
|
49702
50009
|
file,
|
|
49703
50010
|
model,
|
|
50011
|
+
document: document2,
|
|
50012
|
+
loadEmbeddedFonts = true,
|
|
50013
|
+
pageIndexes,
|
|
49704
50014
|
className,
|
|
49705
50015
|
layoutOptions,
|
|
49706
50016
|
emptyState
|
|
@@ -49709,8 +50019,13 @@ function ReactDocxViewer({
|
|
|
49709
50019
|
model: parsedModel,
|
|
49710
50020
|
isLoading,
|
|
49711
50021
|
error
|
|
49712
|
-
} = useDocxModel(model ? void 0 : file);
|
|
49713
|
-
const resolvedModel = model ?? parsedModel;
|
|
50022
|
+
} = useDocxModel(model || document2 ? void 0 : file);
|
|
50023
|
+
const resolvedModel = model ?? document2?.model ?? parsedModel;
|
|
50024
|
+
React2.useEffect(() => {
|
|
50025
|
+
if (document2 && loadEmbeddedFonts && !document2.embeddedFontsLoaded) {
|
|
50026
|
+
void document2.loadEmbeddedFonts();
|
|
50027
|
+
}
|
|
50028
|
+
}, [document2, loadEmbeddedFonts]);
|
|
49714
50029
|
const modelWithSections = React2.useMemo(() => {
|
|
49715
50030
|
if (!resolvedModel) {
|
|
49716
50031
|
return void 0;
|
|
@@ -49742,6 +50057,12 @@ function ReactDocxViewer({
|
|
|
49742
50057
|
}
|
|
49743
50058
|
return layoutDocument(modelWithSections, resolvedLayoutOptions);
|
|
49744
50059
|
}, [modelWithSections, resolvedLayoutOptions]);
|
|
50060
|
+
const requestedPageIndexSet = React2.useMemo(
|
|
50061
|
+
() => pageIndexes === void 0 ? void 0 : new Set(
|
|
50062
|
+
pageIndexes.filter((pageIndex) => Number.isFinite(pageIndex)).map((pageIndex) => Math.trunc(pageIndex))
|
|
50063
|
+
),
|
|
50064
|
+
[pageIndexes]
|
|
50065
|
+
);
|
|
49745
50066
|
if (isLoading) {
|
|
49746
50067
|
return /* @__PURE__ */ jsx2("div", { className, children: "Loading DOCX..." });
|
|
49747
50068
|
}
|
|
@@ -49763,29 +50084,288 @@ function ReactDocxViewer({
|
|
|
49763
50084
|
className,
|
|
49764
50085
|
"data-testid": "react-docx-viewer",
|
|
49765
50086
|
style: containerStyle,
|
|
49766
|
-
children: pages.map(
|
|
49767
|
-
|
|
49768
|
-
|
|
49769
|
-
|
|
49770
|
-
|
|
49771
|
-
|
|
49772
|
-
|
|
49773
|
-
|
|
49774
|
-
|
|
49775
|
-
|
|
49776
|
-
|
|
49777
|
-
|
|
49778
|
-
|
|
49779
|
-
|
|
49780
|
-
|
|
50087
|
+
children: pages.map(
|
|
50088
|
+
(page, pageIndex) => requestedPageIndexSet && !requestedPageIndexSet.has(pageIndex) ? null : /* @__PURE__ */ jsx2(
|
|
50089
|
+
"section",
|
|
50090
|
+
{
|
|
50091
|
+
"data-page": page.number,
|
|
50092
|
+
"data-page-index": pageIndex,
|
|
50093
|
+
style: {
|
|
50094
|
+
width: pageWidth,
|
|
50095
|
+
minHeight: pageHeight,
|
|
50096
|
+
boxSizing: "border-box",
|
|
50097
|
+
padding: pagePadding,
|
|
50098
|
+
background: "#fff",
|
|
50099
|
+
border: "1px solid #d4d4d4",
|
|
50100
|
+
boxShadow: "0 8px 24px rgba(0, 0, 0, 0.08)",
|
|
50101
|
+
display: "grid",
|
|
50102
|
+
gap: 8,
|
|
50103
|
+
alignContent: "start"
|
|
50104
|
+
},
|
|
50105
|
+
children: page.blocks.map(renderBlock)
|
|
49781
50106
|
},
|
|
49782
|
-
|
|
49783
|
-
|
|
49784
|
-
|
|
49785
|
-
))
|
|
50107
|
+
page.number
|
|
50108
|
+
)
|
|
50109
|
+
)
|
|
49786
50110
|
}
|
|
49787
50111
|
);
|
|
49788
50112
|
}
|
|
50113
|
+
function thumbnailNow() {
|
|
50114
|
+
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
50115
|
+
}
|
|
50116
|
+
function canvasToBlob(canvas, mimeType, quality) {
|
|
50117
|
+
return new Promise((resolve, reject) => {
|
|
50118
|
+
canvas.toBlob(
|
|
50119
|
+
(blob) => {
|
|
50120
|
+
if (blob) {
|
|
50121
|
+
resolve(blob);
|
|
50122
|
+
} else {
|
|
50123
|
+
reject(new Error("Failed to encode DOCX thumbnail."));
|
|
50124
|
+
}
|
|
50125
|
+
},
|
|
50126
|
+
mimeType,
|
|
50127
|
+
quality
|
|
50128
|
+
);
|
|
50129
|
+
});
|
|
50130
|
+
}
|
|
50131
|
+
function createDocxThumbnailRenderer(documentModel, options = {}) {
|
|
50132
|
+
const model = "model" in documentModel ? documentModel.model : documentModel;
|
|
50133
|
+
const layout = resolveDocumentLayout(model);
|
|
50134
|
+
const layoutOptions = {
|
|
50135
|
+
pageWidth: layout.pageWidthPx,
|
|
50136
|
+
pageHeight: layout.pageHeightPx
|
|
50137
|
+
};
|
|
50138
|
+
const headerNodes = model.metadata.headerSections[0]?.nodes ?? [];
|
|
50139
|
+
const footerNodes = model.metadata.footerSections[0]?.nodes ?? [];
|
|
50140
|
+
const paginationStartedAt = thumbnailNow();
|
|
50141
|
+
const builtPageSegments = buildDocumentPageNodeSegments(
|
|
50142
|
+
model,
|
|
50143
|
+
Math.max(
|
|
50144
|
+
120,
|
|
50145
|
+
layout.pageHeightPx - layout.marginsPx.top - layout.marginsPx.bottom
|
|
50146
|
+
),
|
|
50147
|
+
Math.max(
|
|
50148
|
+
120,
|
|
50149
|
+
layout.pageWidthPx - layout.marginsPx.left - layout.marginsPx.right
|
|
50150
|
+
),
|
|
50151
|
+
model.metadata.numberingDefinitions
|
|
50152
|
+
);
|
|
50153
|
+
const pageSegments = builtPageSegments.length > 0 ? builtPageSegments : [[]];
|
|
50154
|
+
const paginationMs = thumbnailNow() - paginationStartedAt;
|
|
50155
|
+
const pageLayoutCache = /* @__PURE__ */ new Map();
|
|
50156
|
+
const layoutPage = (pageIndex) => {
|
|
50157
|
+
const cached = pageLayoutCache.get(pageIndex);
|
|
50158
|
+
if (cached) {
|
|
50159
|
+
return { page: cached, paginationMs: 0 };
|
|
50160
|
+
}
|
|
50161
|
+
const startedAt = thumbnailNow();
|
|
50162
|
+
const nodeIndexes = new Set(
|
|
50163
|
+
(pageSegments[pageIndex] ?? []).map((segment) => segment.nodeIndex)
|
|
50164
|
+
);
|
|
50165
|
+
const pageModel = {
|
|
50166
|
+
...model,
|
|
50167
|
+
nodes: [
|
|
50168
|
+
...headerNodes,
|
|
50169
|
+
...model.nodes.filter(
|
|
50170
|
+
(_, nodeIndex) => nodeIndexes.has(nodeIndex)
|
|
50171
|
+
),
|
|
50172
|
+
...footerNodes
|
|
50173
|
+
]
|
|
50174
|
+
};
|
|
50175
|
+
const page = layoutDocument(pageModel, layoutOptions)[0];
|
|
50176
|
+
if (!page) {
|
|
50177
|
+
throw new RangeError(`DOCX page index ${pageIndex} is unavailable.`);
|
|
50178
|
+
}
|
|
50179
|
+
pageLayoutCache.set(pageIndex, page);
|
|
50180
|
+
return { page, paginationMs: thumbnailNow() - startedAt };
|
|
50181
|
+
};
|
|
50182
|
+
const allowedPageIndexes = options.pageIndexes === void 0 ? void 0 : new Set(
|
|
50183
|
+
options.pageIndexes.filter((pageIndex) => Number.isFinite(pageIndex)).map((pageIndex) => Math.trunc(pageIndex))
|
|
50184
|
+
);
|
|
50185
|
+
const queue = new SerialIdleTaskQueue({ minTaskIntervalMs: 0 });
|
|
50186
|
+
let host;
|
|
50187
|
+
let root;
|
|
50188
|
+
let rootPromise;
|
|
50189
|
+
let requestId = 0;
|
|
50190
|
+
let disposed = false;
|
|
50191
|
+
const ensureRoot = async () => {
|
|
50192
|
+
if (disposed) {
|
|
50193
|
+
throw new Error("DOCX thumbnail renderer has been disposed.");
|
|
50194
|
+
}
|
|
50195
|
+
if (root) {
|
|
50196
|
+
return root;
|
|
50197
|
+
}
|
|
50198
|
+
if (!rootPromise) {
|
|
50199
|
+
rootPromise = (async () => {
|
|
50200
|
+
if (typeof document === "undefined") {
|
|
50201
|
+
throw new Error("DOCX thumbnail rendering requires a browser DOM.");
|
|
50202
|
+
}
|
|
50203
|
+
const nextHost = document.createElement("div");
|
|
50204
|
+
nextHost.setAttribute("data-docx-thumbnail-renderer", "true");
|
|
50205
|
+
Object.assign(nextHost.style, {
|
|
50206
|
+
position: "fixed",
|
|
50207
|
+
left: "-100000px",
|
|
50208
|
+
top: "0",
|
|
50209
|
+
overflow: "visible",
|
|
50210
|
+
pointerEvents: "none"
|
|
50211
|
+
});
|
|
50212
|
+
document.body.appendChild(nextHost);
|
|
50213
|
+
host = nextHost;
|
|
50214
|
+
const { createRoot } = await import("react-dom/client");
|
|
50215
|
+
const nextRoot = createRoot(nextHost);
|
|
50216
|
+
if (disposed) {
|
|
50217
|
+
nextRoot.unmount();
|
|
50218
|
+
nextHost.remove();
|
|
50219
|
+
throw new Error("DOCX thumbnail renderer has been disposed.");
|
|
50220
|
+
}
|
|
50221
|
+
root = nextRoot;
|
|
50222
|
+
return root;
|
|
50223
|
+
})();
|
|
50224
|
+
}
|
|
50225
|
+
return rootPromise;
|
|
50226
|
+
};
|
|
50227
|
+
const renderImmediately = async (pageIndex, renderOptions) => {
|
|
50228
|
+
const startedAt = thumbnailNow();
|
|
50229
|
+
if (!Number.isInteger(pageIndex) || pageIndex < 0 || pageIndex >= pageSegments.length) {
|
|
50230
|
+
throw new RangeError(`DOCX page index ${pageIndex} is out of range.`);
|
|
50231
|
+
}
|
|
50232
|
+
if (allowedPageIndexes && !allowedPageIndexes.has(pageIndex)) {
|
|
50233
|
+
throw new RangeError(`DOCX page index ${pageIndex} was not requested.`);
|
|
50234
|
+
}
|
|
50235
|
+
const resolvedPage = layoutPage(pageIndex);
|
|
50236
|
+
const renderPaginationMs = paginationMs + resolvedPage.paginationMs;
|
|
50237
|
+
const pageMountStartedAt = thumbnailNow();
|
|
50238
|
+
const activeRoot = await ensureRoot();
|
|
50239
|
+
flushSync2(() => {
|
|
50240
|
+
activeRoot.render(
|
|
50241
|
+
/* @__PURE__ */ jsx2(
|
|
50242
|
+
"section",
|
|
50243
|
+
{
|
|
50244
|
+
"data-docx-thumbnail-page-index": pageIndex,
|
|
50245
|
+
style: {
|
|
50246
|
+
width: layout.pageWidthPx,
|
|
50247
|
+
minHeight: layout.pageHeightPx,
|
|
50248
|
+
boxSizing: "border-box",
|
|
50249
|
+
padding: `${layout.marginsPx.top}px ${layout.marginsPx.right}px ${layout.marginsPx.bottom}px ${layout.marginsPx.left}px`,
|
|
50250
|
+
background: "#fff",
|
|
50251
|
+
display: "grid",
|
|
50252
|
+
gap: 8,
|
|
50253
|
+
alignContent: "start"
|
|
50254
|
+
},
|
|
50255
|
+
children: resolvedPage.page.blocks.map(renderBlock)
|
|
50256
|
+
}
|
|
50257
|
+
)
|
|
50258
|
+
);
|
|
50259
|
+
});
|
|
50260
|
+
const pageElement = host?.querySelector(
|
|
50261
|
+
`[data-docx-thumbnail-page-index="${pageIndex}"]`
|
|
50262
|
+
);
|
|
50263
|
+
if (!pageElement) {
|
|
50264
|
+
throw new Error("Failed to mount the requested DOCX page.");
|
|
50265
|
+
}
|
|
50266
|
+
const pageMountMs = thumbnailNow() - pageMountStartedAt;
|
|
50267
|
+
const resolution = resolveDocxPageThumbnailResolution({
|
|
50268
|
+
sourceWidthPx: layout.pageWidthPx,
|
|
50269
|
+
sourceHeightPx: layout.pageHeightPx,
|
|
50270
|
+
resolution: renderOptions.resolution ?? options.resolution,
|
|
50271
|
+
maxWidthPx: renderOptions.maxWidth,
|
|
50272
|
+
maxHeightPx: renderOptions.maxHeight,
|
|
50273
|
+
pixelRatio: renderOptions.pixelRatio ?? options.pixelRatio
|
|
50274
|
+
});
|
|
50275
|
+
const rasterStartedAt = thumbnailNow();
|
|
50276
|
+
const surface = await rasterizeDocxThumbnailSurface({
|
|
50277
|
+
pageElement,
|
|
50278
|
+
sourceWidthPx: layout.pageWidthPx,
|
|
50279
|
+
sourceHeightPx: layout.pageHeightPx,
|
|
50280
|
+
widthPx: resolution.widthPx,
|
|
50281
|
+
heightPx: resolution.heightPx,
|
|
50282
|
+
pixelWidthPx: resolution.pixelWidthPx,
|
|
50283
|
+
pixelHeightPx: resolution.pixelHeightPx
|
|
50284
|
+
});
|
|
50285
|
+
const rasterizationMs = thumbnailNow() - rasterStartedAt;
|
|
50286
|
+
const output = renderOptions.output ?? "canvas";
|
|
50287
|
+
const outputCanvas = renderOptions.canvas ?? surface;
|
|
50288
|
+
if (outputCanvas !== surface) {
|
|
50289
|
+
blitDocxThumbnailSurface(surface, outputCanvas, resolution);
|
|
50290
|
+
}
|
|
50291
|
+
const encodingStartedAt = thumbnailNow();
|
|
50292
|
+
let blob;
|
|
50293
|
+
let imageBitmap;
|
|
50294
|
+
if (output === "blob") {
|
|
50295
|
+
blob = await canvasToBlob(
|
|
50296
|
+
outputCanvas,
|
|
50297
|
+
renderOptions.mimeType ?? "image/png",
|
|
50298
|
+
renderOptions.quality
|
|
50299
|
+
);
|
|
50300
|
+
} else if (output === "imageBitmap") {
|
|
50301
|
+
if (typeof createImageBitmap !== "function") {
|
|
50302
|
+
throw new Error("ImageBitmap output is not supported in this browser.");
|
|
50303
|
+
}
|
|
50304
|
+
imageBitmap = await createImageBitmap(outputCanvas);
|
|
50305
|
+
}
|
|
50306
|
+
const encodingMs = thumbnailNow() - encodingStartedAt;
|
|
50307
|
+
return {
|
|
50308
|
+
pageIndex,
|
|
50309
|
+
pageCount: pageSegments.length,
|
|
50310
|
+
width: resolution.widthPx,
|
|
50311
|
+
height: resolution.heightPx,
|
|
50312
|
+
pixelWidth: resolution.pixelWidthPx,
|
|
50313
|
+
pixelHeight: resolution.pixelHeightPx,
|
|
50314
|
+
output,
|
|
50315
|
+
canvas: output === "canvas" ? outputCanvas : void 0,
|
|
50316
|
+
blob,
|
|
50317
|
+
imageBitmap,
|
|
50318
|
+
timings: {
|
|
50319
|
+
paginationMs: renderPaginationMs,
|
|
50320
|
+
pageMountMs,
|
|
50321
|
+
rasterizationMs,
|
|
50322
|
+
encodingMs,
|
|
50323
|
+
totalMs: paginationMs + thumbnailNow() - startedAt
|
|
50324
|
+
}
|
|
50325
|
+
};
|
|
50326
|
+
};
|
|
50327
|
+
return {
|
|
50328
|
+
document: documentModel,
|
|
50329
|
+
pageCount: pageSegments.length,
|
|
50330
|
+
renderPage(pageIndex, renderOptions = {}) {
|
|
50331
|
+
const scheduling = renderOptions.scheduling ?? options.scheduling ?? "idle";
|
|
50332
|
+
if (scheduling === "immediate") {
|
|
50333
|
+
return renderImmediately(pageIndex, renderOptions);
|
|
50334
|
+
}
|
|
50335
|
+
requestId += 1;
|
|
50336
|
+
let result;
|
|
50337
|
+
let failure;
|
|
50338
|
+
return queue.enqueue(
|
|
50339
|
+
`page:${pageIndex}:${requestId}`,
|
|
50340
|
+
async () => {
|
|
50341
|
+
try {
|
|
50342
|
+
result = await renderImmediately(pageIndex, renderOptions);
|
|
50343
|
+
} catch (error) {
|
|
50344
|
+
failure = error;
|
|
50345
|
+
}
|
|
50346
|
+
},
|
|
50347
|
+
{ priority: 0 }
|
|
50348
|
+
).then(() => {
|
|
50349
|
+
if (failure) {
|
|
50350
|
+
throw failure;
|
|
50351
|
+
}
|
|
50352
|
+
if (!result) {
|
|
50353
|
+
throw new Error("DOCX thumbnail request was cancelled.");
|
|
50354
|
+
}
|
|
50355
|
+
return result;
|
|
50356
|
+
});
|
|
50357
|
+
},
|
|
50358
|
+
dispose() {
|
|
50359
|
+
disposed = true;
|
|
50360
|
+
queue.clear();
|
|
50361
|
+
root?.unmount();
|
|
50362
|
+
root = void 0;
|
|
50363
|
+
rootPromise = void 0;
|
|
50364
|
+
host?.remove();
|
|
50365
|
+
host = void 0;
|
|
50366
|
+
}
|
|
50367
|
+
};
|
|
50368
|
+
}
|
|
49789
50369
|
export {
|
|
49790
50370
|
DEFAULT_MIN_PARAGRAPH_LINE_HEIGHT_PX,
|
|
49791
50371
|
DEFAULT_PAGE_OVERFLOW_TOLERANCE_PX,
|
|
@@ -49809,6 +50389,7 @@ export {
|
|
|
49809
50389
|
collectTableExplicitPageBreakInfo2 as collectTableExplicitPageBreakInfo,
|
|
49810
50390
|
collectTopLevelExplicitPageBreakStartNodeIndexes2 as collectTopLevelExplicitPageBreakStartNodeIndexes,
|
|
49811
50391
|
copyParagraphs,
|
|
50392
|
+
createDocxThumbnailRenderer,
|
|
49812
50393
|
createMinimalDocxPackage,
|
|
49813
50394
|
createParagraphComment,
|
|
49814
50395
|
deepFreezeDocModel,
|
|
@@ -49831,6 +50412,7 @@ export {
|
|
|
49831
50412
|
paragraphLetterheadFloatSideAtNodeIndex,
|
|
49832
50413
|
paragraphStartsWithLastRenderedPageBreak2 as paragraphStartsWithLastRenderedPageBreak,
|
|
49833
50414
|
parseDocx,
|
|
50415
|
+
parseDocxForViewer,
|
|
49834
50416
|
parseParagraphsFromClipboard,
|
|
49835
50417
|
parseSectionLayout,
|
|
49836
50418
|
pasteParagraphs,
|