@stll/folio-core 0.33.1 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/apply.d.ts +15 -0
- package/dist/ai-edits/apply.js +271 -48
- package/dist/ai-edits/headless.d.ts +47 -3
- package/dist/ai-edits/headless.js +53 -3
- package/dist/ai-edits/index.d.ts +1 -1
- package/dist/ai-edits/snapshot.d.ts +19 -1
- package/dist/ai-edits/snapshot.js +49 -5
- package/dist/ai-edits/table-geometry.d.ts +56 -0
- package/dist/ai-edits/table-geometry.js +217 -0
- package/dist/ai-edits/table-row-column-mutations.d.ts +34 -16
- package/dist/ai-edits/table-row-column-mutations.js +12 -4
- package/dist/ai-edits/table-template.d.ts +60 -0
- package/dist/ai-edits/table-template.js +176 -0
- package/dist/ai-edits/types.d.ts +13 -6
- package/dist/compare/__fixtures__/body-sequence.d.ts +61 -2
- package/dist/compare/__fixtures__/body-sequence.js +94 -6
- package/dist/compare/compare.d.ts +14 -7
- package/dist/compare/compare.js +136 -38
- package/dist/compare/formatting.d.ts +1 -1
- package/dist/compare/formatting.js +38 -9
- package/dist/compare/plan.d.ts +31 -1
- package/dist/compare/plan.js +233 -66
- package/dist/compare/types.d.ts +9 -7
- package/dist/compare/types.js +7 -5
- package/dist/compare/verification.d.ts +31 -12
- package/dist/compare/verification.js +106 -18
- package/dist/compat/eigenpal.d.ts +4 -4
- package/dist/compat/eigenpal.js +2 -2
- package/dist/controller/headerFooterEditorManager.js +11 -9
- package/dist/controller/layoutPipeline.js +24 -3
- package/dist/display-list/build/watermarkPrimitives.js +15 -3
- package/dist/display-list/primitives.d.ts +1 -1
- package/dist/document-operations.d.ts +10 -1
- package/dist/document-operations.js +33 -5
- package/dist/docx/appVersionNormalization.d.ts +49 -0
- package/dist/docx/appVersionNormalization.js +74 -0
- package/dist/docx/blockContentParser.js +3 -2
- package/dist/docx/drawingUtils.js +4 -3
- package/dist/docx/headerFooterParser.js +8 -14
- package/dist/docx/paragraphParser.js +48 -2
- package/dist/docx/rezip.d.ts +10 -4
- package/dist/docx/rezip.js +54 -18
- package/dist/docx/runParser.js +9 -8
- package/dist/docx/sdtProperties.js +4 -3
- package/dist/docx/selectiveSave.js +7 -6
- package/dist/docx/serializer/commentSerializer.d.ts +1 -1
- package/dist/docx/serializer/commentSerializer.js +43 -19
- package/dist/docx/serializer/documentSerializer.d.ts +3 -1
- package/dist/docx/serializer/documentSerializer.js +42 -78
- package/dist/docx/serializer/fontTableSerializer.js +8 -5
- package/dist/docx/serializer/headerFooterSerializer.d.ts +4 -1
- package/dist/docx/serializer/headerFooterSerializer.js +55 -31
- package/dist/docx/serializer/noteSerializer.js +34 -30
- package/dist/docx/serializer/numberingSerializer.js +8 -4
- package/dist/docx/serializer/paragraphSerializer.d.ts +1 -1
- package/dist/docx/serializer/paragraphSerializer.js +22 -12
- package/dist/docx/serializer/partNamespaces.d.ts +78 -0
- package/dist/docx/serializer/partNamespaces.js +324 -0
- package/dist/docx/serializer/runSerializer.js +1 -1
- package/dist/docx/serializer/settingsSerializer.js +8 -2
- package/dist/docx/serializer/stylesSerializer.js +8 -5
- package/dist/docx/serializer/tableSerializer.js +83 -18
- package/dist/docx/serializer/themeSerializer.js +10 -2
- package/dist/docx/server/build.d.ts +1 -1
- package/dist/docx/settingsParser.js +3 -0
- package/dist/docx/strictValueEncodings.gen.d.ts +15 -0
- package/dist/docx/strictValueEncodings.gen.js +275 -0
- package/dist/docx/tableParser.d.ts +0 -6
- package/dist/docx/tableParser.js +52 -7
- package/dist/docx/transitionalSpelling.d.ts +23 -0
- package/dist/docx/transitionalSpelling.js +36 -0
- package/dist/docx/universalMeasure.d.ts +20 -0
- package/dist/docx/universalMeasure.js +32 -0
- package/dist/docx/verbatimCapture.d.ts +20 -0
- package/dist/docx/verbatimCapture.js +131 -0
- package/dist/docx/vmlImageParser.js +4 -3
- package/dist/docx/watermarkParser.d.ts +2 -4
- package/dist/docx/watermarkParser.js +8 -9
- package/dist/docx/xmlParser.d.ts +23 -2
- package/dist/docx/xmlParser.js +43 -11
- package/dist/headless-layout.js +14 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +2 -2
- package/dist/layout-bridge/convert/footnoteLayout.js +23 -10
- package/dist/layout-bridge/convert/headerFooterLayout.js +13 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +96 -13
- package/dist/layout-engine/index.js +11 -4
- package/dist/layout-engine/justifiedLineFit.d.ts +4 -4
- package/dist/layout-engine/justifiedLineFit.js +4 -4
- package/dist/layout-engine/measure/lineBreakProvider.js +1 -0
- package/dist/layout-engine/measure/measureBlocks.js +1 -1
- package/dist/layout-engine/measure/measureParagraph.js +29 -29
- package/dist/layout-painter/renderPage.js +6 -1
- package/dist/layout-painter/renderParagraph.js +18 -8
- package/dist/layout-painter/renderWatermark.js +11 -4
- package/dist/model.d.ts +3 -3
- package/dist/model.js +2 -2
- package/dist/prosemirror/attrs/index.js +11 -0
- package/dist/prosemirror/commands/comments.js +24 -3
- package/dist/prosemirror/containerFinalParagraph.d.ts +47 -0
- package/dist/prosemirror/containerFinalParagraph.js +92 -0
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +8 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +47 -9
- package/dist/prosemirror/conversion/toProseDoc.js +61 -14
- package/dist/prosemirror/extensions/core/DocExtension.js +7 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +1 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.js +5 -0
- package/dist/prosemirror/schema/marks.d.ts +3 -9
- package/dist/prosemirror/schema/nodes.d.ts +22 -0
- package/dist/server.d.ts +1 -1
- package/dist/types/block-id.d.ts +12 -1
- package/dist/types/block-id.js +17 -1
- package/dist/utils/canonicalJson.d.ts +14 -0
- package/dist/utils/canonicalJson.js +19 -0
- package/dist/utils/fontResolver.js +51 -0
- package/dist/utils/formatToStyle.d.ts +1 -1
- package/dist/utils/formatToStyle.js +41 -1
- package/dist/watermark/index.js +7 -0
- package/package.json +2 -2
|
@@ -13,6 +13,7 @@ import { advanceListMarker, advanceVisibleListMarker, cloneListCounterState, for
|
|
|
13
13
|
import { resolveNumberedRefFields } from "../../prosemirror/numberedRefFields.js";
|
|
14
14
|
import { directionToBidi } from "../../prosemirror/paragraphDirection.js";
|
|
15
15
|
import { cascadeStyleTextFormatting } from "../../prosemirror/styles/styleToggleCascade.js";
|
|
16
|
+
import { expectTextBoxAnchorAttrs } from "../../prosemirror/textBoxAnchorAttrs.js";
|
|
16
17
|
import { assertValidProseMirrorDocument } from "../../prosemirror/validation.js";
|
|
17
18
|
import { normalizeShapeTextAnchor } from "../../types/documentEnumValues.js";
|
|
18
19
|
import { resolveColor, resolveHighlightToCss } from "../../utils/colorResolver.js";
|
|
@@ -20,12 +21,22 @@ import { resolveThemeFont } from "../../utils/fontResolver.js";
|
|
|
20
21
|
import { resolveShadingFill } from "../../utils/formatToStyle.js";
|
|
21
22
|
import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
|
|
22
23
|
import { decodeOoxmlSymbolCharacter } from "../../utils/ooxmlSymbol.js";
|
|
24
|
+
import { sanitizeImageSrc } from "../../utils/sanitizeImageSrc.js";
|
|
23
25
|
import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
|
|
24
26
|
import { AUTO_PARAGRAPH_SPACING_PX, halfPointsToPixels, halfPointsToPoints, pointsToPixels } from "../../utils/units.js";
|
|
25
27
|
import { getColumns } from "../sectionColumns.js";
|
|
26
28
|
import { groupParagraphFrames } from "./paragraphFrames.js";
|
|
29
|
+
import { panic } from "better-result";
|
|
27
30
|
//#region src/layout-bridge/convert/toFlowBlocks.ts
|
|
31
|
+
const DETACHED_WATERMARK_HOST_ATTR = "_detachedWatermarkHost";
|
|
32
|
+
const expectDetachedWatermarkHostAttr = (attrs) => {
|
|
33
|
+
const value = Reflect.get(attrs, DETACHED_WATERMARK_HOST_ATTR);
|
|
34
|
+
if (value === null || value === void 0) return false;
|
|
35
|
+
if (typeof value !== "boolean") panic("Invalid ProseMirror detached watermark host attrs:\nparagraph.attrs._detachedWatermarkHost: Expected a boolean.");
|
|
36
|
+
return value;
|
|
37
|
+
};
|
|
28
38
|
const DEFAULT_FONT = "Calibri";
|
|
39
|
+
const TEXT_BOX_ANCHOR_BLOCK_ID = Symbol.for("stll.textBoxAnchorBlockId");
|
|
29
40
|
const DEFAULT_TABLE_CELL_MARGIN_TWIPS = {
|
|
30
41
|
top: 0,
|
|
31
42
|
right: 108,
|
|
@@ -454,6 +465,9 @@ function buildImageRun(attrs, constrained, pmStart, pmEnd, trackedChange) {
|
|
|
454
465
|
if (trackedChange?.changeRevisionId !== void 0) run.changeRevisionId = trackedChange.changeRevisionId;
|
|
455
466
|
return run;
|
|
456
467
|
}
|
|
468
|
+
/** A package image whose bytes cannot paint still owns its authored line box. */
|
|
469
|
+
const hasRelationshipBackedImageBox = (attrs) => typeof attrs.rId === "string" && attrs.rId.trim().length > 0 && typeof attrs.width === "number" && Number.isFinite(attrs.width) && attrs.width >= 0 && typeof attrs.height === "number" && Number.isFinite(attrs.height) && attrs.height >= 0;
|
|
470
|
+
const hasPaintableImageSource = (src) => sanitizeImageSrc(src) !== void 0;
|
|
457
471
|
/**
|
|
458
472
|
* In TOC paragraphs, strip the resolved Hyperlink character-style colour and
|
|
459
473
|
* underline so the painter's link fallback doesn't fire. The PM doc keeps the
|
|
@@ -564,7 +578,7 @@ function paragraphToRuns(node, startPos, _options) {
|
|
|
564
578
|
}
|
|
565
579
|
if (child.type.name === "image") {
|
|
566
580
|
const attrs = expectImageAttrs(child);
|
|
567
|
-
if (!attrs.src) return;
|
|
581
|
+
if (!hasPaintableImageSource(attrs.src) && !hasRelationshipBackedImageBox(attrs)) return;
|
|
568
582
|
const constrained = constrainImageToPage(attrs.width ?? 100, attrs.height ?? 100, _options.pageContentHeight);
|
|
569
583
|
const trackedFmt = extractRunFormatting(child.marks, theme, fontAlternates);
|
|
570
584
|
const run = buildImageRun(attrs, constrained, childPos, childPos + child.nodeSize, trackedFmt);
|
|
@@ -878,6 +892,9 @@ function mapTabAlignment(align) {
|
|
|
878
892
|
function hasOnlyVisuallyEmptyTextRuns(runs) {
|
|
879
893
|
return runs.length > 0 && runs.every((run) => run.kind === "text" && run.text.replace(/\u00a0/gu, " ").trim().length === 0);
|
|
880
894
|
}
|
|
895
|
+
function hasOnlyHiddenTextRuns(runs) {
|
|
896
|
+
return runs.length > 0 && runs.every((run) => run.kind === "text" && run.hidden === true);
|
|
897
|
+
}
|
|
881
898
|
function convertParagraph(node, startPos, options) {
|
|
882
899
|
const pmAttrs = expectParagraphAttrs(node);
|
|
883
900
|
const runs = paragraphToRuns(node, startPos, options);
|
|
@@ -903,10 +920,10 @@ function convertParagraph(node, startPos, options) {
|
|
|
903
920
|
if (alternate) attrs.defaultAlternateFontFamily = alternate;
|
|
904
921
|
}
|
|
905
922
|
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
923
|
+
const isFullyHiddenParagraph = defaultTextFormatting?.hidden === true && (runs.length === 0 || hasOnlyHiddenTextRuns(runs));
|
|
924
|
+
if (isFullyHiddenParagraph && attrs.listMarker !== void 0) attrs.listMarkerHidden = true;
|
|
925
|
+
if (isFullyHiddenParagraph) attrs.suppressEmptyParagraphHeight = true;
|
|
926
|
+
if (runs.length === 0 && expectDetachedWatermarkHostAttr(node.attrs)) attrs.suppressEmptyParagraphHeight = false;
|
|
910
927
|
const hasVisibleParagraphPayload = attrs.listMarker !== void 0 && !attrs.listMarkerHidden || attrs.borders?.top !== void 0 || attrs.borders?.bottom !== void 0 || attrs.borders?.left !== void 0 || attrs.borders?.right !== void 0 || attrs.borders?.between !== void 0 || attrs.borders?.bar !== void 0 || attrs.shading !== void 0;
|
|
911
928
|
if (runs.length === 0 && pmAttrs._pageBreakCarrier === true && !hasVisibleParagraphPayload) attrs.suppressEmptyParagraphHeight = true;
|
|
912
929
|
const bookmarkNames = pmAttrs.bookmarks?.map((b) => b.name);
|
|
@@ -934,6 +951,11 @@ function convertParagraph(node, startPos, options) {
|
|
|
934
951
|
...frame.yAlign !== void 0 ? { yAlign: frame.yAlign } : {},
|
|
935
952
|
...frame.wrap !== void 0 ? { wrap: frame.wrap } : {}
|
|
936
953
|
});
|
|
954
|
+
node.descendants((child) => {
|
|
955
|
+
if (child.type.name !== "textBoxAnchor") return true;
|
|
956
|
+
options.textBoxAnchorBlockIds.set(expectTextBoxAnchorAttrs(child).anchorId, block.id);
|
|
957
|
+
return false;
|
|
958
|
+
});
|
|
937
959
|
return block;
|
|
938
960
|
}
|
|
939
961
|
/**
|
|
@@ -945,6 +967,7 @@ function convertParagraph(node, startPos, options) {
|
|
|
945
967
|
function isPaintlessTerminalParagraph(block) {
|
|
946
968
|
if (block?.kind !== "paragraph" || block.runs.length !== 0) return false;
|
|
947
969
|
const attrs = block.attrs;
|
|
970
|
+
if (attrs?.suppressEmptyParagraphHeight === false) return false;
|
|
948
971
|
return !(attrs?.listMarker !== void 0 && !attrs.listMarkerHidden || attrs?.borders?.top || attrs?.borders?.bottom || attrs?.borders?.left || attrs?.borders?.right || attrs?.borders?.between || attrs?.borders?.bar || attrs?.shading || attrs?.spacingExplicit?.before || attrs?.spacingExplicit?.after || attrs?.pageBreakBefore || attrs?.renderedPageBreakBefore);
|
|
949
972
|
}
|
|
950
973
|
function suppressFinalEmptyParagraphAfterTable(blocks) {
|
|
@@ -1188,6 +1211,7 @@ function convertTable(node, startPos, options) {
|
|
|
1188
1211
|
*/
|
|
1189
1212
|
function convertImage(node, startPos, pageContentHeight) {
|
|
1190
1213
|
const attrs = expectImageAttrs(node);
|
|
1214
|
+
if (!hasPaintableImageSource(attrs.src) && !hasRelationshipBackedImageBox(attrs)) return;
|
|
1191
1215
|
const wrapType = attrs.wrapType;
|
|
1192
1216
|
const shouldAnchor = wrapType === "behind" || wrapType === "inFront";
|
|
1193
1217
|
const constrained = constrainImageToPage(attrs.width ?? 100, attrs.height ?? 100, pageContentHeight);
|
|
@@ -1269,6 +1293,8 @@ function convertTextBoxNode(node, startPos, opts) {
|
|
|
1269
1293
|
if (attrs.distRight !== void 0) textBox.distRight = attrs.distRight;
|
|
1270
1294
|
if (attrs.position !== void 0) textBox.position = attrs.position;
|
|
1271
1295
|
if (attrs._docxGroupId !== void 0) setTextBoxGroupId(textBox, attrs._docxGroupId);
|
|
1296
|
+
const anchorBlockId = attrs._docxAnchorId ? opts.textBoxAnchorBlockIds.get(attrs._docxAnchorId) : void 0;
|
|
1297
|
+
if (anchorBlockId !== void 0) Reflect.set(textBox, TEXT_BOX_ANCHOR_BLOCK_ID, anchorBlockId);
|
|
1272
1298
|
return textBox;
|
|
1273
1299
|
}
|
|
1274
1300
|
function getLastMapKey(map) {
|
|
@@ -1277,6 +1303,41 @@ function getLastMapKey(map) {
|
|
|
1277
1303
|
return lastKey;
|
|
1278
1304
|
}
|
|
1279
1305
|
/**
|
|
1306
|
+
* Translate section-owned start modes into the boundary-owned values consumed
|
|
1307
|
+
* by the paginator. Each flow section break carries the properties for the
|
|
1308
|
+
* section it ends, so its start mode belongs on the preceding boundary.
|
|
1309
|
+
*/
|
|
1310
|
+
function applySectionStartsToBoundaries(blocks, finalSectionStart) {
|
|
1311
|
+
const breakIndexes = [];
|
|
1312
|
+
for (let index = 0; index < blocks.length; index += 1) if (blocks[index]?.kind === "sectionBreak") breakIndexes.push(index);
|
|
1313
|
+
if (breakIndexes.length === 0) return [...blocks];
|
|
1314
|
+
const result = [...blocks];
|
|
1315
|
+
for (let index = 0; index < breakIndexes.length; index += 1) {
|
|
1316
|
+
const boundaryIndex = breakIndexes[index];
|
|
1317
|
+
if (boundaryIndex === void 0) continue;
|
|
1318
|
+
const boundary = blocks[boundaryIndex];
|
|
1319
|
+
if (boundary?.kind !== "sectionBreak") continue;
|
|
1320
|
+
const nextBoundaryIndex = breakIndexes[index + 1];
|
|
1321
|
+
const nextBoundary = nextBoundaryIndex === void 0 ? void 0 : blocks[nextBoundaryIndex];
|
|
1322
|
+
const nextStart = nextBoundary?.kind === "sectionBreak" ? nextBoundary.type : finalSectionStart;
|
|
1323
|
+
const translated = { ...boundary };
|
|
1324
|
+
if (nextStart === void 0) delete translated.type;
|
|
1325
|
+
else translated.type = nextStart;
|
|
1326
|
+
result[boundaryIndex] = translated;
|
|
1327
|
+
}
|
|
1328
|
+
return result;
|
|
1329
|
+
}
|
|
1330
|
+
function readFinalSectionStart(doc) {
|
|
1331
|
+
const sectionStart = doc.attrs["_finalSectionStart"];
|
|
1332
|
+
switch (sectionStart) {
|
|
1333
|
+
case "continuous":
|
|
1334
|
+
case "nextPage":
|
|
1335
|
+
case "oddPage":
|
|
1336
|
+
case "evenPage": return sectionStart;
|
|
1337
|
+
default: return;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
/**
|
|
1280
1341
|
* Convert a ProseMirror document to FlowBlock array.
|
|
1281
1342
|
*
|
|
1282
1343
|
* Walks the document tree, converting each node to the appropriate block type.
|
|
@@ -1315,6 +1376,7 @@ function toFlowBlocks(doc, options = {}) {
|
|
|
1315
1376
|
final: listCounterState,
|
|
1316
1377
|
original: originalListCounterState
|
|
1317
1378
|
},
|
|
1379
|
+
textBoxAnchorBlockIds: /* @__PURE__ */ new Map(),
|
|
1318
1380
|
numberedRefResults: resolveNumberedRefFields(doc, {
|
|
1319
1381
|
listCounterState: cloneListCounterState(listCounterState),
|
|
1320
1382
|
originalListCounterState: cloneListCounterState(originalListCounterState)
|
|
@@ -1521,9 +1583,11 @@ function toFlowBlocks(doc, options = {}) {
|
|
|
1521
1583
|
case "table":
|
|
1522
1584
|
trackedPush(convertTable(node, pos, opts));
|
|
1523
1585
|
break;
|
|
1524
|
-
case "image":
|
|
1525
|
-
|
|
1586
|
+
case "image": {
|
|
1587
|
+
const image = convertImage(node, pos, opts.pageContentHeight);
|
|
1588
|
+
if (image !== void 0) trackedPush(image);
|
|
1526
1589
|
break;
|
|
1590
|
+
}
|
|
1527
1591
|
case "textBox":
|
|
1528
1592
|
trackedPush(convertTextBoxNode(node, pos, opts));
|
|
1529
1593
|
break;
|
|
@@ -1548,24 +1612,43 @@ function toFlowBlocks(doc, options = {}) {
|
|
|
1548
1612
|
reserveLeadingEmptyOutlineHeight(blocks);
|
|
1549
1613
|
suppressFinalEmptyParagraphAfterTable(blocks);
|
|
1550
1614
|
suppressFinalParagraphInRepeatedEmptySuffix(blocks);
|
|
1551
|
-
|
|
1615
|
+
const mergedBlocks = mergeRunInParagraphs(blocks);
|
|
1616
|
+
const tableCellLinePitch = doc.attrs["_adjustLineHeightInTable"] === true ? "sectionGrid" : void 0;
|
|
1617
|
+
return groupParagraphFrames(applySectionStartsToBoundaries(applySectionDocumentGrid(mergedBlocks, {
|
|
1618
|
+
finalLinePitchTwips: opts.finalSectionDocumentGridLinePitchTwips,
|
|
1619
|
+
tableCellLinePitch
|
|
1620
|
+
}), readFinalSectionStart(doc)), nextBlockId);
|
|
1552
1621
|
}
|
|
1553
|
-
function applySectionDocumentGrid(blocks, finalLinePitchTwips) {
|
|
1622
|
+
function applySectionDocumentGrid(blocks, { finalLinePitchTwips, tableCellLinePitch }) {
|
|
1554
1623
|
const result = [...blocks];
|
|
1555
1624
|
let sectionStart = 0;
|
|
1556
1625
|
const stampSection = (end, linePitchTwips) => {
|
|
1557
1626
|
if (linePitchTwips === void 0 || linePitchTwips <= 0) return;
|
|
1558
1627
|
const linePitch = twipsToPixels(linePitchTwips);
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
if (block?.kind !== "paragraph") continue;
|
|
1562
|
-
result[index] = {
|
|
1628
|
+
const stampBlock = (block) => {
|
|
1629
|
+
if (block.kind === "paragraph") return {
|
|
1563
1630
|
...block,
|
|
1564
1631
|
attrs: {
|
|
1565
1632
|
...block.attrs,
|
|
1566
1633
|
documentGridLinePitch: linePitch
|
|
1567
1634
|
}
|
|
1568
1635
|
};
|
|
1636
|
+
if (block.kind !== "table" || tableCellLinePitch !== "sectionGrid") return block;
|
|
1637
|
+
return {
|
|
1638
|
+
...block,
|
|
1639
|
+
rows: block.rows.map((row) => ({
|
|
1640
|
+
...row,
|
|
1641
|
+
cells: row.cells.map((cell) => ({
|
|
1642
|
+
...cell,
|
|
1643
|
+
blocks: cell.blocks.map(stampBlock)
|
|
1644
|
+
}))
|
|
1645
|
+
}))
|
|
1646
|
+
};
|
|
1647
|
+
};
|
|
1648
|
+
for (let index = sectionStart; index < end; index += 1) {
|
|
1649
|
+
const block = result[index];
|
|
1650
|
+
if (!block) continue;
|
|
1651
|
+
result[index] = stampBlock(block);
|
|
1569
1652
|
}
|
|
1570
1653
|
};
|
|
1571
1654
|
for (let index = 0; index < blocks.length; index += 1) {
|
|
@@ -500,12 +500,15 @@ function getHeaderRowsHeight(measure, headerRowCount) {
|
|
|
500
500
|
return height;
|
|
501
501
|
}
|
|
502
502
|
const tableRowStartsWithRenderedPageBreak = (block, rowIndex) => {
|
|
503
|
-
const
|
|
503
|
+
const row = block.rows[rowIndex];
|
|
504
|
+
const visibleCells = row?.cells.filter((cell) => cell.blocks.some((cellBlock) => cellBlock.kind !== "paragraph" || !isEmptyParagraph(cellBlock)));
|
|
504
505
|
if (!visibleCells || visibleCells.length === 0) return false;
|
|
505
|
-
|
|
506
|
+
const startsWithRenderedPageBreak = (cell) => {
|
|
506
507
|
const firstVisibleBlock = cell.blocks.find((cellBlock) => cellBlock.kind !== "paragraph" || !isEmptyParagraph(cellBlock));
|
|
507
508
|
return firstVisibleBlock?.kind === "paragraph" && firstVisibleBlock.attrs?.renderedPageBreakBefore === true;
|
|
508
|
-
}
|
|
509
|
+
};
|
|
510
|
+
if (row?.heightRule === "exact") return startsWithRenderedPageBreak(visibleCells[0]);
|
|
511
|
+
return visibleCells.every(startsWithRenderedPageBreak);
|
|
509
512
|
};
|
|
510
513
|
const getVerticallyMergedRows = (block) => {
|
|
511
514
|
const mergedRows = /* @__PURE__ */ new Set();
|
|
@@ -866,6 +869,8 @@ function layoutAnchoredImage(block, measure, paginator) {
|
|
|
866
869
|
};
|
|
867
870
|
paginator.addUnflowedFragment(fragment);
|
|
868
871
|
}
|
|
872
|
+
const TEXT_BOX_ANCHOR_BLOCK_ID = Symbol.for("stll.textBoxAnchorBlockId");
|
|
873
|
+
const readTextBoxAnchorBlockId = (block) => Reflect.get(block, TEXT_BOX_ANCHOR_BLOCK_ID);
|
|
869
874
|
/**
|
|
870
875
|
* Layout a text box block onto pages.
|
|
871
876
|
*/
|
|
@@ -909,12 +914,14 @@ function layoutTextBox(block, measure, { paginator, sectionMarginTop, sectionPag
|
|
|
909
914
|
boxWidth: measure.width
|
|
910
915
|
}) : paginator.getColumnX(state.columnIndex);
|
|
911
916
|
const vertical = block.position.vertical;
|
|
917
|
+
const anchorBlockId = readTextBoxAnchorBlockId(block);
|
|
918
|
+
const anchorParagraph = vertical?.relativeTo === "paragraph" && typeof anchorBlockId === "string" ? state.page.fragments.find((fragment) => fragment.kind === "paragraph" && fragment.blockId === anchorBlockId) : void 0;
|
|
912
919
|
const y = isPageFrameRelativeAnchor(vertical?.relativeTo) ? state.topMargin + bandTopContentY(vertical, {
|
|
913
920
|
pageHeight: sectionPageHeight,
|
|
914
921
|
marginTop: sectionMarginTop,
|
|
915
922
|
marginBottom: sectionMarginBottom,
|
|
916
923
|
boxHeight: measure.height
|
|
917
|
-
}) : state.cursorY + emuToPixels(vertical?.posOffset ?? 0);
|
|
924
|
+
}) : (anchorParagraph?.y ?? state.cursorY) + emuToPixels(vertical?.posOffset ?? 0);
|
|
918
925
|
const fragment = {
|
|
919
926
|
kind: "textBox",
|
|
920
927
|
blockId: block.id,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ParagraphBlock } from "./types.js";
|
|
2
2
|
//#region src/layout-engine/justifiedLineFit.d.ts
|
|
3
|
-
declare const
|
|
4
|
-
declare const
|
|
5
|
-
declare const
|
|
3
|
+
declare const JUSTIFIED_FINAL_LINE_MAX_SHRINK_RATIO = 0.025;
|
|
4
|
+
declare const JUSTIFIED_FINAL_LINE_SPACE_CONTRACTION_RATIO = 0.32;
|
|
5
|
+
declare const supportsJustifiedFinalLineContraction: (block: ParagraphBlock) => boolean;
|
|
6
6
|
//#endregion
|
|
7
|
-
export {
|
|
7
|
+
export { JUSTIFIED_FINAL_LINE_MAX_SHRINK_RATIO, JUSTIFIED_FINAL_LINE_SPACE_CONTRACTION_RATIO, supportsJustifiedFinalLineContraction };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/layout-engine/justifiedLineFit.ts
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
2
|
+
const JUSTIFIED_FINAL_LINE_MAX_SHRINK_RATIO = .025;
|
|
3
|
+
const JUSTIFIED_FINAL_LINE_SPACE_CONTRACTION_RATIO = .32;
|
|
4
|
+
const supportsJustifiedFinalLineContraction = (block) => block.attrs?.alignment === "justify" && block.attrs.justificationCompatibility?.type !== "legacy" && (block.attrs.listMarker !== void 0 || (block.attrs.indent?.left ?? 0) > 0);
|
|
5
5
|
//#endregion
|
|
6
|
-
export {
|
|
6
|
+
export { JUSTIFIED_FINAL_LINE_MAX_SHRINK_RATIO, JUSTIFIED_FINAL_LINE_SPACE_CONTRACTION_RATIO, supportsJustifiedFinalLineContraction };
|
|
@@ -169,6 +169,7 @@ const usesEastAsianLineBreaking = (text, locale) => localeUsesEastAsianLineBreak
|
|
|
169
169
|
const allowsBreak = (text, index, policy, usesEastAsianRules, nextLineStart) => {
|
|
170
170
|
const previous = previousCodePoint(text, index);
|
|
171
171
|
const next = nextLineStart ?? firstCodePoint(text, index);
|
|
172
|
+
if (!(usesEastAsianRules || policy?.kinsoku === true || policy?.noLineBreaksBefore !== void 0 || policy?.noLineBreaksAfter !== void 0)) return true;
|
|
172
173
|
if (previous === " " && next === "%" && policy?.kinsoku !== true && policy?.noLineBreaksBefore === void 0 && !usesEastAsianRules) return !isProhibitedLineEnd(previous, policy);
|
|
173
174
|
return !isProhibitedLineEnd(previous, policy) && !isProhibitedLineStart(next, policy);
|
|
174
175
|
};
|
|
@@ -587,7 +587,7 @@ function measureTextBoxBlock(tb, fieldValues) {
|
|
|
587
587
|
return {
|
|
588
588
|
kind: "textBox",
|
|
589
589
|
width: totalWidth,
|
|
590
|
-
height: tb.autoFit === "shape" ?
|
|
590
|
+
height: tb.autoFit === "shape" ? contentBoxHeight : tb.height ?? contentBoxHeight,
|
|
591
591
|
innerMeasures
|
|
592
592
|
};
|
|
593
593
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { CJK_FALLBACK_FONT_FAMILY, isCjkFont } from "../../utils/fontResolver.js";
|
|
2
2
|
import { getHorizontalScaleFactor } from "../../utils/horizontalScale.js";
|
|
3
|
-
import { isRtlParagraph } from "../../utils/paragraphBaseDirection.js";
|
|
4
3
|
import { inlineImageBoundingBox } from "../../utils/rotationBoundingBox.js";
|
|
5
4
|
import { hasCjk, hasComplexScript } from "../../utils/scriptSegments.js";
|
|
6
|
-
import {
|
|
5
|
+
import { JUSTIFIED_FINAL_LINE_MAX_SHRINK_RATIO, JUSTIFIED_FINAL_LINE_SPACE_CONTRACTION_RATIO, supportsJustifiedFinalLineContraction } from "../justifiedLineFit.js";
|
|
7
6
|
import { measuredLineAdvance } from "../lineFlow.js";
|
|
8
7
|
import { isFloatingImageRun } from "../types.js";
|
|
9
8
|
import { clampFloatingWrapMargins } from "./clampFloatingWrapMargins.js";
|
|
@@ -382,7 +381,7 @@ function resolveJustifyFitStrategy(block, isFirstLine, profile) {
|
|
|
382
381
|
};
|
|
383
382
|
return {
|
|
384
383
|
type: "space",
|
|
385
|
-
ratio:
|
|
384
|
+
ratio: JUSTIFIED_FINAL_LINE_SPACE_CONTRACTION_RATIO,
|
|
386
385
|
maxWidthRatio: JUSTIFY_SHRINK_TOLERANCE_RATIO
|
|
387
386
|
};
|
|
388
387
|
}
|
|
@@ -409,10 +408,10 @@ function resolveJustifyFitStrategy(block, isFirstLine, profile) {
|
|
|
409
408
|
};
|
|
410
409
|
}
|
|
411
410
|
function resolveFinalLineJustifyFitStrategy(block, profile) {
|
|
412
|
-
if (
|
|
411
|
+
if (supportsJustifiedFinalLineContraction(block)) return {
|
|
413
412
|
type: "space",
|
|
414
|
-
ratio:
|
|
415
|
-
maxWidthRatio:
|
|
413
|
+
ratio: JUSTIFIED_FINAL_LINE_SPACE_CONTRACTION_RATIO,
|
|
414
|
+
maxWidthRatio: JUSTIFIED_FINAL_LINE_MAX_SHRINK_RATIO
|
|
416
415
|
};
|
|
417
416
|
return resolveJustifyFitStrategy(block, false, profile);
|
|
418
417
|
}
|
|
@@ -433,11 +432,11 @@ function isFinalTextCandidate(block, runIndex, nextBreak) {
|
|
|
433
432
|
return true;
|
|
434
433
|
}
|
|
435
434
|
function resolveTextCandidateFit({ block, line, isFirstLine, isFinalCandidate, candidateWidth, candidateSpaceWidth, fallbackTolerancePx, continuationStrategy, finalStrategy }) {
|
|
436
|
-
if (
|
|
435
|
+
if (!isFinalCandidate || !supportsJustifiedFinalLineContraction(block)) return {
|
|
437
436
|
type: "ordinary",
|
|
438
437
|
tolerancePx: fallbackTolerancePx
|
|
439
438
|
};
|
|
440
|
-
const ordinaryTolerancePx = justifyFitTolerance(line, continuationStrategy, candidateSpaceWidth);
|
|
439
|
+
const ordinaryTolerancePx = isFirstLine ? fallbackTolerancePx : justifyFitTolerance(line, continuationStrategy, candidateSpaceWidth);
|
|
441
440
|
if (candidateWidth <= line.availableWidth + ordinaryTolerancePx) return {
|
|
442
441
|
type: "ordinary",
|
|
443
442
|
tolerancePx: ordinaryTolerancePx
|
|
@@ -713,7 +712,6 @@ function findClearLineY(startY, lineHeight, zones, contentWidth, minWidth) {
|
|
|
713
712
|
function measureParagraph(block, maxWidth, options) {
|
|
714
713
|
const runs = block.runs;
|
|
715
714
|
const attrs = block.attrs;
|
|
716
|
-
const isRtl = isRtlParagraph(block);
|
|
717
715
|
const spacing = attrs?.spacing;
|
|
718
716
|
const isJustifiedParagraph = attrs?.alignment === "justify";
|
|
719
717
|
const justificationProfile = {
|
|
@@ -754,24 +752,26 @@ function measureParagraph(block, maxWidth, options) {
|
|
|
754
752
|
const firstLineWidth = Math.max(1, getFloatingAvailableWidth(firstLineFloatingMargins, baseFirstLineWidth));
|
|
755
753
|
const lines = [];
|
|
756
754
|
let consecutiveHyphenatedLines = 0;
|
|
755
|
+
if (attrs?.suppressEmptyParagraphHeight) {
|
|
756
|
+
const finalRunIndex = Math.max(0, runs.length - 1);
|
|
757
|
+
const finalRun = runs.at(-1);
|
|
758
|
+
lines.push({
|
|
759
|
+
fromRun: 0,
|
|
760
|
+
fromChar: 0,
|
|
761
|
+
toRun: finalRunIndex,
|
|
762
|
+
toChar: finalRun?.kind === "text" ? finalRun.text.length : 0,
|
|
763
|
+
width: 0,
|
|
764
|
+
ascent: 0,
|
|
765
|
+
descent: 0,
|
|
766
|
+
lineHeight: 0
|
|
767
|
+
});
|
|
768
|
+
return {
|
|
769
|
+
kind: "paragraph",
|
|
770
|
+
lines,
|
|
771
|
+
totalHeight: 0
|
|
772
|
+
};
|
|
773
|
+
}
|
|
757
774
|
if (runs.length === 0) {
|
|
758
|
-
if (attrs?.suppressEmptyParagraphHeight) {
|
|
759
|
-
lines.push({
|
|
760
|
-
fromRun: 0,
|
|
761
|
-
fromChar: 0,
|
|
762
|
-
toRun: 0,
|
|
763
|
-
toChar: 0,
|
|
764
|
-
width: 0,
|
|
765
|
-
ascent: 0,
|
|
766
|
-
descent: 0,
|
|
767
|
-
lineHeight: 0
|
|
768
|
-
});
|
|
769
|
-
return {
|
|
770
|
-
kind: "paragraph",
|
|
771
|
-
lines,
|
|
772
|
-
totalHeight: 0
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
775
|
const emptyMetrics = calculateEmptyParagraphMetrics(attrs?.defaultFontSize ?? DEFAULT_FONT_SIZE, spacing, attrs?.defaultFontFamily ?? DEFAULT_FONT_FAMILY, attrs);
|
|
776
776
|
const outlineLineHeight = attrs?.reserveEmptyOutlineHeight ? emptyMetrics.lineHeight * 2 : emptyMetrics.lineHeight;
|
|
777
777
|
lines.push({
|
|
@@ -987,11 +987,11 @@ function measureParagraph(block, maxWidth, options) {
|
|
|
987
987
|
let tabWidth = tabResult.width;
|
|
988
988
|
const authoredEndpoint = contentX + tabWidth + followingWidth;
|
|
989
989
|
const activeContentRightEdge = maxWidth - currentLine.rightOffset;
|
|
990
|
-
const
|
|
990
|
+
const preservesAuthoredEndStop = tabResult.alignment === "end" && authoredEndpoint <= activeContentRightEdge + WIDTH_TOLERANCE;
|
|
991
991
|
const landsOnLeftIndent = tabResult.alignment === "start" && indentLeft > 0 && Math.abs(contentX + tabWidth - indentLeft) <= WIDTH_TOLERANCE;
|
|
992
992
|
const lineRightEdgeX = indentLeft + (isFirstLine ? firstLineOffset + markerInlineWidth : 0) + currentLine.availableWidth + currentLine.leftOffset;
|
|
993
|
-
if (!
|
|
994
|
-
if (
|
|
993
|
+
if (!preservesAuthoredEndStop && !landsOnLeftIndent && !hasFollowingTabOnLine(runs, runIndex) && canClampTabToRightEdge(tabResult.alignment, currentLine.width, hasPriorTabOnLine(runs, runIndex), followingWidth, currentLine.availableWidth) && (tabWidth > 0 || followingWidth > 0) && contentX + tabWidth + followingWidth > lineRightEdgeX + WIDTH_TOLERANCE) tabWidth = Math.max(1, lineRightEdgeX - contentX - followingWidth);
|
|
994
|
+
if (preservesAuthoredEndStop) currentLine.availableWidth = Math.max(currentLine.availableWidth, currentLine.width + tabWidth + followingWidth);
|
|
995
995
|
if (currentLine.width + tabWidth > currentLine.availableWidth + WIDTH_TOLERANCE) {
|
|
996
996
|
startNewLine(runIndex, 0);
|
|
997
997
|
updateMaxFont(style);
|
|
@@ -24,6 +24,7 @@ import { panic } from "better-result";
|
|
|
24
24
|
* Renders a single page from Layout data to DOM elements.
|
|
25
25
|
* Each page contains positioned fragments within a content area.
|
|
26
26
|
*/
|
|
27
|
+
const TEXT_BOX_ANCHOR_BLOCK_ID = Symbol.for("stll.textBoxAnchorBlockId");
|
|
27
28
|
const floatingTableReservesBand = ({ contentX, tableWidth, contentWidth, distLeft, distRight }) => {
|
|
28
29
|
const leftClearance = Math.max(0, contentX - distLeft);
|
|
29
30
|
const rightClearance = Math.max(0, contentWidth - contentX - tableWidth - distRight);
|
|
@@ -442,6 +443,7 @@ function renderHeaderFooterContent(content, context, options, layout) {
|
|
|
442
443
|
...context,
|
|
443
444
|
positioning: "absolute"
|
|
444
445
|
};
|
|
446
|
+
const paragraphStartYByBlockId = /* @__PURE__ */ new Map();
|
|
445
447
|
for (let i = 0; i < content.blocks.length; i++) {
|
|
446
448
|
const block = content.blocks[i];
|
|
447
449
|
const measure = content.measures[i];
|
|
@@ -450,6 +452,7 @@ function renderHeaderFooterContent(content, context, options, layout) {
|
|
|
450
452
|
const paragraphBlock = block;
|
|
451
453
|
const paragraphMeasure = measure;
|
|
452
454
|
const paragraphStartY = cursorY;
|
|
455
|
+
paragraphStartYByBlockId.set(paragraphBlock.id, paragraphStartY);
|
|
453
456
|
const inlineRuns = [];
|
|
454
457
|
for (const run of paragraphBlock.runs) if (run.kind === "image" && (isFloatingImageRun(run) || run.position)) floatingImages.push({
|
|
455
458
|
src: run.src,
|
|
@@ -530,9 +533,11 @@ function renderHeaderFooterContent(content, context, options, layout) {
|
|
|
530
533
|
document: doc,
|
|
531
534
|
renderTable: renderNestedTable
|
|
532
535
|
});
|
|
536
|
+
const anchorBlockId = Reflect.get(block, TEXT_BOX_ANCHOR_BLOCK_ID);
|
|
537
|
+
const paragraphY = block.position?.vertical?.relativeTo === "paragraph" && typeof anchorBlockId === "string" ? paragraphStartYByBlockId.get(anchorBlockId) ?? cursorY : cursorY;
|
|
533
538
|
const textBoxTop = block.position ? resolveHeaderFooterFloatTop({
|
|
534
539
|
height: measure.height,
|
|
535
|
-
paragraphY
|
|
540
|
+
paragraphY,
|
|
536
541
|
position: block.position
|
|
537
542
|
}, layout) : cursorY;
|
|
538
543
|
fragEl.style.top = `${textBoxTop}px`;
|
|
@@ -14,7 +14,7 @@ import "../utils/fontWeights.js";
|
|
|
14
14
|
import { getHorizontalScaleFactor } from "../utils/horizontalScale.js";
|
|
15
15
|
import { resolvePhysicalParagraphInlineLayout } from "../utils/paragraphInlineLayout.js";
|
|
16
16
|
import { inlineImageBoundingBox, parseRotationDegrees, rotatedBoundingBox } from "../utils/rotationBoundingBox.js";
|
|
17
|
-
import {
|
|
17
|
+
import { sanitizeImageSrc } from "../utils/sanitizeImageSrc.js";
|
|
18
18
|
import { SCRIPT_CLASS, hasCjk, hasComplexScript, segmentByScript } from "../utils/scriptSegments.js";
|
|
19
19
|
import { sanitizeExternalUrl } from "../utils/urlSecurity.js";
|
|
20
20
|
import { borderStrokeToCss, resolveParagraphBorderHorizontalOutsets } from "./borderStroke.js";
|
|
@@ -42,6 +42,14 @@ const PARAGRAPH_CLASS_NAMES = {
|
|
|
42
42
|
image: "layout-run-image",
|
|
43
43
|
lineBreak: "layout-run-linebreak"
|
|
44
44
|
};
|
|
45
|
+
const applyImageRunSource = (img, src) => {
|
|
46
|
+
const safeSrc = sanitizeImageSrc(src);
|
|
47
|
+
if (safeSrc === void 0) {
|
|
48
|
+
img.style.visibility = "hidden";
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
img.src = safeSrc;
|
|
52
|
+
};
|
|
45
53
|
const LEFT_TO_RIGHT_DIRECTION = "ltr";
|
|
46
54
|
const RIGHT_TO_LEFT_DIRECTION = "rtl";
|
|
47
55
|
const DISPLAYED_URL_PATTERN = /^(?:https?:\/\/|www\.)\S+$/iu;
|
|
@@ -488,7 +496,7 @@ function getLeaderChar(leader) {
|
|
|
488
496
|
function renderInlineImageRun(run, doc) {
|
|
489
497
|
const img = doc.createElement("img");
|
|
490
498
|
img.className = `${PARAGRAPH_CLASS_NAMES.run} ${PARAGRAPH_CLASS_NAMES.image}`;
|
|
491
|
-
|
|
499
|
+
applyImageRunSource(img, run.src);
|
|
492
500
|
img.width = run.width;
|
|
493
501
|
img.height = run.height;
|
|
494
502
|
img.style.width = `${run.width}px`;
|
|
@@ -556,7 +564,7 @@ function renderBlockImage(run, doc) {
|
|
|
556
564
|
container.style.marginTop = `${run.distTop ?? 6}px`;
|
|
557
565
|
container.style.marginBottom = `${run.distBottom ?? 6}px`;
|
|
558
566
|
const img = doc.createElement("img");
|
|
559
|
-
|
|
567
|
+
applyImageRunSource(img, run.src);
|
|
560
568
|
img.width = run.width;
|
|
561
569
|
img.height = run.height;
|
|
562
570
|
if (run.alt) img.alt = run.alt;
|
|
@@ -1241,7 +1249,7 @@ function renderLine(block, line, alignment, doc, options) {
|
|
|
1241
1249
|
}
|
|
1242
1250
|
}
|
|
1243
1251
|
lineEl.style.whiteSpace = "pre";
|
|
1244
|
-
lineEl.style.overflow = "visible";
|
|
1252
|
+
lineEl.style.overflow = block.attrs?.suppressEmptyParagraphHeight ? "hidden" : "visible";
|
|
1245
1253
|
let tabContext;
|
|
1246
1254
|
const hasScaledTextRun = runsForLine.some((run) => (isTextRun(run) || isFieldRun(run) || isMathRun(run)) && getHorizontalScaleFactor(run.horizontalScale) !== 1);
|
|
1247
1255
|
const measureText = collapsedSpaceMeasureText ?? (hasTabRuns || hasScaledTextRun ? createTextMeasurer(doc) : void 0);
|
|
@@ -1285,7 +1293,11 @@ function renderLine(block, line, alignment, doc, options) {
|
|
|
1285
1293
|
break;
|
|
1286
1294
|
}
|
|
1287
1295
|
}
|
|
1288
|
-
|
|
1296
|
+
const authoredEndpoint = currentX + tabResult.width + followingWidthForCheck;
|
|
1297
|
+
const activeContentRightEdge = options?.contentWidthPx === void 0 ? void 0 : options.contentWidthPx - (options.floatingMargins?.rightMargin ?? 0);
|
|
1298
|
+
const preservesAuthoredEndStop = activeContentRightEdge !== void 0 && tabResult.alignment === "end" && authoredEndpoint <= activeContentRightEdge + RIGHT_EDGE_EPSILON_PX;
|
|
1299
|
+
const preservesAuthoredEndStopPastIndent = lineRightEdgeX !== void 0 && preservesAuthoredEndStop && authoredEndpoint > lineRightEdgeX + RIGHT_EDGE_EPSILON_PX;
|
|
1300
|
+
if (lineRightEdgeX !== void 0 && options?.isRtl !== true && tabResult.alignment === "end" && !hasFollowingTab && !preservesAuthoredEndStopPastIndent && authoredEndpoint >= lineRightEdgeX - RIGHT_EDGE_EPSILON_PX) {
|
|
1289
1301
|
lineEl.style.display = "flex";
|
|
1290
1302
|
lineEl.style.alignItems = "baseline";
|
|
1291
1303
|
lineEl.style.whiteSpace = "pre";
|
|
@@ -1320,10 +1332,8 @@ function renderLine(block, line, alignment, doc, options) {
|
|
|
1320
1332
|
break;
|
|
1321
1333
|
}
|
|
1322
1334
|
let tabWidth = tabResult.width;
|
|
1323
|
-
const activeContentRightEdge = options?.contentWidthPx === void 0 ? void 0 : options.contentWidthPx - (options.floatingMargins?.rightMargin ?? 0);
|
|
1324
|
-
const preservesLogicalRtlEndStop = options?.isRtl === true && tabResult.alignment === "end" && activeContentRightEdge !== void 0 && currentX + tabWidth + followingWidthForCheck <= activeContentRightEdge + RIGHT_EDGE_EPSILON_PX;
|
|
1325
1335
|
const landsOnLeftIndent = tabResult.alignment === "start" && tabLeftIndentPx > 0 && Math.abs(currentX + tabWidth - tabLeftIndentPx) <= RIGHT_EDGE_EPSILON_PX;
|
|
1326
|
-
if (!
|
|
1336
|
+
if (!preservesAuthoredEndStop && !landsOnLeftIndent && lineRightEdgeX !== void 0 && canClampTabToRightEdge(tabResult.alignment, i > 0, runsForLine.slice(0, i).some(isTabRun), options?.isLastLine === true) && currentX + tabWidth + followingWidthForCheck > lineRightEdgeX) tabWidth = Math.max(1, lineRightEdgeX - currentX - followingWidthForCheck);
|
|
1327
1337
|
const tabEl = renderTabRun(run, doc, tabWidth, tabResult.leader);
|
|
1328
1338
|
lineEl.append(tabEl);
|
|
1329
1339
|
currentX += tabWidth;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { resolveFontFamily } from "../utils/fontResolver.js";
|
|
2
2
|
import { applySanitizedImageSrc } from "../utils/sanitizeImageSrc.js";
|
|
3
|
+
import { pointsToPixels } from "../utils/units.js";
|
|
3
4
|
//#region src/layout-painter/renderWatermark.ts
|
|
4
5
|
const WATERMARK_CLASS = "layout-page-watermark";
|
|
6
|
+
const PICTURE_WASHOUT_OPACITY = .18;
|
|
5
7
|
/**
|
|
6
8
|
* Build the watermark overlay element for a page. Returns `null` when
|
|
7
9
|
* the watermark is a picture without a resolved `imageSrc` (the
|
|
@@ -51,10 +53,15 @@ function renderPictureWatermark(watermark, imageSrc, doc) {
|
|
|
51
53
|
applySanitizedImageSrc(img, imageSrc);
|
|
52
54
|
img.alt = "";
|
|
53
55
|
img.setAttribute("aria-hidden", "true");
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
if (watermark.widthPt !== void 0 && watermark.heightPt !== void 0) {
|
|
57
|
+
img.style.width = `${pointsToPixels(watermark.widthPt)}px`;
|
|
58
|
+
img.style.height = `${pointsToPixels(watermark.heightPt)}px`;
|
|
59
|
+
} else {
|
|
60
|
+
const scalePct = (watermark.scale ?? 1) * 100;
|
|
61
|
+
img.style.maxWidth = `${scalePct}%`;
|
|
62
|
+
img.style.maxHeight = `${scalePct}%`;
|
|
63
|
+
}
|
|
64
|
+
img.style.opacity = String(watermark.washout === false ? 1 : PICTURE_WASHOUT_OPACITY);
|
|
58
65
|
img.style.objectFit = "contain";
|
|
59
66
|
return img;
|
|
60
67
|
}
|
package/dist/model.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { document_d_exports } from "./types/document.js";
|
|
2
|
-
import { DeriveBlockIdInput, FolioBlockId, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
|
|
2
|
+
import { DeriveBlockIdInput, FolioBlockId, currentFolioBlockId, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
|
|
3
3
|
import { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, normalizeShapeTextAnchor } from "./types/documentEnumValues.js";
|
|
4
4
|
import { types_d_exports } from "./layout-engine/types.js";
|
|
5
5
|
import { measureTypes_d_exports } from "./layout-engine/measure/measureTypes.js";
|
|
6
6
|
export * from "@stll/docx-core/model";
|
|
7
7
|
declare namespace model_d_exports {
|
|
8
|
-
export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, DeriveBlockIdInput, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, FolioBlockId, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_d_exports as Layout, measureTypes_d_exports as Measure, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
|
|
8
|
+
export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, DeriveBlockIdInput, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, FolioBlockId, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_d_exports as Layout, measureTypes_d_exports as Measure, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, currentFolioBlockId, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
|
|
9
9
|
}
|
|
10
10
|
//#endregion
|
|
11
|
-
export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, DeriveBlockIdInput, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, FolioBlockId, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_d_exports as Layout, type measureTypes_d_exports as Measure, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
|
|
11
|
+
export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, DeriveBlockIdInput, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, FolioBlockId, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_d_exports as Layout, type measureTypes_d_exports as Measure, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, currentFolioBlockId, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
|
package/dist/model.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { types_exports } from "./layout-engine/types.js";
|
|
2
|
-
import { deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
|
|
2
|
+
import { currentFolioBlockId, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
|
|
3
3
|
import { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, normalizeShapeTextAnchor } from "./types/documentEnumValues.js";
|
|
4
|
-
export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_exports as Layout, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
|
|
4
|
+
export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_exports as Layout, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, currentFolioBlockId, deriveBlankBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isBlankFolioBlockId, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
|
|
@@ -91,6 +91,11 @@ const RUN_FORMATTING_OVERRIDE_BOOLEAN_KEYS = [
|
|
|
91
91
|
"outline"
|
|
92
92
|
];
|
|
93
93
|
const RUN_FORMATTING_OVERRIDE_FALSE_KEYS = ["doubleStrike", "rtl"];
|
|
94
|
+
const RUN_FORMATTING_OVERRIDE_DIRECT_FONT_PROPERTIES = [
|
|
95
|
+
"fontFamily",
|
|
96
|
+
"fontSize",
|
|
97
|
+
"color"
|
|
98
|
+
];
|
|
94
99
|
const SECTION_ORIENTATIONS = ["portrait", "landscape"];
|
|
95
100
|
const SECTION_START_TYPES = [
|
|
96
101
|
"continuous",
|
|
@@ -678,6 +683,12 @@ const readRunFormattingOverrideMarkAttrs = (mark) => {
|
|
|
678
683
|
optionalNumber(attrs, "fontSizeCs", "runFormattingOverride.attrs.fontSizeCs", issues);
|
|
679
684
|
optionalBoolean(attrs, "cs", "runFormattingOverride.attrs.cs", issues);
|
|
680
685
|
optionalOneOf(attrs, "underline", "runFormattingOverride.attrs.underline", issues, ["none"]);
|
|
686
|
+
optionalOneOfArray(attrs, "directFontProperties", "runFormattingOverride.attrs.directFontProperties", issues, RUN_FORMATTING_OVERRIDE_DIRECT_FONT_PROPERTIES);
|
|
687
|
+
const directFontProperties = attrs["directFontProperties"];
|
|
688
|
+
if (Array.isArray(directFontProperties) && new Set(directFontProperties).size !== directFontProperties.length) issues.push({
|
|
689
|
+
path: "runFormattingOverride.attrs.directFontProperties",
|
|
690
|
+
message: "Expected unique direct font properties."
|
|
691
|
+
});
|
|
681
692
|
return attrsResult(attrs, issues);
|
|
682
693
|
};
|
|
683
694
|
const expectRunFormattingOverrideMarkAttrs = (mark) => expectCachedMarkAttrs(mark, runFormattingOverrideAttrsCache, readRunFormattingOverrideMarkAttrs, "run formatting override attrs");
|