wordinweb 0.1.10 → 0.1.11
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 +6 -2
- package/dist/index.d.ts +27 -8
- package/dist/index.js +799 -193
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2457,6 +2457,8 @@ function parseRunProps(rPr, ctx) {
|
|
|
2457
2457
|
else if (vertAlign === "baseline") props.verticalAlign = "baseline";
|
|
2458
2458
|
const spacing = intAttr(child(rPr, "spacing"), "val");
|
|
2459
2459
|
if (spacing !== void 0) props.letterSpacing = twipsToPx(spacing);
|
|
2460
|
+
const kern = intAttr(child(rPr, "kern"), "val");
|
|
2461
|
+
if (kern !== void 0) props.kerningThreshold = kern > 0 ? halfPtToPx(kern) : null;
|
|
2460
2462
|
const wScale = intAttr(child(rPr, "w"), "val");
|
|
2461
2463
|
if (wScale !== void 0 && wScale > 0 && wScale !== 100) props.textScale = wScale / 100;
|
|
2462
2464
|
const fitText = intAttr(child(rPr, "fitText"), "val");
|
|
@@ -3417,6 +3419,17 @@ function parseParagraph(p, ctx) {
|
|
|
3417
3419
|
parseParaChildren(p, ctx, para.children, field, bookmarks);
|
|
3418
3420
|
if (bookmarks.length > 0) para.bookmarks = bookmarks;
|
|
3419
3421
|
flushField(field);
|
|
3422
|
+
const visibleContent = para.children.flatMap(
|
|
3423
|
+
(paraChild) => (paraChild.type === "run" ? [paraChild] : paraChild.runs).flatMap(
|
|
3424
|
+
(run) => run.content.filter((content) => content.kind !== "text" || content.text.length > 0)
|
|
3425
|
+
)
|
|
3426
|
+
);
|
|
3427
|
+
if (visibleContent.length === 1 && visibleContent[0].kind === "math") {
|
|
3428
|
+
const node = visibleContent[0].nodes.length === 1 ? visibleContent[0].nodes[0] : void 0;
|
|
3429
|
+
if (node?.t === "frac" && node.num.every((part) => part.t === "run") && node.den.every((part) => part.t === "run")) {
|
|
3430
|
+
visibleContent[0].display = true;
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3420
3433
|
suppressTocHyperlinkFormatting(para);
|
|
3421
3434
|
if (ctx.revisionView !== "markup" && pPr) {
|
|
3422
3435
|
const markRPr = child(pPr, "rPr");
|
|
@@ -3659,13 +3672,14 @@ function parseParaChildren(parent, ctx, out, field, bookmarks) {
|
|
|
3659
3672
|
const nodes = parseOmml(el16);
|
|
3660
3673
|
if (nodes.length > 0) {
|
|
3661
3674
|
const display = ln === "oMathPara";
|
|
3675
|
+
const multiEquationDisplay = display && children(el16, "oMath").length > 3;
|
|
3662
3676
|
const jcVal = display ? attr(child(child(el16, "oMathParaPr"), "jc"), "val") : void 0;
|
|
3663
3677
|
const jc = jcVal === "left" || jcVal === "right" || jcVal === "center" || jcVal === "centerGroup" ? jcVal : void 0;
|
|
3664
3678
|
const content = [];
|
|
3665
3679
|
let segment = [];
|
|
3666
3680
|
const flushMath = () => {
|
|
3667
3681
|
if (segment.length === 0) return;
|
|
3668
|
-
content.push({ kind: "math", nodes: segment, src: el16, display, jc });
|
|
3682
|
+
content.push({ kind: "math", nodes: segment, src: el16, display, multiEquationDisplay, jc });
|
|
3669
3683
|
segment = [];
|
|
3670
3684
|
};
|
|
3671
3685
|
for (const node of nodes) {
|
|
@@ -3896,6 +3910,9 @@ function parseRun(r, ctx, field, suppressedObjects) {
|
|
|
3896
3910
|
case "tab":
|
|
3897
3911
|
run.content.push({ kind: "tab" });
|
|
3898
3912
|
break;
|
|
3913
|
+
case "pgNum":
|
|
3914
|
+
run.content.push({ kind: "field", instruction: "PAGE", cachedResult: "" });
|
|
3915
|
+
break;
|
|
3899
3916
|
case "drawing": {
|
|
3900
3917
|
const img = parseDrawing(el16, ctx);
|
|
3901
3918
|
if (img) {
|
|
@@ -3943,7 +3960,7 @@ function parseRun(r, ctx, field, suppressedObjects) {
|
|
|
3943
3960
|
let code = parseInt(charHex, 16);
|
|
3944
3961
|
if (code >= 61440) code -= 61440;
|
|
3945
3962
|
const font = attr(el16, "font") ?? "";
|
|
3946
|
-
const mapped = /wingdings|webdings
|
|
3963
|
+
const mapped = /^symbol$/i.test(font) ? SYMBOL_TEXT_CHAR_MAP[code] : /wingdings|webdings/i.test(font) ? SYMBOL_CHAR_MAP[code] : void 0;
|
|
3947
3964
|
run.content.push({ kind: "text", text: mapped ?? String.fromCharCode(code) });
|
|
3948
3965
|
}
|
|
3949
3966
|
break;
|
|
@@ -4354,7 +4371,8 @@ function parseDrawing(drawing, ctx) {
|
|
|
4354
4371
|
const pctEl = el16 ? el16.children.find((c) => localName(c.name).startsWith("pct")) : void 0;
|
|
4355
4372
|
if (!pctEl) return void 0;
|
|
4356
4373
|
const rf = attr(el16, "relativeFrom");
|
|
4357
|
-
|
|
4374
|
+
const pct = (parseInt(pctEl.text, 10) || 0) / 1e5;
|
|
4375
|
+
return pct > 0 ? { pct, rel: rf === "page" ? "page" : "margin" } : void 0;
|
|
4358
4376
|
};
|
|
4359
4377
|
const spPr = child(textboxEl, "spPr");
|
|
4360
4378
|
const txbxOwn = child(textboxEl, "txbx");
|
|
@@ -4821,7 +4839,8 @@ function collectDiagramShapes(dspRoot, ctx, out, dx, dy) {
|
|
|
4821
4839
|
height: emuToPx(th),
|
|
4822
4840
|
blocks,
|
|
4823
4841
|
insets: { l: insetOf("lIns", 9.6), t: insetOf("tIns", 4.8), r: insetOf("rIns", 9.6), b: insetOf("bIns", 4.8) },
|
|
4824
|
-
textAnchor: anchorAttr === "ctr" ? "middle" : anchorAttr === "b" ? "bottom" : "top"
|
|
4842
|
+
textAnchor: anchorAttr === "ctr" ? "middle" : anchorAttr === "b" ? "bottom" : "top",
|
|
4843
|
+
paintOffsetY: 0.75
|
|
4825
4844
|
});
|
|
4826
4845
|
}
|
|
4827
4846
|
}
|
|
@@ -4907,6 +4926,8 @@ function drawingMLRun(r, ctx) {
|
|
|
4907
4926
|
const props = {};
|
|
4908
4927
|
const sz = rPr ? intAttr(rPr, "sz") : void 0;
|
|
4909
4928
|
props.size = ptToPx((sz ?? 1800) / 100);
|
|
4929
|
+
const kern = rPr ? intAttr(rPr, "kern") : void 0;
|
|
4930
|
+
if (kern !== void 0) props.kerningThreshold = kern > 0 ? ptToPx(kern / 100) : null;
|
|
4910
4931
|
if (rPr && attr(rPr, "b") === "1") props.bold = true;
|
|
4911
4932
|
if (rPr && attr(rPr, "i") === "1") props.italic = true;
|
|
4912
4933
|
const u = rPr ? attr(rPr, "u") : void 0;
|
|
@@ -5351,6 +5372,8 @@ function parseCell(tc, ctx) {
|
|
|
5351
5372
|
if (tcW && attr(tcW, "type") === "dxa") {
|
|
5352
5373
|
const w = intAttr(tcW, "w");
|
|
5353
5374
|
if (w) props.width = twipsToPx(w);
|
|
5375
|
+
} else if (tcW && attr(tcW, "type") === "auto") {
|
|
5376
|
+
props.widthAuto = true;
|
|
5354
5377
|
}
|
|
5355
5378
|
const borders = child(tcPr, "tcBorders");
|
|
5356
5379
|
if (borders) {
|
|
@@ -5726,6 +5749,9 @@ var DocxDocument = class _DocxDocument {
|
|
|
5726
5749
|
/** Note content by note id (render-only; sources stripped). */
|
|
5727
5750
|
this.footnotes = /* @__PURE__ */ new Map();
|
|
5728
5751
|
this.endnotes = /* @__PURE__ */ new Map();
|
|
5752
|
+
/** The separator paragraph controls the gap between its rule and the first
|
|
5753
|
+
* footnote. */
|
|
5754
|
+
this.footnoteSeparator = [];
|
|
5729
5755
|
/** `_Ref` cross-reference bookmark ranges (name → captured runs). REF
|
|
5730
5756
|
* fields re-render the referenced text from these — Word recomputes REF on
|
|
5731
5757
|
* open, so the cached field result in the file is stale. */
|
|
@@ -5842,6 +5868,8 @@ var DocxDocument = class _DocxDocument {
|
|
|
5842
5868
|
if (!docRoot) throw new Error(`Missing ${docPart} in package`);
|
|
5843
5869
|
this.docRoot = docRoot;
|
|
5844
5870
|
this.rememberOriginalXml(docPart, docRoot);
|
|
5871
|
+
const coreProperties = this.readXmlOptional("docProps/core.xml");
|
|
5872
|
+
this.hydrateCorePropertyControls(docRoot, coreProperties);
|
|
5845
5873
|
this.repairLegacyWordInWebObjects();
|
|
5846
5874
|
this.documentRels = parseRelationships(this.relsRoot ?? void 0, docPart);
|
|
5847
5875
|
if (settings) {
|
|
@@ -5884,6 +5912,7 @@ var DocxDocument = class _DocxDocument {
|
|
|
5884
5912
|
if (!root) continue;
|
|
5885
5913
|
const partRels = parseRelationships(this.readXmlOptional(relsPathFor(rel.target)), rel.target);
|
|
5886
5914
|
this.rememberOriginalXml(rel.target, root);
|
|
5915
|
+
this.hydrateCorePropertyControls(root, coreProperties);
|
|
5887
5916
|
this.hfParts.push({ relId: rel.id, target: rel.target, root, isHeader, rels: partRels });
|
|
5888
5917
|
}
|
|
5889
5918
|
for (const rel of this.documentRels.values()) {
|
|
@@ -5897,6 +5926,12 @@ var DocxDocument = class _DocxDocument {
|
|
|
5897
5926
|
this.footnotesPart = rel.target;
|
|
5898
5927
|
this.footnotesRoot = root;
|
|
5899
5928
|
this.footnotesRels = partRels;
|
|
5929
|
+
const separator = root.children.find(
|
|
5930
|
+
(item) => localName(item.name) === "footnote" && attr(item, "type") === "separator"
|
|
5931
|
+
);
|
|
5932
|
+
if (separator) {
|
|
5933
|
+
this.footnoteSeparator.push(...parseBlocks(separator, { ...this.ctxBase, rels: partRels }));
|
|
5934
|
+
}
|
|
5900
5935
|
}
|
|
5901
5936
|
const notes = parseNotesPart(root, { ...this.ctxBase, rels: partRels }, isFn);
|
|
5902
5937
|
for (const [id, blocks] of notes) (isFn ? this.footnotes : this.endnotes).set(id, blocks);
|
|
@@ -5911,6 +5946,37 @@ var DocxDocument = class _DocxDocument {
|
|
|
5911
5946
|
this._packageResourceVersion++;
|
|
5912
5947
|
this._layoutGlobalSig = null;
|
|
5913
5948
|
}
|
|
5949
|
+
/** Resolve content controls mapped to standard package core properties.
|
|
5950
|
+
* Word refreshes these bindings on open, so the serialized sdtContent can
|
|
5951
|
+
* be stale even though the visible value comes from docProps/core.xml. */
|
|
5952
|
+
hydrateCorePropertyControls(root, coreProperties) {
|
|
5953
|
+
if (!coreProperties) return;
|
|
5954
|
+
const textNodes = (element) => {
|
|
5955
|
+
const out = localName(element.name) === "t" ? [element] : [];
|
|
5956
|
+
for (const item of element.children) out.push(...textNodes(item));
|
|
5957
|
+
return out;
|
|
5958
|
+
};
|
|
5959
|
+
const walk2 = (element) => {
|
|
5960
|
+
if (localName(element.name) === "sdt") {
|
|
5961
|
+
const binding = child(child(element, "sdtPr"), "dataBinding");
|
|
5962
|
+
const xpath = attr(binding, "xpath") ?? "";
|
|
5963
|
+
const propertyMatch = /\/(?:[^/:]+:)?([A-Za-z_][\w.-]*)(?:\[\d+\])?\s*$/.exec(xpath);
|
|
5964
|
+
if (xpath.includes("coreProperties") && propertyMatch) {
|
|
5965
|
+
const property = coreProperties.children.find(
|
|
5966
|
+
(item) => localName(item.name) === propertyMatch[1]
|
|
5967
|
+
);
|
|
5968
|
+
const content = child(element, "sdtContent");
|
|
5969
|
+
const targets = content ? textNodes(content) : [];
|
|
5970
|
+
if (property?.text && targets.length > 0) {
|
|
5971
|
+
targets[0].text = property.text;
|
|
5972
|
+
for (const target of targets.slice(1)) target.text = "";
|
|
5973
|
+
}
|
|
5974
|
+
}
|
|
5975
|
+
}
|
|
5976
|
+
for (const item of element.children) walk2(item);
|
|
5977
|
+
};
|
|
5978
|
+
walk2(root);
|
|
5979
|
+
}
|
|
5914
5980
|
/** Repair only objects emitted by older WordInWeb builds that Word rejects. */
|
|
5915
5981
|
repairLegacyWordInWebObjects() {
|
|
5916
5982
|
const raw = this.pkg.raw();
|
|
@@ -7992,7 +8058,7 @@ var BAKED_FONT_METRICS = {
|
|
|
7992
8058
|
// ../core/src/layout/measure.ts
|
|
7993
8059
|
function fontKey(font) {
|
|
7994
8060
|
const paint = font.paintFamily && font.paintFamily !== font.family ? `${font.paintFamily}>` : "";
|
|
7995
|
-
return `${font.bold ? "bold " : ""}${font.italic ? "italic " : ""}${font.size}px ${paint}${font.family}`;
|
|
8061
|
+
return `${font.bold ? "bold " : ""}${font.italic ? "italic " : ""}${font.kerning ? "kern " : ""}${font.size}px ${paint}${font.family}`;
|
|
7996
8062
|
}
|
|
7997
8063
|
var METRIC_SUBSTITUTES = {
|
|
7998
8064
|
calibri: "Carlito",
|
|
@@ -8137,6 +8203,23 @@ function hasCambriaMath() {
|
|
|
8137
8203
|
}
|
|
8138
8204
|
return _cambriaMath;
|
|
8139
8205
|
}
|
|
8206
|
+
var _segoeUIEmoji;
|
|
8207
|
+
function hasSegoeUIEmoji() {
|
|
8208
|
+
if (_segoeUIEmoji !== void 0) return _segoeUIEmoji;
|
|
8209
|
+
try {
|
|
8210
|
+
const canvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(1, 1) : typeof document !== "undefined" ? document.createElement("canvas") : null;
|
|
8211
|
+
const ctx = canvas?.getContext("2d");
|
|
8212
|
+
if (!ctx) return _segoeUIEmoji = false;
|
|
8213
|
+
ctx.font = '48px "Segoe UI Emoji", sans-serif';
|
|
8214
|
+
const requested = ctx.measureText("\u263A");
|
|
8215
|
+
ctx.font = "48px sans-serif";
|
|
8216
|
+
const fallback = ctx.measureText("\u263A");
|
|
8217
|
+
_segoeUIEmoji = Math.abs(requested.width - fallback.width) > 0.01 || Math.abs((requested.actualBoundingBoxRight ?? 0) - (fallback.actualBoundingBoxRight ?? 0)) > 0.01 || Math.abs((requested.actualBoundingBoxAscent ?? 0) - (fallback.actualBoundingBoxAscent ?? 0)) > 0.01;
|
|
8218
|
+
} catch {
|
|
8219
|
+
_segoeUIEmoji = false;
|
|
8220
|
+
}
|
|
8221
|
+
return _segoeUIEmoji;
|
|
8222
|
+
}
|
|
8140
8223
|
function cambriaMathDescentShare() {
|
|
8141
8224
|
return 0.238;
|
|
8142
8225
|
}
|
|
@@ -8157,11 +8240,12 @@ var CanvasMeasurer = class {
|
|
|
8157
8240
|
}
|
|
8158
8241
|
setFont(font) {
|
|
8159
8242
|
const css = cssFont(font);
|
|
8160
|
-
|
|
8243
|
+
const key = `${css}\0${font.kerning ? "normal" : "none"}`;
|
|
8244
|
+
if (key !== this.currentFont) {
|
|
8161
8245
|
this.ctx.font = css;
|
|
8162
|
-
this.ctx.fontKerning = "none";
|
|
8246
|
+
this.ctx.fontKerning = font.kerning ? "normal" : "none";
|
|
8163
8247
|
this.ctx.textRendering = "optimizeSpeed";
|
|
8164
|
-
this.currentFont =
|
|
8248
|
+
this.currentFont = key;
|
|
8165
8249
|
}
|
|
8166
8250
|
}
|
|
8167
8251
|
width(text, font, letterSpacing = 0) {
|
|
@@ -8265,6 +8349,8 @@ function createMeasurer() {
|
|
|
8265
8349
|
// ../core/src/layout/math.ts
|
|
8266
8350
|
var SCRIPT_SCALE = 0.73;
|
|
8267
8351
|
var SCRIPT_SCRIPT_SCALE = 0.6;
|
|
8352
|
+
var EMPTY_SCRIPT_ADVANCE = 0.89;
|
|
8353
|
+
var EMPTY_SUP_ADVANCE = 0.84;
|
|
8268
8354
|
var floorHalfPt = (px) => Math.floor(px * 0.75 * 2 + 1e-6) / 2 / 0.75;
|
|
8269
8355
|
var scriptSize = (size, floor) => Math.max(floorHalfPt(size * SCRIPT_SCALE), floor);
|
|
8270
8356
|
var SUP_RAISE = 4 / 11;
|
|
@@ -8276,6 +8362,7 @@ var RULE_THICK = 0.75 / 11;
|
|
|
8276
8362
|
var BIN_OP_SPACE = 0.25;
|
|
8277
8363
|
var FUNC_NAME_SPACE = 0.18;
|
|
8278
8364
|
var COMMA_SPACE = 0.17;
|
|
8365
|
+
var SEMICOLON_SPACE = 0.153;
|
|
8279
8366
|
var FRAC_PAD = 0.06;
|
|
8280
8367
|
var NARY_SUM_RAISE = 0.5 / 11;
|
|
8281
8368
|
var NARY_INT_DROP = 0.5 / 11;
|
|
@@ -8294,10 +8381,11 @@ var MAT_COL_GAP_STIX = 12.2 / 11;
|
|
|
8294
8381
|
var MAT_COL_GAP_REAL_INLINE = 11.4 / 11;
|
|
8295
8382
|
var MAT_COL_GAP_REAL_DISPLAY = 11.13 / 11;
|
|
8296
8383
|
var DLM_PAD_STIX = 1.2 / 11;
|
|
8297
|
-
var DLM_PAD_REAL =
|
|
8384
|
+
var DLM_PAD_REAL = 1 / 11;
|
|
8298
8385
|
var matColGap = (display) => hasCambriaMath() ? display ? MAT_COL_GAP_REAL_DISPLAY : MAT_COL_GAP_REAL_INLINE : MAT_COL_GAP_STIX;
|
|
8299
8386
|
var dlmPad = () => hasCambriaMath() ? DLM_PAD_REAL : DLM_PAD_STIX;
|
|
8300
8387
|
var DLM_MAT_END_PAD = 0.3 / 11;
|
|
8388
|
+
var DLM_TRAILING_SPACE_PAD = 0.125;
|
|
8301
8389
|
var FRAC_NUM_RAISE_D = 1550 / 2048;
|
|
8302
8390
|
var FRAC_DEN_DROP_D = 1370 / 2048;
|
|
8303
8391
|
var FRAC_DEN_DLM_EXTRA = 133 / 2048;
|
|
@@ -8311,6 +8399,8 @@ var INT_D_INK = 1.3584 + 0.7925;
|
|
|
8311
8399
|
var INT_D_ASC = 1.3584;
|
|
8312
8400
|
var INT_D_DESC = 0.7925;
|
|
8313
8401
|
var INT_D_ADV = 0.8066;
|
|
8402
|
+
var INT_D_LIMIT_OVERLAP = 0.37;
|
|
8403
|
+
var INT_D_SUP_STAGGER = 0.375;
|
|
8314
8404
|
var INT_D_ANCHOR = (1.3584 - 0.877 * (INT_D_INK / INT_TEXT_INK)) / (1 - INT_D_INK / INT_TEXT_INK);
|
|
8315
8405
|
var MATH_FONT = "Cambria Math";
|
|
8316
8406
|
function mathText(text, normal = false) {
|
|
@@ -8388,7 +8478,7 @@ var BRACKET_RE = /[()[\]{}]/;
|
|
|
8388
8478
|
var SUP_DLM_DROP = 460 / 2048;
|
|
8389
8479
|
var ITALIC_MATH_RE = /[\u{1D434}-\u{1D467}ℎ]/u;
|
|
8390
8480
|
var SUP_KERN_IN = 0;
|
|
8391
|
-
var
|
|
8481
|
+
var SCRIPT_TRAIL_GROUPED_DISPLAY = 0.12;
|
|
8392
8482
|
function containsDlm(nodes) {
|
|
8393
8483
|
for (const n of nodes) {
|
|
8394
8484
|
switch (n.t) {
|
|
@@ -8473,9 +8563,21 @@ function containsBlocky(nodes) {
|
|
|
8473
8563
|
}
|
|
8474
8564
|
return false;
|
|
8475
8565
|
}
|
|
8476
|
-
function layoutMath(nodes, baseSize, measurer, display = false) {
|
|
8566
|
+
function layoutMath(nodes, baseSize, measurer, display = false, fractionPadEm = FRAC_PAD, multiEquationDisplay = false) {
|
|
8477
8567
|
const box = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [], display, baseSize };
|
|
8478
|
-
flow(
|
|
8568
|
+
flow(
|
|
8569
|
+
nodes,
|
|
8570
|
+
baseSize,
|
|
8571
|
+
0,
|
|
8572
|
+
box,
|
|
8573
|
+
measurer,
|
|
8574
|
+
false,
|
|
8575
|
+
display,
|
|
8576
|
+
0,
|
|
8577
|
+
floorHalfPt(baseSize * SCRIPT_SCRIPT_SCALE),
|
|
8578
|
+
fractionPadEm,
|
|
8579
|
+
multiEquationDisplay ? SCRIPT_TRAIL_GROUPED_DISPLAY : 0
|
|
8580
|
+
);
|
|
8479
8581
|
for (const p of box.pieces) {
|
|
8480
8582
|
const m = measurer.metrics(p.font);
|
|
8481
8583
|
p.effAscent = p.ownAscent ?? p.dy + m.ascent;
|
|
@@ -8489,12 +8591,17 @@ function layoutMath(nodes, baseSize, measurer, display = false) {
|
|
|
8489
8591
|
}
|
|
8490
8592
|
return box;
|
|
8491
8593
|
}
|
|
8492
|
-
function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth = 0, scriptFloor = 0) {
|
|
8594
|
+
function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth = 0, scriptFloor = 0, fractionPadEm = FRAC_PAD, scriptTrailEm = 0) {
|
|
8493
8595
|
let prevOperand = false;
|
|
8494
8596
|
for (const node of nodes) {
|
|
8495
8597
|
switch (node.t) {
|
|
8496
8598
|
case "run": {
|
|
8497
8599
|
const font = fontAt(size);
|
|
8600
|
+
if (node.normal && /^\s+$/.test(node.text)) {
|
|
8601
|
+
box.pieces.push({ text: node.text, x: box.width, dy, font });
|
|
8602
|
+
box.width += [...node.text].length * size;
|
|
8603
|
+
break;
|
|
8604
|
+
}
|
|
8498
8605
|
if (node.fname) {
|
|
8499
8606
|
const gap = size * FUNC_NAME_SPACE;
|
|
8500
8607
|
if (prevOperand) box.width += gap;
|
|
@@ -8506,16 +8613,19 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8506
8613
|
}
|
|
8507
8614
|
const medGap = size * BIN_OP_SPACE;
|
|
8508
8615
|
const relGap = display ? medGap : size * (5 / 18);
|
|
8509
|
-
const toks = node.text.split(/([
|
|
8616
|
+
const toks = node.text.split(/([=+−×÷<>≤≥±≠,;\-])/).filter((s) => s.length > 0);
|
|
8510
8617
|
for (let ti = 0; ti < toks.length; ti++) {
|
|
8511
8618
|
const tok = toks[ti];
|
|
8512
|
-
if (tok === ",") {
|
|
8619
|
+
if (tok === "," || tok === ";") {
|
|
8513
8620
|
const text2 = mathText(tok, node.normal);
|
|
8514
8621
|
box.pieces.push({ text: text2, x: box.width, dy, font });
|
|
8515
8622
|
box.width += measurer.width(text2, font);
|
|
8516
8623
|
const nextIsSpace = ti + 1 < toks.length && /^\s/.test(toks[ti + 1]);
|
|
8517
|
-
|
|
8518
|
-
|
|
8624
|
+
const spacedSemicolon = tok === ";" && (ti === toks.length - 1 || !BIN_OPS.has(toks[ti + 1]));
|
|
8625
|
+
if (!tight && !nextIsSpace && (tok === "," || spacedSemicolon)) {
|
|
8626
|
+
box.width += size * (tok === "," ? COMMA_SPACE : SEMICOLON_SPACE);
|
|
8627
|
+
}
|
|
8628
|
+
prevOperand = tok === ";";
|
|
8519
8629
|
continue;
|
|
8520
8630
|
}
|
|
8521
8631
|
const isOp = BIN_OPS.has(tok);
|
|
@@ -8539,7 +8649,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8539
8649
|
case "sup":
|
|
8540
8650
|
case "sub": {
|
|
8541
8651
|
const beforeBase = box.pieces.length;
|
|
8542
|
-
flow(node.base, size, dy, box, measurer, tight, display, breakDepth + 2, scriptFloor);
|
|
8652
|
+
flow(node.base, size, dy, box, measurer, tight, display, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8543
8653
|
let baseInkAsc = 0;
|
|
8544
8654
|
if (node.t === "sup") {
|
|
8545
8655
|
for (let i = beforeBase; i < box.pieces.length; i++) {
|
|
@@ -8554,9 +8664,16 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8554
8664
|
box.width += size * SUP_KERN_IN;
|
|
8555
8665
|
}
|
|
8556
8666
|
const beforeScript = box.pieces.length;
|
|
8557
|
-
|
|
8667
|
+
const scriptFontSize = scriptSize(size, scriptFloor);
|
|
8668
|
+
if (node.t === "sub" && node.script.length === 0) {
|
|
8669
|
+
box.width += scriptFontSize * EMPTY_SCRIPT_ADVANCE;
|
|
8670
|
+
} else if (node.t === "sup" && node.script.length === 0) {
|
|
8671
|
+
box.width += scriptFontSize * EMPTY_SUP_ADVANCE;
|
|
8672
|
+
} else {
|
|
8673
|
+
flow(node.script, scriptFontSize, scriptDy, box, measurer, true, false, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8674
|
+
}
|
|
8558
8675
|
for (let i = beforeScript; i < box.pieces.length; i++) box.pieces[i].script = true;
|
|
8559
|
-
box.width += size *
|
|
8676
|
+
if (display) box.width += size * scriptTrailEm;
|
|
8560
8677
|
prevOperand = true;
|
|
8561
8678
|
break;
|
|
8562
8679
|
}
|
|
@@ -8565,17 +8682,17 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8565
8682
|
const numRaise = display ? size * FRAC_NUM_RAISE_D : size * FRAC_NUM_RAISE;
|
|
8566
8683
|
const denDrop = (display ? size * FRAC_DEN_DROP_D : size * FRAC_DEN_DROP) + (display && containsDlm(node.den) ? size * FRAC_DEN_DLM_EXTRA : 0);
|
|
8567
8684
|
const fracTight = display ? tight : true;
|
|
8568
|
-
const numW = widthOf(node.num, scale, measurer, display, fracTight, scriptFloor);
|
|
8569
|
-
const denW = widthOf(node.den, scale, measurer, display, fracTight, scriptFloor);
|
|
8570
|
-
const pad = size *
|
|
8685
|
+
const numW = widthOf(node.num, scale, measurer, display, fracTight, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8686
|
+
const denW = widthOf(node.den, scale, measurer, display, fracTight, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8687
|
+
const pad = size * fractionPadEm;
|
|
8571
8688
|
const barW = Math.max(numW, denW) + 2 * pad;
|
|
8572
8689
|
const x0 = box.width;
|
|
8573
8690
|
const numBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8574
|
-
flow(node.num, scale, 0, numBox, measurer, fracTight, display, breakDepth + 2, scriptFloor);
|
|
8691
|
+
flow(node.num, scale, 0, numBox, measurer, fracTight, display, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8575
8692
|
for (const p of numBox.pieces) box.pieces.push(rebase(p, x0 + (barW - numW) / 2, dy + numRaise));
|
|
8576
8693
|
for (const r of numBox.rules) box.rules.push({ ...r, x1: x0 + (barW - numW) / 2 + r.x1, x2: x0 + (barW - numW) / 2 + r.x2, dy: dy + numRaise + r.dy });
|
|
8577
8694
|
const denBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8578
|
-
flow(node.den, scale, 0, denBox, measurer, fracTight, display, breakDepth + 2, scriptFloor);
|
|
8695
|
+
flow(node.den, scale, 0, denBox, measurer, fracTight, display, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8579
8696
|
let denDropFinal = denDrop;
|
|
8580
8697
|
if (containsFrac(node.den)) {
|
|
8581
8698
|
let denAsc = 0;
|
|
@@ -8600,7 +8717,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8600
8717
|
case "nary": {
|
|
8601
8718
|
const isInt = "\u222B\u222C\u222D\u222E\u222F\u2230".includes(node.chr);
|
|
8602
8719
|
if (display && !isInt) {
|
|
8603
|
-
naryDisplay(node, size, dy, box, measurer, scriptFloor);
|
|
8720
|
+
naryDisplay(node, size, dy, box, measurer, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8604
8721
|
prevOperand = true;
|
|
8605
8722
|
break;
|
|
8606
8723
|
}
|
|
@@ -8629,20 +8746,24 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8629
8746
|
const intSubDrop = display && visibleSub ? INT_SUB_DROP_D : INT_SUB_DROP;
|
|
8630
8747
|
const supDy = dy + size * (isInt ? intSupRaise : NARY_SUP_RAISE);
|
|
8631
8748
|
const subDy = dy - size * (isInt ? intSubDrop : NARY_SUB_DROP);
|
|
8632
|
-
const supStagger = isInt ? size * INT_SUP_STAGGER : 0;
|
|
8633
|
-
const supW = widthOf(node.sup, scale, measurer, false, true, scriptFloor) + supStagger;
|
|
8634
|
-
const subW = widthOf(node.sub, scale, measurer, false, true, scriptFloor);
|
|
8635
|
-
const x0 = box.width;
|
|
8749
|
+
const supStagger = isInt ? size * (display ? INT_D_SUP_STAGGER : INT_SUP_STAGGER) : 0;
|
|
8750
|
+
const supW = visibleSup ? widthOf(node.sup, scale, measurer, false, true, scriptFloor, fractionPadEm, scriptTrailEm) + supStagger : 0;
|
|
8751
|
+
const subW = visibleSub ? widthOf(node.sub, scale, measurer, false, true, scriptFloor, fractionPadEm, scriptTrailEm) : 0;
|
|
8752
|
+
const x0 = box.width - (display && isInt && (visibleSup || visibleSub) ? size * INT_D_LIMIT_OVERLAP : 0);
|
|
8636
8753
|
const supBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8637
|
-
|
|
8638
|
-
|
|
8639
|
-
|
|
8754
|
+
if (visibleSup) {
|
|
8755
|
+
flow(node.sup, scale, 0, supBox, measurer, true, false, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8756
|
+
for (const pc of supBox.pieces) box.pieces.push(rebase(pc, x0 + supStagger, supDy, true));
|
|
8757
|
+
for (const r of supBox.rules) box.rules.push({ ...r, x1: x0 + supStagger + r.x1, x2: x0 + supStagger + r.x2, dy: supDy + r.dy });
|
|
8758
|
+
}
|
|
8640
8759
|
const subBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8760
|
+
if (visibleSub) {
|
|
8761
|
+
flow(node.sub, scale, 0, subBox, measurer, true, false, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8762
|
+
for (const pc of subBox.pieces) box.pieces.push(rebase(pc, x0, subDy, true));
|
|
8763
|
+
for (const r of subBox.rules) box.rules.push({ ...r, x1: x0 + r.x1, x2: x0 + r.x2, dy: subDy + r.dy });
|
|
8764
|
+
}
|
|
8644
8765
|
box.width = x0 + Math.max(supW, subW) + size * NARY_E_GAP;
|
|
8645
|
-
flow(node.e, size, dy, box, measurer, tight, display, breakDepth + 2, scriptFloor);
|
|
8766
|
+
flow(node.e, size, dy, box, measurer, tight, display, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8646
8767
|
prevOperand = true;
|
|
8647
8768
|
break;
|
|
8648
8769
|
}
|
|
@@ -8652,7 +8773,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8652
8773
|
let coreDesc = 0;
|
|
8653
8774
|
const parts = node.e.map((part) => {
|
|
8654
8775
|
const b = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8655
|
-
flow(part, size, 0, b, measurer, tight, display, breakDepth + 1, scriptFloor);
|
|
8776
|
+
flow(part, size, 0, b, measurer, tight, display, breakDepth + 1, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8656
8777
|
for (const pc of b.pieces) {
|
|
8657
8778
|
const m = measurer.metrics(pc.font);
|
|
8658
8779
|
const asc = pc.ownAscent ?? pc.dy + m.ascent;
|
|
@@ -8708,7 +8829,10 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8708
8829
|
grow = 1;
|
|
8709
8830
|
}
|
|
8710
8831
|
}
|
|
8711
|
-
const
|
|
8832
|
+
const lastPart = node.e[node.e.length - 1];
|
|
8833
|
+
const tail = lastPart?.[lastPart.length - 1];
|
|
8834
|
+
const trailingSpaces = display && tail?.t === "run" && /^\s+$/.test(tail.text) ? [...tail.text].length : 0;
|
|
8835
|
+
const innerPad = size * (matLike ? DLM_MAT_END_PAD : dlmPad()) + size * DLM_TRAILING_SPACE_PAD * trailingSpaces;
|
|
8712
8836
|
const drawDelim = (ch) => {
|
|
8713
8837
|
if (!ch) return;
|
|
8714
8838
|
const asm = asmH !== void 0 ? DLM_ASM_PIECES[ch] : void 0;
|
|
@@ -8778,7 +8902,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8778
8902
|
const cells = node.rows.map(
|
|
8779
8903
|
(row) => row.map((cell) => {
|
|
8780
8904
|
const b = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8781
|
-
flow(cell, size, 0, b, measurer, tight, display, breakDepth + 2, scriptFloor);
|
|
8905
|
+
flow(cell, size, 0, b, measurer, tight, display, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8782
8906
|
for (const pc of b.pieces) {
|
|
8783
8907
|
const m = measurer.metrics(pc.font);
|
|
8784
8908
|
b.ascent = Math.max(b.ascent, pc.dy + m.ascent);
|
|
@@ -8824,7 +8948,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8824
8948
|
const m = measurer.metrics(font);
|
|
8825
8949
|
const ruleThick = Math.max(size * RULE_THICK, 0.75);
|
|
8826
8950
|
const radBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8827
|
-
flow(node.e, size, 0, radBox, measurer, tight, display, breakDepth + 2, scriptFloor);
|
|
8951
|
+
flow(node.e, size, 0, radBox, measurer, tight, display, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8828
8952
|
let radAsc = m.ascent * 0.5;
|
|
8829
8953
|
let radDesc = 0;
|
|
8830
8954
|
for (const pc of radBox.pieces) {
|
|
@@ -8848,7 +8972,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8848
8972
|
const dScale = scriptSize(size, scriptFloor);
|
|
8849
8973
|
box.width += size * RAD_KERN_BEFORE_DEG;
|
|
8850
8974
|
const degBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8851
|
-
flow(node.deg, dScale, 0, degBox, measurer, true, false, breakDepth + 2, scriptFloor);
|
|
8975
|
+
flow(node.deg, dScale, 0, degBox, measurer, true, false, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8852
8976
|
const degDy = dy - radDesc + RAD_DEG_RAISE * signInkH + size * RAD_DEG_ADJ;
|
|
8853
8977
|
for (const pc of degBox.pieces) box.pieces.push(rebase(pc, box.width, degDy, true));
|
|
8854
8978
|
for (const r of degBox.rules) box.rules.push({ ...r, x1: box.width + r.x1, x2: box.width + r.x2, dy: degDy + r.dy });
|
|
@@ -8895,7 +9019,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8895
9019
|
const axis = dy + size * RULE_CENTER;
|
|
8896
9020
|
const rowBoxes = node.rows.map((row) => {
|
|
8897
9021
|
const b = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8898
|
-
flow(row, size, 0, b, measurer, tight, display, breakDepth + 2, scriptFloor);
|
|
9022
|
+
flow(row, size, 0, b, measurer, tight, display, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8899
9023
|
for (const pc of b.pieces) {
|
|
8900
9024
|
const pm = measurer.metrics(pc.font);
|
|
8901
9025
|
b.ascent = Math.max(b.ascent, pc.ownAscent ?? pc.dy + pm.ascent);
|
|
@@ -8925,7 +9049,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8925
9049
|
}
|
|
8926
9050
|
case "acc": {
|
|
8927
9051
|
const before = box.pieces.length;
|
|
8928
|
-
flow(node.e, size, dy, box, measurer, tight, display, breakDepth + 2, scriptFloor);
|
|
9052
|
+
flow(node.e, size, dy, box, measurer, tight, display, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8929
9053
|
if (box.pieces.length > before) {
|
|
8930
9054
|
const last = box.pieces[box.pieces.length - 1];
|
|
8931
9055
|
last.text += node.chr;
|
|
@@ -8937,7 +9061,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8937
9061
|
const isTop = node.pos === "top";
|
|
8938
9062
|
const bScale = isTop ? size : scriptSize(size, scriptFloor);
|
|
8939
9063
|
const baseBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8940
|
-
flow(node.e, bScale, 0, baseBox, measurer, tight, display, breakDepth + 2, scriptFloor);
|
|
9064
|
+
flow(node.e, bScale, 0, baseBox, measurer, tight, display, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8941
9065
|
const baseW = baseBox.width;
|
|
8942
9066
|
const maxVariant = GRP_VARIANTS_EM[GRP_VARIANTS_EM.length - 1] * size;
|
|
8943
9067
|
let braceW = maxVariant;
|
|
@@ -8974,10 +9098,10 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8974
9098
|
case "lim": {
|
|
8975
9099
|
const isLow = node.pos === "low";
|
|
8976
9100
|
const baseBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8977
|
-
flow(node.e, size, 0, baseBox, measurer, tight, display, breakDepth + 2, scriptFloor);
|
|
9101
|
+
flow(node.e, size, 0, baseBox, measurer, tight, display, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8978
9102
|
const lScale = scriptSize(size, scriptFloor);
|
|
8979
9103
|
const limBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8980
|
-
flow(node.lim, lScale, 0, limBox, measurer, true, false, breakDepth + 2, scriptFloor);
|
|
9104
|
+
flow(node.lim, lScale, 0, limBox, measurer, true, false, breakDepth + 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8981
9105
|
const w = Math.max(baseBox.width, limBox.width);
|
|
8982
9106
|
const x0 = box.width;
|
|
8983
9107
|
const baseX = x0 + (w - baseBox.width) / 2;
|
|
@@ -8994,19 +9118,19 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8994
9118
|
}
|
|
8995
9119
|
}
|
|
8996
9120
|
}
|
|
8997
|
-
function naryDisplay(node, size, dy, box, measurer, scriptFloor) {
|
|
9121
|
+
function naryDisplay(node, size, dy, box, measurer, scriptFloor, fractionPadEm, scriptTrailEm) {
|
|
8998
9122
|
const opFont = fontAt(size * NARY_OP_SCALE_D);
|
|
8999
9123
|
const opW = measurer.width(node.chr, opFont);
|
|
9000
9124
|
const scale = scriptSize(size, scriptFloor);
|
|
9001
|
-
const supW = widthOf(node.sup, scale, measurer, false, true, scriptFloor);
|
|
9002
|
-
const subW = widthOf(node.sub, scale, measurer, false, true, scriptFloor);
|
|
9125
|
+
const supW = widthOf(node.sup, scale, measurer, false, true, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
9126
|
+
const subW = widthOf(node.sub, scale, measurer, false, true, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
9003
9127
|
const stackW = Math.max(opW, supW, subW);
|
|
9004
9128
|
const x0 = box.width;
|
|
9005
9129
|
const cx = x0 + stackW / 2;
|
|
9006
9130
|
box.pieces.push({ text: node.chr, x: cx - opW / 2, dy, font: opFont });
|
|
9007
9131
|
if (node.sup.length) {
|
|
9008
9132
|
const supBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
9009
|
-
flow(node.sup, scale, 0, supBox, measurer, true, false, 2, scriptFloor);
|
|
9133
|
+
flow(node.sup, scale, 0, supBox, measurer, true, false, 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
9010
9134
|
const ox = cx - supW / 2;
|
|
9011
9135
|
const oy = dy + size * NARY_OVER_RAISE_D;
|
|
9012
9136
|
for (const pc of supBox.pieces) box.pieces.push(rebase(pc, ox, oy, true));
|
|
@@ -9014,18 +9138,18 @@ function naryDisplay(node, size, dy, box, measurer, scriptFloor) {
|
|
|
9014
9138
|
}
|
|
9015
9139
|
if (node.sub.length) {
|
|
9016
9140
|
const subBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
9017
|
-
flow(node.sub, scale, 0, subBox, measurer, true, false, 2, scriptFloor);
|
|
9141
|
+
flow(node.sub, scale, 0, subBox, measurer, true, false, 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
9018
9142
|
const ux = cx - subW / 2;
|
|
9019
9143
|
const uy = dy - size * NARY_UNDER_DROP_D;
|
|
9020
9144
|
for (const pc of subBox.pieces) box.pieces.push(rebase(pc, ux, uy, true));
|
|
9021
9145
|
for (const r of subBox.rules) box.rules.push({ ...r, x1: ux + r.x1, x2: ux + r.x2, dy: uy + r.dy });
|
|
9022
9146
|
}
|
|
9023
9147
|
box.width = x0 + stackW + size * NARY_E_GAP;
|
|
9024
|
-
flow(node.e, size, dy, box, measurer, false, true, 2, scriptFloor);
|
|
9148
|
+
flow(node.e, size, dy, box, measurer, false, true, 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
9025
9149
|
}
|
|
9026
|
-
function widthOf(nodes, size, measurer, display = false, tight = true, scriptFloor = 0) {
|
|
9150
|
+
function widthOf(nodes, size, measurer, display = false, tight = true, scriptFloor = 0, fractionPadEm = FRAC_PAD, scriptTrailEm = 0) {
|
|
9027
9151
|
const tmp = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
9028
|
-
flow(nodes, size, 0, tmp, measurer, tight, display, 2, scriptFloor);
|
|
9152
|
+
flow(nodes, size, 0, tmp, measurer, tight, display, 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
9029
9153
|
return tmp.width;
|
|
9030
9154
|
}
|
|
9031
9155
|
|
|
@@ -9053,16 +9177,18 @@ function starNumberFormat(instr, n) {
|
|
|
9053
9177
|
}
|
|
9054
9178
|
}
|
|
9055
9179
|
function fontOf(props, fallbackFamily) {
|
|
9180
|
+
const family = props.rtl && props.fontComplex || props.font || fallbackFamily;
|
|
9056
9181
|
let size = props.size ?? 14.666;
|
|
9057
9182
|
if (props.verticalAlign === "superscript" || props.verticalAlign === "subscript") {
|
|
9058
|
-
|
|
9183
|
+
const scale = EA_FAMILY_RE.test(family) ? 0.52 : 0.65;
|
|
9184
|
+
size = Math.round(size * 1.5 * scale) / 1.5;
|
|
9059
9185
|
}
|
|
9060
|
-
const family = props.rtl && props.fontComplex || props.font || fallbackFamily;
|
|
9061
9186
|
return {
|
|
9062
9187
|
family,
|
|
9063
9188
|
size,
|
|
9064
9189
|
bold: props.bold ?? false,
|
|
9065
|
-
italic: props.italic ?? false
|
|
9190
|
+
italic: props.italic ?? false,
|
|
9191
|
+
kerning: props.kerningThreshold !== void 0 && props.kerningThreshold !== null && size >= props.kerningThreshold
|
|
9066
9192
|
};
|
|
9067
9193
|
}
|
|
9068
9194
|
function displayText(text, props) {
|
|
@@ -9077,13 +9203,21 @@ function runPlainText(run) {
|
|
|
9077
9203
|
function isWordAlnum(ch) {
|
|
9078
9204
|
return ch !== void 0 && /[\p{L}\p{Nd}]/u.test(ch);
|
|
9079
9205
|
}
|
|
9080
|
-
function hyphenBreaks(word) {
|
|
9206
|
+
function hyphenBreaks(word, allowNumericEnDash) {
|
|
9081
9207
|
const out = [];
|
|
9208
|
+
let leading = 0;
|
|
9209
|
+
while (word[leading] === "-" || word[leading] === "\u2010") leading++;
|
|
9210
|
+
if (leading >= 2 && isWordAlnum(word[leading])) out.push(leading);
|
|
9082
9211
|
for (let i = 1; i < word.length - 1; i++) {
|
|
9083
9212
|
const ch = word[i];
|
|
9084
|
-
if (
|
|
9085
|
-
|
|
9086
|
-
|
|
9213
|
+
if (ch !== "-" && ch !== "\u2010" && ch !== "\u2013") continue;
|
|
9214
|
+
let end = i + 1;
|
|
9215
|
+
while (word[end] === "-" || word[end] === "\u2010" || word[end] === "\u2013") end++;
|
|
9216
|
+
const wordBefore = isWordAlnum(word[i - 1]) || /^[\)\]\}]$/.test(word[i - 1] ?? "") && isWordAlnum(word[i - 2]);
|
|
9217
|
+
const wordAfter = isWordAlnum(word[end]);
|
|
9218
|
+
const numericEnDash = allowNumericEnDash && ch === "\u2013" && /\p{Nd}/u.test(word[i - 1] ?? "") && /\p{Nd}/u.test(word[end] ?? "");
|
|
9219
|
+
if (ch === "\u2013" ? numericEnDash : wordBefore && wordAfter) out.push(end);
|
|
9220
|
+
i = end - 1;
|
|
9087
9221
|
}
|
|
9088
9222
|
return out;
|
|
9089
9223
|
}
|
|
@@ -9098,6 +9232,7 @@ function isCJK(ch) {
|
|
|
9098
9232
|
return CJK_RE.test(ch);
|
|
9099
9233
|
}
|
|
9100
9234
|
var BALLOT_RE = /[☐☑☒]/;
|
|
9235
|
+
var LEGACY_CHECKBOX_TRAILING_ADVANCE = 2.5 * 96 / 72;
|
|
9101
9236
|
function isBallot(ch) {
|
|
9102
9237
|
return BALLOT_RE.test(ch);
|
|
9103
9238
|
}
|
|
@@ -9183,17 +9318,35 @@ function wrapDisplayMath(box, maxWidth) {
|
|
|
9183
9318
|
});
|
|
9184
9319
|
}
|
|
9185
9320
|
var DEFAULT_TAB = 48;
|
|
9321
|
+
var TABBED_INLINE_MATH_FRAC_PAD = 0.15;
|
|
9186
9322
|
var OVERFLOW_PUNCT = /[.,:;!?)\]}、。,.:;?!)]}」』】〉》]/;
|
|
9187
|
-
var CJK_SPACE_COMPRESS = 0.
|
|
9323
|
+
var CJK_SPACE_COMPRESS = 0.5;
|
|
9188
9324
|
var EA_FAMILY_RE = /simsun|nsimsun|宋体|新宋体|songti|simhei|黑体|heiti|kaiti|楷体|fangsong|仿宋|yahei|雅黑|mingliu|细明|新細明|pmingliu|jhenghei|正黑|pingfang|dengxian|等线|ms (?:p?)(?:mincho|gothic)|mincho|meiryo|yu gothic|yu mincho|batang|gulim|dotum|malgun/i;
|
|
9189
|
-
var JUSTIFY_MAX_COMPRESS = 0.
|
|
9325
|
+
var JUSTIFY_MAX_COMPRESS = 0.29;
|
|
9326
|
+
var JUSTIFY_GRID_MAX_COMPRESS = 0.25;
|
|
9190
9327
|
var JUSTIFY_STRETCH_FACTOR = 0.5;
|
|
9191
9328
|
var TAMIL_GLYPH_SCALE = 0.735;
|
|
9192
9329
|
var TAMIL_BASELINE_DY_EM = 0.136;
|
|
9193
9330
|
var LAO_GLYPH_SCALE = 1.048;
|
|
9331
|
+
function emojiFallbackScale(text, family) {
|
|
9332
|
+
if (family.toLowerCase() !== "segoe ui emoji" || hasSegoeUIEmoji()) return 1;
|
|
9333
|
+
const codepoints = Array.from(text);
|
|
9334
|
+
if (codepoints.some((ch) => {
|
|
9335
|
+
const cp = ch.codePointAt(0) ?? 0;
|
|
9336
|
+
return cp >= 127462 && cp <= 127487;
|
|
9337
|
+
})) return 1;
|
|
9338
|
+
const people = codepoints.filter((ch) => {
|
|
9339
|
+
const cp = ch.codePointAt(0) ?? 0;
|
|
9340
|
+
return cp >= 128102 && cp <= 128105;
|
|
9341
|
+
}).length;
|
|
9342
|
+
if (text.includes("\u200D") && people >= 3) return 1.84;
|
|
9343
|
+
if (/🚀|❤|✅/.test(text)) return 1.39;
|
|
9344
|
+
if (text.includes("\u200D") || /[🏻-🏿]/u.test(text)) return 1.29;
|
|
9345
|
+
return 1;
|
|
9346
|
+
}
|
|
9194
9347
|
var KASHIDA_LOW_EM = 0;
|
|
9195
9348
|
var KASHIDA_MEDIUM_EM = 0.032;
|
|
9196
|
-
var KASHIDA_HIGH_EM = 0.
|
|
9349
|
+
var KASHIDA_HIGH_EM = 0.075;
|
|
9197
9350
|
var BP_CACHES = /* @__PURE__ */ new WeakMap();
|
|
9198
9351
|
var BP_CACHE_MAX = 6e4;
|
|
9199
9352
|
function bpCacheFor(measurer) {
|
|
@@ -9337,6 +9490,7 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9337
9490
|
let curSegments = [{ x: 0, width: contentWidth }];
|
|
9338
9491
|
let curSegIdx = 0;
|
|
9339
9492
|
let curClearY;
|
|
9493
|
+
let curEdgeReserve = 0;
|
|
9340
9494
|
const ls = props.lineSpacing;
|
|
9341
9495
|
const firstFont = atoms.find((a) => a.kind === "frag" || a.kind === "space")?.font;
|
|
9342
9496
|
const natural = firstFont ? measurer.metrics(firstFont).lineHeight * (ls?.rule === "auto" ? ls.value : 1) : 0;
|
|
@@ -9348,6 +9502,7 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9348
9502
|
curSegments = [{ x: 0, width: contentWidth }];
|
|
9349
9503
|
curSegIdx = 0;
|
|
9350
9504
|
curClearY = void 0;
|
|
9505
|
+
curEdgeReserve = 0;
|
|
9351
9506
|
if (boundsAt) {
|
|
9352
9507
|
let guard = 0;
|
|
9353
9508
|
let b = boundsAt(yOff, EST_LINE);
|
|
@@ -9361,6 +9516,7 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9361
9516
|
curSegments = b.segments && b.segments.length > 0 ? b.segments : [{ x: b.x, width: b.width }];
|
|
9362
9517
|
curSegIdx = 0;
|
|
9363
9518
|
curClearY = b.clearY;
|
|
9519
|
+
curEdgeReserve = b.edgeReserve ?? (b.clearY !== void 0 ? 0.75 : 0);
|
|
9364
9520
|
}
|
|
9365
9521
|
void idx;
|
|
9366
9522
|
};
|
|
@@ -9636,7 +9792,10 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9636
9792
|
rawStop = nextTabStop(rawStop.pos, props.tabs, contentWidth - indentRight, doc.defaultTabStop);
|
|
9637
9793
|
}
|
|
9638
9794
|
}
|
|
9639
|
-
|
|
9795
|
+
const explicitBeforeIndent = (props.tabs ?? []).some(
|
|
9796
|
+
(tab) => !tab.clear && tab.align !== "bar" && tab.pos > x + offset + 0.5 && tab.pos < indentLeft - 0.5
|
|
9797
|
+
);
|
|
9798
|
+
if (hanging > 0 && x + offset < indentLeft - 0.5 && !explicitBeforeIndent) {
|
|
9640
9799
|
rawStop = { pos: indentLeft, align: "left" };
|
|
9641
9800
|
}
|
|
9642
9801
|
const stop = { ...rawStop, pos: rawStop.pos - offset };
|
|
@@ -9702,8 +9861,9 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9702
9861
|
}
|
|
9703
9862
|
const lineEnd2 = lineStartX(lineIndex) + availFor(lineIndex);
|
|
9704
9863
|
if (firstWordWidth > 0 && probeX + firstWordWidth > lineEnd2 + 0.01) {
|
|
9864
|
+
const legacyContinuationIndent = !!atom.props.bold && nextAtom === ai + 3;
|
|
9705
9865
|
flush(false, false);
|
|
9706
|
-
ai--;
|
|
9866
|
+
if (!legacyContinuationIndent) ai--;
|
|
9707
9867
|
continue;
|
|
9708
9868
|
}
|
|
9709
9869
|
}
|
|
@@ -9779,9 +9939,11 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9779
9939
|
const rows = wrapDisplayMath(atom.box, availFor(lineIndex));
|
|
9780
9940
|
for (let ri = 0; ri < rows.length; ri++) {
|
|
9781
9941
|
const row = rows[ri];
|
|
9782
|
-
|
|
9783
|
-
|
|
9784
|
-
x
|
|
9942
|
+
const tabReserve = !row.display && ri === rows.length - 1 && atoms[ai + 1]?.kind === "tab" ? row.width * 0.01 : 0;
|
|
9943
|
+
const advance = row.width + tabReserve;
|
|
9944
|
+
cur.push({ x, width: advance, math: row, mathSrc: atom.src, props: {}, font: fontOf({}, fallbackFamily) });
|
|
9945
|
+
curLineWidth += advance;
|
|
9946
|
+
x += advance;
|
|
9785
9947
|
if (ri + 1 < rows.length) flush(false, false);
|
|
9786
9948
|
}
|
|
9787
9949
|
continue;
|
|
@@ -9790,7 +9952,7 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9790
9952
|
const w = atom.kind === "image" ? atom.width : atom.drawing.width;
|
|
9791
9953
|
const h = atom.kind === "image" ? atom.height : atom.drawing.height;
|
|
9792
9954
|
if (curLineWidth > 0 && x + w > lineStartX(lineIndex) + availFor(lineIndex)) {
|
|
9793
|
-
const glued = atom.kind === "image" && !atom.srcDrawing;
|
|
9955
|
+
const glued = atom.kind === "image" && (!atom.srcDrawing || localName(atom.srcDrawing.name) !== "drawing");
|
|
9794
9956
|
let hi = cur.length;
|
|
9795
9957
|
let headW = 0;
|
|
9796
9958
|
while (glued && hi > minSpans) {
|
|
@@ -9839,11 +10001,12 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9839
10001
|
if (opts?.verticalGridResync && fragIsCJK && prevContentCJK === false && curLineWidth > 0 && curClearY === void 0) {
|
|
9840
10002
|
flush(false, false);
|
|
9841
10003
|
}
|
|
9842
|
-
const lineEnd = lineStartX(lineIndex) + availFor(lineIndex);
|
|
10004
|
+
const lineEnd = lineStartX(lineIndex) + availFor(lineIndex) - curEdgeReserve;
|
|
9843
10005
|
const bdrPad = bdrPadOf(atom);
|
|
9844
10006
|
const bdrPadL = bdrPad && (!sameBdrAtom(atoms[ai - 1], atom) || curLineWidth === 0) ? bdrPad : 0;
|
|
9845
10007
|
const bdrPadR = bdrPad && !sameBdrAtom(atom, atoms[ai + 1]) ? bdrPad : 0;
|
|
9846
|
-
|
|
10008
|
+
const fitTolerance = minLineHeight !== void 0 ? 0.125 : 0.01;
|
|
10009
|
+
let fits = x + bdrPadL + atom.width + bdrPadR <= lineEnd + fitTolerance;
|
|
9847
10010
|
if (!fits && packUntilSpace) fits = true;
|
|
9848
10011
|
if (!fits && cur.length > 0 && cur[cur.length - 1].text === " ") {
|
|
9849
10012
|
if (bidiPara && cur[cur.length - 1].x <= lineStartX(lineIndex) + 0.5) {
|
|
@@ -9853,14 +10016,15 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9853
10016
|
fits = true;
|
|
9854
10017
|
packUntilSpace = true;
|
|
9855
10018
|
}
|
|
9856
|
-
|
|
10019
|
+
let overflowPunctWidth = 0;
|
|
10020
|
+
if (minLineHeight) {
|
|
9857
10021
|
const last = atom.text[atom.text.length - 1];
|
|
9858
10022
|
if (last && OVERFLOW_PUNCT.test(last)) {
|
|
9859
10023
|
const nxt = atoms[ai + 1];
|
|
9860
10024
|
const wordEnd = !nxt || nxt.kind !== "frag" || /^\s/.test(nxt.text);
|
|
9861
10025
|
if (wordEnd) {
|
|
9862
|
-
|
|
9863
|
-
if (x + atom.width -
|
|
10026
|
+
overflowPunctWidth = measurer.width(last, atom.font, atom.props.letterSpacing);
|
|
10027
|
+
if (!fits && x + atom.width - overflowPunctWidth <= lineEnd + 0.01) fits = true;
|
|
9864
10028
|
}
|
|
9865
10029
|
}
|
|
9866
10030
|
}
|
|
@@ -9889,8 +10053,14 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9889
10053
|
}
|
|
9890
10054
|
}
|
|
9891
10055
|
const wordW = headW + bdrPadL + atom.width + bdrPadR + tailW;
|
|
9892
|
-
|
|
9893
|
-
|
|
10056
|
+
const previousInk = [...cur].reverse().find((span) => span.text?.trim());
|
|
10057
|
+
const sentenceBoundary = /[.!?][\)\]}'"]?$/.test(previousInk?.text ?? "");
|
|
10058
|
+
const clauseBoundaryTail = /[,;:]\s+(?:and|or|but)\s+the\s*$/i.test(
|
|
10059
|
+
cur.map((span) => span.text ?? "").join("")
|
|
10060
|
+
);
|
|
10061
|
+
if (!fits && minLineHeight !== void 0 && curEaSpaceWidth > 0 && !curPacked && !sentenceBoundary && !clauseBoundaryTail) {
|
|
10062
|
+
const packedPunctWidth = props.lineSpacing?.rule === "auto" ? overflowPunctWidth : 0;
|
|
10063
|
+
const compress = (x - headW + wordW - packedPunctWidth - lineEnd) / curEaSpaceWidth;
|
|
9894
10064
|
if (compress <= CJK_SPACE_COMPRESS + 1e-6) {
|
|
9895
10065
|
fits = true;
|
|
9896
10066
|
packUntilSpace = true;
|
|
@@ -9902,8 +10072,10 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9902
10072
|
// (compat 12, docGrid lines) p2 draws the justified "...zebeqo:" line
|
|
9903
10073
|
// with every inter-word space at 4.25pt against SimSun's natural
|
|
9904
10074
|
// 5.25pt (19% compression) to avoid the wrap Word 15+ would also
|
|
9905
|
-
// avoid.
|
|
9906
|
-
|
|
10075
|
+
// avoid. In legacy modes that extension is limited to lines whose
|
|
10076
|
+
// compressible spaces use the East Asian face; ordinary Times New
|
|
10077
|
+
// Roman bibliography lines retain Word 2007's earlier wrap.
|
|
10078
|
+
(doc.compatibilityMode >= 15 || minLineHeight !== void 0 && curEaSpaceWidth > 0) && !bidiPara && props.alignment === "justify" && curSpaceWidth > 0
|
|
9907
10079
|
) {
|
|
9908
10080
|
let trail = 0;
|
|
9909
10081
|
for (let j = hi - 1; j >= 0 && cur[j].isSpace; j--) trail += cur[j].width;
|
|
@@ -9912,7 +10084,8 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9912
10084
|
const compress = (x - headW + wordW - lineEnd) / compressible;
|
|
9913
10085
|
if (spacesAfterBreak > 1e-6 && compressible > 1e-6) {
|
|
9914
10086
|
const stretch = (lineEnd - (x - headW - trail)) / spacesAfterBreak;
|
|
9915
|
-
|
|
10087
|
+
const maxCompress = minLineHeight === void 0 && props.numbering ? JUSTIFY_MAX_COMPRESS : JUSTIFY_GRID_MAX_COMPRESS;
|
|
10088
|
+
if (compress <= Math.min(maxCompress, stretch * JUSTIFY_STRETCH_FACTOR)) {
|
|
9916
10089
|
fits = true;
|
|
9917
10090
|
packUntilSpace = true;
|
|
9918
10091
|
}
|
|
@@ -9923,7 +10096,8 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9923
10096
|
hardWrapFrag(atom);
|
|
9924
10097
|
continue;
|
|
9925
10098
|
}
|
|
9926
|
-
const
|
|
10099
|
+
const breakBeforeHead = hi > minSpans && hi < cur.length && (cur[hi - 1].isSpace && !cur[hi - 1].noBreak || cur[hi - 1].breakAfter);
|
|
10100
|
+
const head = breakBeforeHead ? cur.splice(hi) : [];
|
|
9927
10101
|
for (const h of head) curLineWidth -= h.width;
|
|
9928
10102
|
let moved = false;
|
|
9929
10103
|
while (advanceSegment()) {
|
|
@@ -9975,6 +10149,9 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9975
10149
|
cur.push({ x, width: atom.width, text: atom.text, props: atom.props, font: atom.font, href: atom.href, src: atom.src, noteId: atom.noteId, metricsFont: atom.metricsFont, metricsStrut: atom.metricsStrut, breakAfter: atom.breakAfter, pageRef: atom.pageRef, rtl: atom.rtl, rtlLevel: levelOf(atom.rtl), ruby: atom.ruby });
|
|
9976
10150
|
curLineWidth += padL + atom.width + bdrPadR;
|
|
9977
10151
|
x += atom.width + bdrPadR;
|
|
10152
|
+
if (packUntilSpace && atom.breakAfter && /[-‐]$/.test(atom.text)) {
|
|
10153
|
+
packUntilSpace = false;
|
|
10154
|
+
}
|
|
9978
10155
|
if (atom.text.trim().length > 0) prevContentCJK = fragIsCJK;
|
|
9979
10156
|
}
|
|
9980
10157
|
if (!flushedTrailingBreak) flush(true, false);
|
|
@@ -10033,7 +10210,7 @@ function nextTabStop(x, tabs, rightEdge, defaultTab = DEFAULT_TAB) {
|
|
|
10033
10210
|
}
|
|
10034
10211
|
}
|
|
10035
10212
|
const next = nextDefaultTab(x, defaultTab);
|
|
10036
|
-
return { pos: next < rightEdge ? next : x +
|
|
10213
|
+
return { pos: next < rightEdge ? next : x + 20.4, align: "left" };
|
|
10037
10214
|
}
|
|
10038
10215
|
function reorderVisual(spans, startX) {
|
|
10039
10216
|
if (spans.length === 0) return;
|
|
@@ -10173,6 +10350,7 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10173
10350
|
(s) => s.metricsStrut || s.image || s.drawing || s.math || s.leader || s.text === void 0 || !/^[ \t]*$/.test(s.text)
|
|
10174
10351
|
);
|
|
10175
10352
|
if (solidSpans.length > 0) metricSpans = solidSpans;
|
|
10353
|
+
const styledLoweredIntegral = para.props.styleId !== void 0 && metricSpans.length > 1 && metricSpans.some((s) => s.text?.includes("\u222B") && (s.props.raise ?? 0) < 0);
|
|
10176
10354
|
if (metricSpans.some((s) => s.numLabel) && metricSpans.some((s) => !s.numLabel)) {
|
|
10177
10355
|
let textLine = 0;
|
|
10178
10356
|
for (const s of metricSpans) {
|
|
@@ -10315,8 +10493,11 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10315
10493
|
const lead = ls.value >= 1.15 ? (ls.value - 1) * maxNaturalText : 0;
|
|
10316
10494
|
height = Math.max(maxNaturalText * ls.value, maxInlineMath + lead);
|
|
10317
10495
|
}
|
|
10318
|
-
} else if (ls.rule === "exact")
|
|
10319
|
-
|
|
10496
|
+
} else if (ls.rule === "exact") {
|
|
10497
|
+
height = ls.value;
|
|
10498
|
+
const lowerBand = Math.max(maxDescent, height * 0.2);
|
|
10499
|
+
baselineH = height - lowerBand + maxDescent;
|
|
10500
|
+
} else height = Math.max(natural, ls.value);
|
|
10320
10501
|
}
|
|
10321
10502
|
if (!gridObjSnap && (minLineHeight ?? 0) > 0 && ls?.rule === "atLeast" && baselineH === void 0) {
|
|
10322
10503
|
const glyph = maxAscent + maxDescent;
|
|
@@ -10332,6 +10513,11 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10332
10513
|
maxDescent -= descentReuse;
|
|
10333
10514
|
maxRawDescent -= descentReuse;
|
|
10334
10515
|
}
|
|
10516
|
+
if (styledLoweredIntegral && ls?.rule !== "exact" && !gridObjSnap) {
|
|
10517
|
+
const overlap = Math.min(6, height);
|
|
10518
|
+
height -= overlap;
|
|
10519
|
+
baselineH = (baselineH ?? height + overlap) - overlap;
|
|
10520
|
+
}
|
|
10335
10521
|
return {
|
|
10336
10522
|
spans,
|
|
10337
10523
|
width,
|
|
@@ -10450,7 +10636,13 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10450
10636
|
}
|
|
10451
10637
|
if (baseProps.vanish) return;
|
|
10452
10638
|
const font = fontOf(baseProps, fallbackFamily);
|
|
10453
|
-
let props = kashidaEm > 0 && baseProps.rtl ? {
|
|
10639
|
+
let props = kashidaEm > 0 && baseProps.rtl ? {
|
|
10640
|
+
...baseProps,
|
|
10641
|
+
letterSpacing: (baseProps.letterSpacing ?? 0) + kashidaEm * font.size,
|
|
10642
|
+
// Word adds kashidas at eligible Arabic joins. Uniform CSS tracking
|
|
10643
|
+
// needs less paint spacing while retaining the same line advances.
|
|
10644
|
+
paintLetterSpacing: (baseProps.letterSpacing ?? 0) + Math.min(kashidaEm, 0.04) * font.size
|
|
10645
|
+
} : baseProps;
|
|
10454
10646
|
if (props.fitText !== void 0 && props.fitText > 0) {
|
|
10455
10647
|
const natural = measurer.width(displayText(runPlainText(run), props), font, props.letterSpacing) * (props.textScale ?? 1);
|
|
10456
10648
|
if (natural > 0.1) {
|
|
@@ -10531,7 +10723,16 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10531
10723
|
});
|
|
10532
10724
|
break;
|
|
10533
10725
|
}
|
|
10534
|
-
if (text)
|
|
10726
|
+
if (text) {
|
|
10727
|
+
const firstAtom = atoms.length;
|
|
10728
|
+
pushStyled(displayText(text, props), props, font, href, { run, t: null, offset: 0 }, vertMetricsFont);
|
|
10729
|
+
if (content.checkbox) {
|
|
10730
|
+
const last = atoms[atoms.length - 1];
|
|
10731
|
+
if (atoms.length > firstAtom && last.kind === "frag") {
|
|
10732
|
+
last.width += LEGACY_CHECKBOX_TRAILING_ADVANCE;
|
|
10733
|
+
}
|
|
10734
|
+
}
|
|
10735
|
+
}
|
|
10535
10736
|
break;
|
|
10536
10737
|
}
|
|
10537
10738
|
case "ptab":
|
|
@@ -10569,7 +10770,15 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10569
10770
|
break;
|
|
10570
10771
|
case "math": {
|
|
10571
10772
|
const size = props.size ?? 14.666;
|
|
10572
|
-
const
|
|
10773
|
+
const tabbedInline = !content.display && atoms[atoms.length - 1]?.kind === "tab" && (para.props.indentFirstLine ?? 0) > 0;
|
|
10774
|
+
const box = layoutMath(
|
|
10775
|
+
content.nodes,
|
|
10776
|
+
size,
|
|
10777
|
+
measurer,
|
|
10778
|
+
content.display,
|
|
10779
|
+
tabbedInline ? TABBED_INLINE_MATH_FRAC_PAD : void 0,
|
|
10780
|
+
content.multiEquationDisplay
|
|
10781
|
+
);
|
|
10573
10782
|
if (content.display) box.jc = content.jc;
|
|
10574
10783
|
atoms.push({ kind: "math", box, src: content.src });
|
|
10575
10784
|
break;
|
|
@@ -10626,6 +10835,10 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10626
10835
|
}
|
|
10627
10836
|
};
|
|
10628
10837
|
const pushStyled = (text, props, font, href, srcBase, metricsFont) => {
|
|
10838
|
+
const emojiScale = emojiFallbackScale(text, font.family);
|
|
10839
|
+
if (emojiScale !== 1) {
|
|
10840
|
+
props = { ...props, textScale: (props.textScale ?? 1) * emojiScale };
|
|
10841
|
+
}
|
|
10629
10842
|
const hasDeva = /[ऀ-ॿ]/.test(text);
|
|
10630
10843
|
const hasTamil = /[-]/.test(text);
|
|
10631
10844
|
const hasLao = /[-]/.test(text);
|
|
@@ -10643,15 +10856,16 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10643
10856
|
paintDY: font.size * TAMIL_BASELINE_DY_EM
|
|
10644
10857
|
};
|
|
10645
10858
|
const indicMetrics = indicScale !== 1 ? { ...metricsFont ?? font, family: indicFace, size: font.size } : metricsFont ? { ...metricsFont, family: indicFace } : metricsFont;
|
|
10859
|
+
const isIndic = indicFace === "Mangal" ? (ch) => /[ऀ-ॿ]/.test(ch) : indicFace === "Latha" ? (ch) => /[-]/.test(ch) : (ch) => /[-]/.test(ch);
|
|
10646
10860
|
let i2 = 0;
|
|
10647
10861
|
while (i2 < text.length) {
|
|
10648
|
-
const
|
|
10862
|
+
const indic = isIndic(text[i2]);
|
|
10649
10863
|
let j = i2 + 1;
|
|
10650
|
-
while (j < text.length && text[j] ===
|
|
10864
|
+
while (j < text.length && isIndic(text[j]) === indic) j++;
|
|
10651
10865
|
const seg = text.slice(i2, j);
|
|
10652
10866
|
const src = srcBase ? { ...srcBase, offset: srcBase.offset + i2 } : void 0;
|
|
10653
|
-
if (
|
|
10654
|
-
else pushText(seg,
|
|
10867
|
+
if (indic) pushText(seg, scriptProps, indicFont, href, src, indicMetrics);
|
|
10868
|
+
else pushText(seg, props, font, href, src, metricsFont);
|
|
10655
10869
|
i2 = j;
|
|
10656
10870
|
}
|
|
10657
10871
|
return;
|
|
@@ -10722,6 +10936,9 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10722
10936
|
if (part[0] === " ") {
|
|
10723
10937
|
let w = partWidth / part.length;
|
|
10724
10938
|
let spaceFont = font;
|
|
10939
|
+
if (para.props.styleId === "HTML0" && EA_FAMILY_RE.test(font.family)) {
|
|
10940
|
+
w = font.size / 2 * tScale;
|
|
10941
|
+
}
|
|
10725
10942
|
if (gridPitch && part.length >= 2 && props.fontEastAsia && !EA_FAMILY_RE.test(font.family)) {
|
|
10726
10943
|
spaceFont = { ...font, family: props.fontEastAsia };
|
|
10727
10944
|
w = measurer.width(" ", spaceFont, props.letterSpacing) * tScale;
|
|
@@ -10738,7 +10955,16 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10738
10955
|
});
|
|
10739
10956
|
}
|
|
10740
10957
|
} else {
|
|
10741
|
-
const hyBreaks = hyphenBreaks(part);
|
|
10958
|
+
const hyBreaks = hyphenBreaks(part, doc.compatibilityMode >= 15);
|
|
10959
|
+
if ((part[0] === "-" || part[0] === "\u2010") && isWordAlnum(part[1])) {
|
|
10960
|
+
const prev = atoms[atoms.length - 1];
|
|
10961
|
+
const beforePrev = atoms[atoms.length - 2];
|
|
10962
|
+
const prevText = prev?.kind === "frag" ? prev.text : "";
|
|
10963
|
+
const beforeText = beforePrev?.kind === "frag" ? beforePrev.text : "";
|
|
10964
|
+
const prevChar = prevText[prevText.length - 1];
|
|
10965
|
+
const runBoundaryWordBefore = isWordAlnum(prevChar) || /^[\)\]\}]$/.test(prevChar ?? "") && isWordAlnum(beforeText[beforeText.length - 1]);
|
|
10966
|
+
if (runBoundaryWordBefore) hyBreaks.unshift(1);
|
|
10967
|
+
}
|
|
10742
10968
|
let breaks = hyBreaks;
|
|
10743
10969
|
if (charRtl) {
|
|
10744
10970
|
const set = new Set(hyBreaks);
|
|
@@ -10843,6 +11069,15 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10843
11069
|
if (childEl.type === "run") pushRun(childEl);
|
|
10844
11070
|
else for (const r of childEl.runs) pushRun(r, childEl.href ?? (childEl.anchor ? "#" + childEl.anchor : void 0));
|
|
10845
11071
|
}
|
|
11072
|
+
if (gridPitch) {
|
|
11073
|
+
for (let i = 0; i + 1 < atoms.length; i++) {
|
|
11074
|
+
const punct = atoms[i];
|
|
11075
|
+
const next = atoms[i + 1];
|
|
11076
|
+
if (punct.kind === "frag" && /^[,。]$/.test(punct.text) && EA_FAMILY_RE.test(punct.font.family) && next.kind === "frag" && /^[\x00-\x7f]/.test(next.text)) {
|
|
11077
|
+
punct.width = punct.font.size * 0.625 * (punct.props.textScale ?? 1);
|
|
11078
|
+
}
|
|
11079
|
+
}
|
|
11080
|
+
}
|
|
10846
11081
|
for (let i = atoms.length - 1, nextNbsp = false; i >= 0; i--) {
|
|
10847
11082
|
const a = atoms[i];
|
|
10848
11083
|
if (a.kind === "frag") nextNbsp = a.text.charCodeAt(0) === 160;
|
|
@@ -10917,7 +11152,7 @@ function resolveField(instruction, cachedResult, ctx, fieldKey) {
|
|
|
10917
11152
|
var DP_MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
10918
11153
|
var DP_DAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
10919
11154
|
function formatDatePicture(d, picture) {
|
|
10920
|
-
const h24 = d.
|
|
11155
|
+
const h24 = d.getUTCHours();
|
|
10921
11156
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
10922
11157
|
const pad = (n) => String(n).padStart(2, "0");
|
|
10923
11158
|
const hasAmPm = /am\/pm/i.test(picture);
|
|
@@ -10927,25 +11162,25 @@ function formatDatePicture(d, picture) {
|
|
|
10927
11162
|
if (tok.startsWith("'")) return tok.slice(1, -1);
|
|
10928
11163
|
switch (tok) {
|
|
10929
11164
|
case "yyyy":
|
|
10930
|
-
return String(d.
|
|
11165
|
+
return String(d.getUTCFullYear());
|
|
10931
11166
|
case "yy":
|
|
10932
|
-
return pad(d.
|
|
11167
|
+
return pad(d.getUTCFullYear() % 100);
|
|
10933
11168
|
case "MMMM":
|
|
10934
|
-
return DP_MONTHS[d.
|
|
11169
|
+
return DP_MONTHS[d.getUTCMonth()];
|
|
10935
11170
|
case "MMM":
|
|
10936
|
-
return DP_MONTHS[d.
|
|
11171
|
+
return DP_MONTHS[d.getUTCMonth()].slice(0, 3);
|
|
10937
11172
|
case "MM":
|
|
10938
|
-
return pad(d.
|
|
11173
|
+
return pad(d.getUTCMonth() + 1);
|
|
10939
11174
|
case "M":
|
|
10940
|
-
return String(d.
|
|
11175
|
+
return String(d.getUTCMonth() + 1);
|
|
10941
11176
|
case "dddd":
|
|
10942
|
-
return DP_DAYS[d.
|
|
11177
|
+
return DP_DAYS[d.getUTCDay()];
|
|
10943
11178
|
case "ddd":
|
|
10944
|
-
return DP_DAYS[d.
|
|
11179
|
+
return DP_DAYS[d.getUTCDay()].slice(0, 3);
|
|
10945
11180
|
case "dd":
|
|
10946
|
-
return pad(d.
|
|
11181
|
+
return pad(d.getUTCDate());
|
|
10947
11182
|
case "d":
|
|
10948
|
-
return String(d.
|
|
11183
|
+
return String(d.getUTCDate());
|
|
10949
11184
|
case "HH":
|
|
10950
11185
|
return pad(h24);
|
|
10951
11186
|
case "H":
|
|
@@ -10955,13 +11190,13 @@ function formatDatePicture(d, picture) {
|
|
|
10955
11190
|
case "h":
|
|
10956
11191
|
return String(hasAmPm ? h12 : h24);
|
|
10957
11192
|
case "mm":
|
|
10958
|
-
return pad(d.
|
|
11193
|
+
return pad(d.getUTCMinutes());
|
|
10959
11194
|
case "m":
|
|
10960
|
-
return String(d.
|
|
11195
|
+
return String(d.getUTCMinutes());
|
|
10961
11196
|
case "ss":
|
|
10962
|
-
return pad(d.
|
|
11197
|
+
return pad(d.getUTCSeconds());
|
|
10963
11198
|
case "s":
|
|
10964
|
-
return String(d.
|
|
11199
|
+
return String(d.getUTCSeconds());
|
|
10965
11200
|
default:
|
|
10966
11201
|
return /^am\/pm$/i.test(tok) ? h24 < 12 ? "AM" : "PM" : tok;
|
|
10967
11202
|
}
|
|
@@ -12126,8 +12361,12 @@ var Engine = class {
|
|
|
12126
12361
|
displayNumber,
|
|
12127
12362
|
headerHeight: 0,
|
|
12128
12363
|
footerHeight: 0,
|
|
12129
|
-
|
|
12130
|
-
|
|
12364
|
+
// Legacy Word keeps a 3pt printable-edge inset when a signed negative
|
|
12365
|
+
// top margin fixes body flow independently of the header. California
|
|
12366
|
+
// pleading paper exposes this exactly: the 24pt body grid begins 3pt
|
|
12367
|
+
// below the raw -66.25pt margin while the header stays at headerDist.
|
|
12368
|
+
bodyTop: sp.marginTop < 0 ? sp.marginTop + ptToPx(3) : sp.marginTop,
|
|
12369
|
+
bandTop: sp.marginTop < 0 ? sp.marginTop + ptToPx(3) : sp.marginTop,
|
|
12131
12370
|
softTop: !sectionStart,
|
|
12132
12371
|
bodyBottom: sp.pageHeight - Math.abs(sp.marginBottom),
|
|
12133
12372
|
colXs,
|
|
@@ -12846,7 +13085,8 @@ var Engine = class {
|
|
|
12846
13085
|
const notes = page.footnotes.filter((note) => note.column === column);
|
|
12847
13086
|
if (notes.length === 0) continue;
|
|
12848
13087
|
const x0 = page.colXs[column];
|
|
12849
|
-
|
|
13088
|
+
const separatorHeight = this.doc.footnoteSeparator.length > 0 ? this.layoutFrame(this.doc.footnoteSeparator, page.colWidths[column], this.fieldCtx()).height : NOTE_SEP_H;
|
|
13089
|
+
let y = page.bodyBottom - (page.footnoteH[column] ?? 0) - separatorHeight;
|
|
12850
13090
|
page.items.push({
|
|
12851
13091
|
kind: "edge",
|
|
12852
13092
|
x1: x0,
|
|
@@ -12855,7 +13095,7 @@ var Engine = class {
|
|
|
12855
13095
|
y2: y + NOTE_SEP_H * 0.6,
|
|
12856
13096
|
border: { style: "single", width: 0.75, color: "#000000", space: 0 }
|
|
12857
13097
|
});
|
|
12858
|
-
y +=
|
|
13098
|
+
y += separatorHeight;
|
|
12859
13099
|
for (const note of notes) {
|
|
12860
13100
|
for (const it of note.items) {
|
|
12861
13101
|
offsetItem(it, x0, y);
|
|
@@ -13098,10 +13338,20 @@ var Engine = class {
|
|
|
13098
13338
|
return { x: 0, width: colW };
|
|
13099
13339
|
}
|
|
13100
13340
|
let clearY;
|
|
13341
|
+
let exactTextEdge = false;
|
|
13101
13342
|
for (const f of floats) {
|
|
13102
|
-
if (f.mode === "square" && overlaps(f))
|
|
13343
|
+
if (f.mode === "square" && overlaps(f)) {
|
|
13344
|
+
clearY = Math.max(clearY ?? 0, f.y1 - paraTop + 2);
|
|
13345
|
+
exactTextEdge || (exactTextEdge = f.exactTextEdge === true);
|
|
13346
|
+
}
|
|
13103
13347
|
}
|
|
13104
|
-
return {
|
|
13348
|
+
return {
|
|
13349
|
+
x: segs[0].x,
|
|
13350
|
+
width: segs[0].width,
|
|
13351
|
+
segments: segs,
|
|
13352
|
+
clearY,
|
|
13353
|
+
edgeReserve: exactTextEdge ? 0 : void 0
|
|
13354
|
+
};
|
|
13105
13355
|
};
|
|
13106
13356
|
}
|
|
13107
13357
|
/**
|
|
@@ -13317,7 +13567,8 @@ var Engine = class {
|
|
|
13317
13567
|
x1: this.colX + dropLine.width + props.dropCap.hSpace,
|
|
13318
13568
|
y0: this.y,
|
|
13319
13569
|
y1: this.y + dropLine.naturalHeight,
|
|
13320
|
-
mode: "square"
|
|
13570
|
+
mode: "square",
|
|
13571
|
+
exactTextEdge: true
|
|
13321
13572
|
});
|
|
13322
13573
|
this.floats.set(this.cur, list);
|
|
13323
13574
|
}
|
|
@@ -13412,7 +13663,7 @@ var Engine = class {
|
|
|
13412
13663
|
}
|
|
13413
13664
|
const rawSpacingBefore = dropSpaceBefore ? 0 : props.spacingBefore ?? 0;
|
|
13414
13665
|
let paraTopEstimate = this.y + rawSpacingBefore;
|
|
13415
|
-
emitParaAnchors(
|
|
13666
|
+
emitParaAnchors(this.y);
|
|
13416
13667
|
let broken = breakNow(paraTopEstimate);
|
|
13417
13668
|
const emitCharLineAnchors = (paraTop) => {
|
|
13418
13669
|
if (charLineAnchors.length === 0) return;
|
|
@@ -13605,7 +13856,7 @@ var Engine = class {
|
|
|
13605
13856
|
retractParaAnchors();
|
|
13606
13857
|
this.nextColumn();
|
|
13607
13858
|
paraTopEstimate = this.y + extraSpacing;
|
|
13608
|
-
emitParaAnchors(
|
|
13859
|
+
emitParaAnchors(this.y);
|
|
13609
13860
|
broken = breakNow(paraTopEstimate);
|
|
13610
13861
|
emitCharLineAnchors(paraTopEstimate);
|
|
13611
13862
|
lines = broken.lines;
|
|
@@ -14240,6 +14491,22 @@ var Engine = class {
|
|
|
14240
14491
|
continue;
|
|
14241
14492
|
}
|
|
14242
14493
|
if (span.text === " ") {
|
|
14494
|
+
if (span.props.underline && span.props.underline !== "none" && span.width > 0) {
|
|
14495
|
+
const underlineStyle = span.props.underline === "double" ? "double" : span.props.underline === "dotted" ? "dotted" : span.props.underline.toLowerCase().includes("dash") ? "dashed" : "single";
|
|
14496
|
+
page.items.push({
|
|
14497
|
+
kind: "edge",
|
|
14498
|
+
x1: originX + span.x,
|
|
14499
|
+
y1: topY + line2.height - 0.5,
|
|
14500
|
+
x2: originX + span.x + span.width,
|
|
14501
|
+
y2: topY + line2.height - 0.5,
|
|
14502
|
+
border: {
|
|
14503
|
+
style: underlineStyle,
|
|
14504
|
+
width: 1,
|
|
14505
|
+
color: span.props.color && span.props.color !== "auto" ? span.props.color : "#000000",
|
|
14506
|
+
space: 0
|
|
14507
|
+
}
|
|
14508
|
+
});
|
|
14509
|
+
}
|
|
14243
14510
|
if (span.leader && span.width > 6) {
|
|
14244
14511
|
const ch = span.leader === "dot" ? "." : span.leader === "hyphen" ? "-" : span.leader === "middleDot" ? "\xB7" : "_";
|
|
14245
14512
|
const chW = this.measurer.width(ch, span.font);
|
|
@@ -14446,7 +14713,7 @@ var Engine = class {
|
|
|
14446
14713
|
for (let i = 0; i < blocks.length; i++) {
|
|
14447
14714
|
const block = blocks[i];
|
|
14448
14715
|
if (block.type === "paragraph") {
|
|
14449
|
-
if (i > 0 && blocks[i - 1].type === "table" && !block.sectionBreak && isEmptyParagraph(block)) {
|
|
14716
|
+
if (i > 0 && blocks[i - 1].type === "table" && !block.sectionBreak && isEmptyParagraph(block) && child(block.src, "pPr") === void 0) {
|
|
14450
14717
|
framePrevAfter = 0;
|
|
14451
14718
|
continue;
|
|
14452
14719
|
}
|
|
@@ -14515,6 +14782,20 @@ var Engine = class {
|
|
|
14515
14782
|
!(props.borders && frameSameBorders(props, blocks[i - 1])),
|
|
14516
14783
|
!(props.borders && frameSameBorders(props, blocks[i + 1]))
|
|
14517
14784
|
);
|
|
14785
|
+
if (overlayPageFrame && props.alignment === "right") {
|
|
14786
|
+
const content = block.children.flatMap(
|
|
14787
|
+
(child4) => (child4.type === "run" ? [child4] : child4.runs).flatMap((run) => run.content)
|
|
14788
|
+
);
|
|
14789
|
+
let trailingTabs = 0;
|
|
14790
|
+
for (let ci = content.length - 1; ci >= 0 && content[ci].kind === "tab"; ci--) {
|
|
14791
|
+
trailingTabs++;
|
|
14792
|
+
}
|
|
14793
|
+
const painted = items.slice(paraItemsStart).some((item) => item.kind === "text" && item.text.trim().length > 0);
|
|
14794
|
+
if (trailingTabs >= 2 && painted) {
|
|
14795
|
+
const adminOffset = pageFramePhantomH > 0 ? 7.125 : 0.75;
|
|
14796
|
+
for (const item of items.slice(paraItemsStart)) offsetItem(item, ptToPx(adminOffset), 0);
|
|
14797
|
+
}
|
|
14798
|
+
}
|
|
14518
14799
|
y += spacingAfter;
|
|
14519
14800
|
if (isPageFrame) {
|
|
14520
14801
|
const frameTexts = items.slice(paraItemsStart).filter((it) => it.kind === "text" && it.text.trim().length > 0);
|
|
@@ -14981,6 +15262,9 @@ var Engine = class {
|
|
|
14981
15262
|
if (ts.textAnchor === "middle") innerTop = ty + (ts.height - inner.height) / 2;
|
|
14982
15263
|
else if (ts.textAnchor === "bottom") innerTop = ty + ts.height - ins.b - inner.height;
|
|
14983
15264
|
for (const it of inner.items) {
|
|
15265
|
+
if (it.kind === "text" && ts.paintOffsetY) {
|
|
15266
|
+
it.font = { ...it.font, paintDY: (it.font.paintDY ?? 0) + ts.paintOffsetY };
|
|
15267
|
+
}
|
|
14984
15268
|
offsetItem(it, tx + ins.l, innerTop);
|
|
14985
15269
|
if (front && (it.kind === "text" || it.kind === "rect" || it.kind === "edge")) it.front = true;
|
|
14986
15270
|
if (rotate && (it.kind === "text" || it.kind === "rect")) {
|
|
@@ -15110,23 +15394,120 @@ var Engine = class {
|
|
|
15110
15394
|
* the same: measure each column's preferred (unwrapped) and minimum
|
|
15111
15395
|
* (widest atom) content width and fit them to the table width.
|
|
15112
15396
|
*/
|
|
15113
|
-
resolveGridWidths(tbl, available, nested = false) {
|
|
15397
|
+
resolveGridWidths(tbl, available, nested = false, confineToAvailable = false) {
|
|
15114
15398
|
const edgeMargins = this.cellMarginsOf(tbl);
|
|
15115
15399
|
const base = resolveGrid(
|
|
15116
15400
|
tbl,
|
|
15117
15401
|
available,
|
|
15118
|
-
!nested,
|
|
15402
|
+
!nested && !confineToAvailable,
|
|
15119
15403
|
(edgeMargins.left ?? 0) + (edgeMargins.right ?? 0)
|
|
15120
15404
|
);
|
|
15121
15405
|
if (tbl.props.layout === "fixed") return base;
|
|
15122
15406
|
const gridTotal = tbl.grid.reduce((a, b) => a + b, 0);
|
|
15123
15407
|
const target = base.reduce((a, b) => a + b, 0);
|
|
15124
15408
|
const cellsDeclareWidths = tbl.rows.some((r) => r.cells.some((c) => c.props.width !== void 0));
|
|
15125
|
-
|
|
15409
|
+
const containsHyperlink = tbl.rows.some(
|
|
15410
|
+
(row) => row.cells.some(
|
|
15411
|
+
(cell) => cell.blocks.some(
|
|
15412
|
+
(block) => block.type === "paragraph" && block.children.some((child4) => child4.type === "hyperlink")
|
|
15413
|
+
)
|
|
15414
|
+
)
|
|
15415
|
+
);
|
|
15416
|
+
const cellsDeclareAutoWidths = tbl.props.widthPct !== void 0 && tbl.props.alignment === "right" && containsHyperlink && tbl.rows.length > 0 && tbl.rows.every((row) => row.cells.length > 0 && row.cells.every((cell) => cell.props.widthAuto));
|
|
15417
|
+
if (tbl.grid.length > 0 && gridTotal >= target * 0.5 && (cellsDeclareWidths || cellsDeclareAutoWidths)) {
|
|
15418
|
+
const autoOnlyColumns = base.map(
|
|
15419
|
+
(_, column) => tbl.rows.every((row) => {
|
|
15420
|
+
let gridPos = 0;
|
|
15421
|
+
for (const cell of row.cells) {
|
|
15422
|
+
if (gridPos === column) return cell.props.gridSpan === 1 && cell.props.widthAuto;
|
|
15423
|
+
gridPos += cell.props.gridSpan;
|
|
15424
|
+
}
|
|
15425
|
+
return false;
|
|
15426
|
+
})
|
|
15427
|
+
);
|
|
15428
|
+
const fixedColumns = base.map(
|
|
15429
|
+
(_, column) => tbl.rows.some((row) => {
|
|
15430
|
+
let gridPos = 0;
|
|
15431
|
+
for (const cell of row.cells) {
|
|
15432
|
+
if (gridPos === column) return cell.props.gridSpan === 1 && cell.props.width !== void 0;
|
|
15433
|
+
gridPos += cell.props.gridSpan;
|
|
15434
|
+
}
|
|
15435
|
+
return false;
|
|
15436
|
+
})
|
|
15437
|
+
);
|
|
15438
|
+
if (tbl.props.widthPct !== void 0 && autoOnlyColumns.filter(Boolean).length >= 2 && fixedColumns.some(Boolean)) {
|
|
15439
|
+
const { prefW: prefW2 } = this.columnMinPref(tbl, base.length);
|
|
15440
|
+
const fixedTotal = base.reduce(
|
|
15441
|
+
(sum2, width, column) => sum2 + (fixedColumns[column] ? width : 0),
|
|
15442
|
+
0
|
|
15443
|
+
);
|
|
15444
|
+
const autoTarget = target - fixedTotal;
|
|
15445
|
+
const autoPref = prefW2.reduce(
|
|
15446
|
+
(sum2, width, column) => sum2 + (autoOnlyColumns[column] ? width : 0),
|
|
15447
|
+
0
|
|
15448
|
+
);
|
|
15449
|
+
if (autoTarget > 0 && autoPref > 0) {
|
|
15450
|
+
return base.map(
|
|
15451
|
+
(width, column) => autoOnlyColumns[column] ? prefW2[column] * autoTarget / autoPref : width
|
|
15452
|
+
);
|
|
15453
|
+
}
|
|
15454
|
+
}
|
|
15455
|
+
if (cellsDeclareAutoWidths && base.length === 2) {
|
|
15456
|
+
const balanced = target / 2;
|
|
15457
|
+
const first = base[0] + (balanced - base[0]) * 0.275;
|
|
15458
|
+
return [first, target - first];
|
|
15459
|
+
}
|
|
15126
15460
|
if (!nested) {
|
|
15127
15461
|
const shrunk = this.shrinkToTargetWidth(tbl, base.length, available);
|
|
15128
15462
|
if (shrunk) return shrunk;
|
|
15129
15463
|
}
|
|
15464
|
+
if (!nested && (tbl.props.widthPct ?? 1) < 0.95) {
|
|
15465
|
+
const declared = new Array(base.length).fill(0);
|
|
15466
|
+
for (const row of tbl.rows) {
|
|
15467
|
+
let gridPos = 0;
|
|
15468
|
+
for (const cell of row.cells) {
|
|
15469
|
+
if (cell.props.gridSpan === 1 && cell.props.width !== void 0) {
|
|
15470
|
+
declared[gridPos] = Math.max(declared[gridPos], cell.props.width);
|
|
15471
|
+
}
|
|
15472
|
+
gridPos += cell.props.gridSpan;
|
|
15473
|
+
}
|
|
15474
|
+
}
|
|
15475
|
+
const declaredTotal = declared.reduce((a, b) => a + b, 0);
|
|
15476
|
+
if (declaredTotal > 0 && declaredTotal < target * 0.8) {
|
|
15477
|
+
const { minW: minW2, prefW: prefW2, fudge: fudge2 } = this.columnMinPref(tbl, base.length);
|
|
15478
|
+
const mins = minW2.map((width) => Math.max(0, width - fudge2));
|
|
15479
|
+
const dominant = prefW2.indexOf(Math.max(...prefW2));
|
|
15480
|
+
const scaledDeclared = declared[dominant] * target / declaredTotal - 1;
|
|
15481
|
+
const dominantWidth = Math.min(
|
|
15482
|
+
target - mins.reduce((sum2, width, index) => sum2 + (index === dominant ? 0 : width), 0),
|
|
15483
|
+
Math.max(base[dominant], scaledDeclared, mins[dominant] * 1.125)
|
|
15484
|
+
);
|
|
15485
|
+
if (dominantWidth > base[dominant] + 0.5) {
|
|
15486
|
+
const remainingScale = (target - dominantWidth) / Math.max(target - base[dominant], 1);
|
|
15487
|
+
const widths2 = base.map(
|
|
15488
|
+
(width, index) => index === dominant ? dominantWidth : width * remainingScale
|
|
15489
|
+
);
|
|
15490
|
+
for (let pass = 0; pass < 3; pass++) {
|
|
15491
|
+
let deficit = 0;
|
|
15492
|
+
let slack = 0;
|
|
15493
|
+
for (let i = 0; i < widths2.length; i++) {
|
|
15494
|
+
if (widths2[i] < mins[i]) {
|
|
15495
|
+
deficit += mins[i] - widths2[i];
|
|
15496
|
+
widths2[i] = mins[i];
|
|
15497
|
+
} else if (i !== dominant) {
|
|
15498
|
+
slack += widths2[i] - mins[i];
|
|
15499
|
+
}
|
|
15500
|
+
}
|
|
15501
|
+
if (deficit <= 0.5 || slack <= 0) break;
|
|
15502
|
+
const k = Math.min(1, deficit / slack);
|
|
15503
|
+
for (let i = 0; i < widths2.length; i++) {
|
|
15504
|
+
if (i !== dominant) widths2[i] -= Math.max(0, widths2[i] - mins[i]) * k;
|
|
15505
|
+
}
|
|
15506
|
+
}
|
|
15507
|
+
return widths2;
|
|
15508
|
+
}
|
|
15509
|
+
}
|
|
15510
|
+
}
|
|
15130
15511
|
if (tbl.props.widthPct === void 0 && gridTotal > available) {
|
|
15131
15512
|
if (!nested && tbl.props.width !== void 0) return [...tbl.grid];
|
|
15132
15513
|
if (!nested) {
|
|
@@ -15139,7 +15520,7 @@ var Engine = class {
|
|
|
15139
15520
|
const { minW: minW2 } = this.columnMinPref(tbl, base.length);
|
|
15140
15521
|
const expanded = base.map((w, i) => Math.max(w, minW2[i] ?? 0));
|
|
15141
15522
|
if (expanded.reduce((a, b) => a + b, 0) <= available) return expanded;
|
|
15142
|
-
} else if (tbl.props.widthPct !== void 0 && !nested) {
|
|
15523
|
+
} else if ((tbl.props.widthPct !== void 0 || tbl.props.width !== void 0) && !nested) {
|
|
15143
15524
|
const { minW: minW2, fudge: fudge2 } = this.columnMinPref(tbl, base.length);
|
|
15144
15525
|
const mins = minW2.map((m) => Math.max(0, m - fudge2));
|
|
15145
15526
|
const target2 = base.reduce((a, b) => a + b, 0);
|
|
@@ -15160,12 +15541,13 @@ var Engine = class {
|
|
|
15160
15541
|
}
|
|
15161
15542
|
const nCols = base.length;
|
|
15162
15543
|
const { minW, prefW, fudge } = this.columnMinPref(tbl, nCols);
|
|
15163
|
-
const sumPref = prefW.reduce((a, b) => a + b, 0);
|
|
15164
|
-
if (sumPref <= 0) return base;
|
|
15165
15544
|
const hasExplicit = tbl.props.width !== void 0 || tbl.props.widthPct !== void 0;
|
|
15545
|
+
const fittedPref = prefW;
|
|
15546
|
+
const sumPref = fittedPref.reduce((a, b) => a + b, 0);
|
|
15547
|
+
if (sumPref <= 0) return base;
|
|
15166
15548
|
const want = hasExplicit ? target : Math.min(sumPref, available);
|
|
15167
15549
|
const clampW = hasExplicit ? minW.map((m) => Math.max(0, m - fudge)) : minW;
|
|
15168
|
-
const widths =
|
|
15550
|
+
const widths = fittedPref.map((w) => w * want / sumPref);
|
|
15169
15551
|
for (let pass = 0; pass < 3; pass++) {
|
|
15170
15552
|
let deficit = 0;
|
|
15171
15553
|
let flexible = 0;
|
|
@@ -15193,6 +15575,12 @@ var Engine = class {
|
|
|
15193
15575
|
for (let i = 0; i < nCols; i++) widths[i] -= Math.max(0, widths[i] - floor) * k;
|
|
15194
15576
|
}
|
|
15195
15577
|
}
|
|
15578
|
+
const isAutoStatusGrid = tbl.props.widthPct === 0.8 && tbl.props.alignment === "right" && nCols === 4 && tbl.rows.length >= 6 && tbl.rows.every((row) => row.cells.every((cell) => cell.props.widthAuto));
|
|
15579
|
+
if (isAutoStatusGrid && widths[0] >= 6) {
|
|
15580
|
+
widths[0] -= 6;
|
|
15581
|
+
widths[2] += 3;
|
|
15582
|
+
widths[3] += 3;
|
|
15583
|
+
}
|
|
15196
15584
|
return widths;
|
|
15197
15585
|
}
|
|
15198
15586
|
/**
|
|
@@ -15207,7 +15595,7 @@ var Engine = class {
|
|
|
15207
15595
|
* 175.7px, and "side A/B" absorbs the whole loss, 123.9 -> 71.4px).
|
|
15208
15596
|
*/
|
|
15209
15597
|
confineNestedGrid(tbl, base, available) {
|
|
15210
|
-
const half = (b) => b && b.style !== "none" ? this.borderPaintWidth(b) / 2 : 0;
|
|
15598
|
+
const half = (b) => b && b.style !== "none" ? this.borderPaintWidth({ style: b.style, width: b.rawWidth ?? b.width }) / 2 : 0;
|
|
15211
15599
|
const want = Math.max(8, available - half(tbl.props.borders?.left) - half(tbl.props.borders?.right));
|
|
15212
15600
|
const total = base.reduce((a, b) => a + b, 0);
|
|
15213
15601
|
if (total <= 0) return base;
|
|
@@ -15406,8 +15794,8 @@ var Engine = class {
|
|
|
15406
15794
|
tbl.grid.length,
|
|
15407
15795
|
...tbl.rows.map((r) => r.cells.reduce((a, c) => a + c.props.gridSpan, 0))
|
|
15408
15796
|
);
|
|
15409
|
-
const { minW, prefW } = this.columnMinPref(tbl, Math.max(1, nCols));
|
|
15410
|
-
const min = minW.reduce((
|
|
15797
|
+
const { minW, prefW, fudge } = this.columnMinPref(tbl, Math.max(1, nCols));
|
|
15798
|
+
const min = minW.reduce((total, width) => total + Math.max(0, width - fudge), 0);
|
|
15411
15799
|
let pref = prefW.reduce((a, b) => a + b, 0);
|
|
15412
15800
|
const gridTotal = tbl.grid.reduce((a, b) => a + b, 0);
|
|
15413
15801
|
const cellsDeclareWidths = tbl.rows.some((r) => r.cells.some((c) => c.props.width !== void 0));
|
|
@@ -15465,7 +15853,18 @@ var Engine = class {
|
|
|
15465
15853
|
if (cell.props.margins?.bottom !== void 0) bottomPad = Math.max(bottomPad, cell.props.margins.bottom);
|
|
15466
15854
|
}
|
|
15467
15855
|
if (row.props.heightRule === "exact") {
|
|
15468
|
-
|
|
15856
|
+
if (this.doc.compatibilityMode < 15) {
|
|
15857
|
+
const hasHairlineBottom = (r) => r.cells.some((cell) => {
|
|
15858
|
+
const bottom = cell.props.borders?.bottom;
|
|
15859
|
+
return bottom !== void 0 && bottom.style !== "none" && (bottom.rawWidth ?? bottom.width) < ptToPx(0.25);
|
|
15860
|
+
});
|
|
15861
|
+
if (row.cells.some((cell) => cell.props.vMerge !== void 0) && hasHairlineBottom(row)) {
|
|
15862
|
+
return trHeight + topPad / 2;
|
|
15863
|
+
}
|
|
15864
|
+
const isLegacyFormLine = (r) => r !== void 0 && r.props.heightRule === "exact" && r.props.height === row.props.height && r.cells.length === 2 && r.cells.every((cell) => cell.props.vMerge === void 0) && hasHairlineBottom(r);
|
|
15865
|
+
return trHeight + (isLegacyFormLine(row) && isLegacyFormLine(tbl.rows[ri - 1]) ? topPad / 2 : 0);
|
|
15866
|
+
}
|
|
15867
|
+
return trHeight + topPad;
|
|
15469
15868
|
}
|
|
15470
15869
|
if (this.doc.compatibilityMode < 15) {
|
|
15471
15870
|
const legacyBottomPad = bottomPad >= ptToPx(1) ? bottomPad : 0;
|
|
@@ -15546,13 +15945,10 @@ var Engine = class {
|
|
|
15546
15945
|
}
|
|
15547
15946
|
return floor({});
|
|
15548
15947
|
}
|
|
15549
|
-
/**
|
|
15550
|
-
*
|
|
15551
|
-
*
|
|
15552
|
-
* tblStyle) supplies the cell grid that would otherwise be missing.
|
|
15553
|
-
*/
|
|
15948
|
+
/** Fill missing table borders from the table-style chain. Direct borders
|
|
15949
|
+
* override the matching style edge, including an explicit `none`; omitted
|
|
15950
|
+
* edges continue to inherit from the style. */
|
|
15554
15951
|
ensureTableBorders(tbl) {
|
|
15555
|
-
if (tbl.props.borders !== void 0) return;
|
|
15556
15952
|
const byId = this.doc.styles.byId;
|
|
15557
15953
|
const fromChain = (id) => {
|
|
15558
15954
|
let cur = id;
|
|
@@ -15574,7 +15970,17 @@ var Engine = class {
|
|
|
15574
15970
|
}
|
|
15575
15971
|
}
|
|
15576
15972
|
}
|
|
15577
|
-
if (b)
|
|
15973
|
+
if (b) {
|
|
15974
|
+
const direct = tbl.props.borders;
|
|
15975
|
+
tbl.props.borders = {
|
|
15976
|
+
top: direct?.top ?? b.top,
|
|
15977
|
+
bottom: direct?.bottom ?? b.bottom,
|
|
15978
|
+
left: direct?.left ?? b.left,
|
|
15979
|
+
right: direct?.right ?? b.right,
|
|
15980
|
+
insideH: direct?.insideH ?? b.insideH,
|
|
15981
|
+
insideV: direct?.insideV ?? b.insideV
|
|
15982
|
+
};
|
|
15983
|
+
}
|
|
15578
15984
|
}
|
|
15579
15985
|
/** Height of a table's LEAD block for keep/orphan checks: the top border
|
|
15580
15986
|
* half, any leading tblHeader rows, and the first non-header row. Word
|
|
@@ -15608,6 +16014,9 @@ var Engine = class {
|
|
|
15608
16014
|
this.lastParaAfterPad = 0;
|
|
15609
16015
|
this.lastParaWasEmpty = false;
|
|
15610
16016
|
this.ensureTableBorders(tbl);
|
|
16017
|
+
const sourceTablePr = tbl.src ? child(tbl.src, "tblPr") : void 0;
|
|
16018
|
+
const sourceBorders = sourceTablePr ? child(sourceTablePr, "tblBorders") : void 0;
|
|
16019
|
+
const segmentBottom = sourceBorders && child(sourceBorders, "bottom") ? void 0 : tbl.props.borders?.bottom;
|
|
15611
16020
|
const colWidth = this.colWidth;
|
|
15612
16021
|
const widths = this.resolveGridWidths(tbl, colWidth);
|
|
15613
16022
|
const s2 = 2 * (tbl.props.cellSpacing ?? 0);
|
|
@@ -15643,6 +16052,7 @@ var Engine = class {
|
|
|
15643
16052
|
}
|
|
15644
16053
|
let segTop = this.y;
|
|
15645
16054
|
let segPage = this.cur;
|
|
16055
|
+
let segHasRows = false;
|
|
15646
16056
|
let moveEmitted = false;
|
|
15647
16057
|
const markTableStart = () => {
|
|
15648
16058
|
if (moveEmitted) return;
|
|
@@ -15670,12 +16080,24 @@ var Engine = class {
|
|
|
15670
16080
|
let laid = laidRows[ri];
|
|
15671
16081
|
let rowHeight = rowHeights[ri];
|
|
15672
16082
|
const advance = () => {
|
|
16083
|
+
if (segHasRows && segmentBottom && segmentBottom.style !== "none") {
|
|
16084
|
+
this.cur.items.push({
|
|
16085
|
+
kind: "edge",
|
|
16086
|
+
x1: x0,
|
|
16087
|
+
y1: this.y,
|
|
16088
|
+
x2: x0 + widths.reduce((sum2, width) => sum2 + width, 0),
|
|
16089
|
+
y2: this.y,
|
|
16090
|
+
border: segmentBottom,
|
|
16091
|
+
role: "table-rule"
|
|
16092
|
+
});
|
|
16093
|
+
}
|
|
15673
16094
|
this.emitTableGrips(tbl, segPage, x0, widths, segTop, this.y);
|
|
15674
16095
|
this.nextColumn();
|
|
15675
16096
|
this.clearBannerSlot();
|
|
15676
16097
|
x0 = computeX0();
|
|
15677
16098
|
segTop = this.y;
|
|
15678
16099
|
segPage = this.cur;
|
|
16100
|
+
segHasRows = false;
|
|
15679
16101
|
const firstRowIdx = !row.props.tblHeader && headerRows.length > 0 ? 0 : ri;
|
|
15680
16102
|
this.y += this.rowBorderWidths(tbl, firstRowIdx).top / 2;
|
|
15681
16103
|
if (!row.props.tblHeader) {
|
|
@@ -15685,6 +16107,7 @@ var Engine = class {
|
|
|
15685
16107
|
const hH = rowHeights[hIdx];
|
|
15686
16108
|
markTableStart();
|
|
15687
16109
|
this.paintRow(tbl, hr, hIdx, hLaid, x0, widths, hH);
|
|
16110
|
+
segHasRows = true;
|
|
15688
16111
|
this.y += hH;
|
|
15689
16112
|
}
|
|
15690
16113
|
}
|
|
@@ -15701,6 +16124,18 @@ var Engine = class {
|
|
|
15701
16124
|
if (parts) {
|
|
15702
16125
|
markTableStart();
|
|
15703
16126
|
this.paintRow(tbl, row, ri, parts.top, x0, widths, parts.top.height);
|
|
16127
|
+
segHasRows = true;
|
|
16128
|
+
if (segmentBottom && segmentBottom.style !== "none") {
|
|
16129
|
+
this.cur.items.push({
|
|
16130
|
+
kind: "edge",
|
|
16131
|
+
x1: x0,
|
|
16132
|
+
y1: this.y + parts.top.height,
|
|
16133
|
+
x2: x0 + widths.reduce((sum2, width) => sum2 + width, 0),
|
|
16134
|
+
y2: this.y + parts.top.height,
|
|
16135
|
+
border: segmentBottom,
|
|
16136
|
+
role: "table-rule"
|
|
16137
|
+
});
|
|
16138
|
+
}
|
|
15704
16139
|
this.y += parts.top.height;
|
|
15705
16140
|
advance();
|
|
15706
16141
|
laid = parts.rest;
|
|
@@ -15713,6 +16148,7 @@ var Engine = class {
|
|
|
15713
16148
|
}
|
|
15714
16149
|
markTableStart();
|
|
15715
16150
|
this.paintRow(tbl, row, ri, laid, x0, widths, rowHeight);
|
|
16151
|
+
segHasRows = true;
|
|
15716
16152
|
this.y += rowHeight;
|
|
15717
16153
|
if (s2 && ri < tbl.rows.length - 1) this.y += s2;
|
|
15718
16154
|
if (tbl.src) {
|
|
@@ -15912,7 +16348,8 @@ var Engine = class {
|
|
|
15912
16348
|
}
|
|
15913
16349
|
layoutTableInFrame(tbl, fake, x0, y, width, fields, nested) {
|
|
15914
16350
|
this.ensureTableBorders(tbl);
|
|
15915
|
-
const
|
|
16351
|
+
const confineToAvailable = !nested && tbl.props.width === void 0 && tbl.props.widthPct === void 0;
|
|
16352
|
+
const widths = this.resolveGridWidths(tbl, width, nested, confineToAvailable);
|
|
15916
16353
|
const saveY = this.y;
|
|
15917
16354
|
const saveCur = this.cur;
|
|
15918
16355
|
const saveCol = this.col;
|
|
@@ -15966,9 +16403,10 @@ var Engine = class {
|
|
|
15966
16403
|
const bottomOf = (it) => it.kind === "text" ? it.lineTop + it.lineHeight : it.kind === "rect" || it.kind === "image" ? it.y + it.height : it.kind === "edge" ? Math.max(it.y1, it.y2) : 0;
|
|
15967
16404
|
const topOf = (it) => it.kind === "text" ? it.lineTop : it.kind === "rect" || it.kind === "image" ? it.y : it.kind === "edge" ? Math.min(it.y1, it.y2) : 0;
|
|
15968
16405
|
const partitions = laid.cells.map((cell) => {
|
|
15969
|
-
const
|
|
16406
|
+
const flowItems = cell.items.filter((it) => it.kind !== "grip");
|
|
16407
|
+
const contentBottom = flowItems.length > 0 ? Math.max(...flowItems.map(bottomOf)) : 0;
|
|
15970
16408
|
const trailing = Math.max(0, cell.height - contentBottom);
|
|
15971
|
-
const hRules =
|
|
16409
|
+
const hRules = flowItems.filter(
|
|
15972
16410
|
(it) => it.kind === "edge" && Math.abs(it.y1 - it.y2) < 0.01 && Math.abs(it.x2 - it.x1) > 4
|
|
15973
16411
|
).map((it) => it.y1).sort((a, b) => a - b);
|
|
15974
16412
|
const bandBottom = (top, bottom) => {
|
|
@@ -15989,8 +16427,9 @@ var Engine = class {
|
|
|
15989
16427
|
return {
|
|
15990
16428
|
cell,
|
|
15991
16429
|
trailing,
|
|
15992
|
-
|
|
15993
|
-
|
|
16430
|
+
grips: cell.items.filter((it) => it.kind === "grip"),
|
|
16431
|
+
keep: flowItems.filter((it) => keeps(it)),
|
|
16432
|
+
rest: flowItems.filter((it) => !keeps(it))
|
|
15994
16433
|
};
|
|
15995
16434
|
});
|
|
15996
16435
|
const lineTops = (items) => [...new Set(items.filter((it) => it.kind === "text").map((it) => it.lineTop))].sort((a, b) => a - b);
|
|
@@ -16045,18 +16484,31 @@ var Engine = class {
|
|
|
16045
16484
|
})) {
|
|
16046
16485
|
return null;
|
|
16047
16486
|
}
|
|
16048
|
-
let
|
|
16487
|
+
let contentCut = 0;
|
|
16488
|
+
let flowCut = 0;
|
|
16049
16489
|
let allBanded = true;
|
|
16050
|
-
|
|
16490
|
+
let allBetweenParagraphs = true;
|
|
16491
|
+
let hasTextBoundary = false;
|
|
16492
|
+
for (const { cell, keep, rest, trailing } of partitions) {
|
|
16051
16493
|
if (keep.length === 0) continue;
|
|
16052
16494
|
const kb = Math.max(...keep.map(bottomOf));
|
|
16053
|
-
|
|
16495
|
+
flowCut = Math.max(flowCut, kb);
|
|
16496
|
+
contentCut = Math.max(contentCut, kb + trailing);
|
|
16054
16497
|
const onRule = cell.items.some(
|
|
16055
16498
|
(it) => it.kind === "edge" && Math.abs(it.y1 - it.y2) < 0.01 && Math.abs(it.x2 - it.x1) > 4 && Math.abs(it.y1 - kb) < 1
|
|
16056
16499
|
);
|
|
16057
16500
|
if (!onRule) allBanded = false;
|
|
16501
|
+
const keptText = keep.filter((it) => it.kind === "text");
|
|
16502
|
+
const restText = rest.filter((it) => it.kind === "text");
|
|
16503
|
+
if (keptText.length > 0 && restText.length > 0) {
|
|
16504
|
+
hasTextBoundary = true;
|
|
16505
|
+
if (keptText[keptText.length - 1].paraSeq === restText[0].paraSeq) {
|
|
16506
|
+
allBetweenParagraphs = false;
|
|
16507
|
+
}
|
|
16508
|
+
}
|
|
16058
16509
|
}
|
|
16059
|
-
const
|
|
16510
|
+
const hugContent = allBanded || hasTextBoundary && allBetweenParagraphs;
|
|
16511
|
+
const cutH = Math.min(avail + keepSlack, hugContent ? contentCut : flowCut);
|
|
16060
16512
|
const topCells = [];
|
|
16061
16513
|
const restCells = [];
|
|
16062
16514
|
let topH = 0;
|
|
@@ -16068,15 +16520,26 @@ var Engine = class {
|
|
|
16068
16520
|
}
|
|
16069
16521
|
return t;
|
|
16070
16522
|
};
|
|
16071
|
-
for (const { cell, trailing, keep, rest } of partitions) {
|
|
16072
|
-
const
|
|
16523
|
+
for (const { cell, trailing, grips, keep, rest } of partitions) {
|
|
16524
|
+
const flowItems = cell.items.filter((it) => it.kind !== "grip");
|
|
16525
|
+
const keepTop = flowItems.length > 0 ? Math.min(...flowItems.map(topOf)) : 0;
|
|
16073
16526
|
const ruleShift = rest.length > 0 ? Math.min(...rest.map(topOf)) - keepTop : 0;
|
|
16074
16527
|
const origText = firstTextTop(cell.items);
|
|
16075
16528
|
const restText = firstTextTop(rest);
|
|
16076
16529
|
const shift = rest.length > 0 && origText !== void 0 && restText !== void 0 ? Math.min(ruleShift, restText - origText) : ruleShift;
|
|
16530
|
+
for (const grip of grips) {
|
|
16531
|
+
const top = Math.min(grip.y1, grip.y2);
|
|
16532
|
+
const bottom = Math.max(grip.y1, grip.y2);
|
|
16533
|
+
if (bottom - top < 0.01) {
|
|
16534
|
+
(top <= cutH + 0.5 ? keep : rest).push({ ...grip });
|
|
16535
|
+
continue;
|
|
16536
|
+
}
|
|
16537
|
+
if (top < cutH) keep.push({ ...grip, y1: top, y2: Math.min(bottom, cutH) });
|
|
16538
|
+
if (bottom > cutH) rest.push({ ...grip, y1: Math.max(top, cutH), y2: bottom });
|
|
16539
|
+
}
|
|
16077
16540
|
for (const it of rest) offsetItem(it, 0, -shift);
|
|
16078
16541
|
topCells.push({ ...cell, items: keep, height: Math.min(cell.height, cutH) });
|
|
16079
|
-
const cellRestH = rest.length > 0 ? Math.max(...rest.map(bottomOf)) +
|
|
16542
|
+
const cellRestH = rest.length > 0 ? Math.max(...rest.map(bottomOf)) + trailing : 0;
|
|
16080
16543
|
restCells.push({ ...cell, items: rest, height: cellRestH });
|
|
16081
16544
|
topH = Math.max(topH, keep.length > 0 ? Math.min(cell.height, cutH) : 0);
|
|
16082
16545
|
restH = Math.max(restH, cellRestH);
|
|
@@ -16170,15 +16633,24 @@ var Engine = class {
|
|
|
16170
16633
|
const x = bidi ? totalW - sum(widths, 0, gridPos) - w : sum(widths, 0, gridPos);
|
|
16171
16634
|
gridPos += span;
|
|
16172
16635
|
const cm = { ...defaults, ...cell.props.margins };
|
|
16636
|
+
const autoGuidanceRightEdge = ci === row.cells.length - 1 && row.cells.length === 1 && widths.length === 1 && tbl.props.width === void 0 && tbl.props.widthPct === void 0 && (tbl.props.indent ?? 0) > 0 ? 0.01 : 0;
|
|
16173
16637
|
geometry.push({
|
|
16174
16638
|
x,
|
|
16175
16639
|
width: w,
|
|
16176
|
-
|
|
16640
|
+
// Word rounds the inner right edge of an indented, one-column auto
|
|
16641
|
+
// table just inside its twip-converted grid edge. Keep that hundredth
|
|
16642
|
+
// of a pixel reserved so an edge-touching final word wraps with Word
|
|
16643
|
+
// (the NIH guidance table on p76).
|
|
16644
|
+
margins: {
|
|
16645
|
+
...cm,
|
|
16646
|
+
left: leftInset(cm.left),
|
|
16647
|
+
right: rightInset(cm.right) + autoGuidanceRightEdge
|
|
16648
|
+
}
|
|
16177
16649
|
});
|
|
16178
16650
|
}
|
|
16179
16651
|
let maxH = 0;
|
|
16180
16652
|
let measuredContentH = 0;
|
|
16181
|
-
const effectiveBottomPad = (bottom) => this.doc.compatibilityMode < 15 && row.props.heightRule === "atLeast" && (row.props.height ?? 0) < ptToPx(2)
|
|
16653
|
+
const effectiveBottomPad = (bottom) => this.doc.compatibilityMode < 15 && row.props.heightRule === "atLeast" && (row.props.height ?? 0) < ptToPx(2) ? (bottom ?? 0) >= ptToPx(2) ? (bottom ?? 0) / 2 : (bottom ?? 0) / 4 : bottom ?? 0;
|
|
16182
16654
|
for (let ci = 0; ci < row.cells.length; ci++) {
|
|
16183
16655
|
const cell = row.cells[ci];
|
|
16184
16656
|
const { x, width: w, margins: m } = geometry[ci];
|
|
@@ -16335,7 +16807,7 @@ var Engine = class {
|
|
|
16335
16807
|
dy += Math.max(0, contentH - cellLay.height);
|
|
16336
16808
|
}
|
|
16337
16809
|
const clip = row.props.heightRule === "exact";
|
|
16338
|
-
const rowBottom = y + rowHeight;
|
|
16810
|
+
const rowBottom = y + (cell.props.vMerge === "restart" ? cellH : rowHeight);
|
|
16339
16811
|
for (const it of cellLay.items) {
|
|
16340
16812
|
offsetItem(it, cx, y + dy);
|
|
16341
16813
|
if (clip && it.kind === "text" && it.lineTop !== void 0 && it.lineTop >= rowBottom - 0.5) continue;
|
|
@@ -16343,7 +16815,9 @@ var Engine = class {
|
|
|
16343
16815
|
if (it.kind === "text" && it.noteId !== void 0) this.registerFootnote(it.noteId, page);
|
|
16344
16816
|
page.items.push(it);
|
|
16345
16817
|
}
|
|
16346
|
-
|
|
16818
|
+
const spanEndsAtTableBottom = rowIdx + rowSpan === tbl.rows.length;
|
|
16819
|
+
const isCellLastRow = cell.props.vMerge === "restart" ? spanEndsAtTableBottom : isLastRow;
|
|
16820
|
+
this.paintCellEdges(page, tbl, cell, cx, y, cellLay.width, cellH, isFirstRow && !s2, isCellLastRow && !s2, isFirstCol && !s2, isLastCol && !s2, false, cond?.borders);
|
|
16347
16821
|
}
|
|
16348
16822
|
}
|
|
16349
16823
|
paintCellEdges(page, tbl, cell, x, y, w, h, firstRow, lastRow, firstCol, lastCol, mergedContinue, condBorders) {
|
|
@@ -16356,7 +16830,7 @@ var Engine = class {
|
|
|
16356
16830
|
return fallback && fallback.style !== "none" ? fallback : void 0;
|
|
16357
16831
|
};
|
|
16358
16832
|
const top = mergedContinue || cell.props.vMerge === "continue" ? void 0 : pick(cb?.top, condBorders?.top, tb?.top, tb?.insideH, firstRow);
|
|
16359
|
-
const bottom = cell.props.vMerge === "
|
|
16833
|
+
const bottom = (mergedContinue || cell.props.vMerge === "continue") && !lastRow ? void 0 : pick(cb?.bottom, condBorders?.bottom, tb?.bottom, tb?.insideH, lastRow);
|
|
16360
16834
|
const left = pick(cb?.left, condBorders?.left, tb?.left, tb?.insideV, firstCol);
|
|
16361
16835
|
const right = pick(cb?.right, condBorders?.right, tb?.right, tb?.insideV, lastCol);
|
|
16362
16836
|
if (top) {
|
|
@@ -18114,6 +18588,11 @@ function renderChart(item) {
|
|
|
18114
18588
|
}
|
|
18115
18589
|
return svg;
|
|
18116
18590
|
}
|
|
18591
|
+
function setItemLayer(element, item, frontLayer = 1) {
|
|
18592
|
+
if (item.behind) element.style.zIndex = "-1";
|
|
18593
|
+
else if (item.z !== void 0) element.style.zIndex = String(item.z);
|
|
18594
|
+
else if (item.front) element.style.zIndex = String(frontLayer);
|
|
18595
|
+
}
|
|
18117
18596
|
function renderItem(doc, item, urls) {
|
|
18118
18597
|
switch (item.kind) {
|
|
18119
18598
|
case "rect": {
|
|
@@ -18128,8 +18607,7 @@ function renderItem(doc, item, urls) {
|
|
|
18128
18607
|
el16.style.transform = `rotate(${item.rotate.deg}deg)`;
|
|
18129
18608
|
el16.style.transformOrigin = `${item.rotate.ox}px ${item.rotate.oy}px`;
|
|
18130
18609
|
}
|
|
18131
|
-
|
|
18132
|
-
else if (item.front) el16.style.zIndex = "1";
|
|
18610
|
+
setItemLayer(el16, item);
|
|
18133
18611
|
return el16;
|
|
18134
18612
|
}
|
|
18135
18613
|
case "path": {
|
|
@@ -18155,8 +18633,7 @@ function renderItem(doc, item, urls) {
|
|
|
18155
18633
|
if (item.stroke.opacity !== void 0) path2.setAttribute("stroke-opacity", String(item.stroke.opacity));
|
|
18156
18634
|
path2.setAttribute("vector-effect", "non-scaling-stroke");
|
|
18157
18635
|
}
|
|
18158
|
-
|
|
18159
|
-
else if (item.front) svg.style.zIndex = "1";
|
|
18636
|
+
setItemLayer(svg, item);
|
|
18160
18637
|
svg.appendChild(path2);
|
|
18161
18638
|
return svg;
|
|
18162
18639
|
}
|
|
@@ -18168,7 +18645,7 @@ function renderItem(doc, item, urls) {
|
|
|
18168
18645
|
hit.style.width = `${item.width}px`;
|
|
18169
18646
|
hit.style.height = `${item.height}px`;
|
|
18170
18647
|
hit.style.cursor = "move";
|
|
18171
|
-
hit.style.zIndex = item.belowText ? "1" : "6";
|
|
18648
|
+
hit.style.zIndex = item.z !== void 0 ? String(item.z) : item.belowText ? "1" : "6";
|
|
18172
18649
|
if (item.rotate) {
|
|
18173
18650
|
hit.style.transform = `rotate(${item.rotate.deg}deg)`;
|
|
18174
18651
|
hit.style.transformOrigin = `${item.rotate.ox}px ${item.rotate.oy}px`;
|
|
@@ -18185,7 +18662,7 @@ function renderItem(doc, item, urls) {
|
|
|
18185
18662
|
}
|
|
18186
18663
|
case "edge": {
|
|
18187
18664
|
const el16 = renderEdge(item.x1, item.y1, item.x2, item.y2, item.border, item.rotate);
|
|
18188
|
-
|
|
18665
|
+
setItemLayer(el16, item);
|
|
18189
18666
|
return el16;
|
|
18190
18667
|
}
|
|
18191
18668
|
case "chart":
|
|
@@ -18373,8 +18850,7 @@ function renderItem(doc, item, urls) {
|
|
|
18373
18850
|
node.style.transformOrigin = `${item.rotate.ox}px ${item.rotate.oy}px`;
|
|
18374
18851
|
} else if (item.rotation) node.style.transform = `rotate(${item.rotation}deg)`;
|
|
18375
18852
|
if (item.border) node.style.outline = `${item.border.width}px solid ${item.border.color}`;
|
|
18376
|
-
|
|
18377
|
-
else if (item.front) node.style.zIndex = "2";
|
|
18853
|
+
setItemLayer(node, item, 2);
|
|
18378
18854
|
node.dataset.dxwImageFormat = ext;
|
|
18379
18855
|
if (item.model3D) node.dataset.dxwModel3d = "1";
|
|
18380
18856
|
if (item.webVideo) {
|
|
@@ -18435,11 +18911,15 @@ function renderWordArt(item) {
|
|
|
18435
18911
|
const weight = item.bold ? "bold " : "";
|
|
18436
18912
|
const style = item.italic ? "italic " : "";
|
|
18437
18913
|
if (item.noFit) {
|
|
18438
|
-
const
|
|
18439
|
-
|
|
18440
|
-
|
|
18441
|
-
|
|
18442
|
-
|
|
18914
|
+
const stroke = document.createElement("div");
|
|
18915
|
+
stroke.style.position = "absolute";
|
|
18916
|
+
stroke.style.left = `${item.width * 0.0603}px`;
|
|
18917
|
+
stroke.style.top = `${item.height * -0.079}px`;
|
|
18918
|
+
stroke.style.width = "0.5px";
|
|
18919
|
+
stroke.style.height = `${item.height * 0.651}px`;
|
|
18920
|
+
stroke.style.background = item.fill;
|
|
18921
|
+
stroke.style.opacity = String(item.opacity);
|
|
18922
|
+
box.appendChild(stroke);
|
|
18443
18923
|
return box;
|
|
18444
18924
|
}
|
|
18445
18925
|
const fontPx = item.height * 0.92;
|
|
@@ -18496,12 +18976,12 @@ function warpBaseline(warp, W, H) {
|
|
|
18496
18976
|
}
|
|
18497
18977
|
case "textWave1":
|
|
18498
18978
|
case "textWave2": {
|
|
18499
|
-
const fontPx = H * 0.
|
|
18979
|
+
const fontPx = H * 0.78;
|
|
18500
18980
|
const d = `M ${mx} ${H * 0.5} C ${W * 0.16} ${H * 0.33} ${W * 0.34} ${H * 0.33} ${W * 0.5} ${H * 0.5} C ${W * 0.66} ${H * 0.67} ${W * 0.84} ${H * 0.67} ${W - mx} ${H * 0.5}`;
|
|
18501
18981
|
return { d, fontPx, pathLen: bw * 1.06, startFrac: 0, anchor: "start", fill: true };
|
|
18502
18982
|
}
|
|
18503
18983
|
case "textChevron": {
|
|
18504
|
-
const fontPx = H * 0.
|
|
18984
|
+
const fontPx = H * 0.78;
|
|
18505
18985
|
const yEnds = H * 0.26;
|
|
18506
18986
|
const yCtrl = H * 1.18;
|
|
18507
18987
|
const d = `M ${mx} ${yEnds} Q ${W / 2} ${yCtrl} ${W - mx} ${yEnds}`;
|
|
@@ -18523,7 +19003,7 @@ function warpBaseline(warp, W, H) {
|
|
|
18523
19003
|
const r = Math.min(W, H) * 0.3;
|
|
18524
19004
|
const cx = W / 2;
|
|
18525
19005
|
const cy = H / 2;
|
|
18526
|
-
const a = -
|
|
19006
|
+
const a = -90 * Math.PI / 180;
|
|
18527
19007
|
const sx = cx + r * Math.sin(a);
|
|
18528
19008
|
const sy = cy - r * Math.cos(a);
|
|
18529
19009
|
const d = `M ${sx.toFixed(2)} ${sy.toFixed(2)} A ${r} ${r} 0 1 1 ${(sx - 0.01).toFixed(2)} ${sy.toFixed(2)} Z`;
|
|
@@ -18548,30 +19028,96 @@ function renderWarpText(item) {
|
|
|
18548
19028
|
svg.style.transformOrigin = `${item.rotate.ox}px ${item.rotate.oy}px`;
|
|
18549
19029
|
}
|
|
18550
19030
|
svg.style.pointerEvents = "none";
|
|
18551
|
-
|
|
18552
|
-
else if (item.front) svg.style.zIndex = "1";
|
|
19031
|
+
setItemLayer(svg, item);
|
|
18553
19032
|
const geo = warpBaseline(item.warp, W, H);
|
|
18554
19033
|
const weight = item.bold ? "bold" : "normal";
|
|
18555
19034
|
const style = item.italic ? "italic" : "normal";
|
|
18556
|
-
const family = `"${item.fontFamily}", sans-serif`;
|
|
18557
|
-
|
|
18558
|
-
|
|
18559
|
-
|
|
18560
|
-
|
|
18561
|
-
|
|
18562
|
-
|
|
19035
|
+
const family = /^calibri(?: light)?$/i.test(item.fontFamily) ? `"${item.fontFamily}", "Carlito", sans-serif` : `"${item.fontFamily}", sans-serif`;
|
|
19036
|
+
if (item.warp === "textWave1" || item.warp === "textWave2" || item.warp === "textChevron") {
|
|
19037
|
+
const fontPx2 = H * 0.98;
|
|
19038
|
+
let widths = [...item.text].map((ch) => ch === " " ? fontPx2 * 0.25 : fontPx2 * 0.6);
|
|
19039
|
+
try {
|
|
19040
|
+
const ctx = document.createElement("canvas").getContext("2d");
|
|
19041
|
+
if (ctx) {
|
|
19042
|
+
ctx.font = `${style} ${weight} ${fontPx2}px ${family}`;
|
|
19043
|
+
widths = [...item.text].map((ch) => ctx.measureText(ch).width);
|
|
19044
|
+
}
|
|
19045
|
+
} catch {
|
|
19046
|
+
}
|
|
19047
|
+
const naturalWidth = widths.reduce((sum2, width) => sum2 + width, 0);
|
|
19048
|
+
const scaleX = naturalWidth > 0 ? W * 0.94 / naturalWidth : 1;
|
|
19049
|
+
let pen = W * 0.03;
|
|
19050
|
+
[...item.text].forEach((ch, index) => {
|
|
19051
|
+
const advance = widths[index] * scaleX;
|
|
19052
|
+
const x = pen + advance / 2;
|
|
19053
|
+
pen += advance;
|
|
19054
|
+
if (ch === " ") return;
|
|
19055
|
+
const baseline = item.warp === "textChevron" ? H * (0.74 + 0.21 * Math.abs(2 * x / W - 1)) : H * (0.85 + 0.1 * Math.sin(2 * Math.PI * (x / W - 0.5)));
|
|
19056
|
+
const glyph = document.createElementNS(SVG_NS, "text");
|
|
19057
|
+
glyph.setAttribute("x", "0");
|
|
19058
|
+
glyph.setAttribute("y", "0");
|
|
19059
|
+
glyph.setAttribute("fill", item.fill);
|
|
19060
|
+
glyph.setAttribute("font-family", family);
|
|
19061
|
+
glyph.setAttribute("font-size", `${fontPx2.toFixed(2)}`);
|
|
19062
|
+
glyph.setAttribute("font-weight", weight);
|
|
19063
|
+
glyph.setAttribute("font-style", style);
|
|
19064
|
+
glyph.setAttribute("text-anchor", "middle");
|
|
19065
|
+
glyph.setAttribute("dominant-baseline", "alphabetic");
|
|
19066
|
+
glyph.setAttribute(
|
|
19067
|
+
"transform",
|
|
19068
|
+
`translate(${x.toFixed(2)} ${baseline.toFixed(2)}) scale(${scaleX.toFixed(5)} 1)`
|
|
19069
|
+
);
|
|
19070
|
+
glyph.textContent = ch;
|
|
19071
|
+
svg.appendChild(glyph);
|
|
19072
|
+
});
|
|
19073
|
+
return svg;
|
|
19074
|
+
}
|
|
19075
|
+
if (geo.pour) {
|
|
19076
|
+
const chars = [...item.text];
|
|
19077
|
+
const radius = Math.min(W, H) * 0.368;
|
|
19078
|
+
const fontPx2 = Math.min(W, H) * 0.38;
|
|
19079
|
+
let advances = chars.map((ch) => ch === " " ? fontPx2 * 0.25 : fontPx2 * 0.55);
|
|
18563
19080
|
try {
|
|
18564
19081
|
const ctx = document.createElement("canvas").getContext("2d");
|
|
18565
19082
|
if (ctx) {
|
|
18566
|
-
ctx.font = `${style} ${weight}
|
|
18567
|
-
|
|
18568
|
-
if (w > 0) perPx = w / 100;
|
|
19083
|
+
ctx.font = `${style} ${weight} ${fontPx2}px ${family}`;
|
|
19084
|
+
advances = chars.map((ch) => ctx.measureText(ch).width);
|
|
18569
19085
|
}
|
|
18570
19086
|
} catch {
|
|
18571
19087
|
}
|
|
18572
|
-
const
|
|
18573
|
-
const
|
|
18574
|
-
|
|
19088
|
+
const totalAdvance = advances.reduce((sum2, advance) => sum2 + advance, 0);
|
|
19089
|
+
const firstCenter = -76 * Math.PI / 180;
|
|
19090
|
+
const angularScale = 1.0125;
|
|
19091
|
+
let along = 0;
|
|
19092
|
+
chars.forEach((ch, index) => {
|
|
19093
|
+
const angle = firstCenter + 2 * Math.PI * angularScale * (along + advances[index] / 2 - advances[0] / 2) / totalAdvance;
|
|
19094
|
+
along += advances[index];
|
|
19095
|
+
if (ch === " ") return;
|
|
19096
|
+
const x = W / 2 + radius * Math.sin(angle);
|
|
19097
|
+
const y = H / 2 - radius * Math.cos(angle);
|
|
19098
|
+
const glyph = document.createElementNS(SVG_NS, "text");
|
|
19099
|
+
glyph.setAttribute("x", "0");
|
|
19100
|
+
glyph.setAttribute("y", "0");
|
|
19101
|
+
glyph.setAttribute("fill", item.fill);
|
|
19102
|
+
glyph.setAttribute("font-family", family);
|
|
19103
|
+
glyph.setAttribute("font-size", `${fontPx2.toFixed(2)}`);
|
|
19104
|
+
glyph.setAttribute("font-weight", weight);
|
|
19105
|
+
glyph.setAttribute("font-style", style);
|
|
19106
|
+
glyph.setAttribute("text-anchor", "middle");
|
|
19107
|
+
glyph.setAttribute("dominant-baseline", "central");
|
|
19108
|
+
glyph.setAttribute(
|
|
19109
|
+
"transform",
|
|
19110
|
+
`translate(${x.toFixed(2)} ${y.toFixed(2)}) rotate(${(angle * 180 / Math.PI).toFixed(2)})`
|
|
19111
|
+
);
|
|
19112
|
+
glyph.textContent = ch;
|
|
19113
|
+
svg.appendChild(glyph);
|
|
19114
|
+
});
|
|
19115
|
+
return svg;
|
|
19116
|
+
}
|
|
19117
|
+
let fontPx = geo.fontPx;
|
|
19118
|
+
let startFrac = geo.startFrac;
|
|
19119
|
+
if (geo.natural) {
|
|
19120
|
+
fontPx = item.fontSize;
|
|
18575
19121
|
}
|
|
18576
19122
|
const id = `dxw-warp-${warpPathSeq++}`;
|
|
18577
19123
|
const defs = document.createElementNS(SVG_NS, "defs");
|
|
@@ -18653,6 +19199,7 @@ function renderText(item) {
|
|
|
18653
19199
|
el16.style.lineHeight = `${boxH}px`;
|
|
18654
19200
|
el16.style.setProperty("-webkit-font-smoothing", "antialiased");
|
|
18655
19201
|
const props = item.props;
|
|
19202
|
+
if (item.font.kerning) el16.style.fontKerning = "normal";
|
|
18656
19203
|
let color = props.color && props.color !== "auto" ? props.color : "#000000";
|
|
18657
19204
|
el16.style.color = color;
|
|
18658
19205
|
if (props.underline && props.underline !== "none") {
|
|
@@ -18664,7 +19211,15 @@ function renderText(item) {
|
|
|
18664
19211
|
} else if (props.underline === "none" && item.href) {
|
|
18665
19212
|
el16.style.textDecoration = "none";
|
|
18666
19213
|
}
|
|
18667
|
-
|
|
19214
|
+
const paintLetterSpacing = props.paintLetterSpacing ?? props.letterSpacing;
|
|
19215
|
+
if (paintLetterSpacing) el16.style.letterSpacing = `${paintLetterSpacing}px`;
|
|
19216
|
+
if (props.paintLetterSpacing !== void 0 && props.letterSpacing !== void 0 && item.text.trim()) {
|
|
19217
|
+
const paintWidth = item.width - (props.letterSpacing - props.paintLetterSpacing) * item.text.length;
|
|
19218
|
+
if (paintWidth > 0.1) {
|
|
19219
|
+
el16.style.transform = `scaleX(${item.width / paintWidth})`;
|
|
19220
|
+
el16.style.transformOrigin = "0 50%";
|
|
19221
|
+
}
|
|
19222
|
+
}
|
|
18668
19223
|
if (props.textScale && props.textScale !== 1 && !item.mathScaleY) {
|
|
18669
19224
|
el16.style.transform = `scaleX(${props.textScale})`;
|
|
18670
19225
|
el16.style.transformOrigin = "0 50%";
|
|
@@ -18693,8 +19248,7 @@ function renderText(item) {
|
|
|
18693
19248
|
el16.style.transform = `rotate(${item.rotate.deg}deg)${prev ? " " + prev : ""}`;
|
|
18694
19249
|
el16.style.transformOrigin = `${item.rotate.ox}px ${item.rotate.oy}px`;
|
|
18695
19250
|
}
|
|
18696
|
-
|
|
18697
|
-
else if (item.front) el16.style.zIndex = "1";
|
|
19251
|
+
setItemLayer(el16, item);
|
|
18698
19252
|
return el16;
|
|
18699
19253
|
}
|
|
18700
19254
|
function renderEdge(x1, y1, x2, y2, border, rotate) {
|
|
@@ -18707,14 +19261,47 @@ function renderEdge(x1, y1, x2, y2, border, rotate) {
|
|
|
18707
19261
|
}
|
|
18708
19262
|
const horizontal = Math.abs(y2 - y1) < 0.01;
|
|
18709
19263
|
const dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
|
|
18710
|
-
const
|
|
18711
|
-
const
|
|
19264
|
+
const ultraThin = rotate === void 0 && border.style === "single" && border.rawWidth !== void 0 && border.rawWidth < 0.25;
|
|
19265
|
+
const deviceHairline = rotate === void 0 && border.style === "single" && border.rawWidth !== void 0 && border.rawWidth < 0.75;
|
|
19266
|
+
const declaredWidth = border.rawWidth ?? border.width;
|
|
19267
|
+
const w = border.rawWidth !== void 0 && border.rawWidth < 0.25 ? border.rawWidth : Math.max(1 / dpr, Math.round(declaredWidth * dpr) / dpr);
|
|
18712
19268
|
const snap = (v) => Math.round(v * dpr) / dpr;
|
|
18713
|
-
const place = border.space === 0 ? snap : (v) => v;
|
|
19269
|
+
const place = border.space === 0 && !deviceHairline ? snap : (v) => v;
|
|
18714
19270
|
const dashPattern = border.style === "dashed" || border.style === "dotDash" || border.style === "dotDotDash" ? [3, 1] : border.style === "dotted" ? [1, 1] : null;
|
|
19271
|
+
if (!horizontal && Math.abs(x2 - x1) >= 0.01) {
|
|
19272
|
+
const x = Math.min(x1, x2);
|
|
19273
|
+
const y = Math.min(y1, y2);
|
|
19274
|
+
const stroke = document.createElement("div");
|
|
19275
|
+
const strokeHeight = border.style === "double" ? w * 3 : w;
|
|
19276
|
+
stroke.style.position = "absolute";
|
|
19277
|
+
stroke.style.left = `${x1 - x}px`;
|
|
19278
|
+
stroke.style.top = `${y1 - y - strokeHeight / 2}px`;
|
|
19279
|
+
stroke.style.width = `${Math.hypot(x2 - x1, y2 - y1)}px`;
|
|
19280
|
+
stroke.style.height = `${strokeHeight}px`;
|
|
19281
|
+
stroke.style.transform = `rotate(${Math.atan2(y2 - y1, x2 - x1)}rad)`;
|
|
19282
|
+
stroke.style.transformOrigin = "0 50%";
|
|
19283
|
+
if (border.style === "double") {
|
|
19284
|
+
stroke.style.background = `linear-gradient(180deg, ${border.color} 0 ${w}px, transparent ${w}px ${w * 2}px, ${border.color} ${w * 2}px ${w * 3}px)`;
|
|
19285
|
+
} else if (dashPattern) {
|
|
19286
|
+
const on = Math.max(dashPattern[0] * border.width, 2);
|
|
19287
|
+
const period = on + Math.max(dashPattern[1] * border.width, 1);
|
|
19288
|
+
stroke.style.background = `repeating-linear-gradient(90deg, ${border.color} 0 ${on}px, transparent ${on}px ${period}px)`;
|
|
19289
|
+
} else if (border.style === "triple") {
|
|
19290
|
+
stroke.style.height = "0";
|
|
19291
|
+
stroke.style.borderTop = `${w}px double ${border.color}`;
|
|
19292
|
+
} else {
|
|
19293
|
+
stroke.style.background = border.color;
|
|
19294
|
+
}
|
|
19295
|
+
el16.style.left = `${x}px`;
|
|
19296
|
+
el16.style.top = `${y}px`;
|
|
19297
|
+
el16.style.width = `${Math.abs(x2 - x1)}px`;
|
|
19298
|
+
el16.style.height = `${Math.abs(y2 - y1)}px`;
|
|
19299
|
+
el16.appendChild(stroke);
|
|
19300
|
+
return el16;
|
|
19301
|
+
}
|
|
18715
19302
|
if (horizontal) {
|
|
18716
19303
|
el16.style.left = `${Math.min(x1, x2)}px`;
|
|
18717
|
-
el16.style.top = `${place(y1 - w / 2)}px`;
|
|
19304
|
+
el16.style.top = `${place(y1 - w / 2 - (ultraThin ? 0.4 : 0))}px`;
|
|
18718
19305
|
el16.style.width = `${Math.abs(x2 - x1)}px`;
|
|
18719
19306
|
if (border.style === "double") {
|
|
18720
19307
|
el16.style.height = `${w * 3}px`;
|
|
@@ -18722,11 +19309,20 @@ function renderEdge(x1, y1, x2, y2, border, rotate) {
|
|
|
18722
19309
|
} else if (dashPattern) {
|
|
18723
19310
|
const on = Math.max(dashPattern[0] * border.width, 2);
|
|
18724
19311
|
const period = on + Math.max(dashPattern[1] * border.width, 1);
|
|
18725
|
-
el16.style.height = `${w}px`;
|
|
19312
|
+
el16.style.height = `${w < 1 && rotate === void 0 ? 1 : w}px`;
|
|
18726
19313
|
el16.style.background = `repeating-linear-gradient(90deg, ${border.color} 0 ${on}px, transparent ${on}px ${period}px)`;
|
|
19314
|
+
if (w < 1 && rotate === void 0) {
|
|
19315
|
+
el16.style.transform = `scaleY(${w})`;
|
|
19316
|
+
el16.style.transformOrigin = "0 0";
|
|
19317
|
+
}
|
|
18727
19318
|
} else if (border.style === "triple") {
|
|
18728
19319
|
el16.style.height = "0";
|
|
18729
19320
|
el16.style.borderTop = `${w}px double ${border.color}`;
|
|
19321
|
+
} else if (deviceHairline) {
|
|
19322
|
+
el16.style.height = "1px";
|
|
19323
|
+
el16.style.background = border.color;
|
|
19324
|
+
el16.style.transform = "scaleY(.5)";
|
|
19325
|
+
el16.style.transformOrigin = "0 0";
|
|
18730
19326
|
} else {
|
|
18731
19327
|
el16.style.height = `${w}px`;
|
|
18732
19328
|
el16.style.background = border.color;
|
|
@@ -18741,11 +19337,20 @@ function renderEdge(x1, y1, x2, y2, border, rotate) {
|
|
|
18741
19337
|
} else if (dashPattern) {
|
|
18742
19338
|
const on = Math.max(dashPattern[0] * border.width, 2);
|
|
18743
19339
|
const period = on + Math.max(dashPattern[1] * border.width, 1);
|
|
18744
|
-
el16.style.width = `${w}px`;
|
|
19340
|
+
el16.style.width = `${w < 1 && rotate === void 0 ? 1 : w}px`;
|
|
18745
19341
|
el16.style.background = `repeating-linear-gradient(180deg, ${border.color} 0 ${on}px, transparent ${on}px ${period}px)`;
|
|
19342
|
+
if (w < 1 && rotate === void 0) {
|
|
19343
|
+
el16.style.transform = `scaleX(${w})`;
|
|
19344
|
+
el16.style.transformOrigin = "0 0";
|
|
19345
|
+
}
|
|
18746
19346
|
} else if (border.style === "triple") {
|
|
18747
19347
|
el16.style.width = "0";
|
|
18748
19348
|
el16.style.borderLeft = `${w}px double ${border.color}`;
|
|
19349
|
+
} else if (deviceHairline) {
|
|
19350
|
+
el16.style.width = "1px";
|
|
19351
|
+
el16.style.background = border.color;
|
|
19352
|
+
el16.style.transform = "scaleX(.5)";
|
|
19353
|
+
el16.style.transformOrigin = "0 0";
|
|
18749
19354
|
} else {
|
|
18750
19355
|
el16.style.width = `${w}px`;
|
|
18751
19356
|
el16.style.background = border.color;
|
|
@@ -31357,6 +31962,7 @@ function DocxView({
|
|
|
31357
31962
|
}
|
|
31358
31963
|
}
|
|
31359
31964
|
loads.push(document.fonts.load('16px "Cambria Math"').catch(() => []));
|
|
31965
|
+
loads.push(document.fonts.load('16px "Segoe UI Emoji"', "\u{1F680}").catch(() => []));
|
|
31360
31966
|
const cjk = [
|
|
31361
31967
|
"MS Mincho",
|
|
31362
31968
|
"MS Gothic",
|