wordinweb 0.1.9 → 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 +49 -2
- package/dist/index.d.ts +55 -10
- package/dist/index.js +2056 -398
- 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;
|
|
@@ -3955,10 +3972,12 @@ function parseRun(r, ctx, field, suppressedObjects) {
|
|
|
3955
3972
|
case "endnoteReference": {
|
|
3956
3973
|
const id = intAttr(el16, "id");
|
|
3957
3974
|
if (id !== void 0) {
|
|
3975
|
+
const customMark = attr(el16, "customMarkFollows");
|
|
3958
3976
|
run.content.push({
|
|
3959
3977
|
kind: "noteRef",
|
|
3960
3978
|
noteType: ln === "footnoteReference" ? "footnote" : "endnote",
|
|
3961
|
-
id
|
|
3979
|
+
id,
|
|
3980
|
+
customMarkFollows: customMark !== void 0 && customMark !== "0" && customMark !== "false" && customMark !== "off"
|
|
3962
3981
|
});
|
|
3963
3982
|
}
|
|
3964
3983
|
break;
|
|
@@ -4352,7 +4371,8 @@ function parseDrawing(drawing, ctx) {
|
|
|
4352
4371
|
const pctEl = el16 ? el16.children.find((c) => localName(c.name).startsWith("pct")) : void 0;
|
|
4353
4372
|
if (!pctEl) return void 0;
|
|
4354
4373
|
const rf = attr(el16, "relativeFrom");
|
|
4355
|
-
|
|
4374
|
+
const pct = (parseInt(pctEl.text, 10) || 0) / 1e5;
|
|
4375
|
+
return pct > 0 ? { pct, rel: rf === "page" ? "page" : "margin" } : void 0;
|
|
4356
4376
|
};
|
|
4357
4377
|
const spPr = child(textboxEl, "spPr");
|
|
4358
4378
|
const txbxOwn = child(textboxEl, "txbx");
|
|
@@ -4361,6 +4381,7 @@ function parseDrawing(drawing, ctx) {
|
|
|
4361
4381
|
const rot = intAttr(xfrm, "rot");
|
|
4362
4382
|
const lnEl = child(spPr, "ln");
|
|
4363
4383
|
const strokeColor = lnEl && !child(lnEl, "noFill") ? fillColorOf(lnEl) : void 0;
|
|
4384
|
+
const fill = child(spPr, "noFill") ? void 0 : fillColorOf(spPr) ?? styleFillOf(textboxEl);
|
|
4364
4385
|
const bodyPr = child(textboxEl, "bodyPr");
|
|
4365
4386
|
const insetOf = (name, dflt) => {
|
|
4366
4387
|
const v = bodyPr ? intAttr(bodyPr, name) : void 0;
|
|
@@ -4404,7 +4425,7 @@ function parseDrawing(drawing, ctx) {
|
|
|
4404
4425
|
vAlign: vAlignOf(posV),
|
|
4405
4426
|
blocks: txbxContent ? parseBlocks(txbxContent, ctx) : [],
|
|
4406
4427
|
...textboxChainId !== void 0 ? { chainId: textboxChainId, chainSeq: textboxChainSeq ?? 0 } : {},
|
|
4407
|
-
...
|
|
4428
|
+
...fill ? { fill } : {},
|
|
4408
4429
|
...strokeColor ? { stroke: { color: strokeColor, weight: Math.max(emuToPx(intAttr(lnEl, "w") ?? 0), 0.75) } } : {},
|
|
4409
4430
|
textAnchor: anchorAttr === "ctr" ? "middle" : anchorAttr === "b" ? "bottom" : anchorAttr === "t" ? "top" : void 0,
|
|
4410
4431
|
insets: {
|
|
@@ -4818,7 +4839,8 @@ function collectDiagramShapes(dspRoot, ctx, out, dx, dy) {
|
|
|
4818
4839
|
height: emuToPx(th),
|
|
4819
4840
|
blocks,
|
|
4820
4841
|
insets: { l: insetOf("lIns", 9.6), t: insetOf("tIns", 4.8), r: insetOf("rIns", 9.6), b: insetOf("bIns", 4.8) },
|
|
4821
|
-
textAnchor: anchorAttr === "ctr" ? "middle" : anchorAttr === "b" ? "bottom" : "top"
|
|
4842
|
+
textAnchor: anchorAttr === "ctr" ? "middle" : anchorAttr === "b" ? "bottom" : "top",
|
|
4843
|
+
paintOffsetY: 0.75
|
|
4822
4844
|
});
|
|
4823
4845
|
}
|
|
4824
4846
|
}
|
|
@@ -4904,6 +4926,8 @@ function drawingMLRun(r, ctx) {
|
|
|
4904
4926
|
const props = {};
|
|
4905
4927
|
const sz = rPr ? intAttr(rPr, "sz") : void 0;
|
|
4906
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;
|
|
4907
4931
|
if (rPr && attr(rPr, "b") === "1") props.bold = true;
|
|
4908
4932
|
if (rPr && attr(rPr, "i") === "1") props.italic = true;
|
|
4909
4933
|
const u = rPr ? attr(rPr, "u") : void 0;
|
|
@@ -5348,6 +5372,8 @@ function parseCell(tc, ctx) {
|
|
|
5348
5372
|
if (tcW && attr(tcW, "type") === "dxa") {
|
|
5349
5373
|
const w = intAttr(tcW, "w");
|
|
5350
5374
|
if (w) props.width = twipsToPx(w);
|
|
5375
|
+
} else if (tcW && attr(tcW, "type") === "auto") {
|
|
5376
|
+
props.widthAuto = true;
|
|
5351
5377
|
}
|
|
5352
5378
|
const borders = child(tcPr, "tcBorders");
|
|
5353
5379
|
if (borders) {
|
|
@@ -5723,6 +5749,9 @@ var DocxDocument = class _DocxDocument {
|
|
|
5723
5749
|
/** Note content by note id (render-only; sources stripped). */
|
|
5724
5750
|
this.footnotes = /* @__PURE__ */ new Map();
|
|
5725
5751
|
this.endnotes = /* @__PURE__ */ new Map();
|
|
5752
|
+
/** The separator paragraph controls the gap between its rule and the first
|
|
5753
|
+
* footnote. */
|
|
5754
|
+
this.footnoteSeparator = [];
|
|
5726
5755
|
/** `_Ref` cross-reference bookmark ranges (name → captured runs). REF
|
|
5727
5756
|
* fields re-render the referenced text from these — Word recomputes REF on
|
|
5728
5757
|
* open, so the cached field result in the file is stale. */
|
|
@@ -5839,6 +5868,8 @@ var DocxDocument = class _DocxDocument {
|
|
|
5839
5868
|
if (!docRoot) throw new Error(`Missing ${docPart} in package`);
|
|
5840
5869
|
this.docRoot = docRoot;
|
|
5841
5870
|
this.rememberOriginalXml(docPart, docRoot);
|
|
5871
|
+
const coreProperties = this.readXmlOptional("docProps/core.xml");
|
|
5872
|
+
this.hydrateCorePropertyControls(docRoot, coreProperties);
|
|
5842
5873
|
this.repairLegacyWordInWebObjects();
|
|
5843
5874
|
this.documentRels = parseRelationships(this.relsRoot ?? void 0, docPart);
|
|
5844
5875
|
if (settings) {
|
|
@@ -5881,6 +5912,7 @@ var DocxDocument = class _DocxDocument {
|
|
|
5881
5912
|
if (!root) continue;
|
|
5882
5913
|
const partRels = parseRelationships(this.readXmlOptional(relsPathFor(rel.target)), rel.target);
|
|
5883
5914
|
this.rememberOriginalXml(rel.target, root);
|
|
5915
|
+
this.hydrateCorePropertyControls(root, coreProperties);
|
|
5884
5916
|
this.hfParts.push({ relId: rel.id, target: rel.target, root, isHeader, rels: partRels });
|
|
5885
5917
|
}
|
|
5886
5918
|
for (const rel of this.documentRels.values()) {
|
|
@@ -5894,6 +5926,12 @@ var DocxDocument = class _DocxDocument {
|
|
|
5894
5926
|
this.footnotesPart = rel.target;
|
|
5895
5927
|
this.footnotesRoot = root;
|
|
5896
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
|
+
}
|
|
5897
5935
|
}
|
|
5898
5936
|
const notes = parseNotesPart(root, { ...this.ctxBase, rels: partRels }, isFn);
|
|
5899
5937
|
for (const [id, blocks] of notes) (isFn ? this.footnotes : this.endnotes).set(id, blocks);
|
|
@@ -5908,6 +5946,37 @@ var DocxDocument = class _DocxDocument {
|
|
|
5908
5946
|
this._packageResourceVersion++;
|
|
5909
5947
|
this._layoutGlobalSig = null;
|
|
5910
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
|
+
}
|
|
5911
5980
|
/** Repair only objects emitted by older WordInWeb builds that Word rejects. */
|
|
5912
5981
|
repairLegacyWordInWebObjects() {
|
|
5913
5982
|
const raw = this.pkg.raw();
|
|
@@ -7989,7 +8058,7 @@ var BAKED_FONT_METRICS = {
|
|
|
7989
8058
|
// ../core/src/layout/measure.ts
|
|
7990
8059
|
function fontKey(font) {
|
|
7991
8060
|
const paint = font.paintFamily && font.paintFamily !== font.family ? `${font.paintFamily}>` : "";
|
|
7992
|
-
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}`;
|
|
7993
8062
|
}
|
|
7994
8063
|
var METRIC_SUBSTITUTES = {
|
|
7995
8064
|
calibri: "Carlito",
|
|
@@ -8092,7 +8161,10 @@ var WORD_FONT_METRICS = {
|
|
|
8092
8161
|
// baselines 118.80 + n x 20.00; first attempt baked the multiple into the
|
|
8093
8162
|
// profile and over-pitched every line by 1.08x).
|
|
8094
8163
|
mangal: { asc: 1.245, desc: 0.4399, gap: 0 },
|
|
8095
|
-
latha: { asc: 0.9266, desc: 0.3369, gap: 0 }
|
|
8164
|
+
latha: { asc: 0.9266, desc: 0.3369, gap: 0 },
|
|
8165
|
+
// Word substitutes Lao text to DokChampa. Its hhea box is 2850/-1117 at
|
|
8166
|
+
// 2048 UPEM; this is also the line profile Word uses in the reference PDF.
|
|
8167
|
+
"noto sans lao looped": { asc: 1.391602, desc: 0.54541, gap: 0 }
|
|
8096
8168
|
};
|
|
8097
8169
|
var QUARTER_PT_PX = 1 / 3;
|
|
8098
8170
|
function quantizeQuarterPt(px) {
|
|
@@ -8131,6 +8203,23 @@ function hasCambriaMath() {
|
|
|
8131
8203
|
}
|
|
8132
8204
|
return _cambriaMath;
|
|
8133
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
|
+
}
|
|
8134
8223
|
function cambriaMathDescentShare() {
|
|
8135
8224
|
return 0.238;
|
|
8136
8225
|
}
|
|
@@ -8151,11 +8240,12 @@ var CanvasMeasurer = class {
|
|
|
8151
8240
|
}
|
|
8152
8241
|
setFont(font) {
|
|
8153
8242
|
const css = cssFont(font);
|
|
8154
|
-
|
|
8243
|
+
const key = `${css}\0${font.kerning ? "normal" : "none"}`;
|
|
8244
|
+
if (key !== this.currentFont) {
|
|
8155
8245
|
this.ctx.font = css;
|
|
8156
|
-
this.ctx.fontKerning = "none";
|
|
8246
|
+
this.ctx.fontKerning = font.kerning ? "normal" : "none";
|
|
8157
8247
|
this.ctx.textRendering = "optimizeSpeed";
|
|
8158
|
-
this.currentFont =
|
|
8248
|
+
this.currentFont = key;
|
|
8159
8249
|
}
|
|
8160
8250
|
}
|
|
8161
8251
|
width(text, font, letterSpacing = 0) {
|
|
@@ -8259,6 +8349,8 @@ function createMeasurer() {
|
|
|
8259
8349
|
// ../core/src/layout/math.ts
|
|
8260
8350
|
var SCRIPT_SCALE = 0.73;
|
|
8261
8351
|
var SCRIPT_SCRIPT_SCALE = 0.6;
|
|
8352
|
+
var EMPTY_SCRIPT_ADVANCE = 0.89;
|
|
8353
|
+
var EMPTY_SUP_ADVANCE = 0.84;
|
|
8262
8354
|
var floorHalfPt = (px) => Math.floor(px * 0.75 * 2 + 1e-6) / 2 / 0.75;
|
|
8263
8355
|
var scriptSize = (size, floor) => Math.max(floorHalfPt(size * SCRIPT_SCALE), floor);
|
|
8264
8356
|
var SUP_RAISE = 4 / 11;
|
|
@@ -8270,6 +8362,7 @@ var RULE_THICK = 0.75 / 11;
|
|
|
8270
8362
|
var BIN_OP_SPACE = 0.25;
|
|
8271
8363
|
var FUNC_NAME_SPACE = 0.18;
|
|
8272
8364
|
var COMMA_SPACE = 0.17;
|
|
8365
|
+
var SEMICOLON_SPACE = 0.153;
|
|
8273
8366
|
var FRAC_PAD = 0.06;
|
|
8274
8367
|
var NARY_SUM_RAISE = 0.5 / 11;
|
|
8275
8368
|
var NARY_INT_DROP = 0.5 / 11;
|
|
@@ -8288,10 +8381,11 @@ var MAT_COL_GAP_STIX = 12.2 / 11;
|
|
|
8288
8381
|
var MAT_COL_GAP_REAL_INLINE = 11.4 / 11;
|
|
8289
8382
|
var MAT_COL_GAP_REAL_DISPLAY = 11.13 / 11;
|
|
8290
8383
|
var DLM_PAD_STIX = 1.2 / 11;
|
|
8291
|
-
var DLM_PAD_REAL =
|
|
8384
|
+
var DLM_PAD_REAL = 1 / 11;
|
|
8292
8385
|
var matColGap = (display) => hasCambriaMath() ? display ? MAT_COL_GAP_REAL_DISPLAY : MAT_COL_GAP_REAL_INLINE : MAT_COL_GAP_STIX;
|
|
8293
8386
|
var dlmPad = () => hasCambriaMath() ? DLM_PAD_REAL : DLM_PAD_STIX;
|
|
8294
8387
|
var DLM_MAT_END_PAD = 0.3 / 11;
|
|
8388
|
+
var DLM_TRAILING_SPACE_PAD = 0.125;
|
|
8295
8389
|
var FRAC_NUM_RAISE_D = 1550 / 2048;
|
|
8296
8390
|
var FRAC_DEN_DROP_D = 1370 / 2048;
|
|
8297
8391
|
var FRAC_DEN_DLM_EXTRA = 133 / 2048;
|
|
@@ -8305,6 +8399,8 @@ var INT_D_INK = 1.3584 + 0.7925;
|
|
|
8305
8399
|
var INT_D_ASC = 1.3584;
|
|
8306
8400
|
var INT_D_DESC = 0.7925;
|
|
8307
8401
|
var INT_D_ADV = 0.8066;
|
|
8402
|
+
var INT_D_LIMIT_OVERLAP = 0.37;
|
|
8403
|
+
var INT_D_SUP_STAGGER = 0.375;
|
|
8308
8404
|
var INT_D_ANCHOR = (1.3584 - 0.877 * (INT_D_INK / INT_TEXT_INK)) / (1 - INT_D_INK / INT_TEXT_INK);
|
|
8309
8405
|
var MATH_FONT = "Cambria Math";
|
|
8310
8406
|
function mathText(text, normal = false) {
|
|
@@ -8382,7 +8478,7 @@ var BRACKET_RE = /[()[\]{}]/;
|
|
|
8382
8478
|
var SUP_DLM_DROP = 460 / 2048;
|
|
8383
8479
|
var ITALIC_MATH_RE = /[\u{1D434}-\u{1D467}ℎ]/u;
|
|
8384
8480
|
var SUP_KERN_IN = 0;
|
|
8385
|
-
var
|
|
8481
|
+
var SCRIPT_TRAIL_GROUPED_DISPLAY = 0.12;
|
|
8386
8482
|
function containsDlm(nodes) {
|
|
8387
8483
|
for (const n of nodes) {
|
|
8388
8484
|
switch (n.t) {
|
|
@@ -8467,9 +8563,21 @@ function containsBlocky(nodes) {
|
|
|
8467
8563
|
}
|
|
8468
8564
|
return false;
|
|
8469
8565
|
}
|
|
8470
|
-
function layoutMath(nodes, baseSize, measurer, display = false) {
|
|
8566
|
+
function layoutMath(nodes, baseSize, measurer, display = false, fractionPadEm = FRAC_PAD, multiEquationDisplay = false) {
|
|
8471
8567
|
const box = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [], display, baseSize };
|
|
8472
|
-
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
|
+
);
|
|
8473
8581
|
for (const p of box.pieces) {
|
|
8474
8582
|
const m = measurer.metrics(p.font);
|
|
8475
8583
|
p.effAscent = p.ownAscent ?? p.dy + m.ascent;
|
|
@@ -8483,12 +8591,17 @@ function layoutMath(nodes, baseSize, measurer, display = false) {
|
|
|
8483
8591
|
}
|
|
8484
8592
|
return box;
|
|
8485
8593
|
}
|
|
8486
|
-
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) {
|
|
8487
8595
|
let prevOperand = false;
|
|
8488
8596
|
for (const node of nodes) {
|
|
8489
8597
|
switch (node.t) {
|
|
8490
8598
|
case "run": {
|
|
8491
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
|
+
}
|
|
8492
8605
|
if (node.fname) {
|
|
8493
8606
|
const gap = size * FUNC_NAME_SPACE;
|
|
8494
8607
|
if (prevOperand) box.width += gap;
|
|
@@ -8500,16 +8613,19 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8500
8613
|
}
|
|
8501
8614
|
const medGap = size * BIN_OP_SPACE;
|
|
8502
8615
|
const relGap = display ? medGap : size * (5 / 18);
|
|
8503
|
-
const toks = node.text.split(/([
|
|
8616
|
+
const toks = node.text.split(/([=+−×÷<>≤≥±≠,;\-])/).filter((s) => s.length > 0);
|
|
8504
8617
|
for (let ti = 0; ti < toks.length; ti++) {
|
|
8505
8618
|
const tok = toks[ti];
|
|
8506
|
-
if (tok === ",") {
|
|
8619
|
+
if (tok === "," || tok === ";") {
|
|
8507
8620
|
const text2 = mathText(tok, node.normal);
|
|
8508
8621
|
box.pieces.push({ text: text2, x: box.width, dy, font });
|
|
8509
8622
|
box.width += measurer.width(text2, font);
|
|
8510
8623
|
const nextIsSpace = ti + 1 < toks.length && /^\s/.test(toks[ti + 1]);
|
|
8511
|
-
|
|
8512
|
-
|
|
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 === ";";
|
|
8513
8629
|
continue;
|
|
8514
8630
|
}
|
|
8515
8631
|
const isOp = BIN_OPS.has(tok);
|
|
@@ -8533,7 +8649,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8533
8649
|
case "sup":
|
|
8534
8650
|
case "sub": {
|
|
8535
8651
|
const beforeBase = box.pieces.length;
|
|
8536
|
-
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);
|
|
8537
8653
|
let baseInkAsc = 0;
|
|
8538
8654
|
if (node.t === "sup") {
|
|
8539
8655
|
for (let i = beforeBase; i < box.pieces.length; i++) {
|
|
@@ -8548,9 +8664,16 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8548
8664
|
box.width += size * SUP_KERN_IN;
|
|
8549
8665
|
}
|
|
8550
8666
|
const beforeScript = box.pieces.length;
|
|
8551
|
-
|
|
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
|
+
}
|
|
8552
8675
|
for (let i = beforeScript; i < box.pieces.length; i++) box.pieces[i].script = true;
|
|
8553
|
-
box.width += size *
|
|
8676
|
+
if (display) box.width += size * scriptTrailEm;
|
|
8554
8677
|
prevOperand = true;
|
|
8555
8678
|
break;
|
|
8556
8679
|
}
|
|
@@ -8559,17 +8682,17 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8559
8682
|
const numRaise = display ? size * FRAC_NUM_RAISE_D : size * FRAC_NUM_RAISE;
|
|
8560
8683
|
const denDrop = (display ? size * FRAC_DEN_DROP_D : size * FRAC_DEN_DROP) + (display && containsDlm(node.den) ? size * FRAC_DEN_DLM_EXTRA : 0);
|
|
8561
8684
|
const fracTight = display ? tight : true;
|
|
8562
|
-
const numW = widthOf(node.num, scale, measurer, display, fracTight, scriptFloor);
|
|
8563
|
-
const denW = widthOf(node.den, scale, measurer, display, fracTight, scriptFloor);
|
|
8564
|
-
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;
|
|
8565
8688
|
const barW = Math.max(numW, denW) + 2 * pad;
|
|
8566
8689
|
const x0 = box.width;
|
|
8567
8690
|
const numBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8568
|
-
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);
|
|
8569
8692
|
for (const p of numBox.pieces) box.pieces.push(rebase(p, x0 + (barW - numW) / 2, dy + numRaise));
|
|
8570
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 });
|
|
8571
8694
|
const denBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8572
|
-
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);
|
|
8573
8696
|
let denDropFinal = denDrop;
|
|
8574
8697
|
if (containsFrac(node.den)) {
|
|
8575
8698
|
let denAsc = 0;
|
|
@@ -8594,7 +8717,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8594
8717
|
case "nary": {
|
|
8595
8718
|
const isInt = "\u222B\u222C\u222D\u222E\u222F\u2230".includes(node.chr);
|
|
8596
8719
|
if (display && !isInt) {
|
|
8597
|
-
naryDisplay(node, size, dy, box, measurer, scriptFloor);
|
|
8720
|
+
naryDisplay(node, size, dy, box, measurer, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
8598
8721
|
prevOperand = true;
|
|
8599
8722
|
break;
|
|
8600
8723
|
}
|
|
@@ -8623,20 +8746,24 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8623
8746
|
const intSubDrop = display && visibleSub ? INT_SUB_DROP_D : INT_SUB_DROP;
|
|
8624
8747
|
const supDy = dy + size * (isInt ? intSupRaise : NARY_SUP_RAISE);
|
|
8625
8748
|
const subDy = dy - size * (isInt ? intSubDrop : NARY_SUB_DROP);
|
|
8626
|
-
const supStagger = isInt ? size * INT_SUP_STAGGER : 0;
|
|
8627
|
-
const supW = widthOf(node.sup, scale, measurer, false, true, scriptFloor) + supStagger;
|
|
8628
|
-
const subW = widthOf(node.sub, scale, measurer, false, true, scriptFloor);
|
|
8629
|
-
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);
|
|
8630
8753
|
const supBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
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
|
+
}
|
|
8634
8759
|
const subBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8635
|
-
|
|
8636
|
-
|
|
8637
|
-
|
|
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
|
+
}
|
|
8638
8765
|
box.width = x0 + Math.max(supW, subW) + size * NARY_E_GAP;
|
|
8639
|
-
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);
|
|
8640
8767
|
prevOperand = true;
|
|
8641
8768
|
break;
|
|
8642
8769
|
}
|
|
@@ -8646,7 +8773,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8646
8773
|
let coreDesc = 0;
|
|
8647
8774
|
const parts = node.e.map((part) => {
|
|
8648
8775
|
const b = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8649
|
-
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);
|
|
8650
8777
|
for (const pc of b.pieces) {
|
|
8651
8778
|
const m = measurer.metrics(pc.font);
|
|
8652
8779
|
const asc = pc.ownAscent ?? pc.dy + m.ascent;
|
|
@@ -8702,7 +8829,10 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8702
8829
|
grow = 1;
|
|
8703
8830
|
}
|
|
8704
8831
|
}
|
|
8705
|
-
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;
|
|
8706
8836
|
const drawDelim = (ch) => {
|
|
8707
8837
|
if (!ch) return;
|
|
8708
8838
|
const asm = asmH !== void 0 ? DLM_ASM_PIECES[ch] : void 0;
|
|
@@ -8772,7 +8902,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8772
8902
|
const cells = node.rows.map(
|
|
8773
8903
|
(row) => row.map((cell) => {
|
|
8774
8904
|
const b = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8775
|
-
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);
|
|
8776
8906
|
for (const pc of b.pieces) {
|
|
8777
8907
|
const m = measurer.metrics(pc.font);
|
|
8778
8908
|
b.ascent = Math.max(b.ascent, pc.dy + m.ascent);
|
|
@@ -8818,7 +8948,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8818
8948
|
const m = measurer.metrics(font);
|
|
8819
8949
|
const ruleThick = Math.max(size * RULE_THICK, 0.75);
|
|
8820
8950
|
const radBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8821
|
-
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);
|
|
8822
8952
|
let radAsc = m.ascent * 0.5;
|
|
8823
8953
|
let radDesc = 0;
|
|
8824
8954
|
for (const pc of radBox.pieces) {
|
|
@@ -8842,7 +8972,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8842
8972
|
const dScale = scriptSize(size, scriptFloor);
|
|
8843
8973
|
box.width += size * RAD_KERN_BEFORE_DEG;
|
|
8844
8974
|
const degBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8845
|
-
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);
|
|
8846
8976
|
const degDy = dy - radDesc + RAD_DEG_RAISE * signInkH + size * RAD_DEG_ADJ;
|
|
8847
8977
|
for (const pc of degBox.pieces) box.pieces.push(rebase(pc, box.width, degDy, true));
|
|
8848
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 });
|
|
@@ -8889,7 +9019,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8889
9019
|
const axis = dy + size * RULE_CENTER;
|
|
8890
9020
|
const rowBoxes = node.rows.map((row) => {
|
|
8891
9021
|
const b = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8892
|
-
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);
|
|
8893
9023
|
for (const pc of b.pieces) {
|
|
8894
9024
|
const pm = measurer.metrics(pc.font);
|
|
8895
9025
|
b.ascent = Math.max(b.ascent, pc.ownAscent ?? pc.dy + pm.ascent);
|
|
@@ -8919,7 +9049,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8919
9049
|
}
|
|
8920
9050
|
case "acc": {
|
|
8921
9051
|
const before = box.pieces.length;
|
|
8922
|
-
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);
|
|
8923
9053
|
if (box.pieces.length > before) {
|
|
8924
9054
|
const last = box.pieces[box.pieces.length - 1];
|
|
8925
9055
|
last.text += node.chr;
|
|
@@ -8931,7 +9061,7 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8931
9061
|
const isTop = node.pos === "top";
|
|
8932
9062
|
const bScale = isTop ? size : scriptSize(size, scriptFloor);
|
|
8933
9063
|
const baseBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8934
|
-
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);
|
|
8935
9065
|
const baseW = baseBox.width;
|
|
8936
9066
|
const maxVariant = GRP_VARIANTS_EM[GRP_VARIANTS_EM.length - 1] * size;
|
|
8937
9067
|
let braceW = maxVariant;
|
|
@@ -8968,10 +9098,10 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8968
9098
|
case "lim": {
|
|
8969
9099
|
const isLow = node.pos === "low";
|
|
8970
9100
|
const baseBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8971
|
-
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);
|
|
8972
9102
|
const lScale = scriptSize(size, scriptFloor);
|
|
8973
9103
|
const limBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
8974
|
-
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);
|
|
8975
9105
|
const w = Math.max(baseBox.width, limBox.width);
|
|
8976
9106
|
const x0 = box.width;
|
|
8977
9107
|
const baseX = x0 + (w - baseBox.width) / 2;
|
|
@@ -8988,19 +9118,19 @@ function flow(nodes, size, dy, box, measurer, tight, display = false, breakDepth
|
|
|
8988
9118
|
}
|
|
8989
9119
|
}
|
|
8990
9120
|
}
|
|
8991
|
-
function naryDisplay(node, size, dy, box, measurer, scriptFloor) {
|
|
9121
|
+
function naryDisplay(node, size, dy, box, measurer, scriptFloor, fractionPadEm, scriptTrailEm) {
|
|
8992
9122
|
const opFont = fontAt(size * NARY_OP_SCALE_D);
|
|
8993
9123
|
const opW = measurer.width(node.chr, opFont);
|
|
8994
9124
|
const scale = scriptSize(size, scriptFloor);
|
|
8995
|
-
const supW = widthOf(node.sup, scale, measurer, false, true, scriptFloor);
|
|
8996
|
-
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);
|
|
8997
9127
|
const stackW = Math.max(opW, supW, subW);
|
|
8998
9128
|
const x0 = box.width;
|
|
8999
9129
|
const cx = x0 + stackW / 2;
|
|
9000
9130
|
box.pieces.push({ text: node.chr, x: cx - opW / 2, dy, font: opFont });
|
|
9001
9131
|
if (node.sup.length) {
|
|
9002
9132
|
const supBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
9003
|
-
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);
|
|
9004
9134
|
const ox = cx - supW / 2;
|
|
9005
9135
|
const oy = dy + size * NARY_OVER_RAISE_D;
|
|
9006
9136
|
for (const pc of supBox.pieces) box.pieces.push(rebase(pc, ox, oy, true));
|
|
@@ -9008,18 +9138,18 @@ function naryDisplay(node, size, dy, box, measurer, scriptFloor) {
|
|
|
9008
9138
|
}
|
|
9009
9139
|
if (node.sub.length) {
|
|
9010
9140
|
const subBox = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
9011
|
-
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);
|
|
9012
9142
|
const ux = cx - subW / 2;
|
|
9013
9143
|
const uy = dy - size * NARY_UNDER_DROP_D;
|
|
9014
9144
|
for (const pc of subBox.pieces) box.pieces.push(rebase(pc, ux, uy, true));
|
|
9015
9145
|
for (const r of subBox.rules) box.rules.push({ ...r, x1: ux + r.x1, x2: ux + r.x2, dy: uy + r.dy });
|
|
9016
9146
|
}
|
|
9017
9147
|
box.width = x0 + stackW + size * NARY_E_GAP;
|
|
9018
|
-
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);
|
|
9019
9149
|
}
|
|
9020
|
-
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) {
|
|
9021
9151
|
const tmp = { width: 0, ascent: 0, descent: 0, pieces: [], rules: [] };
|
|
9022
|
-
flow(nodes, size, 0, tmp, measurer, tight, display, 2, scriptFloor);
|
|
9152
|
+
flow(nodes, size, 0, tmp, measurer, tight, display, 2, scriptFloor, fractionPadEm, scriptTrailEm);
|
|
9023
9153
|
return tmp.width;
|
|
9024
9154
|
}
|
|
9025
9155
|
|
|
@@ -9047,16 +9177,18 @@ function starNumberFormat(instr, n) {
|
|
|
9047
9177
|
}
|
|
9048
9178
|
}
|
|
9049
9179
|
function fontOf(props, fallbackFamily) {
|
|
9180
|
+
const family = props.rtl && props.fontComplex || props.font || fallbackFamily;
|
|
9050
9181
|
let size = props.size ?? 14.666;
|
|
9051
9182
|
if (props.verticalAlign === "superscript" || props.verticalAlign === "subscript") {
|
|
9052
|
-
|
|
9183
|
+
const scale = EA_FAMILY_RE.test(family) ? 0.52 : 0.65;
|
|
9184
|
+
size = Math.round(size * 1.5 * scale) / 1.5;
|
|
9053
9185
|
}
|
|
9054
|
-
const family = props.rtl && props.fontComplex || props.font || fallbackFamily;
|
|
9055
9186
|
return {
|
|
9056
9187
|
family,
|
|
9057
9188
|
size,
|
|
9058
9189
|
bold: props.bold ?? false,
|
|
9059
|
-
italic: props.italic ?? false
|
|
9190
|
+
italic: props.italic ?? false,
|
|
9191
|
+
kerning: props.kerningThreshold !== void 0 && props.kerningThreshold !== null && size >= props.kerningThreshold
|
|
9060
9192
|
};
|
|
9061
9193
|
}
|
|
9062
9194
|
function displayText(text, props) {
|
|
@@ -9071,13 +9203,21 @@ function runPlainText(run) {
|
|
|
9071
9203
|
function isWordAlnum(ch) {
|
|
9072
9204
|
return ch !== void 0 && /[\p{L}\p{Nd}]/u.test(ch);
|
|
9073
9205
|
}
|
|
9074
|
-
function hyphenBreaks(word) {
|
|
9206
|
+
function hyphenBreaks(word, allowNumericEnDash) {
|
|
9075
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);
|
|
9076
9211
|
for (let i = 1; i < word.length - 1; i++) {
|
|
9077
9212
|
const ch = word[i];
|
|
9078
|
-
if (
|
|
9079
|
-
|
|
9080
|
-
|
|
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;
|
|
9081
9221
|
}
|
|
9082
9222
|
return out;
|
|
9083
9223
|
}
|
|
@@ -9092,6 +9232,7 @@ function isCJK(ch) {
|
|
|
9092
9232
|
return CJK_RE.test(ch);
|
|
9093
9233
|
}
|
|
9094
9234
|
var BALLOT_RE = /[☐☑☒]/;
|
|
9235
|
+
var LEGACY_CHECKBOX_TRAILING_ADVANCE = 2.5 * 96 / 72;
|
|
9095
9236
|
function isBallot(ch) {
|
|
9096
9237
|
return BALLOT_RE.test(ch);
|
|
9097
9238
|
}
|
|
@@ -9177,16 +9318,35 @@ function wrapDisplayMath(box, maxWidth) {
|
|
|
9177
9318
|
});
|
|
9178
9319
|
}
|
|
9179
9320
|
var DEFAULT_TAB = 48;
|
|
9321
|
+
var TABBED_INLINE_MATH_FRAC_PAD = 0.15;
|
|
9180
9322
|
var OVERFLOW_PUNCT = /[.,:;!?)\]}、。,.:;?!)]}」』】〉》]/;
|
|
9181
|
-
var CJK_SPACE_COMPRESS = 0.
|
|
9323
|
+
var CJK_SPACE_COMPRESS = 0.5;
|
|
9182
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;
|
|
9183
|
-
var JUSTIFY_MAX_COMPRESS = 0.
|
|
9325
|
+
var JUSTIFY_MAX_COMPRESS = 0.29;
|
|
9326
|
+
var JUSTIFY_GRID_MAX_COMPRESS = 0.25;
|
|
9184
9327
|
var JUSTIFY_STRETCH_FACTOR = 0.5;
|
|
9185
9328
|
var TAMIL_GLYPH_SCALE = 0.735;
|
|
9186
9329
|
var TAMIL_BASELINE_DY_EM = 0.136;
|
|
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
|
+
}
|
|
9187
9347
|
var KASHIDA_LOW_EM = 0;
|
|
9188
9348
|
var KASHIDA_MEDIUM_EM = 0.032;
|
|
9189
|
-
var KASHIDA_HIGH_EM = 0.
|
|
9349
|
+
var KASHIDA_HIGH_EM = 0.075;
|
|
9190
9350
|
var BP_CACHES = /* @__PURE__ */ new WeakMap();
|
|
9191
9351
|
var BP_CACHE_MAX = 6e4;
|
|
9192
9352
|
function bpCacheFor(measurer) {
|
|
@@ -9330,6 +9490,7 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9330
9490
|
let curSegments = [{ x: 0, width: contentWidth }];
|
|
9331
9491
|
let curSegIdx = 0;
|
|
9332
9492
|
let curClearY;
|
|
9493
|
+
let curEdgeReserve = 0;
|
|
9333
9494
|
const ls = props.lineSpacing;
|
|
9334
9495
|
const firstFont = atoms.find((a) => a.kind === "frag" || a.kind === "space")?.font;
|
|
9335
9496
|
const natural = firstFont ? measurer.metrics(firstFont).lineHeight * (ls?.rule === "auto" ? ls.value : 1) : 0;
|
|
@@ -9341,6 +9502,7 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9341
9502
|
curSegments = [{ x: 0, width: contentWidth }];
|
|
9342
9503
|
curSegIdx = 0;
|
|
9343
9504
|
curClearY = void 0;
|
|
9505
|
+
curEdgeReserve = 0;
|
|
9344
9506
|
if (boundsAt) {
|
|
9345
9507
|
let guard = 0;
|
|
9346
9508
|
let b = boundsAt(yOff, EST_LINE);
|
|
@@ -9354,6 +9516,7 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9354
9516
|
curSegments = b.segments && b.segments.length > 0 ? b.segments : [{ x: b.x, width: b.width }];
|
|
9355
9517
|
curSegIdx = 0;
|
|
9356
9518
|
curClearY = b.clearY;
|
|
9519
|
+
curEdgeReserve = b.edgeReserve ?? (b.clearY !== void 0 ? 0.75 : 0);
|
|
9357
9520
|
}
|
|
9358
9521
|
void idx;
|
|
9359
9522
|
};
|
|
@@ -9538,6 +9701,7 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9538
9701
|
href: atom.href,
|
|
9539
9702
|
src: atom.src ? { ...atom.src, offset: atom.src.offset + sliceOff } : void 0,
|
|
9540
9703
|
metricsFont: atom.metricsFont,
|
|
9704
|
+
metricsStrut: atom.metricsStrut,
|
|
9541
9705
|
rtl: atom.rtl,
|
|
9542
9706
|
rtlLevel: levelOf(atom.rtl)
|
|
9543
9707
|
});
|
|
@@ -9628,7 +9792,10 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9628
9792
|
rawStop = nextTabStop(rawStop.pos, props.tabs, contentWidth - indentRight, doc.defaultTabStop);
|
|
9629
9793
|
}
|
|
9630
9794
|
}
|
|
9631
|
-
|
|
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) {
|
|
9632
9799
|
rawStop = { pos: indentLeft, align: "left" };
|
|
9633
9800
|
}
|
|
9634
9801
|
const stop = { ...rawStop, pos: rawStop.pos - offset };
|
|
@@ -9661,6 +9828,45 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9661
9828
|
if (found) target = stop.pos - pre;
|
|
9662
9829
|
}
|
|
9663
9830
|
}
|
|
9831
|
+
if (doc.compatibilityMode < 15 && stop.align === "left" && !bidiPara && curLineWidth > 0) {
|
|
9832
|
+
let nextAtom = ai + 1;
|
|
9833
|
+
let probeX = Math.max(target, x + 2);
|
|
9834
|
+
while (atoms[nextAtom]?.kind === "tab") {
|
|
9835
|
+
let probeStop = nextTabStop(
|
|
9836
|
+
probeX + offset,
|
|
9837
|
+
props.tabs,
|
|
9838
|
+
contentWidth - indentRight,
|
|
9839
|
+
doc.defaultTabStop
|
|
9840
|
+
);
|
|
9841
|
+
if (opts?.inTableCell) {
|
|
9842
|
+
let guard = 0;
|
|
9843
|
+
while (probeStop.align === "decimal" && guard++ < 8) {
|
|
9844
|
+
probeStop = nextTabStop(
|
|
9845
|
+
probeStop.pos,
|
|
9846
|
+
props.tabs,
|
|
9847
|
+
contentWidth - indentRight,
|
|
9848
|
+
doc.defaultTabStop
|
|
9849
|
+
);
|
|
9850
|
+
}
|
|
9851
|
+
}
|
|
9852
|
+
if (probeStop.align !== "left") break;
|
|
9853
|
+
probeX = Math.max(probeStop.pos - offset, probeX + 2);
|
|
9854
|
+
nextAtom++;
|
|
9855
|
+
}
|
|
9856
|
+
let firstWordWidth = 0;
|
|
9857
|
+
for (let j = nextAtom; j < atoms.length; j++) {
|
|
9858
|
+
const a = atoms[j];
|
|
9859
|
+
if (a.kind !== "frag") break;
|
|
9860
|
+
firstWordWidth += a.width;
|
|
9861
|
+
}
|
|
9862
|
+
const lineEnd2 = lineStartX(lineIndex) + availFor(lineIndex);
|
|
9863
|
+
if (firstWordWidth > 0 && probeX + firstWordWidth > lineEnd2 + 0.01) {
|
|
9864
|
+
const legacyContinuationIndent = !!atom.props.bold && nextAtom === ai + 3;
|
|
9865
|
+
flush(false, false);
|
|
9866
|
+
if (!legacyContinuationIndent) ai--;
|
|
9867
|
+
continue;
|
|
9868
|
+
}
|
|
9869
|
+
}
|
|
9664
9870
|
const aligned = (stop.align === "right" || stop.align === "decimal") && !bidiPara;
|
|
9665
9871
|
if (aligned && curLineWidth > 0 && x > target + 0.75) {
|
|
9666
9872
|
flush(false, false);
|
|
@@ -9733,9 +9939,11 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9733
9939
|
const rows = wrapDisplayMath(atom.box, availFor(lineIndex));
|
|
9734
9940
|
for (let ri = 0; ri < rows.length; ri++) {
|
|
9735
9941
|
const row = rows[ri];
|
|
9736
|
-
|
|
9737
|
-
|
|
9738
|
-
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;
|
|
9739
9947
|
if (ri + 1 < rows.length) flush(false, false);
|
|
9740
9948
|
}
|
|
9741
9949
|
continue;
|
|
@@ -9744,7 +9952,7 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9744
9952
|
const w = atom.kind === "image" ? atom.width : atom.drawing.width;
|
|
9745
9953
|
const h = atom.kind === "image" ? atom.height : atom.drawing.height;
|
|
9746
9954
|
if (curLineWidth > 0 && x + w > lineStartX(lineIndex) + availFor(lineIndex)) {
|
|
9747
|
-
const glued = atom.kind === "image" && !atom.srcDrawing;
|
|
9955
|
+
const glued = atom.kind === "image" && (!atom.srcDrawing || localName(atom.srcDrawing.name) !== "drawing");
|
|
9748
9956
|
let hi = cur.length;
|
|
9749
9957
|
let headW = 0;
|
|
9750
9958
|
while (glued && hi > minSpans) {
|
|
@@ -9793,11 +10001,12 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9793
10001
|
if (opts?.verticalGridResync && fragIsCJK && prevContentCJK === false && curLineWidth > 0 && curClearY === void 0) {
|
|
9794
10002
|
flush(false, false);
|
|
9795
10003
|
}
|
|
9796
|
-
const lineEnd = lineStartX(lineIndex) + availFor(lineIndex);
|
|
10004
|
+
const lineEnd = lineStartX(lineIndex) + availFor(lineIndex) - curEdgeReserve;
|
|
9797
10005
|
const bdrPad = bdrPadOf(atom);
|
|
9798
10006
|
const bdrPadL = bdrPad && (!sameBdrAtom(atoms[ai - 1], atom) || curLineWidth === 0) ? bdrPad : 0;
|
|
9799
10007
|
const bdrPadR = bdrPad && !sameBdrAtom(atom, atoms[ai + 1]) ? bdrPad : 0;
|
|
9800
|
-
|
|
10008
|
+
const fitTolerance = minLineHeight !== void 0 ? 0.125 : 0.01;
|
|
10009
|
+
let fits = x + bdrPadL + atom.width + bdrPadR <= lineEnd + fitTolerance;
|
|
9801
10010
|
if (!fits && packUntilSpace) fits = true;
|
|
9802
10011
|
if (!fits && cur.length > 0 && cur[cur.length - 1].text === " ") {
|
|
9803
10012
|
if (bidiPara && cur[cur.length - 1].x <= lineStartX(lineIndex) + 0.5) {
|
|
@@ -9807,14 +10016,15 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9807
10016
|
fits = true;
|
|
9808
10017
|
packUntilSpace = true;
|
|
9809
10018
|
}
|
|
9810
|
-
|
|
10019
|
+
let overflowPunctWidth = 0;
|
|
10020
|
+
if (minLineHeight) {
|
|
9811
10021
|
const last = atom.text[atom.text.length - 1];
|
|
9812
10022
|
if (last && OVERFLOW_PUNCT.test(last)) {
|
|
9813
10023
|
const nxt = atoms[ai + 1];
|
|
9814
10024
|
const wordEnd = !nxt || nxt.kind !== "frag" || /^\s/.test(nxt.text);
|
|
9815
10025
|
if (wordEnd) {
|
|
9816
|
-
|
|
9817
|
-
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;
|
|
9818
10028
|
}
|
|
9819
10029
|
}
|
|
9820
10030
|
}
|
|
@@ -9843,8 +10053,14 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9843
10053
|
}
|
|
9844
10054
|
}
|
|
9845
10055
|
const wordW = headW + bdrPadL + atom.width + bdrPadR + tailW;
|
|
9846
|
-
|
|
9847
|
-
|
|
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;
|
|
9848
10064
|
if (compress <= CJK_SPACE_COMPRESS + 1e-6) {
|
|
9849
10065
|
fits = true;
|
|
9850
10066
|
packUntilSpace = true;
|
|
@@ -9856,8 +10072,10 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9856
10072
|
// (compat 12, docGrid lines) p2 draws the justified "...zebeqo:" line
|
|
9857
10073
|
// with every inter-word space at 4.25pt against SimSun's natural
|
|
9858
10074
|
// 5.25pt (19% compression) to avoid the wrap Word 15+ would also
|
|
9859
|
-
// avoid.
|
|
9860
|
-
|
|
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
|
|
9861
10079
|
) {
|
|
9862
10080
|
let trail = 0;
|
|
9863
10081
|
for (let j = hi - 1; j >= 0 && cur[j].isSpace; j--) trail += cur[j].width;
|
|
@@ -9866,7 +10084,8 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9866
10084
|
const compress = (x - headW + wordW - lineEnd) / compressible;
|
|
9867
10085
|
if (spacesAfterBreak > 1e-6 && compressible > 1e-6) {
|
|
9868
10086
|
const stretch = (lineEnd - (x - headW - trail)) / spacesAfterBreak;
|
|
9869
|
-
|
|
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)) {
|
|
9870
10089
|
fits = true;
|
|
9871
10090
|
packUntilSpace = true;
|
|
9872
10091
|
}
|
|
@@ -9877,7 +10096,8 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9877
10096
|
hardWrapFrag(atom);
|
|
9878
10097
|
continue;
|
|
9879
10098
|
}
|
|
9880
|
-
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) : [];
|
|
9881
10101
|
for (const h of head) curLineWidth -= h.width;
|
|
9882
10102
|
let moved = false;
|
|
9883
10103
|
while (advanceSegment()) {
|
|
@@ -9926,9 +10146,12 @@ function breakParagraphImpl(doc, measurer, para, contentWidth, fields, numbering
|
|
|
9926
10146
|
}
|
|
9927
10147
|
const padL = bdrPad && (!sameBdrAtom(atoms[ai - 1], atom) || curLineWidth === 0) ? bdrPad : 0;
|
|
9928
10148
|
x += padL;
|
|
9929
|
-
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, breakAfter: atom.breakAfter, pageRef: atom.pageRef, rtl: atom.rtl, rtlLevel: levelOf(atom.rtl), ruby: atom.ruby });
|
|
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 });
|
|
9930
10150
|
curLineWidth += padL + atom.width + bdrPadR;
|
|
9931
10151
|
x += atom.width + bdrPadR;
|
|
10152
|
+
if (packUntilSpace && atom.breakAfter && /[-‐]$/.test(atom.text)) {
|
|
10153
|
+
packUntilSpace = false;
|
|
10154
|
+
}
|
|
9932
10155
|
if (atom.text.trim().length > 0) prevContentCJK = fragIsCJK;
|
|
9933
10156
|
}
|
|
9934
10157
|
if (!flushedTrailingBreak) flush(true, false);
|
|
@@ -9987,7 +10210,7 @@ function nextTabStop(x, tabs, rightEdge, defaultTab = DEFAULT_TAB) {
|
|
|
9987
10210
|
}
|
|
9988
10211
|
}
|
|
9989
10212
|
const next = nextDefaultTab(x, defaultTab);
|
|
9990
|
-
return { pos: next < rightEdge ? next : x +
|
|
10213
|
+
return { pos: next < rightEdge ? next : x + 20.4, align: "left" };
|
|
9991
10214
|
}
|
|
9992
10215
|
function reorderVisual(spans, startX) {
|
|
9993
10216
|
if (spans.length === 0) return;
|
|
@@ -10083,6 +10306,7 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10083
10306
|
let maxBorderedAscent = 0;
|
|
10084
10307
|
let maxBorderedDescent = 0;
|
|
10085
10308
|
let tallestTextIsEa = false;
|
|
10309
|
+
let metricsStrutHeight = 0;
|
|
10086
10310
|
const consider = (font, imageHeight, objRaise = 0, descShift = 0) => {
|
|
10087
10311
|
if (imageHeight !== void 0) {
|
|
10088
10312
|
maxAscent = Math.max(maxAscent, imageHeight + objRaise);
|
|
@@ -10123,9 +10347,10 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10123
10347
|
};
|
|
10124
10348
|
let metricSpans = spans.filter((s) => !(s.text === " " && !s.leader));
|
|
10125
10349
|
const solidSpans = metricSpans.filter(
|
|
10126
|
-
(s) => s.image || s.drawing || s.math || s.leader || s.text === void 0 || !/^[ \t]*$/.test(s.text)
|
|
10350
|
+
(s) => s.metricsStrut || s.image || s.drawing || s.math || s.leader || s.text === void 0 || !/^[ \t]*$/.test(s.text)
|
|
10127
10351
|
);
|
|
10128
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);
|
|
10129
10354
|
if (metricSpans.some((s) => s.numLabel) && metricSpans.some((s) => !s.numLabel)) {
|
|
10130
10355
|
let textLine = 0;
|
|
10131
10356
|
for (const s of metricSpans) {
|
|
@@ -10156,7 +10381,13 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10156
10381
|
const lineHasObject = metricSpans.some((s) => s.image || s.drawing);
|
|
10157
10382
|
for (const s of metricSpans) {
|
|
10158
10383
|
let textMetrics;
|
|
10159
|
-
if (s.
|
|
10384
|
+
if (s.metricsStrut) {
|
|
10385
|
+
metricsStrutHeight = Math.max(
|
|
10386
|
+
metricsStrutHeight,
|
|
10387
|
+
measurer.metrics(s.metricsFont ?? s.font).lineHeight
|
|
10388
|
+
);
|
|
10389
|
+
consider(s.metricsFont ?? s.font);
|
|
10390
|
+
} else if (s.image || s.drawing) {
|
|
10160
10391
|
const objectMetrics = measurer.metrics(s.metricsFont ?? s.font);
|
|
10161
10392
|
const objectHeight = s.image?.height ?? s.drawing.height;
|
|
10162
10393
|
const objRaise = s.props.raise ?? 0;
|
|
@@ -10211,6 +10442,14 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10211
10442
|
const commonLower = metricSpans.length > 0 && metricSpans.every(
|
|
10212
10443
|
(s) => !s.image && !s.drawing && !s.math && (s.props.raise ?? 0) < 0
|
|
10213
10444
|
) ? Math.min(...metricSpans.map((s) => -s.props.raise)) : 0;
|
|
10445
|
+
if (metricsStrutHeight > 0) {
|
|
10446
|
+
for (const s of spans) {
|
|
10447
|
+
if (s.metricsStrut || s.image || s.drawing || s.math) continue;
|
|
10448
|
+
const spanHeight = measurer.metrics(s.font).lineHeight;
|
|
10449
|
+
const paintDY = Math.max(0, (metricsStrutHeight - spanHeight) / 2);
|
|
10450
|
+
if (paintDY > 0) s.font = { ...s.font, paintDY: (s.font.paintDY ?? 0) + paintDY };
|
|
10451
|
+
}
|
|
10452
|
+
}
|
|
10214
10453
|
const natural = Math.max(maxNatural, maxAscent + maxDescent, minLineHeight ?? 0);
|
|
10215
10454
|
let height = natural;
|
|
10216
10455
|
let baselineH;
|
|
@@ -10254,8 +10493,11 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10254
10493
|
const lead = ls.value >= 1.15 ? (ls.value - 1) * maxNaturalText : 0;
|
|
10255
10494
|
height = Math.max(maxNaturalText * ls.value, maxInlineMath + lead);
|
|
10256
10495
|
}
|
|
10257
|
-
} else if (ls.rule === "exact")
|
|
10258
|
-
|
|
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);
|
|
10259
10501
|
}
|
|
10260
10502
|
if (!gridObjSnap && (minLineHeight ?? 0) > 0 && ls?.rule === "atLeast" && baselineH === void 0) {
|
|
10261
10503
|
const glyph = maxAscent + maxDescent;
|
|
@@ -10271,6 +10513,11 @@ function finishLine(spans, width, props, measurer, fallbackFamily, para, doc, is
|
|
|
10271
10513
|
maxDescent -= descentReuse;
|
|
10272
10514
|
maxRawDescent -= descentReuse;
|
|
10273
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
|
+
}
|
|
10274
10521
|
return {
|
|
10275
10522
|
spans,
|
|
10276
10523
|
width,
|
|
@@ -10371,14 +10618,31 @@ function resolveBidiRtl(text) {
|
|
|
10371
10618
|
function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
10372
10619
|
const atoms = [];
|
|
10373
10620
|
const anchors = [];
|
|
10621
|
+
const stylelessOleParagraph = doc.styles.defaultRPr.font === void 0 && doc.styles.defaultRPr.size === void 0 && para.children.some((child4) => {
|
|
10622
|
+
const runs = child4.type === "run" ? [child4] : child4.runs;
|
|
10623
|
+
return runs.some(
|
|
10624
|
+
(run) => run.content.some(
|
|
10625
|
+
(content) => content.kind === "image" && content.embeddedObject !== void 0
|
|
10626
|
+
)
|
|
10627
|
+
);
|
|
10628
|
+
});
|
|
10374
10629
|
const bidiPara = doc.effectiveParaProps(para).bidi === true;
|
|
10375
10630
|
const kashidaKind = doc.effectiveParaProps(para).justifyKind;
|
|
10376
10631
|
const kashidaEm = kashidaKind === "highKashida" ? KASHIDA_HIGH_EM : kashidaKind === "mediumKashida" ? KASHIDA_MEDIUM_EM : kashidaKind === "lowKashida" ? KASHIDA_LOW_EM : 0;
|
|
10377
10632
|
const pushRun = (run, href) => {
|
|
10378
|
-
|
|
10633
|
+
let baseProps = doc.effectiveRunProps(para, run.props);
|
|
10634
|
+
if (stylelessOleParagraph && baseProps.size === void 0) {
|
|
10635
|
+
baseProps = { ...baseProps, size: 16 };
|
|
10636
|
+
}
|
|
10379
10637
|
if (baseProps.vanish) return;
|
|
10380
10638
|
const font = fontOf(baseProps, fallbackFamily);
|
|
10381
|
-
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;
|
|
10382
10646
|
if (props.fitText !== void 0 && props.fitText > 0) {
|
|
10383
10647
|
const natural = measurer.width(displayText(runPlainText(run), props), font, props.letterSpacing) * (props.textScale ?? 1);
|
|
10384
10648
|
if (natural > 0.1) {
|
|
@@ -10445,7 +10709,30 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10445
10709
|
});
|
|
10446
10710
|
break;
|
|
10447
10711
|
}
|
|
10448
|
-
if (text)
|
|
10712
|
+
if (!text && /^\s*SEQ\b/i.test(content.instruction) && /\\h(\s|$)/i.test(content.instruction)) {
|
|
10713
|
+
atoms.push({
|
|
10714
|
+
kind: "frag",
|
|
10715
|
+
text: "",
|
|
10716
|
+
props,
|
|
10717
|
+
font,
|
|
10718
|
+
width: 0,
|
|
10719
|
+
href,
|
|
10720
|
+
src: { run, t: null, offset: 0 },
|
|
10721
|
+
metricsFont: vertMetricsFont,
|
|
10722
|
+
metricsStrut: true
|
|
10723
|
+
});
|
|
10724
|
+
break;
|
|
10725
|
+
}
|
|
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
|
+
}
|
|
10449
10736
|
break;
|
|
10450
10737
|
}
|
|
10451
10738
|
case "ptab":
|
|
@@ -10483,13 +10770,21 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10483
10770
|
break;
|
|
10484
10771
|
case "math": {
|
|
10485
10772
|
const size = props.size ?? 14.666;
|
|
10486
|
-
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
|
+
);
|
|
10487
10782
|
if (content.display) box.jc = content.jc;
|
|
10488
10783
|
atoms.push({ kind: "math", box, src: content.src });
|
|
10489
10784
|
break;
|
|
10490
10785
|
}
|
|
10491
10786
|
case "noteRef": {
|
|
10492
|
-
const text = content.self ? fields.selfNoteMark?.() ?? "" : fields.noteMark?.(content.noteType, content.id) ?? "";
|
|
10787
|
+
const text = content.self ? fields.selfNoteMark?.() ?? "" : content.customMarkFollows ? "" : fields.noteMark?.(content.noteType, content.id) ?? "";
|
|
10493
10788
|
if (!text) break;
|
|
10494
10789
|
const markProps = props.verticalAlign ? props : { ...props, verticalAlign: "superscript" };
|
|
10495
10790
|
const markFont = fontOf(markProps, fallbackFamily);
|
|
@@ -10540,11 +10835,16 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10540
10835
|
}
|
|
10541
10836
|
};
|
|
10542
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
|
+
}
|
|
10543
10842
|
const hasDeva = /[ऀ-ॿ]/.test(text);
|
|
10544
10843
|
const hasTamil = /[-]/.test(text);
|
|
10545
10844
|
const hasLao = /[-]/.test(text);
|
|
10546
10845
|
const indicFace = hasDeva && !hasTamil && !hasLao ? "Mangal" : hasTamil && !hasDeva && !hasLao ? "Latha" : hasLao && !hasDeva && !hasTamil ? "Noto Sans Lao Looped" : null;
|
|
10547
10846
|
if (indicFace && font.family.toLowerCase() !== indicFace.toLowerCase()) {
|
|
10847
|
+
const scriptProps = indicFace === "Noto Sans Lao Looped" ? { ...props, textScale: (props.textScale ?? 1) * LAO_GLYPH_SCALE } : props;
|
|
10548
10848
|
const indicScale = indicFace === "Latha" ? TAMIL_GLYPH_SCALE : 1;
|
|
10549
10849
|
const indicFont = indicScale === 1 ? { ...font, family: indicFace } : {
|
|
10550
10850
|
...font,
|
|
@@ -10556,15 +10856,16 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10556
10856
|
paintDY: font.size * TAMIL_BASELINE_DY_EM
|
|
10557
10857
|
};
|
|
10558
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);
|
|
10559
10860
|
let i2 = 0;
|
|
10560
10861
|
while (i2 < text.length) {
|
|
10561
|
-
const
|
|
10862
|
+
const indic = isIndic(text[i2]);
|
|
10562
10863
|
let j = i2 + 1;
|
|
10563
|
-
while (j < text.length && text[j] ===
|
|
10864
|
+
while (j < text.length && isIndic(text[j]) === indic) j++;
|
|
10564
10865
|
const seg = text.slice(i2, j);
|
|
10565
10866
|
const src = srcBase ? { ...srcBase, offset: srcBase.offset + i2 } : void 0;
|
|
10566
|
-
if (
|
|
10567
|
-
else pushText(seg, props,
|
|
10867
|
+
if (indic) pushText(seg, scriptProps, indicFont, href, src, indicMetrics);
|
|
10868
|
+
else pushText(seg, props, font, href, src, metricsFont);
|
|
10568
10869
|
i2 = j;
|
|
10569
10870
|
}
|
|
10570
10871
|
return;
|
|
@@ -10635,6 +10936,9 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10635
10936
|
if (part[0] === " ") {
|
|
10636
10937
|
let w = partWidth / part.length;
|
|
10637
10938
|
let spaceFont = font;
|
|
10939
|
+
if (para.props.styleId === "HTML0" && EA_FAMILY_RE.test(font.family)) {
|
|
10940
|
+
w = font.size / 2 * tScale;
|
|
10941
|
+
}
|
|
10638
10942
|
if (gridPitch && part.length >= 2 && props.fontEastAsia && !EA_FAMILY_RE.test(font.family)) {
|
|
10639
10943
|
spaceFont = { ...font, family: props.fontEastAsia };
|
|
10640
10944
|
w = measurer.width(" ", spaceFont, props.letterSpacing) * tScale;
|
|
@@ -10651,7 +10955,16 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10651
10955
|
});
|
|
10652
10956
|
}
|
|
10653
10957
|
} else {
|
|
10654
|
-
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
|
+
}
|
|
10655
10968
|
let breaks = hyBreaks;
|
|
10656
10969
|
if (charRtl) {
|
|
10657
10970
|
const set = new Set(hyBreaks);
|
|
@@ -10756,6 +11069,15 @@ function buildAtoms(doc, para, measurer, fields, fallbackFamily, gridPitch) {
|
|
|
10756
11069
|
if (childEl.type === "run") pushRun(childEl);
|
|
10757
11070
|
else for (const r of childEl.runs) pushRun(r, childEl.href ?? (childEl.anchor ? "#" + childEl.anchor : void 0));
|
|
10758
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
|
+
}
|
|
10759
11081
|
for (let i = atoms.length - 1, nextNbsp = false; i >= 0; i--) {
|
|
10760
11082
|
const a = atoms[i];
|
|
10761
11083
|
if (a.kind === "frag") nextNbsp = a.text.charCodeAt(0) === 160;
|
|
@@ -10787,8 +11109,8 @@ function resolveField(instruction, cachedResult, ctx, fieldKey) {
|
|
|
10787
11109
|
}
|
|
10788
11110
|
case "SEQ": {
|
|
10789
11111
|
const ident = instr.split(/\s+/)[1];
|
|
10790
|
-
|
|
10791
|
-
return
|
|
11112
|
+
const value = ident && ctx.seq && fieldKey ? ctx.seq(ident, fieldKey, instr) : cachedResult || "";
|
|
11113
|
+
return /\\h(\s|$)/i.test(instr) ? "" : value;
|
|
10792
11114
|
}
|
|
10793
11115
|
case "REF": {
|
|
10794
11116
|
const bookmark = instr.split(/\s+/)[1];
|
|
@@ -10830,7 +11152,7 @@ function resolveField(instruction, cachedResult, ctx, fieldKey) {
|
|
|
10830
11152
|
var DP_MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
10831
11153
|
var DP_DAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
10832
11154
|
function formatDatePicture(d, picture) {
|
|
10833
|
-
const h24 = d.
|
|
11155
|
+
const h24 = d.getUTCHours();
|
|
10834
11156
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
10835
11157
|
const pad = (n) => String(n).padStart(2, "0");
|
|
10836
11158
|
const hasAmPm = /am\/pm/i.test(picture);
|
|
@@ -10840,25 +11162,25 @@ function formatDatePicture(d, picture) {
|
|
|
10840
11162
|
if (tok.startsWith("'")) return tok.slice(1, -1);
|
|
10841
11163
|
switch (tok) {
|
|
10842
11164
|
case "yyyy":
|
|
10843
|
-
return String(d.
|
|
11165
|
+
return String(d.getUTCFullYear());
|
|
10844
11166
|
case "yy":
|
|
10845
|
-
return pad(d.
|
|
11167
|
+
return pad(d.getUTCFullYear() % 100);
|
|
10846
11168
|
case "MMMM":
|
|
10847
|
-
return DP_MONTHS[d.
|
|
11169
|
+
return DP_MONTHS[d.getUTCMonth()];
|
|
10848
11170
|
case "MMM":
|
|
10849
|
-
return DP_MONTHS[d.
|
|
11171
|
+
return DP_MONTHS[d.getUTCMonth()].slice(0, 3);
|
|
10850
11172
|
case "MM":
|
|
10851
|
-
return pad(d.
|
|
11173
|
+
return pad(d.getUTCMonth() + 1);
|
|
10852
11174
|
case "M":
|
|
10853
|
-
return String(d.
|
|
11175
|
+
return String(d.getUTCMonth() + 1);
|
|
10854
11176
|
case "dddd":
|
|
10855
|
-
return DP_DAYS[d.
|
|
11177
|
+
return DP_DAYS[d.getUTCDay()];
|
|
10856
11178
|
case "ddd":
|
|
10857
|
-
return DP_DAYS[d.
|
|
11179
|
+
return DP_DAYS[d.getUTCDay()].slice(0, 3);
|
|
10858
11180
|
case "dd":
|
|
10859
|
-
return pad(d.
|
|
11181
|
+
return pad(d.getUTCDate());
|
|
10860
11182
|
case "d":
|
|
10861
|
-
return String(d.
|
|
11183
|
+
return String(d.getUTCDate());
|
|
10862
11184
|
case "HH":
|
|
10863
11185
|
return pad(h24);
|
|
10864
11186
|
case "H":
|
|
@@ -10868,13 +11190,13 @@ function formatDatePicture(d, picture) {
|
|
|
10868
11190
|
case "h":
|
|
10869
11191
|
return String(hasAmPm ? h12 : h24);
|
|
10870
11192
|
case "mm":
|
|
10871
|
-
return pad(d.
|
|
11193
|
+
return pad(d.getUTCMinutes());
|
|
10872
11194
|
case "m":
|
|
10873
|
-
return String(d.
|
|
11195
|
+
return String(d.getUTCMinutes());
|
|
10874
11196
|
case "ss":
|
|
10875
|
-
return pad(d.
|
|
11197
|
+
return pad(d.getUTCSeconds());
|
|
10876
11198
|
case "s":
|
|
10877
|
-
return String(d.
|
|
11199
|
+
return String(d.getUTCSeconds());
|
|
10878
11200
|
default:
|
|
10879
11201
|
return /^am\/pm$/i.test(tok) ? h24 < 12 ? "AM" : "PM" : tok;
|
|
10880
11202
|
}
|
|
@@ -11011,6 +11333,7 @@ var MULTI_COL_NOTE_SEP_RESERVE = 26;
|
|
|
11011
11333
|
var NOTE_SEP_LEN = 192;
|
|
11012
11334
|
var NOTE_SEP_GAP = 4.4;
|
|
11013
11335
|
var ROW_OVERHANG_TOL = 3;
|
|
11336
|
+
var CUSTOM_NOTE_BANNER_OVERHANG = 3;
|
|
11014
11337
|
var CHICAGO = ["*", "\u2020", "\u2021", "\xA7"];
|
|
11015
11338
|
var AUTO_PARA_SPACING_PX = 14 * (96 / 72);
|
|
11016
11339
|
var FRAME_WRAP_HSPACE_PX = 6 * (96 / 72);
|
|
@@ -11118,6 +11441,7 @@ var Engine = class {
|
|
|
11118
11441
|
/** Vertical flow already consumed in the current later-column pre-banner
|
|
11119
11442
|
* slot. It reduces the below-banner capacity by the same amount. */
|
|
11120
11443
|
this.bannerSlotUsed = 0;
|
|
11444
|
+
this.customNoteBannerFit = false;
|
|
11121
11445
|
/** True while a section-level tbRl vertical flow is being laid: paragraphs
|
|
11122
11446
|
* re-establish the vertical grid after embedded Western runs (see
|
|
11123
11447
|
* breakParagraph's verticalGridResync). */
|
|
@@ -11235,7 +11559,7 @@ var Engine = class {
|
|
|
11235
11559
|
const contentWidth = page.sp.pageWidth - page.sp.marginLeft - page.sp.marginRight - page.sp.gutter;
|
|
11236
11560
|
const header = this.doc.headers.get(page.headerRel ?? "");
|
|
11237
11561
|
const footer = this.doc.footers.get(page.footerRel ?? "");
|
|
11238
|
-
const headerHeight = this.measureHeaderFooter(header, page, contentWidth, this.pageFieldFrameOverlay(header));
|
|
11562
|
+
const headerHeight = this.measureHeaderFooter(header, page, contentWidth, this.pageFieldFrameOverlay(header), true);
|
|
11239
11563
|
const footerHeight = this.measureHeaderFooter(footer, page, contentWidth, this.pageFieldFrameOverlay(footer));
|
|
11240
11564
|
if (headerHeight !== page.headerHeight || footerHeight !== page.footerHeight) return null;
|
|
11241
11565
|
}
|
|
@@ -11335,6 +11659,7 @@ var Engine = class {
|
|
|
11335
11659
|
if (this.pages.length === 0) {
|
|
11336
11660
|
this.sp = sections[0]?.props ?? {};
|
|
11337
11661
|
}
|
|
11662
|
+
this.applyOpeningFlowOverlap();
|
|
11338
11663
|
this.placeEndnotes();
|
|
11339
11664
|
this.emitFootnoteAreas();
|
|
11340
11665
|
this.emitColumnSeparators();
|
|
@@ -11363,6 +11688,43 @@ var Engine = class {
|
|
|
11363
11688
|
}
|
|
11364
11689
|
return result;
|
|
11365
11690
|
}
|
|
11691
|
+
/** Some document-opening empty paragraphs reserve a second mark line for
|
|
11692
|
+
* pagination while the following content paints over it on page one. Keep
|
|
11693
|
+
* the reservation in flow so later page breaks stay unchanged, then lift
|
|
11694
|
+
* only the painted first-page body. */
|
|
11695
|
+
applyOpeningFlowOverlap() {
|
|
11696
|
+
const opening = this.doc.sections[0]?.blocks[0];
|
|
11697
|
+
const next = this.doc.sections[0]?.blocks[1];
|
|
11698
|
+
const page = this.pages[0];
|
|
11699
|
+
if (!page || page.openingFlowOverlapApplied || opening?.type !== "paragraph" || opening.sectionBreak || paragraphHasContent(opening)) {
|
|
11700
|
+
return;
|
|
11701
|
+
}
|
|
11702
|
+
const beforeNegativeTable = next?.type === "table" && (next.props.indent ?? 0) < 0;
|
|
11703
|
+
const header = this.doc.headers.get(page.headerRel ?? "");
|
|
11704
|
+
const headerAnchors = header?.blocks.flatMap(
|
|
11705
|
+
(block) => block.type === "paragraph" ? this.collectAnchors(block) : []
|
|
11706
|
+
) ?? [];
|
|
11707
|
+
const beforeParagraphUnderUnwrappedHeader = next?.type === "paragraph" && page.headerGrown === true && headerAnchors.length > 0 && headerAnchors.every(
|
|
11708
|
+
(shape) => !("wrap" in shape) || shape.wrap === void 0 || shape.wrap === "none"
|
|
11709
|
+
);
|
|
11710
|
+
if (!beforeNegativeTable && !beforeParagraphUnderUnwrappedHeader) return;
|
|
11711
|
+
const firstBodyItem = page.items.findIndex(
|
|
11712
|
+
(item) => item.kind !== "text" || item.text.length > 0
|
|
11713
|
+
);
|
|
11714
|
+
if (firstBodyItem < 0) return;
|
|
11715
|
+
const paraProps = this.doc.effectiveParaProps(opening);
|
|
11716
|
+
const markProps = this.doc.effectiveRunProps(opening, paraProps.markRunProps ?? {});
|
|
11717
|
+
let overlap = this.measurer.metrics(
|
|
11718
|
+
fontOf(markProps, this.doc.styles.defaultRPr.font ?? "Calibri")
|
|
11719
|
+
).lineHeight;
|
|
11720
|
+
if (beforeParagraphUnderUnwrappedHeader) {
|
|
11721
|
+
overlap += paraProps.spacingAfter ?? 0;
|
|
11722
|
+
}
|
|
11723
|
+
for (let i = firstBodyItem; i < page.items.length; i++) {
|
|
11724
|
+
offsetItem(page.items[i], 0, -overlap);
|
|
11725
|
+
}
|
|
11726
|
+
page.openingFlowOverlapApplied = true;
|
|
11727
|
+
}
|
|
11366
11728
|
/** Whether this document is in the envelope the incremental path handles:
|
|
11367
11729
|
* one section, no notes, single column, upright flow, no line numbering /
|
|
11368
11730
|
* mirror margins / vertical alignment, and no positioned/floating content or
|
|
@@ -11621,7 +11983,7 @@ var Engine = class {
|
|
|
11621
11983
|
const contentWidth = shifted.sp.pageWidth - shifted.sp.marginLeft - shifted.sp.marginRight - shifted.sp.gutter;
|
|
11622
11984
|
const header = this.doc.headers.get(headerRel ?? "");
|
|
11623
11985
|
const footer = this.doc.footers.get(footerRel ?? "");
|
|
11624
|
-
const headerHeight = this.measureHeaderFooter(header, shifted, contentWidth, this.pageFieldFrameOverlay(header));
|
|
11986
|
+
const headerHeight = this.measureHeaderFooter(header, shifted, contentWidth, this.pageFieldFrameOverlay(header), true);
|
|
11625
11987
|
const footerHeight = this.measureHeaderFooter(footer, shifted, contentWidth, this.pageFieldFrameOverlay(footer));
|
|
11626
11988
|
if (headerHeight !== page.headerHeight || footerHeight !== page.footerHeight) return null;
|
|
11627
11989
|
shifted.headerHeight = headerHeight;
|
|
@@ -11999,8 +12361,12 @@ var Engine = class {
|
|
|
11999
12361
|
displayNumber,
|
|
12000
12362
|
headerHeight: 0,
|
|
12001
12363
|
footerHeight: 0,
|
|
12002
|
-
|
|
12003
|
-
|
|
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,
|
|
12004
12370
|
softTop: !sectionStart,
|
|
12005
12371
|
bodyBottom: sp.pageHeight - Math.abs(sp.marginBottom),
|
|
12006
12372
|
colXs,
|
|
@@ -12024,13 +12390,17 @@ var Engine = class {
|
|
|
12024
12390
|
}
|
|
12025
12391
|
const header = this.doc.headers.get(page.headerRel ?? "");
|
|
12026
12392
|
const footer = this.doc.footers.get(page.footerRel ?? "");
|
|
12027
|
-
const headerH = this.measureHeaderFooter(header, page, contentWidth, this.pageFieldFrameOverlay(header));
|
|
12393
|
+
const headerH = this.measureHeaderFooter(header, page, contentWidth, this.pageFieldFrameOverlay(header), true);
|
|
12028
12394
|
const footerOverlay = this.pageFieldFrameOverlay(footer);
|
|
12029
12395
|
const footerH = this.measureHeaderFooter(footer, page, contentWidth, footerOverlay);
|
|
12030
12396
|
page.headerHeight = headerH;
|
|
12031
12397
|
page.footerHeight = footerH;
|
|
12032
12398
|
if (sp.marginTop >= 0) {
|
|
12033
|
-
|
|
12399
|
+
const headerBodyHeight = this.doc.compatibilityMode < 15 && header?.blocks.every((block) => block.type === "paragraph" && !paragraphHasContent(block)) ? ptToPx(7) : headerH;
|
|
12400
|
+
page.bodyTop = Math.max(
|
|
12401
|
+
sp.marginTop,
|
|
12402
|
+
headerBodyHeight > 0 ? sp.headerDistance + headerBodyHeight : 0
|
|
12403
|
+
);
|
|
12034
12404
|
page.bandTop = page.bodyTop;
|
|
12035
12405
|
page.headerGrown = page.bodyTop > sp.marginTop;
|
|
12036
12406
|
}
|
|
@@ -12270,7 +12640,7 @@ var Engine = class {
|
|
|
12270
12640
|
if (this.col + 1 < this.cur.colXs.length) {
|
|
12271
12641
|
this.col++;
|
|
12272
12642
|
this.y = this.columnStartY(this.col);
|
|
12273
|
-
this.bannerSlotUsed = 0;
|
|
12643
|
+
this.bannerSlotUsed = this.cur.bannerTop !== void 0 ? this.cur.openingColumnReserve ?? 0 : 0;
|
|
12274
12644
|
this.lastParaSpacingAfter = 0;
|
|
12275
12645
|
this.lastParaAfterPad = 0;
|
|
12276
12646
|
this.lastParaAfterPad = 0;
|
|
@@ -12607,7 +12977,7 @@ var Engine = class {
|
|
|
12607
12977
|
const runs = c.type === "run" ? [c] : c.runs;
|
|
12608
12978
|
for (const r of runs) {
|
|
12609
12979
|
for (const rc of r.content) {
|
|
12610
|
-
if (rc.kind !== "noteRef" || rc.self) continue;
|
|
12980
|
+
if (rc.kind !== "noteRef" || rc.self || rc.customMarkFollows) continue;
|
|
12611
12981
|
if (rc.noteType === "footnote" && this.doc.footnotes.has(rc.id) && !this.footnoteNumbers.has(rc.id)) {
|
|
12612
12982
|
this.footnoteNumbers.set(rc.id, fnStart + fn++);
|
|
12613
12983
|
} else if (rc.noteType === "endnote" && this.doc.endnotes.has(rc.id) && !this.endnoteNumbers.has(rc.id)) {
|
|
@@ -12715,7 +13085,8 @@ var Engine = class {
|
|
|
12715
13085
|
const notes = page.footnotes.filter((note) => note.column === column);
|
|
12716
13086
|
if (notes.length === 0) continue;
|
|
12717
13087
|
const x0 = page.colXs[column];
|
|
12718
|
-
|
|
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;
|
|
12719
13090
|
page.items.push({
|
|
12720
13091
|
kind: "edge",
|
|
12721
13092
|
x1: x0,
|
|
@@ -12724,7 +13095,7 @@ var Engine = class {
|
|
|
12724
13095
|
y2: y + NOTE_SEP_H * 0.6,
|
|
12725
13096
|
border: { style: "single", width: 0.75, color: "#000000", space: 0 }
|
|
12726
13097
|
});
|
|
12727
|
-
y +=
|
|
13098
|
+
y += separatorHeight;
|
|
12728
13099
|
for (const note of notes) {
|
|
12729
13100
|
for (const it of note.items) {
|
|
12730
13101
|
offsetItem(it, x0, y);
|
|
@@ -12967,10 +13338,20 @@ var Engine = class {
|
|
|
12967
13338
|
return { x: 0, width: colW };
|
|
12968
13339
|
}
|
|
12969
13340
|
let clearY;
|
|
13341
|
+
let exactTextEdge = false;
|
|
12970
13342
|
for (const f of floats) {
|
|
12971
|
-
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
|
+
}
|
|
12972
13347
|
}
|
|
12973
|
-
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
|
+
};
|
|
12974
13355
|
};
|
|
12975
13356
|
}
|
|
12976
13357
|
/**
|
|
@@ -13120,6 +13501,20 @@ var Engine = class {
|
|
|
13120
13501
|
}
|
|
13121
13502
|
placeParagraph(para, prev, next, siblings, index) {
|
|
13122
13503
|
const props = this.doc.effectiveParaProps(para);
|
|
13504
|
+
const detachedFootnotes = customFootnoteAnchorIds(para);
|
|
13505
|
+
if (detachedFootnotes && next?.type === "paragraph") {
|
|
13506
|
+
const nextProps2 = this.doc.effectiveParaProps(next);
|
|
13507
|
+
const nextFrame = nextProps2.frame ? this.resolveFrame(nextProps2.frame) : void 0;
|
|
13508
|
+
if (nextFrame?.wrap === "notBeside" && nextFrame.w !== void 0 && this.cur.colXs.length > 1 && nextFrame.w > this.colWidth + 1) {
|
|
13509
|
+
for (const id of detachedFootnotes) this.registerFootnote(id, this.cur);
|
|
13510
|
+
const markProps = this.doc.effectiveRunProps(para, props.markRunProps ?? {});
|
|
13511
|
+
this.cur.openingColumnReserve = this.measurer.metrics(
|
|
13512
|
+
fontOf(markProps, this.doc.styles.defaultRPr.font ?? "Calibri")
|
|
13513
|
+
).lineHeight;
|
|
13514
|
+
this.customNoteBannerFit = true;
|
|
13515
|
+
return;
|
|
13516
|
+
}
|
|
13517
|
+
}
|
|
13123
13518
|
if (this.consumedFrames.has(para)) return;
|
|
13124
13519
|
if (props.frame && !props.dropCap && this.cur.physIndex !== -1) {
|
|
13125
13520
|
const fr = this.resolveFrame(props.frame);
|
|
@@ -13172,7 +13567,8 @@ var Engine = class {
|
|
|
13172
13567
|
x1: this.colX + dropLine.width + props.dropCap.hSpace,
|
|
13173
13568
|
y0: this.y,
|
|
13174
13569
|
y1: this.y + dropLine.naturalHeight,
|
|
13175
|
-
mode: "square"
|
|
13570
|
+
mode: "square",
|
|
13571
|
+
exactTextEdge: true
|
|
13176
13572
|
});
|
|
13177
13573
|
this.floats.set(this.cur, list);
|
|
13178
13574
|
}
|
|
@@ -13252,16 +13648,22 @@ var Engine = class {
|
|
|
13252
13648
|
if (breakBeforeForced && !(isLeadingPageBreak && keepSpBeforeAtPageTop)) dropSpaceBefore = true;
|
|
13253
13649
|
if (this.docGridDropBefore) {
|
|
13254
13650
|
if (props.snapToGrid === false && this.sp.docGridLinePitch) {
|
|
13255
|
-
const reduction = 2 * this.sp.docGridLinePitch;
|
|
13651
|
+
const reduction = (props.spacingBefore ?? 0) > 0 ? 4 * this.sp.docGridLinePitch : 2 * this.sp.docGridLinePitch;
|
|
13256
13652
|
this.cur.bodyTop -= reduction;
|
|
13257
13653
|
this.y -= reduction;
|
|
13654
|
+
} else if (para.props.styleId === "Heading1" && this.sp.docGridLinePitch) {
|
|
13655
|
+
const reduction = 3 * this.sp.docGridLinePitch - ptToPx(1.5);
|
|
13656
|
+
this.cur.bodyTop -= reduction;
|
|
13657
|
+
this.y -= reduction;
|
|
13658
|
+
dropSpaceBefore = true;
|
|
13659
|
+
} else {
|
|
13660
|
+
dropSpaceBefore = true;
|
|
13258
13661
|
}
|
|
13259
13662
|
this.docGridDropBefore = false;
|
|
13260
|
-
dropSpaceBefore = true;
|
|
13261
13663
|
}
|
|
13262
13664
|
const rawSpacingBefore = dropSpaceBefore ? 0 : props.spacingBefore ?? 0;
|
|
13263
13665
|
let paraTopEstimate = this.y + rawSpacingBefore;
|
|
13264
|
-
emitParaAnchors(
|
|
13666
|
+
emitParaAnchors(this.y);
|
|
13265
13667
|
let broken = breakNow(paraTopEstimate);
|
|
13266
13668
|
const emitCharLineAnchors = (paraTop) => {
|
|
13267
13669
|
if (charLineAnchors.length === 0) return;
|
|
@@ -13431,7 +13833,7 @@ var Engine = class {
|
|
|
13431
13833
|
const nextProps = nextPara ? this.doc.effectiveParaProps(nextPara) : void 0;
|
|
13432
13834
|
const nextLeadBreak = nextPara ? leadingBreakOf(nextPara) : void 0;
|
|
13433
13835
|
let legacyBreakChain = false;
|
|
13434
|
-
if (lines.length > 0 && this.pageIsEmptyAtCursor() && this.doc.compatibilityMode < 15 && this.sp.docGridType === "default" && props.keepNext && nextPara && nextProps?.keepNext && nextLeadBreak?.type === "page") {
|
|
13836
|
+
if (lines.length > 0 && this.pageIsEmptyAtCursor() && this.doc.compatibilityMode < 15 && this.sp.docGridType === "default" && !this.cur.footerRel && props.keepNext && nextPara && nextProps?.keepNext && nextLeadBreak?.type === "page") {
|
|
13435
13837
|
const breakProps = this.doc.effectiveRunProps(nextPara, nextLeadBreak.run.props);
|
|
13436
13838
|
const breakFont = fontOf(breakProps, this.doc.styles.defaultRPr.font ?? "Calibri");
|
|
13437
13839
|
let breakHeight = this.measurer.metrics(breakFont).lineHeight;
|
|
@@ -13454,7 +13856,7 @@ var Engine = class {
|
|
|
13454
13856
|
retractParaAnchors();
|
|
13455
13857
|
this.nextColumn();
|
|
13456
13858
|
paraTopEstimate = this.y + extraSpacing;
|
|
13457
|
-
emitParaAnchors(
|
|
13859
|
+
emitParaAnchors(this.y);
|
|
13458
13860
|
broken = breakNow(paraTopEstimate);
|
|
13459
13861
|
emitCharLineAnchors(paraTopEstimate);
|
|
13460
13862
|
lines = broken.lines;
|
|
@@ -13602,6 +14004,7 @@ var Engine = class {
|
|
|
13602
14004
|
let simCol = this.col;
|
|
13603
14005
|
let simOnCurrentPage = true;
|
|
13604
14006
|
let simBannerUsed = this.bannerSlotUsed;
|
|
14007
|
+
const paragraphOverhang = this.customNoteBannerFit ? CUSTOM_NOTE_BANNER_OVERHANG : 0;
|
|
13605
14008
|
const updateBottom = () => {
|
|
13606
14009
|
bottom = simOnCurrentPage && this.balanceBottom !== void 0 && simCol + 1 < this.cur.colXs.length ? this.balanceBottom - simBannerUsed : this.cur.bodyBottom - (simOnCurrentPage ? this.footnoteReserve(this.cur, simCol) + simBannerUsed : 0);
|
|
13607
14010
|
};
|
|
@@ -13624,16 +14027,17 @@ var Engine = class {
|
|
|
13624
14027
|
}
|
|
13625
14028
|
};
|
|
13626
14029
|
const nextSimColumn = () => {
|
|
13627
|
-
simBannerUsed = 0;
|
|
13628
14030
|
simNotes = 0;
|
|
13629
14031
|
simNoted.clear();
|
|
13630
14032
|
if (simCol + 1 < this.cur.colXs.length) {
|
|
13631
14033
|
simCol++;
|
|
13632
14034
|
simY = simOnCurrentPage ? this.columnStartY(simCol) : this.cur.bodyTop;
|
|
14035
|
+
simBannerUsed = simOnCurrentPage && this.cur.bannerTop !== void 0 ? this.cur.openingColumnReserve ?? 0 : 0;
|
|
13633
14036
|
} else {
|
|
13634
14037
|
simCol = 0;
|
|
13635
14038
|
simOnCurrentPage = false;
|
|
13636
14039
|
simY = this.cur.bodyTop;
|
|
14040
|
+
simBannerUsed = 0;
|
|
13637
14041
|
}
|
|
13638
14042
|
updateBottom();
|
|
13639
14043
|
};
|
|
@@ -13652,7 +14056,7 @@ var Engine = class {
|
|
|
13652
14056
|
const noteAdd = lineNoteHeights(lines[li]);
|
|
13653
14057
|
const baseNotes = simOnCurrentPage ? this.cur.footnoteH[simCol] ?? 0 : 0;
|
|
13654
14058
|
const simSep = simNotes + noteAdd > 0 && baseNotes === 0 ? this.noteSeparatorReserve(this.cur) : 0;
|
|
13655
|
-
const overflowsHere = !postTablePageBreak && (simBalancing ? simY > bottom + 0.01 : simY + lines[li].fitHeight + (li === lines.length - 1 ? keepNextTail : 0) > bottom - simNotes - noteAdd - simSep + 0.01);
|
|
14059
|
+
const overflowsHere = !postTablePageBreak && (simBalancing ? simY > bottom + 0.01 : simY + lines[li].fitHeight + (li === lines.length - 1 ? keepNextTail : 0) > bottom - simNotes - noteAdd - simSep + paragraphOverhang + 0.01);
|
|
13656
14060
|
if (overflowsHere && li === segStart && segStart === 0 && onPartialPage && !simBalancing) {
|
|
13657
14061
|
breaks2.add(0);
|
|
13658
14062
|
segStart = 0;
|
|
@@ -13738,7 +14142,7 @@ var Engine = class {
|
|
|
13738
14142
|
const pendingNotes = this.pendingNoteHeight(line2);
|
|
13739
14143
|
const balancing = this.balanceBottom !== void 0 && this.col + 1 < this.cur.colXs.length;
|
|
13740
14144
|
const balBottomBased = balancing && this.colWidth < 40;
|
|
13741
|
-
const overflow = !postTablePageBreak && (balancing ? (balBottomBased ? this.y + line2.fitHeight : this.y) > this.bodyBottom + 0.01 : this.y + line2.fitHeight > this.bodyBottom - pendingNotes + 0.01) && !this.pageIsEmptyAtCursor();
|
|
14145
|
+
const overflow = !postTablePageBreak && (balancing ? (balBottomBased ? this.y + line2.fitHeight : this.y) > this.bodyBottom + 0.01 : this.y + line2.fitHeight > this.bodyBottom - pendingNotes + (this.customNoteBannerFit ? CUSTOM_NOTE_BANNER_OVERHANG : 0) + 0.01) && !this.pageIsEmptyAtCursor();
|
|
13742
14146
|
if ((planned || overflow) && li > fragStartLine) {
|
|
13743
14147
|
closeFragment(li, false);
|
|
13744
14148
|
this.nextColumn();
|
|
@@ -14087,6 +14491,22 @@ var Engine = class {
|
|
|
14087
14491
|
continue;
|
|
14088
14492
|
}
|
|
14089
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
|
+
}
|
|
14090
14510
|
if (span.leader && span.width > 6) {
|
|
14091
14511
|
const ch = span.leader === "dot" ? "." : span.leader === "hyphen" ? "-" : span.leader === "middleDot" ? "\xB7" : "_";
|
|
14092
14512
|
const chW = this.measurer.width(ch, span.font);
|
|
@@ -14293,7 +14713,7 @@ var Engine = class {
|
|
|
14293
14713
|
for (let i = 0; i < blocks.length; i++) {
|
|
14294
14714
|
const block = blocks[i];
|
|
14295
14715
|
if (block.type === "paragraph") {
|
|
14296
|
-
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) {
|
|
14297
14717
|
framePrevAfter = 0;
|
|
14298
14718
|
continue;
|
|
14299
14719
|
}
|
|
@@ -14362,6 +14782,20 @@ var Engine = class {
|
|
|
14362
14782
|
!(props.borders && frameSameBorders(props, blocks[i - 1])),
|
|
14363
14783
|
!(props.borders && frameSameBorders(props, blocks[i + 1]))
|
|
14364
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
|
+
}
|
|
14365
14799
|
y += spacingAfter;
|
|
14366
14800
|
if (isPageFrame) {
|
|
14367
14801
|
const frameTexts = items.slice(paraItemsStart).filter((it) => it.kind === "text" && it.text.trim().length > 0);
|
|
@@ -14406,13 +14840,35 @@ var Engine = class {
|
|
|
14406
14840
|
y = Math.max(y, pendingPageFrame.bottom);
|
|
14407
14841
|
pendingPageFrame = null;
|
|
14408
14842
|
}
|
|
14409
|
-
y = this.layoutTableInFrame(block, fake, 0, y, width, fields);
|
|
14843
|
+
y = this.layoutTableInFrame(block, fake, 0, y, width, fields, inCell === true);
|
|
14410
14844
|
framePrevAfter = 0;
|
|
14411
14845
|
}
|
|
14412
14846
|
}
|
|
14413
14847
|
if (pendingPageFrame) y = Math.max(y, pendingPageFrame.bottom);
|
|
14848
|
+
const itemBottom = (item) => {
|
|
14849
|
+
if (item.kind === "text") return (item.glyphTop ?? item.lineTop) + item.lineHeight;
|
|
14850
|
+
if (item.kind === "rect" || item.kind === "image" || item.kind === "path" || item.kind === "drawingHit") {
|
|
14851
|
+
return item.y + item.height;
|
|
14852
|
+
}
|
|
14853
|
+
if (item.kind === "edge") return Math.max(item.y1, item.y2);
|
|
14854
|
+
if (item.kind === "wordart" || item.kind === "warptext") return item.y + item.height;
|
|
14855
|
+
return 0;
|
|
14856
|
+
};
|
|
14857
|
+
const headerBandBottom = this.sp.marginTop - (origin?.y ?? 0);
|
|
14858
|
+
const paintedHeaderBottom = items.reduce((bottom, item) => {
|
|
14859
|
+
const itemEnd = itemBottom(item);
|
|
14860
|
+
return "behind" in item && item.behind && itemEnd <= headerBandBottom + 0.01 ? Math.max(bottom, itemEnd) : bottom;
|
|
14861
|
+
}, 0);
|
|
14862
|
+
const wrappedBottom = (this.floats.get(fake) ?? []).reduce(
|
|
14863
|
+
(bottom, float) => Math.max(bottom, float.y1 - (origin?.y ?? 0)),
|
|
14864
|
+
0
|
|
14865
|
+
);
|
|
14414
14866
|
this.floats.delete(fake);
|
|
14415
|
-
return {
|
|
14867
|
+
return {
|
|
14868
|
+
items,
|
|
14869
|
+
height: y + pageFramePhantomH,
|
|
14870
|
+
contentBottom: Math.max(y + pageFramePhantomH, paintedHeaderBottom, wrappedBottom)
|
|
14871
|
+
};
|
|
14416
14872
|
}
|
|
14417
14873
|
/**
|
|
14418
14874
|
* Emit floating shapes anchored at (textX, textY). Coordinates in the shape
|
|
@@ -14806,6 +15262,9 @@ var Engine = class {
|
|
|
14806
15262
|
if (ts.textAnchor === "middle") innerTop = ty + (ts.height - inner.height) / 2;
|
|
14807
15263
|
else if (ts.textAnchor === "bottom") innerTop = ty + ts.height - ins.b - inner.height;
|
|
14808
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
|
+
}
|
|
14809
15268
|
offsetItem(it, tx + ins.l, innerTop);
|
|
14810
15269
|
if (front && (it.kind === "text" || it.kind === "rect" || it.kind === "edge")) it.front = true;
|
|
14811
15270
|
if (rotate && (it.kind === "text" || it.kind === "rect")) {
|
|
@@ -14818,7 +15277,7 @@ var Engine = class {
|
|
|
14818
15277
|
page.items.push(it);
|
|
14819
15278
|
}
|
|
14820
15279
|
}
|
|
14821
|
-
measureHeaderFooter(hf, page, contentWidth, overlayPageFrame = false) {
|
|
15280
|
+
measureHeaderFooter(hf, page, contentWidth, overlayPageFrame = false, reserveBodyClearance = false) {
|
|
14822
15281
|
if (!hf || hf.blocks.length === 0) return 0;
|
|
14823
15282
|
const fields = {
|
|
14824
15283
|
pageNumber: () => page.displayNumber,
|
|
@@ -14827,10 +15286,25 @@ var Engine = class {
|
|
|
14827
15286
|
};
|
|
14828
15287
|
const snapshot = new Map(Array.from(this.counters, ([k, v]) => [k, [...v]]));
|
|
14829
15288
|
const seenSnapshot = new Set(this.seenNumIds);
|
|
14830
|
-
const {
|
|
15289
|
+
const origin = reserveBodyClearance ? { x: page.sp.marginLeft + page.sp.gutter, y: page.sp.headerDistance } : void 0;
|
|
15290
|
+
const { height, contentBottom } = this.layoutFrame(
|
|
15291
|
+
hf.blocks,
|
|
15292
|
+
contentWidth,
|
|
15293
|
+
fields,
|
|
15294
|
+
origin,
|
|
15295
|
+
false,
|
|
15296
|
+
overlayPageFrame
|
|
15297
|
+
);
|
|
14831
15298
|
this.counters = snapshot;
|
|
14832
15299
|
this.seenNumIds = seenSnapshot;
|
|
14833
|
-
|
|
15300
|
+
const anchors = hf.blocks.flatMap(
|
|
15301
|
+
(block) => block.type === "paragraph" ? this.collectAnchors(block) : []
|
|
15302
|
+
);
|
|
15303
|
+
const hasOnlyUnwrappedAnchors = anchors.length > 0 && anchors.every(
|
|
15304
|
+
(shape) => !("wrap" in shape) || shape.wrap === void 0 || shape.wrap === "none"
|
|
15305
|
+
);
|
|
15306
|
+
const complexHeader = anchors.length > 0 || hf.blocks.some((block) => block.type === "table");
|
|
15307
|
+
return reserveBodyClearance ? Math.max(height, contentBottom) + (!hasOnlyUnwrappedAnchors && complexHeader ? ptToPx(22.5) : 0) : height;
|
|
14834
15308
|
}
|
|
14835
15309
|
pageFieldFrameOverlay(hf) {
|
|
14836
15310
|
if (!hf) return false;
|
|
@@ -14892,7 +15366,10 @@ var Engine = class {
|
|
|
14892
15366
|
const measured = this.layoutFrame(footer.blocks, contentWidth, fields, void 0, false, overlayPageFrame);
|
|
14893
15367
|
this.counters = snapshot;
|
|
14894
15368
|
this.seenNumIds = seenSnapshot;
|
|
14895
|
-
const
|
|
15369
|
+
const legacyPageFrame = this.doc.compatibilityMode < 15 && footer.blocks.some(
|
|
15370
|
+
(block) => block.type === "paragraph" && this.doc.effectiveParaProps(block).frame?.vAnchor === "page"
|
|
15371
|
+
);
|
|
15372
|
+
const top = sp.pageHeight - sp.footerDistance - (legacyPageFrame ? 0 : measured.height);
|
|
14896
15373
|
snapshot = new Map(Array.from(this.counters, ([k, v]) => [k, [...v]]));
|
|
14897
15374
|
seenSnapshot = new Set(this.seenNumIds);
|
|
14898
15375
|
this.hfMarginVTop = page.bodyTop;
|
|
@@ -14917,23 +15394,120 @@ var Engine = class {
|
|
|
14917
15394
|
* the same: measure each column's preferred (unwrapped) and minimum
|
|
14918
15395
|
* (widest atom) content width and fit them to the table width.
|
|
14919
15396
|
*/
|
|
14920
|
-
resolveGridWidths(tbl, available, nested = false) {
|
|
15397
|
+
resolveGridWidths(tbl, available, nested = false, confineToAvailable = false) {
|
|
14921
15398
|
const edgeMargins = this.cellMarginsOf(tbl);
|
|
14922
15399
|
const base = resolveGrid(
|
|
14923
15400
|
tbl,
|
|
14924
15401
|
available,
|
|
14925
|
-
!nested,
|
|
15402
|
+
!nested && !confineToAvailable,
|
|
14926
15403
|
(edgeMargins.left ?? 0) + (edgeMargins.right ?? 0)
|
|
14927
15404
|
);
|
|
14928
15405
|
if (tbl.props.layout === "fixed") return base;
|
|
14929
15406
|
const gridTotal = tbl.grid.reduce((a, b) => a + b, 0);
|
|
14930
15407
|
const target = base.reduce((a, b) => a + b, 0);
|
|
14931
15408
|
const cellsDeclareWidths = tbl.rows.some((r) => r.cells.some((c) => c.props.width !== void 0));
|
|
14932
|
-
|
|
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
|
+
}
|
|
14933
15460
|
if (!nested) {
|
|
14934
15461
|
const shrunk = this.shrinkToTargetWidth(tbl, base.length, available);
|
|
14935
15462
|
if (shrunk) return shrunk;
|
|
14936
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
|
+
}
|
|
14937
15511
|
if (tbl.props.widthPct === void 0 && gridTotal > available) {
|
|
14938
15512
|
if (!nested && tbl.props.width !== void 0) return [...tbl.grid];
|
|
14939
15513
|
if (!nested) {
|
|
@@ -14946,7 +15520,7 @@ var Engine = class {
|
|
|
14946
15520
|
const { minW: minW2 } = this.columnMinPref(tbl, base.length);
|
|
14947
15521
|
const expanded = base.map((w, i) => Math.max(w, minW2[i] ?? 0));
|
|
14948
15522
|
if (expanded.reduce((a, b) => a + b, 0) <= available) return expanded;
|
|
14949
|
-
} else if (tbl.props.widthPct !== void 0 && !nested) {
|
|
15523
|
+
} else if ((tbl.props.widthPct !== void 0 || tbl.props.width !== void 0) && !nested) {
|
|
14950
15524
|
const { minW: minW2, fudge: fudge2 } = this.columnMinPref(tbl, base.length);
|
|
14951
15525
|
const mins = minW2.map((m) => Math.max(0, m - fudge2));
|
|
14952
15526
|
const target2 = base.reduce((a, b) => a + b, 0);
|
|
@@ -14967,12 +15541,13 @@ var Engine = class {
|
|
|
14967
15541
|
}
|
|
14968
15542
|
const nCols = base.length;
|
|
14969
15543
|
const { minW, prefW, fudge } = this.columnMinPref(tbl, nCols);
|
|
14970
|
-
const sumPref = prefW.reduce((a, b) => a + b, 0);
|
|
14971
|
-
if (sumPref <= 0) return base;
|
|
14972
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;
|
|
14973
15548
|
const want = hasExplicit ? target : Math.min(sumPref, available);
|
|
14974
15549
|
const clampW = hasExplicit ? minW.map((m) => Math.max(0, m - fudge)) : minW;
|
|
14975
|
-
const widths =
|
|
15550
|
+
const widths = fittedPref.map((w) => w * want / sumPref);
|
|
14976
15551
|
for (let pass = 0; pass < 3; pass++) {
|
|
14977
15552
|
let deficit = 0;
|
|
14978
15553
|
let flexible = 0;
|
|
@@ -15000,6 +15575,12 @@ var Engine = class {
|
|
|
15000
15575
|
for (let i = 0; i < nCols; i++) widths[i] -= Math.max(0, widths[i] - floor) * k;
|
|
15001
15576
|
}
|
|
15002
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
|
+
}
|
|
15003
15584
|
return widths;
|
|
15004
15585
|
}
|
|
15005
15586
|
/**
|
|
@@ -15014,7 +15595,7 @@ var Engine = class {
|
|
|
15014
15595
|
* 175.7px, and "side A/B" absorbs the whole loss, 123.9 -> 71.4px).
|
|
15015
15596
|
*/
|
|
15016
15597
|
confineNestedGrid(tbl, base, available) {
|
|
15017
|
-
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;
|
|
15018
15599
|
const want = Math.max(8, available - half(tbl.props.borders?.left) - half(tbl.props.borders?.right));
|
|
15019
15600
|
const total = base.reduce((a, b) => a + b, 0);
|
|
15020
15601
|
if (total <= 0) return base;
|
|
@@ -15213,8 +15794,8 @@ var Engine = class {
|
|
|
15213
15794
|
tbl.grid.length,
|
|
15214
15795
|
...tbl.rows.map((r) => r.cells.reduce((a, c) => a + c.props.gridSpan, 0))
|
|
15215
15796
|
);
|
|
15216
|
-
const { minW, prefW } = this.columnMinPref(tbl, Math.max(1, nCols));
|
|
15217
|
-
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);
|
|
15218
15799
|
let pref = prefW.reduce((a, b) => a + b, 0);
|
|
15219
15800
|
const gridTotal = tbl.grid.reduce((a, b) => a + b, 0);
|
|
15220
15801
|
const cellsDeclareWidths = tbl.rows.some((r) => r.cells.some((c) => c.props.width !== void 0));
|
|
@@ -15271,7 +15852,25 @@ var Engine = class {
|
|
|
15271
15852
|
if (cell.props.margins?.top !== void 0) topPad = Math.max(topPad, cell.props.margins.top);
|
|
15272
15853
|
if (cell.props.margins?.bottom !== void 0) bottomPad = Math.max(bottomPad, cell.props.margins.bottom);
|
|
15273
15854
|
}
|
|
15274
|
-
if (row.props.heightRule === "exact")
|
|
15855
|
+
if (row.props.heightRule === "exact") {
|
|
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;
|
|
15868
|
+
}
|
|
15869
|
+
if (this.doc.compatibilityMode < 15) {
|
|
15870
|
+
const legacyBottomPad = bottomPad >= ptToPx(1) ? bottomPad : 0;
|
|
15871
|
+
const legacyTopPad = row.props.heightRule === "atLeast" && (row.props.height ?? 0) >= ptToPx(30) ? Math.max(topPad - ptToPx(0.25), 0) : topPad;
|
|
15872
|
+
return Math.max(contentHeight, trHeight + legacyTopPad + legacyBottomPad);
|
|
15873
|
+
}
|
|
15275
15874
|
const borderPad = this.rowBorderShare(tbl, ri);
|
|
15276
15875
|
return Math.max(contentHeight, trHeight + topPad + bottomPad + borderPad);
|
|
15277
15876
|
}
|
|
@@ -15346,13 +15945,10 @@ var Engine = class {
|
|
|
15346
15945
|
}
|
|
15347
15946
|
return floor({});
|
|
15348
15947
|
}
|
|
15349
|
-
/**
|
|
15350
|
-
*
|
|
15351
|
-
*
|
|
15352
|
-
* tblStyle) supplies the cell grid that would otherwise be missing.
|
|
15353
|
-
*/
|
|
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. */
|
|
15354
15951
|
ensureTableBorders(tbl) {
|
|
15355
|
-
if (tbl.props.borders !== void 0) return;
|
|
15356
15952
|
const byId = this.doc.styles.byId;
|
|
15357
15953
|
const fromChain = (id) => {
|
|
15358
15954
|
let cur = id;
|
|
@@ -15374,7 +15970,17 @@ var Engine = class {
|
|
|
15374
15970
|
}
|
|
15375
15971
|
}
|
|
15376
15972
|
}
|
|
15377
|
-
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
|
+
}
|
|
15378
15984
|
}
|
|
15379
15985
|
/** Height of a table's LEAD block for keep/orphan checks: the top border
|
|
15380
15986
|
* half, any leading tblHeader rows, and the first non-header row. Word
|
|
@@ -15408,6 +16014,9 @@ var Engine = class {
|
|
|
15408
16014
|
this.lastParaAfterPad = 0;
|
|
15409
16015
|
this.lastParaWasEmpty = false;
|
|
15410
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;
|
|
15411
16020
|
const colWidth = this.colWidth;
|
|
15412
16021
|
const widths = this.resolveGridWidths(tbl, colWidth);
|
|
15413
16022
|
const s2 = 2 * (tbl.props.cellSpacing ?? 0);
|
|
@@ -15443,6 +16052,7 @@ var Engine = class {
|
|
|
15443
16052
|
}
|
|
15444
16053
|
let segTop = this.y;
|
|
15445
16054
|
let segPage = this.cur;
|
|
16055
|
+
let segHasRows = false;
|
|
15446
16056
|
let moveEmitted = false;
|
|
15447
16057
|
const markTableStart = () => {
|
|
15448
16058
|
if (moveEmitted) return;
|
|
@@ -15470,12 +16080,24 @@ var Engine = class {
|
|
|
15470
16080
|
let laid = laidRows[ri];
|
|
15471
16081
|
let rowHeight = rowHeights[ri];
|
|
15472
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
|
+
}
|
|
15473
16094
|
this.emitTableGrips(tbl, segPage, x0, widths, segTop, this.y);
|
|
15474
16095
|
this.nextColumn();
|
|
15475
16096
|
this.clearBannerSlot();
|
|
15476
16097
|
x0 = computeX0();
|
|
15477
16098
|
segTop = this.y;
|
|
15478
16099
|
segPage = this.cur;
|
|
16100
|
+
segHasRows = false;
|
|
15479
16101
|
const firstRowIdx = !row.props.tblHeader && headerRows.length > 0 ? 0 : ri;
|
|
15480
16102
|
this.y += this.rowBorderWidths(tbl, firstRowIdx).top / 2;
|
|
15481
16103
|
if (!row.props.tblHeader) {
|
|
@@ -15485,13 +16107,14 @@ var Engine = class {
|
|
|
15485
16107
|
const hH = rowHeights[hIdx];
|
|
15486
16108
|
markTableStart();
|
|
15487
16109
|
this.paintRow(tbl, hr, hIdx, hLaid, x0, widths, hH);
|
|
16110
|
+
segHasRows = true;
|
|
15488
16111
|
this.y += hH;
|
|
15489
16112
|
}
|
|
15490
16113
|
}
|
|
15491
16114
|
};
|
|
15492
16115
|
let guard = 0;
|
|
15493
16116
|
const noteReserve = this.rowNoteHeight(laid) + this.footnoteReserve(this.cur, this.col);
|
|
15494
|
-
const overhang = noteReserve > 0 || row.props.cantSplit
|
|
16117
|
+
const overhang = noteReserve > 0 || row.props.heightRule === "exact" ? 0 : row.props.cantSplit ? this.doc.compatibilityMode < 15 && (row.props.heightRule !== "atLeast" || (row.props.height ?? 0) >= ptToPx(2)) ? this.cur.footerHeight : 0 : ROW_OVERHANG_TOL;
|
|
15495
16118
|
while (this.y + rowHeight > this.bodyBottom - this.rowNoteHeight(laid) + overhang + 0.01 && guard++ < 50) {
|
|
15496
16119
|
const atColumnTop = this.pageIsEmptyAtCursor() || this.y <= this.cur.bodyTop + this.rowBorderWidths(tbl, ri).top / 2 + 0.01;
|
|
15497
16120
|
const cantSplitHolds = row.props.cantSplit === true && (rowHeight <= this.cur.bodyBottom - this.cur.bodyTop + 0.01 || !atColumnTop);
|
|
@@ -15501,6 +16124,18 @@ var Engine = class {
|
|
|
15501
16124
|
if (parts) {
|
|
15502
16125
|
markTableStart();
|
|
15503
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
|
+
}
|
|
15504
16139
|
this.y += parts.top.height;
|
|
15505
16140
|
advance();
|
|
15506
16141
|
laid = parts.rest;
|
|
@@ -15513,6 +16148,7 @@ var Engine = class {
|
|
|
15513
16148
|
}
|
|
15514
16149
|
markTableStart();
|
|
15515
16150
|
this.paintRow(tbl, row, ri, laid, x0, widths, rowHeight);
|
|
16151
|
+
segHasRows = true;
|
|
15516
16152
|
this.y += rowHeight;
|
|
15517
16153
|
if (s2 && ri < tbl.rows.length - 1) this.y += s2;
|
|
15518
16154
|
if (tbl.src) {
|
|
@@ -15710,9 +16346,10 @@ var Engine = class {
|
|
|
15710
16346
|
});
|
|
15711
16347
|
}
|
|
15712
16348
|
}
|
|
15713
|
-
layoutTableInFrame(tbl, fake, x0, y, width, fields) {
|
|
16349
|
+
layoutTableInFrame(tbl, fake, x0, y, width, fields, nested) {
|
|
15714
16350
|
this.ensureTableBorders(tbl);
|
|
15715
|
-
const
|
|
16351
|
+
const confineToAvailable = !nested && tbl.props.width === void 0 && tbl.props.widthPct === void 0;
|
|
16352
|
+
const widths = this.resolveGridWidths(tbl, width, nested, confineToAvailable);
|
|
15716
16353
|
const saveY = this.y;
|
|
15717
16354
|
const saveCur = this.cur;
|
|
15718
16355
|
const saveCol = this.col;
|
|
@@ -15766,9 +16403,10 @@ var Engine = class {
|
|
|
15766
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;
|
|
15767
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;
|
|
15768
16405
|
const partitions = laid.cells.map((cell) => {
|
|
15769
|
-
const
|
|
16406
|
+
const flowItems = cell.items.filter((it) => it.kind !== "grip");
|
|
16407
|
+
const contentBottom = flowItems.length > 0 ? Math.max(...flowItems.map(bottomOf)) : 0;
|
|
15770
16408
|
const trailing = Math.max(0, cell.height - contentBottom);
|
|
15771
|
-
const hRules =
|
|
16409
|
+
const hRules = flowItems.filter(
|
|
15772
16410
|
(it) => it.kind === "edge" && Math.abs(it.y1 - it.y2) < 0.01 && Math.abs(it.x2 - it.x1) > 4
|
|
15773
16411
|
).map((it) => it.y1).sort((a, b) => a - b);
|
|
15774
16412
|
const bandBottom = (top, bottom) => {
|
|
@@ -15789,8 +16427,9 @@ var Engine = class {
|
|
|
15789
16427
|
return {
|
|
15790
16428
|
cell,
|
|
15791
16429
|
trailing,
|
|
15792
|
-
|
|
15793
|
-
|
|
16430
|
+
grips: cell.items.filter((it) => it.kind === "grip"),
|
|
16431
|
+
keep: flowItems.filter((it) => keeps(it)),
|
|
16432
|
+
rest: flowItems.filter((it) => !keeps(it))
|
|
15794
16433
|
};
|
|
15795
16434
|
});
|
|
15796
16435
|
const lineTops = (items) => [...new Set(items.filter((it) => it.kind === "text").map((it) => it.lineTop))].sort((a, b) => a - b);
|
|
@@ -15845,18 +16484,31 @@ var Engine = class {
|
|
|
15845
16484
|
})) {
|
|
15846
16485
|
return null;
|
|
15847
16486
|
}
|
|
15848
|
-
let
|
|
16487
|
+
let contentCut = 0;
|
|
16488
|
+
let flowCut = 0;
|
|
15849
16489
|
let allBanded = true;
|
|
15850
|
-
|
|
16490
|
+
let allBetweenParagraphs = true;
|
|
16491
|
+
let hasTextBoundary = false;
|
|
16492
|
+
for (const { cell, keep, rest, trailing } of partitions) {
|
|
15851
16493
|
if (keep.length === 0) continue;
|
|
15852
16494
|
const kb = Math.max(...keep.map(bottomOf));
|
|
15853
|
-
|
|
16495
|
+
flowCut = Math.max(flowCut, kb);
|
|
16496
|
+
contentCut = Math.max(contentCut, kb + trailing);
|
|
15854
16497
|
const onRule = cell.items.some(
|
|
15855
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
|
|
15856
16499
|
);
|
|
15857
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
|
+
}
|
|
15858
16509
|
}
|
|
15859
|
-
const
|
|
16510
|
+
const hugContent = allBanded || hasTextBoundary && allBetweenParagraphs;
|
|
16511
|
+
const cutH = Math.min(avail + keepSlack, hugContent ? contentCut : flowCut);
|
|
15860
16512
|
const topCells = [];
|
|
15861
16513
|
const restCells = [];
|
|
15862
16514
|
let topH = 0;
|
|
@@ -15868,15 +16520,26 @@ var Engine = class {
|
|
|
15868
16520
|
}
|
|
15869
16521
|
return t;
|
|
15870
16522
|
};
|
|
15871
|
-
for (const { cell, trailing, keep, rest } of partitions) {
|
|
15872
|
-
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;
|
|
15873
16526
|
const ruleShift = rest.length > 0 ? Math.min(...rest.map(topOf)) - keepTop : 0;
|
|
15874
16527
|
const origText = firstTextTop(cell.items);
|
|
15875
16528
|
const restText = firstTextTop(rest);
|
|
15876
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
|
+
}
|
|
15877
16540
|
for (const it of rest) offsetItem(it, 0, -shift);
|
|
15878
16541
|
topCells.push({ ...cell, items: keep, height: Math.min(cell.height, cutH) });
|
|
15879
|
-
const cellRestH = rest.length > 0 ? Math.max(...rest.map(bottomOf)) +
|
|
16542
|
+
const cellRestH = rest.length > 0 ? Math.max(...rest.map(bottomOf)) + trailing : 0;
|
|
15880
16543
|
restCells.push({ ...cell, items: rest, height: cellRestH });
|
|
15881
16544
|
topH = Math.max(topH, keep.length > 0 ? Math.min(cell.height, cutH) : 0);
|
|
15882
16545
|
restH = Math.max(restH, cellRestH);
|
|
@@ -15970,14 +16633,24 @@ var Engine = class {
|
|
|
15970
16633
|
const x = bidi ? totalW - sum(widths, 0, gridPos) - w : sum(widths, 0, gridPos);
|
|
15971
16634
|
gridPos += span;
|
|
15972
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;
|
|
15973
16637
|
geometry.push({
|
|
15974
16638
|
x,
|
|
15975
16639
|
width: w,
|
|
15976
|
-
|
|
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
|
+
}
|
|
15977
16649
|
});
|
|
15978
16650
|
}
|
|
15979
16651
|
let maxH = 0;
|
|
15980
16652
|
let measuredContentH = 0;
|
|
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;
|
|
15981
16654
|
for (let ci = 0; ci < row.cells.length; ci++) {
|
|
15982
16655
|
const cell = row.cells[ci];
|
|
15983
16656
|
const { x, width: w, margins: m } = geometry[ci];
|
|
@@ -15997,7 +16670,7 @@ var Engine = class {
|
|
|
15997
16670
|
true
|
|
15998
16671
|
);
|
|
15999
16672
|
for (const it of items) offsetItem(it, m.left ?? 0, m.top ?? 0);
|
|
16000
|
-
const cellHeight = height + (m.top ?? 0) + (m.bottom
|
|
16673
|
+
const cellHeight = height + (m.top ?? 0) + effectiveBottomPad(m.bottom);
|
|
16001
16674
|
cells[ci] = { items, height: cellHeight, x, width: w, cellIdx: ci };
|
|
16002
16675
|
measuredContentH = Math.max(measuredContentH, height);
|
|
16003
16676
|
maxH = Math.max(maxH, cellHeight);
|
|
@@ -16041,7 +16714,7 @@ var Engine = class {
|
|
|
16041
16714
|
it.rotate = { deg, ox: centerX - it.x, oy: centerY - top };
|
|
16042
16715
|
}
|
|
16043
16716
|
}
|
|
16044
|
-
const cellHeight = frameWidth + (m.top ?? 0) + (m.bottom
|
|
16717
|
+
const cellHeight = frameWidth + (m.top ?? 0) + effectiveBottomPad(m.bottom);
|
|
16045
16718
|
cells[ci] = { items, height: cellHeight, x, width: w, cellIdx: ci, rotated: true };
|
|
16046
16719
|
maxH = Math.max(maxH, cellHeight);
|
|
16047
16720
|
}
|
|
@@ -16134,7 +16807,7 @@ var Engine = class {
|
|
|
16134
16807
|
dy += Math.max(0, contentH - cellLay.height);
|
|
16135
16808
|
}
|
|
16136
16809
|
const clip = row.props.heightRule === "exact";
|
|
16137
|
-
const rowBottom = y + rowHeight;
|
|
16810
|
+
const rowBottom = y + (cell.props.vMerge === "restart" ? cellH : rowHeight);
|
|
16138
16811
|
for (const it of cellLay.items) {
|
|
16139
16812
|
offsetItem(it, cx, y + dy);
|
|
16140
16813
|
if (clip && it.kind === "text" && it.lineTop !== void 0 && it.lineTop >= rowBottom - 0.5) continue;
|
|
@@ -16142,7 +16815,9 @@ var Engine = class {
|
|
|
16142
16815
|
if (it.kind === "text" && it.noteId !== void 0) this.registerFootnote(it.noteId, page);
|
|
16143
16816
|
page.items.push(it);
|
|
16144
16817
|
}
|
|
16145
|
-
|
|
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);
|
|
16146
16821
|
}
|
|
16147
16822
|
}
|
|
16148
16823
|
paintCellEdges(page, tbl, cell, x, y, w, h, firstRow, lastRow, firstCol, lastCol, mergedContinue, condBorders) {
|
|
@@ -16155,7 +16830,7 @@ var Engine = class {
|
|
|
16155
16830
|
return fallback && fallback.style !== "none" ? fallback : void 0;
|
|
16156
16831
|
};
|
|
16157
16832
|
const top = mergedContinue || cell.props.vMerge === "continue" ? void 0 : pick(cb?.top, condBorders?.top, tb?.top, tb?.insideH, firstRow);
|
|
16158
|
-
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);
|
|
16159
16834
|
const left = pick(cb?.left, condBorders?.left, tb?.left, tb?.insideV, firstCol);
|
|
16160
16835
|
const right = pick(cb?.right, condBorders?.right, tb?.right, tb?.insideV, lastCol);
|
|
16161
16836
|
if (top) {
|
|
@@ -16190,6 +16865,24 @@ var Engine = class {
|
|
|
16190
16865
|
}
|
|
16191
16866
|
}
|
|
16192
16867
|
};
|
|
16868
|
+
function customFootnoteAnchorIds(p) {
|
|
16869
|
+
const ids = [];
|
|
16870
|
+
for (const child4 of p.children) {
|
|
16871
|
+
const runs = child4.type === "run" ? [child4] : child4.runs;
|
|
16872
|
+
for (const run of runs) {
|
|
16873
|
+
for (const content of run.content) {
|
|
16874
|
+
if (content.kind === "text") {
|
|
16875
|
+
if (content.text.trim().length > 0) return void 0;
|
|
16876
|
+
} else if (content.kind === "noteRef" && content.noteType === "footnote" && !content.self && content.customMarkFollows) {
|
|
16877
|
+
ids.push(content.id);
|
|
16878
|
+
} else {
|
|
16879
|
+
return void 0;
|
|
16880
|
+
}
|
|
16881
|
+
}
|
|
16882
|
+
}
|
|
16883
|
+
}
|
|
16884
|
+
return ids.length > 0 ? ids : void 0;
|
|
16885
|
+
}
|
|
16193
16886
|
function isEmptyParagraph(p) {
|
|
16194
16887
|
for (const child4 of p.children) {
|
|
16195
16888
|
const runs = child4.type === "run" ? [child4] : child4.runs;
|
|
@@ -17895,6 +18588,11 @@ function renderChart(item) {
|
|
|
17895
18588
|
}
|
|
17896
18589
|
return svg;
|
|
17897
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
|
+
}
|
|
17898
18596
|
function renderItem(doc, item, urls) {
|
|
17899
18597
|
switch (item.kind) {
|
|
17900
18598
|
case "rect": {
|
|
@@ -17909,8 +18607,7 @@ function renderItem(doc, item, urls) {
|
|
|
17909
18607
|
el16.style.transform = `rotate(${item.rotate.deg}deg)`;
|
|
17910
18608
|
el16.style.transformOrigin = `${item.rotate.ox}px ${item.rotate.oy}px`;
|
|
17911
18609
|
}
|
|
17912
|
-
|
|
17913
|
-
else if (item.front) el16.style.zIndex = "1";
|
|
18610
|
+
setItemLayer(el16, item);
|
|
17914
18611
|
return el16;
|
|
17915
18612
|
}
|
|
17916
18613
|
case "path": {
|
|
@@ -17936,8 +18633,7 @@ function renderItem(doc, item, urls) {
|
|
|
17936
18633
|
if (item.stroke.opacity !== void 0) path2.setAttribute("stroke-opacity", String(item.stroke.opacity));
|
|
17937
18634
|
path2.setAttribute("vector-effect", "non-scaling-stroke");
|
|
17938
18635
|
}
|
|
17939
|
-
|
|
17940
|
-
else if (item.front) svg.style.zIndex = "1";
|
|
18636
|
+
setItemLayer(svg, item);
|
|
17941
18637
|
svg.appendChild(path2);
|
|
17942
18638
|
return svg;
|
|
17943
18639
|
}
|
|
@@ -17949,7 +18645,7 @@ function renderItem(doc, item, urls) {
|
|
|
17949
18645
|
hit.style.width = `${item.width}px`;
|
|
17950
18646
|
hit.style.height = `${item.height}px`;
|
|
17951
18647
|
hit.style.cursor = "move";
|
|
17952
|
-
hit.style.zIndex = item.belowText ? "1" : "6";
|
|
18648
|
+
hit.style.zIndex = item.z !== void 0 ? String(item.z) : item.belowText ? "1" : "6";
|
|
17953
18649
|
if (item.rotate) {
|
|
17954
18650
|
hit.style.transform = `rotate(${item.rotate.deg}deg)`;
|
|
17955
18651
|
hit.style.transformOrigin = `${item.rotate.ox}px ${item.rotate.oy}px`;
|
|
@@ -17957,11 +18653,16 @@ function renderItem(doc, item, urls) {
|
|
|
17957
18653
|
hit.dataset.dxwDrawing = "1";
|
|
17958
18654
|
if (item.ink) hit.dataset.dxwInk = "1";
|
|
17959
18655
|
if (item.smartArt) hit.dataset.dxwSmartArt = "1";
|
|
18656
|
+
if (item.height < 12) {
|
|
18657
|
+
const target = document.createElement("div");
|
|
18658
|
+
target.style.cssText = `position:absolute;left:0;top:${-(12 - item.height) / 2}px;width:100%;height:12px;cursor:move;`;
|
|
18659
|
+
hit.appendChild(target);
|
|
18660
|
+
}
|
|
17960
18661
|
return hit;
|
|
17961
18662
|
}
|
|
17962
18663
|
case "edge": {
|
|
17963
18664
|
const el16 = renderEdge(item.x1, item.y1, item.x2, item.y2, item.border, item.rotate);
|
|
17964
|
-
|
|
18665
|
+
setItemLayer(el16, item);
|
|
17965
18666
|
return el16;
|
|
17966
18667
|
}
|
|
17967
18668
|
case "chart":
|
|
@@ -18149,8 +18850,7 @@ function renderItem(doc, item, urls) {
|
|
|
18149
18850
|
node.style.transformOrigin = `${item.rotate.ox}px ${item.rotate.oy}px`;
|
|
18150
18851
|
} else if (item.rotation) node.style.transform = `rotate(${item.rotation}deg)`;
|
|
18151
18852
|
if (item.border) node.style.outline = `${item.border.width}px solid ${item.border.color}`;
|
|
18152
|
-
|
|
18153
|
-
else if (item.front) node.style.zIndex = "2";
|
|
18853
|
+
setItemLayer(node, item, 2);
|
|
18154
18854
|
node.dataset.dxwImageFormat = ext;
|
|
18155
18855
|
if (item.model3D) node.dataset.dxwModel3d = "1";
|
|
18156
18856
|
if (item.webVideo) {
|
|
@@ -18211,11 +18911,15 @@ function renderWordArt(item) {
|
|
|
18211
18911
|
const weight = item.bold ? "bold " : "";
|
|
18212
18912
|
const style = item.italic ? "italic " : "";
|
|
18213
18913
|
if (item.noFit) {
|
|
18214
|
-
const
|
|
18215
|
-
|
|
18216
|
-
|
|
18217
|
-
|
|
18218
|
-
|
|
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);
|
|
18219
18923
|
return box;
|
|
18220
18924
|
}
|
|
18221
18925
|
const fontPx = item.height * 0.92;
|
|
@@ -18272,12 +18976,12 @@ function warpBaseline(warp, W, H) {
|
|
|
18272
18976
|
}
|
|
18273
18977
|
case "textWave1":
|
|
18274
18978
|
case "textWave2": {
|
|
18275
|
-
const fontPx = H * 0.
|
|
18979
|
+
const fontPx = H * 0.78;
|
|
18276
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}`;
|
|
18277
18981
|
return { d, fontPx, pathLen: bw * 1.06, startFrac: 0, anchor: "start", fill: true };
|
|
18278
18982
|
}
|
|
18279
18983
|
case "textChevron": {
|
|
18280
|
-
const fontPx = H * 0.
|
|
18984
|
+
const fontPx = H * 0.78;
|
|
18281
18985
|
const yEnds = H * 0.26;
|
|
18282
18986
|
const yCtrl = H * 1.18;
|
|
18283
18987
|
const d = `M ${mx} ${yEnds} Q ${W / 2} ${yCtrl} ${W - mx} ${yEnds}`;
|
|
@@ -18299,7 +19003,7 @@ function warpBaseline(warp, W, H) {
|
|
|
18299
19003
|
const r = Math.min(W, H) * 0.3;
|
|
18300
19004
|
const cx = W / 2;
|
|
18301
19005
|
const cy = H / 2;
|
|
18302
|
-
const a = -
|
|
19006
|
+
const a = -90 * Math.PI / 180;
|
|
18303
19007
|
const sx = cx + r * Math.sin(a);
|
|
18304
19008
|
const sy = cy - r * Math.cos(a);
|
|
18305
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`;
|
|
@@ -18324,30 +19028,96 @@ function renderWarpText(item) {
|
|
|
18324
19028
|
svg.style.transformOrigin = `${item.rotate.ox}px ${item.rotate.oy}px`;
|
|
18325
19029
|
}
|
|
18326
19030
|
svg.style.pointerEvents = "none";
|
|
18327
|
-
|
|
18328
|
-
else if (item.front) svg.style.zIndex = "1";
|
|
19031
|
+
setItemLayer(svg, item);
|
|
18329
19032
|
const geo = warpBaseline(item.warp, W, H);
|
|
18330
19033
|
const weight = item.bold ? "bold" : "normal";
|
|
18331
19034
|
const style = item.italic ? "italic" : "normal";
|
|
18332
|
-
const family = `"${item.fontFamily}", sans-serif`;
|
|
18333
|
-
|
|
18334
|
-
|
|
18335
|
-
|
|
18336
|
-
|
|
18337
|
-
|
|
18338
|
-
|
|
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);
|
|
18339
19080
|
try {
|
|
18340
19081
|
const ctx = document.createElement("canvas").getContext("2d");
|
|
18341
19082
|
if (ctx) {
|
|
18342
|
-
ctx.font = `${style} ${weight}
|
|
18343
|
-
|
|
18344
|
-
if (w > 0) perPx = w / 100;
|
|
19083
|
+
ctx.font = `${style} ${weight} ${fontPx2}px ${family}`;
|
|
19084
|
+
advances = chars.map((ch) => ctx.measureText(ch).width);
|
|
18345
19085
|
}
|
|
18346
19086
|
} catch {
|
|
18347
19087
|
}
|
|
18348
|
-
const
|
|
18349
|
-
const
|
|
18350
|
-
|
|
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;
|
|
18351
19121
|
}
|
|
18352
19122
|
const id = `dxw-warp-${warpPathSeq++}`;
|
|
18353
19123
|
const defs = document.createElementNS(SVG_NS, "defs");
|
|
@@ -18416,6 +19186,10 @@ function renderText(item) {
|
|
|
18416
19186
|
el16.style.alignItems = "flex-end";
|
|
18417
19187
|
el16.style.whiteSpace = "pre";
|
|
18418
19188
|
el16.style.font = cssFont(item.font);
|
|
19189
|
+
if (item.font.paintDY) {
|
|
19190
|
+
const transform = el16.style.transform;
|
|
19191
|
+
el16.style.transform = `${transform ? `${transform} ` : ""}translateY(${item.font.paintDY}px)`;
|
|
19192
|
+
}
|
|
18419
19193
|
}
|
|
18420
19194
|
if (item.rtl) {
|
|
18421
19195
|
el16.style.direction = "rtl";
|
|
@@ -18425,6 +19199,7 @@ function renderText(item) {
|
|
|
18425
19199
|
el16.style.lineHeight = `${boxH}px`;
|
|
18426
19200
|
el16.style.setProperty("-webkit-font-smoothing", "antialiased");
|
|
18427
19201
|
const props = item.props;
|
|
19202
|
+
if (item.font.kerning) el16.style.fontKerning = "normal";
|
|
18428
19203
|
let color = props.color && props.color !== "auto" ? props.color : "#000000";
|
|
18429
19204
|
el16.style.color = color;
|
|
18430
19205
|
if (props.underline && props.underline !== "none") {
|
|
@@ -18436,7 +19211,15 @@ function renderText(item) {
|
|
|
18436
19211
|
} else if (props.underline === "none" && item.href) {
|
|
18437
19212
|
el16.style.textDecoration = "none";
|
|
18438
19213
|
}
|
|
18439
|
-
|
|
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
|
+
}
|
|
18440
19223
|
if (props.textScale && props.textScale !== 1 && !item.mathScaleY) {
|
|
18441
19224
|
el16.style.transform = `scaleX(${props.textScale})`;
|
|
18442
19225
|
el16.style.transformOrigin = "0 50%";
|
|
@@ -18465,8 +19248,7 @@ function renderText(item) {
|
|
|
18465
19248
|
el16.style.transform = `rotate(${item.rotate.deg}deg)${prev ? " " + prev : ""}`;
|
|
18466
19249
|
el16.style.transformOrigin = `${item.rotate.ox}px ${item.rotate.oy}px`;
|
|
18467
19250
|
}
|
|
18468
|
-
|
|
18469
|
-
else if (item.front) el16.style.zIndex = "1";
|
|
19251
|
+
setItemLayer(el16, item);
|
|
18470
19252
|
return el16;
|
|
18471
19253
|
}
|
|
18472
19254
|
function renderEdge(x1, y1, x2, y2, border, rotate) {
|
|
@@ -18479,13 +19261,47 @@ function renderEdge(x1, y1, x2, y2, border, rotate) {
|
|
|
18479
19261
|
}
|
|
18480
19262
|
const horizontal = Math.abs(y2 - y1) < 0.01;
|
|
18481
19263
|
const dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
|
|
18482
|
-
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);
|
|
18483
19268
|
const snap = (v) => Math.round(v * dpr) / dpr;
|
|
18484
|
-
const place = border.space === 0 ? snap : (v) => v;
|
|
19269
|
+
const place = border.space === 0 && !deviceHairline ? snap : (v) => v;
|
|
18485
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
|
+
}
|
|
18486
19302
|
if (horizontal) {
|
|
18487
19303
|
el16.style.left = `${Math.min(x1, x2)}px`;
|
|
18488
|
-
el16.style.top = `${place(y1 - w / 2)}px`;
|
|
19304
|
+
el16.style.top = `${place(y1 - w / 2 - (ultraThin ? 0.4 : 0))}px`;
|
|
18489
19305
|
el16.style.width = `${Math.abs(x2 - x1)}px`;
|
|
18490
19306
|
if (border.style === "double") {
|
|
18491
19307
|
el16.style.height = `${w * 3}px`;
|
|
@@ -18493,11 +19309,20 @@ function renderEdge(x1, y1, x2, y2, border, rotate) {
|
|
|
18493
19309
|
} else if (dashPattern) {
|
|
18494
19310
|
const on = Math.max(dashPattern[0] * border.width, 2);
|
|
18495
19311
|
const period = on + Math.max(dashPattern[1] * border.width, 1);
|
|
18496
|
-
el16.style.height = `${w}px`;
|
|
19312
|
+
el16.style.height = `${w < 1 && rotate === void 0 ? 1 : w}px`;
|
|
18497
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
|
+
}
|
|
18498
19318
|
} else if (border.style === "triple") {
|
|
18499
19319
|
el16.style.height = "0";
|
|
18500
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";
|
|
18501
19326
|
} else {
|
|
18502
19327
|
el16.style.height = `${w}px`;
|
|
18503
19328
|
el16.style.background = border.color;
|
|
@@ -18512,11 +19337,20 @@ function renderEdge(x1, y1, x2, y2, border, rotate) {
|
|
|
18512
19337
|
} else if (dashPattern) {
|
|
18513
19338
|
const on = Math.max(dashPattern[0] * border.width, 2);
|
|
18514
19339
|
const period = on + Math.max(dashPattern[1] * border.width, 1);
|
|
18515
|
-
el16.style.width = `${w}px`;
|
|
19340
|
+
el16.style.width = `${w < 1 && rotate === void 0 ? 1 : w}px`;
|
|
18516
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
|
+
}
|
|
18517
19346
|
} else if (border.style === "triple") {
|
|
18518
19347
|
el16.style.width = "0";
|
|
18519
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";
|
|
18520
19354
|
} else {
|
|
18521
19355
|
el16.style.width = `${w}px`;
|
|
18522
19356
|
el16.style.background = border.color;
|
|
@@ -20700,23 +21534,44 @@ function insertShapeAt(doc, caretT, preset, text = "") {
|
|
|
20700
21534
|
if (!caretRun || !parent || localName(caretRun.name) !== "r") return null;
|
|
20701
21535
|
const w = prefixOf8(caretRun);
|
|
20702
21536
|
const id = String(doc.nextDrawingId());
|
|
20703
|
-
const
|
|
20704
|
-
const
|
|
21537
|
+
const isLine = preset === "line";
|
|
21538
|
+
const width = isLine ? 240 : preset === "textBox" ? 240 : 192;
|
|
21539
|
+
const height = isLine ? 2 : preset === "textBox" ? 72 : 96;
|
|
20705
21540
|
const cx = String(Math.round(width * EMU_PER_PX4));
|
|
20706
21541
|
const cy = String(Math.round(height * EMU_PER_PX4));
|
|
20707
21542
|
const geometry = preset === "roundedRectangle" ? "roundRect" : preset === "rectangle" || preset === "textBox" ? "rect" : preset;
|
|
20708
21543
|
const isTextBox = preset === "textBox";
|
|
20709
|
-
const shapeName = isTextBox ? `Text Box ${id}` : `Shape ${id}`;
|
|
21544
|
+
const shapeName = isLine ? `Line ${id}` : isTextBox ? `Text Box ${id}` : `Shape ${id}`;
|
|
20710
21545
|
const spPr = [
|
|
20711
|
-
el6("a:xfrm", {}, [
|
|
21546
|
+
el6("a:xfrm", {}, [
|
|
21547
|
+
el6("a:off", { x: "0", y: "0" }),
|
|
21548
|
+
el6("a:ext", { cx, cy })
|
|
21549
|
+
]),
|
|
20712
21550
|
el6("a:prstGeom", { prst: geometry }, [el6("a:avLst")]),
|
|
20713
|
-
isTextBox ? el6("a:noFill") : el6("a:solidFill", {}, [el6("a:srgbClr", { val: "4472C4" })]),
|
|
20714
|
-
el6("a:ln", { w: "12700" }, [el6("a:solidFill", {}, [el6("a:srgbClr", { val: isTextBox ? "404040" : "2F5597" })])])
|
|
21551
|
+
isTextBox || isLine ? el6("a:noFill") : el6("a:solidFill", {}, [el6("a:srgbClr", { val: "4472C4" })]),
|
|
21552
|
+
el6("a:ln", { w: "12700" }, [el6("a:solidFill", {}, [el6("a:srgbClr", { val: isTextBox || isLine ? "404040" : "2F5597" })])])
|
|
20715
21553
|
];
|
|
20716
21554
|
const textRun = el6(`${w}r`, {}, [
|
|
20717
21555
|
el6(`${w}rPr`, {}, [el6(`${w}color`, { [`${w}val`]: isTextBox ? "202124" : "FFFFFF" }), el6(`${w}sz`, { [`${w}val`]: "22" })]),
|
|
20718
21556
|
el6(`${w}t`, { "xml:space": "preserve" }, [], text)
|
|
20719
21557
|
]);
|
|
21558
|
+
const shapeChildren = isLine ? [
|
|
21559
|
+
el6("wps:cNvCnPr", {}, [el6("a:cxnSpLocks", { noChangeShapeType: "1" })]),
|
|
21560
|
+
el6("wps:spPr", { bwMode: "auto" }, spPr),
|
|
21561
|
+
el6("wps:bodyPr")
|
|
21562
|
+
] : [
|
|
21563
|
+
el6("wps:cNvSpPr", isTextBox ? { txBox: "1" } : {}),
|
|
21564
|
+
el6("wps:spPr", {}, spPr),
|
|
21565
|
+
el6("wps:txbx", {}, [
|
|
21566
|
+
el6(`${w}txbxContent`, {}, [
|
|
21567
|
+
el6(`${w}p`, {}, [
|
|
21568
|
+
el6(`${w}pPr`, {}, [el6(`${w}jc`, { [`${w}val`]: isTextBox ? "left" : "center" })]),
|
|
21569
|
+
textRun
|
|
21570
|
+
])
|
|
21571
|
+
])
|
|
21572
|
+
]),
|
|
21573
|
+
el6("wps:bodyPr", { rot: "0", anchor: isTextBox ? "t" : "ctr" }, [el6("a:noAutofit")])
|
|
21574
|
+
];
|
|
20720
21575
|
const drawing = el6(`${w}drawing`, {}, [
|
|
20721
21576
|
el6("wp:anchor", {
|
|
20722
21577
|
"xmlns:wp": NS_WP3,
|
|
@@ -20736,24 +21591,12 @@ function insertShapeAt(doc, caretT, preset, text = "") {
|
|
|
20736
21591
|
el6("wp:positionV", { relativeFrom: "paragraph" }, [el6("wp:posOffset", {}, [], "0")]),
|
|
20737
21592
|
el6("wp:extent", { cx, cy }),
|
|
20738
21593
|
el6("wp:effectExtent", { l: "0", t: "0", r: "0", b: "0" }),
|
|
20739
|
-
el6("wp:wrapSquare", { wrapText: "bothSides" }),
|
|
21594
|
+
isLine ? el6("wp:wrapNone") : el6("wp:wrapSquare", { wrapText: "bothSides" }),
|
|
20740
21595
|
el6("wp:docPr", { id, name: shapeName }),
|
|
20741
21596
|
el6("wp:cNvGraphicFramePr"),
|
|
20742
21597
|
el6("a:graphic", { "xmlns:a": NS_A3 }, [
|
|
20743
21598
|
el6("a:graphicData", { uri: NS_WPS }, [
|
|
20744
|
-
el6("wps:wsp", { "xmlns:wps": NS_WPS },
|
|
20745
|
-
el6("wps:cNvSpPr", { txBox: "1" }),
|
|
20746
|
-
el6("wps:spPr", {}, spPr),
|
|
20747
|
-
el6("wps:txbx", {}, [
|
|
20748
|
-
el6(`${w}txbxContent`, {}, [
|
|
20749
|
-
el6(`${w}p`, {}, [
|
|
20750
|
-
el6(`${w}pPr`, {}, [el6(`${w}jc`, { [`${w}val`]: isTextBox ? "left" : "center" })]),
|
|
20751
|
-
textRun
|
|
20752
|
-
])
|
|
20753
|
-
])
|
|
20754
|
-
]),
|
|
20755
|
-
el6("wps:bodyPr", { rot: "0", anchor: isTextBox ? "t" : "ctr" }, [el6("a:noAutofit")])
|
|
20756
|
-
])
|
|
21599
|
+
el6("wps:wsp", { "xmlns:wps": NS_WPS }, shapeChildren)
|
|
20757
21600
|
])
|
|
20758
21601
|
])
|
|
20759
21602
|
])
|
|
@@ -20815,6 +21658,25 @@ function setDrawingWordArtText(doc, drawing, text) {
|
|
|
20815
21658
|
doc.refresh();
|
|
20816
21659
|
return true;
|
|
20817
21660
|
}
|
|
21661
|
+
function drawingLineStyle(drawing) {
|
|
21662
|
+
const line2 = descendant3(drawing, "ln");
|
|
21663
|
+
if (!line2) return null;
|
|
21664
|
+
const color = descendant3(line2, "srgbClr")?.attrs.val ?? "000000";
|
|
21665
|
+
const width = Math.max((parseInt(line2.attrs.w ?? "0", 10) || 0) / EMU_PER_PX4, 0.75);
|
|
21666
|
+
return { color: `#${color.toUpperCase()}`, width };
|
|
21667
|
+
}
|
|
21668
|
+
function setDrawingLineStyle(doc, drawing, color, widthPx) {
|
|
21669
|
+
const line2 = descendant3(drawing, "ln");
|
|
21670
|
+
if (!line2) return false;
|
|
21671
|
+
line2.attrs.w = String(Math.max(1, Math.round(widthPx * EMU_PER_PX4)));
|
|
21672
|
+
line2.children = line2.children.filter((child4) => {
|
|
21673
|
+
const name = localName(child4.name);
|
|
21674
|
+
return name !== "solidFill" && name !== "noFill";
|
|
21675
|
+
});
|
|
21676
|
+
line2.children.unshift(el6("a:solidFill", {}, [el6("a:srgbClr", { val: color.replace(/^#/, "").toUpperCase() })]));
|
|
21677
|
+
doc.refresh();
|
|
21678
|
+
return true;
|
|
21679
|
+
}
|
|
20818
21680
|
function insertInkAt(doc, caretT, points, color = "#202124", widthPx = 2, opacity = 1, refreshModel = true) {
|
|
20819
21681
|
if (points.length < 2) return null;
|
|
20820
21682
|
const caretRun = doc.findParentOf(caretT);
|
|
@@ -21223,11 +22085,116 @@ function deleteWatermark(doc, shapeEl) {
|
|
|
21223
22085
|
return true;
|
|
21224
22086
|
}
|
|
21225
22087
|
|
|
21226
|
-
// ../core/src/edit/
|
|
21227
|
-
var
|
|
21228
|
-
|
|
21229
|
-
|
|
21230
|
-
|
|
22088
|
+
// ../core/src/edit/dialog.ts
|
|
22089
|
+
var dialogSequence = 0;
|
|
22090
|
+
function requestTextInputDialog(anchor, options) {
|
|
22091
|
+
const doc = anchor.ownerDocument;
|
|
22092
|
+
const win = doc.defaultView;
|
|
22093
|
+
return new Promise((resolve) => {
|
|
22094
|
+
const id = `dxw-input-dialog-${++dialogSequence}`;
|
|
22095
|
+
const previousFocus = doc.activeElement instanceof HTMLElement ? doc.activeElement : null;
|
|
22096
|
+
const backdrop = doc.createElement("div");
|
|
22097
|
+
backdrop.className = "dxw-input-dialog-backdrop";
|
|
22098
|
+
backdrop.dataset.dxwInputDialog = "";
|
|
22099
|
+
backdrop.style.cssText = "position:fixed;inset:0;z-index:var(--dxw-dialog-z-index,1000);display:grid;place-items:center;padding:16px;box-sizing:border-box;background:var(--dxw-dialog-backdrop,rgba(32,33,36,.38));";
|
|
22100
|
+
if (win) {
|
|
22101
|
+
const computed = win.getComputedStyle(anchor);
|
|
22102
|
+
for (const property of [
|
|
22103
|
+
"--dxw-toolbar-fg",
|
|
22104
|
+
"--dxw-toolbar-border",
|
|
22105
|
+
"--dxw-toolbar-muted",
|
|
22106
|
+
"--dxw-accent",
|
|
22107
|
+
"--dxw-accent-fg",
|
|
22108
|
+
"--dxw-popover-bg",
|
|
22109
|
+
"--dxw-popover-shadow",
|
|
22110
|
+
"--dxw-dialog-backdrop",
|
|
22111
|
+
"--dxw-dialog-z-index",
|
|
22112
|
+
"--dxw-dialog-width",
|
|
22113
|
+
"--dxw-dialog-radius",
|
|
22114
|
+
"--dxw-dialog-field-bg"
|
|
22115
|
+
]) {
|
|
22116
|
+
const value = computed.getPropertyValue(property);
|
|
22117
|
+
if (value) backdrop.style.setProperty(property, value);
|
|
22118
|
+
}
|
|
22119
|
+
}
|
|
22120
|
+
const form = doc.createElement("form");
|
|
22121
|
+
form.className = "dxw-input-dialog";
|
|
22122
|
+
form.setAttribute("role", "dialog");
|
|
22123
|
+
form.setAttribute("aria-modal", "true");
|
|
22124
|
+
form.setAttribute("aria-labelledby", id);
|
|
22125
|
+
form.style.cssText = "width:min(var(--dxw-dialog-width,420px),calc(100vw - 32px));box-sizing:border-box;display:grid;gap:10px;padding:16px;border:1px solid var(--dxw-toolbar-border,#dadce0);border-radius:var(--dxw-dialog-radius,10px);color:var(--dxw-toolbar-fg,#3c4043);background:var(--dxw-popover-bg,#fff);box-shadow:var(--dxw-popover-shadow,0 8px 28px rgba(0,0,0,.24));font:13px system-ui,sans-serif;";
|
|
22126
|
+
const title = doc.createElement("strong");
|
|
22127
|
+
title.id = id;
|
|
22128
|
+
title.className = "dxw-input-dialog-title";
|
|
22129
|
+
title.textContent = options.title;
|
|
22130
|
+
title.style.cssText = "font-size:15px;line-height:1.35;";
|
|
22131
|
+
form.appendChild(title);
|
|
22132
|
+
const label = doc.createElement("label");
|
|
22133
|
+
label.className = "dxw-input-dialog-label";
|
|
22134
|
+
label.textContent = options.label ?? options.title;
|
|
22135
|
+
label.style.cssText = "display:grid;gap:5px;color:var(--dxw-toolbar-muted,#5f6368);font-size:12px;";
|
|
22136
|
+
const field = options.multiline ? doc.createElement("textarea") : doc.createElement("input");
|
|
22137
|
+
field.className = "dxw-input-dialog-field";
|
|
22138
|
+
field.value = options.value ?? "";
|
|
22139
|
+
field.placeholder = options.placeholder ?? "";
|
|
22140
|
+
field.setAttribute("aria-label", options.label ?? options.title);
|
|
22141
|
+
if (field instanceof HTMLTextAreaElement) field.rows = 4;
|
|
22142
|
+
field.style.cssText = "width:100%;min-height:34px;box-sizing:border-box;padding:7px 9px;border:1px solid var(--dxw-toolbar-border,#dadce0);border-radius:6px;outline:none;color:var(--dxw-toolbar-fg,#3c4043);background:var(--dxw-dialog-field-bg,var(--dxw-popover-bg,#fff));font:13px system-ui,sans-serif;resize:vertical;";
|
|
22143
|
+
label.appendChild(field);
|
|
22144
|
+
form.appendChild(label);
|
|
22145
|
+
const actions = doc.createElement("div");
|
|
22146
|
+
actions.className = "dxw-input-dialog-actions";
|
|
22147
|
+
actions.style.cssText = "display:flex;justify-content:flex-end;gap:7px;";
|
|
22148
|
+
const cancel = doc.createElement("button");
|
|
22149
|
+
cancel.type = "button";
|
|
22150
|
+
cancel.className = "dxw-input-dialog-cancel";
|
|
22151
|
+
cancel.textContent = "Cancel";
|
|
22152
|
+
cancel.style.cssText = "min-height:32px;padding:0 12px;border:1px solid var(--dxw-toolbar-border,#dadce0);border-radius:7px;color:var(--dxw-toolbar-fg,#3c4043);background:var(--dxw-popover-bg,#fff);cursor:pointer;font:600 12px system-ui,sans-serif;";
|
|
22153
|
+
const submit = doc.createElement("button");
|
|
22154
|
+
submit.type = "submit";
|
|
22155
|
+
submit.className = "dxw-input-dialog-submit";
|
|
22156
|
+
submit.textContent = options.submitLabel ?? "Apply";
|
|
22157
|
+
submit.style.cssText = "min-height:32px;padding:0 14px;border:1px solid transparent;border-radius:7px;color:var(--dxw-accent-fg,#fff);background:var(--dxw-accent,#1a73e8);cursor:pointer;font:600 12px system-ui,sans-serif;";
|
|
22158
|
+
actions.append(cancel, submit);
|
|
22159
|
+
form.appendChild(actions);
|
|
22160
|
+
backdrop.appendChild(form);
|
|
22161
|
+
doc.body.appendChild(backdrop);
|
|
22162
|
+
let finished = false;
|
|
22163
|
+
const finish = (value) => {
|
|
22164
|
+
if (finished) return;
|
|
22165
|
+
finished = true;
|
|
22166
|
+
doc.removeEventListener("keydown", onKeyDown, true);
|
|
22167
|
+
backdrop.remove();
|
|
22168
|
+
previousFocus?.focus({ preventScroll: true });
|
|
22169
|
+
resolve(value);
|
|
22170
|
+
};
|
|
22171
|
+
const onKeyDown = (event) => {
|
|
22172
|
+
if (event.key === "Escape") {
|
|
22173
|
+
event.preventDefault();
|
|
22174
|
+
finish(null);
|
|
22175
|
+
}
|
|
22176
|
+
};
|
|
22177
|
+
doc.addEventListener("keydown", onKeyDown, true);
|
|
22178
|
+
backdrop.addEventListener("mousedown", (event) => {
|
|
22179
|
+
if (event.target === backdrop) finish(null);
|
|
22180
|
+
});
|
|
22181
|
+
cancel.addEventListener("click", () => finish(null));
|
|
22182
|
+
form.addEventListener("submit", (event) => {
|
|
22183
|
+
event.preventDefault();
|
|
22184
|
+
finish(field.value);
|
|
22185
|
+
});
|
|
22186
|
+
requestAnimationFrame(() => {
|
|
22187
|
+
field.focus({ preventScroll: true });
|
|
22188
|
+
field.select();
|
|
22189
|
+
});
|
|
22190
|
+
});
|
|
22191
|
+
}
|
|
22192
|
+
|
|
22193
|
+
// ../core/src/edit/grapheme.ts
|
|
22194
|
+
var segmenter = null;
|
|
22195
|
+
var segmenterTried = false;
|
|
22196
|
+
function getSegmenter() {
|
|
22197
|
+
if (segmenterTried) return segmenter;
|
|
21231
22198
|
segmenterTried = true;
|
|
21232
22199
|
try {
|
|
21233
22200
|
const ctor = Intl.Segmenter;
|
|
@@ -21936,6 +22903,7 @@ var _DocxEditor = class _DocxEditor {
|
|
|
21936
22903
|
* snapshot that the following text insertion belongs to. */
|
|
21937
22904
|
this.pendingClickTypeCheckpoint = false;
|
|
21938
22905
|
this.clickTypeCheckpointUntil = 0;
|
|
22906
|
+
this.textContextMenu = null;
|
|
21939
22907
|
/** True while a drag-selection is in progress (checked by onMouseUp, which
|
|
21940
22908
|
* bubbles from the container BEFORE the document-level drag-end listener). */
|
|
21941
22909
|
this.dragSelecting = false;
|
|
@@ -22325,6 +23293,102 @@ var _DocxEditor = class _DocxEditor {
|
|
|
22325
23293
|
};
|
|
22326
23294
|
/** Which part tree the element lives in: document body or header/footer. */
|
|
22327
23295
|
this.mathEditorEl = null;
|
|
23296
|
+
this.dismissTextContextMenu = () => {
|
|
23297
|
+
this.textContextMenu?.remove();
|
|
23298
|
+
this.textContextMenu = null;
|
|
23299
|
+
document.removeEventListener("mousedown", this.onContextMenuDocumentMouseDown);
|
|
23300
|
+
};
|
|
23301
|
+
this.onContextMenuDocumentMouseDown = (event) => {
|
|
23302
|
+
if (!this.textContextMenu?.contains(event.target)) this.dismissTextContextMenu();
|
|
23303
|
+
};
|
|
23304
|
+
this.onContextMenu = (event) => {
|
|
23305
|
+
const target = event.target;
|
|
23306
|
+
if (!target?.closest('[data-dxw-item-kind="text"]')) return;
|
|
23307
|
+
const caret = this.caretFromPoint(event.clientX, event.clientY);
|
|
23308
|
+
if (!caret || this.regionOf(caret.t) === "hf" !== this.inHeaderFooter) return;
|
|
23309
|
+
event.preventDefault();
|
|
23310
|
+
event.stopPropagation();
|
|
23311
|
+
this.dismissTextContextMenu();
|
|
23312
|
+
if (!this.hasSelection()) {
|
|
23313
|
+
this.caret = caret;
|
|
23314
|
+
this.selectWordAt(caret);
|
|
23315
|
+
}
|
|
23316
|
+
const menu = document.createElement("div");
|
|
23317
|
+
menu.dataset.dxwTextContextMenu = "1";
|
|
23318
|
+
menu.setAttribute("role", "menu");
|
|
23319
|
+
menu.style.cssText = `position:fixed;left:${event.clientX}px;top:${event.clientY}px;z-index:2147483647;min-width:210px;padding:5px;background:#fff;border:1px solid #dadce0;border-radius:8px;box-shadow:0 4px 18px rgba(0,0,0,.2);font:13px system-ui,sans-serif;color:#202124;`;
|
|
23320
|
+
const isApplePlatform = /Mac|iPhone|iPad/.test(navigator.platform);
|
|
23321
|
+
const mod = isApplePlatform ? "\u2318" : "Ctrl+";
|
|
23322
|
+
const item = (label, shortcut, disabled, action) => {
|
|
23323
|
+
const button = document.createElement("button");
|
|
23324
|
+
button.type = "button";
|
|
23325
|
+
button.disabled = disabled;
|
|
23326
|
+
button.setAttribute("role", "menuitem");
|
|
23327
|
+
button.style.cssText = `display:flex;width:100%;align-items:center;justify-content:space-between;gap:24px;border:0;border-radius:5px;padding:7px 9px;background:transparent;color:${disabled ? "#9aa0a6" : "#202124"};cursor:${disabled ? "default" : "pointer"};`;
|
|
23328
|
+
const name = document.createElement("span");
|
|
23329
|
+
name.textContent = label;
|
|
23330
|
+
const keys = document.createElement("span");
|
|
23331
|
+
keys.textContent = shortcut;
|
|
23332
|
+
keys.style.color = "#5f6368";
|
|
23333
|
+
keys.style.fontSize = "11px";
|
|
23334
|
+
button.append(name, keys);
|
|
23335
|
+
button.addEventListener("mouseenter", () => {
|
|
23336
|
+
if (!button.disabled) button.style.background = "#f1f3f4";
|
|
23337
|
+
});
|
|
23338
|
+
button.addEventListener("mouseleave", () => {
|
|
23339
|
+
button.style.background = "transparent";
|
|
23340
|
+
});
|
|
23341
|
+
button.addEventListener("click", () => {
|
|
23342
|
+
if (button.disabled) return;
|
|
23343
|
+
this.dismissTextContextMenu();
|
|
23344
|
+
action();
|
|
23345
|
+
});
|
|
23346
|
+
menu.appendChild(button);
|
|
23347
|
+
};
|
|
23348
|
+
const separator = () => {
|
|
23349
|
+
const line2 = document.createElement("div");
|
|
23350
|
+
line2.style.cssText = "height:1px;background:#e8eaed;margin:4px 2px;";
|
|
23351
|
+
menu.appendChild(line2);
|
|
23352
|
+
};
|
|
23353
|
+
const selectedText = selectionTextLogical(this.host.doc, this.getSelectionSegments());
|
|
23354
|
+
const clipboard = navigator.clipboard;
|
|
23355
|
+
const copy = () => clipboard.writeText(selectedText);
|
|
23356
|
+
item("Copy", `${mod}C`, !selectedText || !clipboard?.writeText, () => void copy());
|
|
23357
|
+
item("Cut", `${mod}X`, !selectedText || !clipboard?.writeText, () => {
|
|
23358
|
+
void copy().then(() => {
|
|
23359
|
+
this.host.history?.checkpoint();
|
|
23360
|
+
this.removeSelectedText();
|
|
23361
|
+
this.commit();
|
|
23362
|
+
});
|
|
23363
|
+
});
|
|
23364
|
+
item("Paste", `${mod}V`, !clipboard?.readText, () => {
|
|
23365
|
+
void clipboard.readText().then((text) => {
|
|
23366
|
+
if (text) this.insertText(text);
|
|
23367
|
+
});
|
|
23368
|
+
});
|
|
23369
|
+
separator();
|
|
23370
|
+
item("Bold", `${mod}B`, !selectedText, () => this.host.onFormatShortcut?.("bold"));
|
|
23371
|
+
item("Italic", `${mod}I`, !selectedText, () => this.host.onFormatShortcut?.("italic"));
|
|
23372
|
+
item("Underline", `${mod}U`, !selectedText, () => this.host.onFormatShortcut?.("underline"));
|
|
23373
|
+
separator();
|
|
23374
|
+
item("Link\u2026", `${mod}K`, !selectedText, () => this.host.onTextCommand?.("link"));
|
|
23375
|
+
item("New comment\u2026", isApplePlatform ? "\u2318\u2325A" : "Ctrl+Alt+M", !selectedText, () => this.host.onTextCommand?.("comment"));
|
|
23376
|
+
item("Bulleted list", `${mod}Shift+L`, false, () => this.host.onTextCommand?.("bullet"));
|
|
23377
|
+
item("Numbered list", `${mod}Shift+7`, false, () => this.host.onTextCommand?.("number"));
|
|
23378
|
+
separator();
|
|
23379
|
+
item("Align left", `${mod}L`, false, () => this.host.onTextCommand?.("alignLeft"));
|
|
23380
|
+
item("Center", `${mod}E`, false, () => this.host.onTextCommand?.("alignCenter"));
|
|
23381
|
+
item("Align right", `${mod}R`, false, () => this.host.onTextCommand?.("alignRight"));
|
|
23382
|
+
item("Justify", `${mod}J`, false, () => this.host.onTextCommand?.("justify"));
|
|
23383
|
+
separator();
|
|
23384
|
+
item("Select all", `${mod}A`, false, () => this.selectAll());
|
|
23385
|
+
document.body.appendChild(menu);
|
|
23386
|
+
const rect = menu.getBoundingClientRect();
|
|
23387
|
+
menu.style.left = `${Math.max(6, Math.min(event.clientX, window.innerWidth - rect.width - 6))}px`;
|
|
23388
|
+
menu.style.top = `${Math.max(6, Math.min(event.clientY, window.innerHeight - rect.height - 6))}px`;
|
|
23389
|
+
this.textContextMenu = menu;
|
|
23390
|
+
setTimeout(() => document.addEventListener("mousedown", this.onContextMenuDocumentMouseDown), 0);
|
|
23391
|
+
};
|
|
22328
23392
|
// ---------- keyboard ----------
|
|
22329
23393
|
this.onKeyDown = (e) => {
|
|
22330
23394
|
if (this.composing || e.isComposing || e.keyCode === 229) return;
|
|
@@ -22332,6 +23396,11 @@ var _DocxEditor = class _DocxEditor {
|
|
|
22332
23396
|
this.pendingClickTypeCheckpoint = false;
|
|
22333
23397
|
this.clickTypeCheckpointUntil = 0;
|
|
22334
23398
|
}
|
|
23399
|
+
if (this.textContextMenu) {
|
|
23400
|
+
if (e.key === "Escape") e.preventDefault();
|
|
23401
|
+
this.dismissTextContextMenu();
|
|
23402
|
+
if (e.key === "Escape") return;
|
|
23403
|
+
}
|
|
22335
23404
|
if (e.key === "Escape" && this.drawingTool) {
|
|
22336
23405
|
e.preventDefault();
|
|
22337
23406
|
this.setDrawingTool(null);
|
|
@@ -22446,6 +23515,12 @@ var _DocxEditor = class _DocxEditor {
|
|
|
22446
23515
|
}
|
|
22447
23516
|
}
|
|
22448
23517
|
const meta = e.metaKey || e.ctrlKey;
|
|
23518
|
+
const isApplePlatform = /Mac|iPhone|iPad/.test(navigator.platform);
|
|
23519
|
+
if (isApplePlatform ? e.metaKey && e.altKey && e.key.toLowerCase() === "a" : e.ctrlKey && e.altKey && e.key.toLowerCase() === "m") {
|
|
23520
|
+
e.preventDefault();
|
|
23521
|
+
if (this.hasSelection()) this.host.onTextCommand?.("comment");
|
|
23522
|
+
return;
|
|
23523
|
+
}
|
|
22449
23524
|
if (meta && e.altKey && /^[0-6]$/.test(e.key)) {
|
|
22450
23525
|
e.preventDefault();
|
|
22451
23526
|
this.host.onStyleShortcut?.(e.key === "0" ? null : `Heading${e.key}`);
|
|
@@ -22465,6 +23540,28 @@ var _DocxEditor = class _DocxEditor {
|
|
|
22465
23540
|
}
|
|
22466
23541
|
return;
|
|
22467
23542
|
}
|
|
23543
|
+
if (!e.shiftKey && k === "k") {
|
|
23544
|
+
e.preventDefault();
|
|
23545
|
+
if (this.hasSelection()) this.host.onTextCommand?.("link");
|
|
23546
|
+
return;
|
|
23547
|
+
}
|
|
23548
|
+
if (e.shiftKey && (k === "l" || k === "8")) {
|
|
23549
|
+
e.preventDefault();
|
|
23550
|
+
this.host.onTextCommand?.("bullet");
|
|
23551
|
+
return;
|
|
23552
|
+
}
|
|
23553
|
+
if (e.shiftKey && k === "7") {
|
|
23554
|
+
e.preventDefault();
|
|
23555
|
+
this.host.onTextCommand?.("number");
|
|
23556
|
+
return;
|
|
23557
|
+
}
|
|
23558
|
+
if (!e.shiftKey && (k === "l" || k === "e" || k === "r" || k === "j")) {
|
|
23559
|
+
e.preventDefault();
|
|
23560
|
+
this.host.onTextCommand?.(
|
|
23561
|
+
k === "l" ? "alignLeft" : k === "e" ? "alignCenter" : k === "r" ? "alignRight" : "justify"
|
|
23562
|
+
);
|
|
23563
|
+
return;
|
|
23564
|
+
}
|
|
22468
23565
|
if (e.key.startsWith("Arrow")) {
|
|
22469
23566
|
e.preventDefault();
|
|
22470
23567
|
const extend = e.shiftKey;
|
|
@@ -23100,6 +24197,7 @@ var _DocxEditor = class _DocxEditor {
|
|
|
23100
24197
|
c.addEventListener("copy", this.onCopy);
|
|
23101
24198
|
c.addEventListener("cut", this.onCut);
|
|
23102
24199
|
c.addEventListener("paste", this.onPaste);
|
|
24200
|
+
c.addEventListener("contextmenu", this.onContextMenu);
|
|
23103
24201
|
c.addEventListener("dragover", this.onDragOver);
|
|
23104
24202
|
c.addEventListener("drop", this.onDrop);
|
|
23105
24203
|
this.applyHfChrome();
|
|
@@ -23119,8 +24217,10 @@ var _DocxEditor = class _DocxEditor {
|
|
|
23119
24217
|
c.removeEventListener("copy", this.onCopy);
|
|
23120
24218
|
c.removeEventListener("cut", this.onCut);
|
|
23121
24219
|
c.removeEventListener("paste", this.onPaste);
|
|
24220
|
+
c.removeEventListener("contextmenu", this.onContextMenu);
|
|
23122
24221
|
c.removeEventListener("dragover", this.onDragOver);
|
|
23123
24222
|
c.removeEventListener("drop", this.onDrop);
|
|
24223
|
+
this.dismissTextContextMenu();
|
|
23124
24224
|
this.dismissSuggestionPopover();
|
|
23125
24225
|
this.setDrawingTool(null);
|
|
23126
24226
|
this.deselectInkGroup();
|
|
@@ -23990,23 +25090,73 @@ var _DocxEditor = class _DocxEditor {
|
|
|
23990
25090
|
};
|
|
23991
25091
|
extra("Alt", "Alternative text", () => {
|
|
23992
25092
|
const cur = imageAltText(src);
|
|
23993
|
-
|
|
23994
|
-
|
|
23995
|
-
|
|
23996
|
-
|
|
23997
|
-
|
|
25093
|
+
void requestTextInputDialog(this.host.container, {
|
|
25094
|
+
title: "Alternative text",
|
|
25095
|
+
label: "Describe this object for screen readers",
|
|
25096
|
+
value: cur
|
|
25097
|
+
}).then((next) => {
|
|
25098
|
+
if (next === null) return;
|
|
25099
|
+
this.host.history?.checkpoint();
|
|
25100
|
+
if (setImageAltText(this.host.doc, src, next)) this.host.rerender();
|
|
25101
|
+
this.deselectImage();
|
|
25102
|
+
});
|
|
23998
25103
|
});
|
|
23999
25104
|
extra("Size", "Exact size (px)", () => {
|
|
24000
25105
|
const curW = parseFloat(el16.style.width) || 0;
|
|
24001
25106
|
const curH = parseFloat(el16.style.height) || 0;
|
|
24002
25107
|
const cur = `${Math.round(curW)}x${Math.round(curH)}`;
|
|
24003
|
-
|
|
24004
|
-
|
|
24005
|
-
|
|
24006
|
-
|
|
24007
|
-
|
|
24008
|
-
|
|
25108
|
+
void requestTextInputDialog(this.host.container, {
|
|
25109
|
+
title: "Exact size",
|
|
25110
|
+
label: "Width \xD7 height in pixels",
|
|
25111
|
+
value: cur,
|
|
25112
|
+
placeholder: "640 \xD7 360"
|
|
25113
|
+
}).then((next) => {
|
|
25114
|
+
const match = next && /^\s*(\d+)\s*[x×]\s*(\d+)\s*$/i.exec(next);
|
|
25115
|
+
if (!match) return;
|
|
25116
|
+
this.host.history?.checkpoint();
|
|
25117
|
+
if (resizeDrawing(this.host.doc, src, parseInt(match[1], 10), parseInt(match[2], 10))) this.host.rerender();
|
|
25118
|
+
this.deselectImage();
|
|
25119
|
+
});
|
|
25120
|
+
});
|
|
25121
|
+
extra("Position", "Exact page position (px)", () => {
|
|
25122
|
+
const curX = parseFloat(el16.style.left) || 0;
|
|
25123
|
+
const curY = parseFloat(el16.style.top) || 0;
|
|
25124
|
+
void requestTextInputDialog(this.host.container, {
|
|
25125
|
+
title: "Page position",
|
|
25126
|
+
label: "X, Y in pixels",
|
|
25127
|
+
value: `${Math.round(curX)}, ${Math.round(curY)}`,
|
|
25128
|
+
placeholder: "120, 80"
|
|
25129
|
+
}).then((next) => {
|
|
25130
|
+
const match = next && /^\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*$/.exec(next);
|
|
25131
|
+
if (!match) return;
|
|
25132
|
+
this.host.history?.checkpoint();
|
|
25133
|
+
if (!isFloatingDrawing(src)) setImageWrap(this.host.doc, src, "square", { x: 0, y: 0 });
|
|
25134
|
+
if (setFloatingPagePosition(this.host.doc, src, parseFloat(match[1]), parseFloat(match[2]))) {
|
|
25135
|
+
this.host.rerender();
|
|
25136
|
+
this.reselectImage(src);
|
|
25137
|
+
}
|
|
25138
|
+
});
|
|
24009
25139
|
});
|
|
25140
|
+
if (kind === "drawing") {
|
|
25141
|
+
extra("Outline", "Outline color and weight", () => {
|
|
25142
|
+
const style = drawingLineStyle(src);
|
|
25143
|
+
if (!style) return;
|
|
25144
|
+
void requestTextInputDialog(this.host.container, {
|
|
25145
|
+
title: "Outline",
|
|
25146
|
+
label: "Color and width in pixels",
|
|
25147
|
+
value: `${style.color}, ${Number(style.width.toFixed(2))}`,
|
|
25148
|
+
placeholder: "#1a73e8, 1.5"
|
|
25149
|
+
}).then((next) => {
|
|
25150
|
+
const match = next && /^\s*#?([0-9a-f]{6})\s*,\s*(\d+(?:\.\d+)?)\s*$/i.exec(next);
|
|
25151
|
+
if (!match) return;
|
|
25152
|
+
this.host.history?.checkpoint();
|
|
25153
|
+
if (setDrawingLineStyle(this.host.doc, src, `#${match[1]}`, parseFloat(match[2]))) {
|
|
25154
|
+
this.host.rerender();
|
|
25155
|
+
this.reselectImage(src);
|
|
25156
|
+
}
|
|
25157
|
+
});
|
|
25158
|
+
});
|
|
25159
|
+
}
|
|
24010
25160
|
if (kind === "drawing" && isDrawingWordArt(src)) {
|
|
24011
25161
|
extra("Edit text", "Edit WordArt text", () => this.editDrawingWordArt(src));
|
|
24012
25162
|
}
|
|
@@ -24160,13 +25310,17 @@ var _DocxEditor = class _DocxEditor {
|
|
|
24160
25310
|
};
|
|
24161
25311
|
button("Edit text", "Edit watermark text", () => {
|
|
24162
25312
|
const cur = wordArtText(src);
|
|
24163
|
-
|
|
24164
|
-
|
|
24165
|
-
|
|
24166
|
-
|
|
24167
|
-
|
|
24168
|
-
this.
|
|
24169
|
-
|
|
25313
|
+
void requestTextInputDialog(this.host.container, {
|
|
25314
|
+
title: "Watermark text",
|
|
25315
|
+
value: cur
|
|
25316
|
+
}).then((next) => {
|
|
25317
|
+
if (next === null || next === cur) return;
|
|
25318
|
+
this.host.history?.checkpoint();
|
|
25319
|
+
if (setWordArtText(this.host.doc, src, next)) {
|
|
25320
|
+
this.host.rerender();
|
|
25321
|
+
this.reselectWordArt(src);
|
|
25322
|
+
}
|
|
25323
|
+
});
|
|
24170
25324
|
});
|
|
24171
25325
|
const sep1 = document.createElement("span");
|
|
24172
25326
|
sep1.style.cssText = "width:1px;background:#dadce0;margin:2px 2px;";
|
|
@@ -24178,15 +25332,20 @@ var _DocxEditor = class _DocxEditor {
|
|
|
24178
25332
|
bar.appendChild(sep2);
|
|
24179
25333
|
button("Rotate", "Set rotation (degrees)", () => {
|
|
24180
25334
|
const cur = wordArtRotation(src);
|
|
24181
|
-
|
|
24182
|
-
|
|
24183
|
-
|
|
24184
|
-
|
|
24185
|
-
|
|
24186
|
-
|
|
24187
|
-
|
|
24188
|
-
|
|
24189
|
-
|
|
25335
|
+
void requestTextInputDialog(this.host.container, {
|
|
25336
|
+
title: "Watermark rotation",
|
|
25337
|
+
label: "Degrees clockwise",
|
|
25338
|
+
value: String(cur)
|
|
25339
|
+
}).then((next) => {
|
|
25340
|
+
if (next === null) return;
|
|
25341
|
+
const degrees = parseFloat(next);
|
|
25342
|
+
if (!Number.isFinite(degrees)) return;
|
|
25343
|
+
this.host.history?.checkpoint();
|
|
25344
|
+
if (setWordArtRotation(this.host.doc, src, degrees)) {
|
|
25345
|
+
this.host.rerender();
|
|
25346
|
+
this.reselectWordArt(src);
|
|
25347
|
+
}
|
|
25348
|
+
});
|
|
24190
25349
|
});
|
|
24191
25350
|
const sep3 = document.createElement("span");
|
|
24192
25351
|
sep3.style.cssText = "width:1px;background:#dadce0;margin:2px 2px;";
|
|
@@ -25034,16 +26193,19 @@ var _DocxEditor = class _DocxEditor {
|
|
|
25034
26193
|
};
|
|
25035
26194
|
const split = this.splitParagraphCore();
|
|
25036
26195
|
if (!split) return null;
|
|
25037
|
-
const
|
|
26196
|
+
const hasPageBreak = (element) => localName(element.name) === "br" && attr(element, "type") === "page" || element.children.some(hasPageBreak);
|
|
26197
|
+
const insertBeforeTrailingBreak = hasPageBreak(split.after);
|
|
26198
|
+
const afterSources = insertBeforeTrailingBreak ? [] : [split.after];
|
|
25038
26199
|
const w = split.after.name.includes(":") ? split.after.name.slice(0, split.after.name.indexOf(":") + 1) : "";
|
|
25039
26200
|
const templatePPr = split.after.children.find((child4) => localName(child4.name) === "pPr");
|
|
25040
26201
|
const templateRun = split.after.children.find(
|
|
25041
26202
|
(child4) => localName(child4.name) === "r" && child4.children.includes(this.caret.t)
|
|
25042
26203
|
);
|
|
25043
26204
|
const templateRPr = templateRun?.children.find((child4) => localName(child4.name) === "rPr");
|
|
25044
|
-
let previous = split.after;
|
|
26205
|
+
let previous = insertBeforeTrailingBreak ? split.before : split.after;
|
|
26206
|
+
let caretSource = split.after;
|
|
25045
26207
|
for (let i = 1; i < lineCount; i++) {
|
|
25046
|
-
if (this.suggesting) markParagraphGlyph(previous, "ins", this.revMeta());
|
|
26208
|
+
if (this.suggesting && previous !== split.before) markParagraphGlyph(previous, "ins", this.revMeta());
|
|
25047
26209
|
const t = {
|
|
25048
26210
|
name: this.caret.t.name,
|
|
25049
26211
|
attrs: { ...this.caret.t.attrs, "xml:space": "preserve" },
|
|
@@ -25066,11 +26228,14 @@ var _DocxEditor = class _DocxEditor {
|
|
|
25066
26228
|
parent.children.splice(previousIndex + 1, 0, paragraph2);
|
|
25067
26229
|
afterSources.push(paragraph2);
|
|
25068
26230
|
previous = paragraph2;
|
|
26231
|
+
caretSource = paragraph2;
|
|
25069
26232
|
this.caret = { t, run: caret.run, offset: 0 };
|
|
25070
26233
|
}
|
|
26234
|
+
if (insertBeforeTrailingBreak) afterSources.push(split.after);
|
|
25071
26235
|
const reparsed = this.host.doc.reparseDirectBodyParagraphSplits(split.before, afterSources);
|
|
25072
26236
|
if (reparsed) {
|
|
25073
|
-
|
|
26237
|
+
const caretParagraph = reparsed[afterSources.indexOf(caretSource) + 1];
|
|
26238
|
+
for (const child4 of caretParagraph.children) {
|
|
25074
26239
|
const runs = child4.type === "run" ? [child4] : child4.runs;
|
|
25075
26240
|
const run = runs.find(
|
|
25076
26241
|
(candidate) => candidate.content.some((content) => content.kind === "text" && content.srcT === this.caret.t)
|
|
@@ -27387,7 +28552,8 @@ function detectMissingFonts(layout) {
|
|
|
27387
28552
|
for (const page of layout.pages) {
|
|
27388
28553
|
for (const item of page.items) {
|
|
27389
28554
|
if (item.kind !== "text" || !item.text.trim()) continue;
|
|
27390
|
-
const
|
|
28555
|
+
const requested = item.font.family.split(",")[0].trim().replace(/^"|"$/g, "");
|
|
28556
|
+
const primary = normalizeFamily(requested, item.font.bold, item.font.italic).family;
|
|
27391
28557
|
if (!primary || GENERIC.has(primary.toLowerCase())) continue;
|
|
27392
28558
|
const existing = samples.get(primary);
|
|
27393
28559
|
if (!existing || !/[^-ɏ]/.test(existing) && /[^-ɏ]/.test(item.text)) {
|
|
@@ -27519,15 +28685,6 @@ var btnStyle = (active) => ({
|
|
|
27519
28685
|
padding: "0 5px",
|
|
27520
28686
|
color: T.fg
|
|
27521
28687
|
});
|
|
27522
|
-
var selectStyle = {
|
|
27523
|
-
height: 26,
|
|
27524
|
-
border: "1px solid transparent",
|
|
27525
|
-
background: "transparent",
|
|
27526
|
-
borderRadius: 4,
|
|
27527
|
-
fontSize: 13,
|
|
27528
|
-
color: T.fg,
|
|
27529
|
-
cursor: "pointer"
|
|
27530
|
-
};
|
|
27531
28688
|
var PAGE_SIZES = [
|
|
27532
28689
|
{ value: "letter", label: "Letter", description: '8.5" \xD7 11"', width: 8.5, height: 11 },
|
|
27533
28690
|
{ value: "legal", label: "Legal", description: '8.5" \xD7 14"', width: 8.5, height: 14 },
|
|
@@ -27631,6 +28788,264 @@ function HighlightIcon({ color }) {
|
|
|
27631
28788
|
/* @__PURE__ */ jsx("rect", { x: "2", y: "13.5", width: "12", height: "2.5", rx: "0.5", fill: color })
|
|
27632
28789
|
] });
|
|
27633
28790
|
}
|
|
28791
|
+
function ToolbarMenuSelect({
|
|
28792
|
+
value,
|
|
28793
|
+
options,
|
|
28794
|
+
onChange,
|
|
28795
|
+
placeholder = "Choose\u2026",
|
|
28796
|
+
title,
|
|
28797
|
+
ariaLabel,
|
|
28798
|
+
triggerAriaLabel,
|
|
28799
|
+
width,
|
|
28800
|
+
menuWidth,
|
|
28801
|
+
className,
|
|
28802
|
+
style
|
|
28803
|
+
}) {
|
|
28804
|
+
const [open, setOpen] = useState(false);
|
|
28805
|
+
const [position, setPosition] = useState({ left: 8, top: 8, width: menuWidth ?? 180, maxHeight: 320 });
|
|
28806
|
+
const rootRef = useRef(null);
|
|
28807
|
+
const triggerRef = useRef(null);
|
|
28808
|
+
const menuRef = useRef(null);
|
|
28809
|
+
const keyboardOpen = useRef(null);
|
|
28810
|
+
const id = useId();
|
|
28811
|
+
const selected = options.find((option) => option.value === value);
|
|
28812
|
+
useLayoutEffect(() => {
|
|
28813
|
+
if (!open) return;
|
|
28814
|
+
const update = () => {
|
|
28815
|
+
const trigger = triggerRef.current;
|
|
28816
|
+
if (!trigger) return;
|
|
28817
|
+
const rect = trigger.getBoundingClientRect();
|
|
28818
|
+
const nextWidth = Math.min(
|
|
28819
|
+
window.innerWidth - 16,
|
|
28820
|
+
menuWidth ?? Math.max(rect.width, menuRef.current?.scrollWidth ?? 180)
|
|
28821
|
+
);
|
|
28822
|
+
const below = window.innerHeight - rect.bottom - 8;
|
|
28823
|
+
const above = rect.top - 8;
|
|
28824
|
+
const placeAbove = below < 140 && above > below;
|
|
28825
|
+
const maxHeight = Math.max(96, Math.min(320, placeAbove ? above : below));
|
|
28826
|
+
const shownHeight = Math.min(menuRef.current?.scrollHeight ?? maxHeight, maxHeight);
|
|
28827
|
+
setPosition({
|
|
28828
|
+
left: Math.max(8, Math.min(rect.left, window.innerWidth - nextWidth - 8)),
|
|
28829
|
+
top: placeAbove ? Math.max(8, rect.top - shownHeight - 4) : rect.bottom + 4,
|
|
28830
|
+
width: nextWidth,
|
|
28831
|
+
maxHeight
|
|
28832
|
+
});
|
|
28833
|
+
};
|
|
28834
|
+
update();
|
|
28835
|
+
const frame = requestAnimationFrame(() => {
|
|
28836
|
+
update();
|
|
28837
|
+
if (!keyboardOpen.current) return;
|
|
28838
|
+
const items = menuRef.current?.querySelectorAll('[role="option"]');
|
|
28839
|
+
const item = keyboardOpen.current === "last" ? items?.[items.length - 1] : items?.[0];
|
|
28840
|
+
item?.focus({ preventScroll: true });
|
|
28841
|
+
keyboardOpen.current = null;
|
|
28842
|
+
});
|
|
28843
|
+
const close = (event) => {
|
|
28844
|
+
if (!rootRef.current?.contains(event.target)) setOpen(false);
|
|
28845
|
+
};
|
|
28846
|
+
const keydown = (event) => {
|
|
28847
|
+
if (event.key === "Escape") {
|
|
28848
|
+
setOpen(false);
|
|
28849
|
+
requestAnimationFrame(() => triggerRef.current?.focus({ preventScroll: true }));
|
|
28850
|
+
}
|
|
28851
|
+
};
|
|
28852
|
+
document.addEventListener("mousedown", close);
|
|
28853
|
+
document.addEventListener("keydown", keydown);
|
|
28854
|
+
window.addEventListener("resize", update);
|
|
28855
|
+
window.addEventListener("scroll", update, true);
|
|
28856
|
+
return () => {
|
|
28857
|
+
cancelAnimationFrame(frame);
|
|
28858
|
+
document.removeEventListener("mousedown", close);
|
|
28859
|
+
document.removeEventListener("keydown", keydown);
|
|
28860
|
+
window.removeEventListener("resize", update);
|
|
28861
|
+
window.removeEventListener("scroll", update, true);
|
|
28862
|
+
};
|
|
28863
|
+
}, [open, menuWidth]);
|
|
28864
|
+
const pick = (next) => {
|
|
28865
|
+
const option = options.find((item) => item.value === next);
|
|
28866
|
+
if (!option || option.disabled) return;
|
|
28867
|
+
onChange(next);
|
|
28868
|
+
setOpen(false);
|
|
28869
|
+
};
|
|
28870
|
+
const onMenuKeyDown = (event) => {
|
|
28871
|
+
const items = menuRef.current ? Array.from(menuRef.current.querySelectorAll('[role="option"]:not(:disabled)')) : [];
|
|
28872
|
+
const current = items.indexOf(document.activeElement);
|
|
28873
|
+
let next = current;
|
|
28874
|
+
if (event.key === "ArrowDown") next = current < 0 ? 0 : (current + 1) % items.length;
|
|
28875
|
+
else if (event.key === "ArrowUp") next = current < 0 ? items.length - 1 : (current - 1 + items.length) % items.length;
|
|
28876
|
+
else if (event.key === "Home") next = 0;
|
|
28877
|
+
else if (event.key === "End") next = items.length - 1;
|
|
28878
|
+
else if ((event.key === "Enter" || event.key === " ") && current >= 0) {
|
|
28879
|
+
event.preventDefault();
|
|
28880
|
+
items[current].click();
|
|
28881
|
+
return;
|
|
28882
|
+
} else if (event.key === "Escape" || event.key === "Tab") {
|
|
28883
|
+
event.preventDefault();
|
|
28884
|
+
setOpen(false);
|
|
28885
|
+
requestAnimationFrame(() => triggerRef.current?.focus({ preventScroll: true }));
|
|
28886
|
+
return;
|
|
28887
|
+
} else return;
|
|
28888
|
+
event.preventDefault();
|
|
28889
|
+
items[next]?.focus({ preventScroll: true });
|
|
28890
|
+
};
|
|
28891
|
+
let previousGroup;
|
|
28892
|
+
return /* @__PURE__ */ jsxs(
|
|
28893
|
+
"span",
|
|
28894
|
+
{
|
|
28895
|
+
ref: rootRef,
|
|
28896
|
+
className: `dxw-menu-select${className ? ` ${className}` : ""}`,
|
|
28897
|
+
"data-dxw-menu-select": "",
|
|
28898
|
+
style: { position: "relative", display: "inline-flex", width },
|
|
28899
|
+
children: [
|
|
28900
|
+
/* @__PURE__ */ jsxs(
|
|
28901
|
+
"select",
|
|
28902
|
+
{
|
|
28903
|
+
tabIndex: -1,
|
|
28904
|
+
title,
|
|
28905
|
+
"aria-label": ariaLabel,
|
|
28906
|
+
"aria-hidden": "true",
|
|
28907
|
+
value,
|
|
28908
|
+
onChange: (event) => pick(event.target.value),
|
|
28909
|
+
"data-dxw-native-bridge": "",
|
|
28910
|
+
style: {
|
|
28911
|
+
position: "absolute",
|
|
28912
|
+
width: 1,
|
|
28913
|
+
height: 1,
|
|
28914
|
+
inset: 0,
|
|
28915
|
+
opacity: 0,
|
|
28916
|
+
pointerEvents: "none"
|
|
28917
|
+
},
|
|
28918
|
+
children: [
|
|
28919
|
+
!options.some((option) => option.value === value) && /* @__PURE__ */ jsx("option", { value: "", children: String(placeholder) }),
|
|
28920
|
+
options.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, disabled: option.disabled, children: String(option.label) }, option.value))
|
|
28921
|
+
]
|
|
28922
|
+
}
|
|
28923
|
+
),
|
|
28924
|
+
/* @__PURE__ */ jsxs(
|
|
28925
|
+
"button",
|
|
28926
|
+
{
|
|
28927
|
+
ref: triggerRef,
|
|
28928
|
+
type: "button",
|
|
28929
|
+
"aria-haspopup": "listbox",
|
|
28930
|
+
"aria-expanded": open,
|
|
28931
|
+
"aria-controls": open ? id : void 0,
|
|
28932
|
+
"aria-label": triggerAriaLabel,
|
|
28933
|
+
"data-tip": title,
|
|
28934
|
+
className: "dxw-menu-select-trigger",
|
|
28935
|
+
"data-dxw-menu-select-trigger": "",
|
|
28936
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
28937
|
+
onClick: () => setOpen(!open),
|
|
28938
|
+
onKeyDown: (event) => {
|
|
28939
|
+
if (!open && (event.key === "Enter" || event.key === " " || event.key === "ArrowDown" || event.key === "ArrowUp")) {
|
|
28940
|
+
event.preventDefault();
|
|
28941
|
+
keyboardOpen.current = event.key === "ArrowUp" ? "last" : "first";
|
|
28942
|
+
setOpen(true);
|
|
28943
|
+
}
|
|
28944
|
+
},
|
|
28945
|
+
style: {
|
|
28946
|
+
width: "100%",
|
|
28947
|
+
minWidth: 0,
|
|
28948
|
+
height: "var(--dxw-select-height, 26px)",
|
|
28949
|
+
border: "1px solid var(--dxw-select-border, transparent)",
|
|
28950
|
+
borderRadius: "var(--dxw-select-radius, 4px)",
|
|
28951
|
+
background: "var(--dxw-select-bg, transparent)",
|
|
28952
|
+
color: "var(--dxw-select-fg, var(--dxw-toolbar-fg, #3c4043))",
|
|
28953
|
+
padding: "var(--dxw-select-padding, 0 6px)",
|
|
28954
|
+
display: "inline-flex",
|
|
28955
|
+
alignItems: "center",
|
|
28956
|
+
justifyContent: "space-between",
|
|
28957
|
+
gap: 6,
|
|
28958
|
+
cursor: "pointer",
|
|
28959
|
+
font: "var(--dxw-select-font, 13px system-ui, sans-serif)",
|
|
28960
|
+
...style
|
|
28961
|
+
},
|
|
28962
|
+
children: [
|
|
28963
|
+
/* @__PURE__ */ jsx("span", { style: { minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontFamily: selected?.fontFamily }, children: selected?.label ?? placeholder }),
|
|
28964
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "dxw-menu-select-chevron", style: { flexShrink: 0, fontSize: 10 }, children: "\u2304" })
|
|
28965
|
+
]
|
|
28966
|
+
}
|
|
28967
|
+
),
|
|
28968
|
+
open && /* @__PURE__ */ jsx(
|
|
28969
|
+
"div",
|
|
28970
|
+
{
|
|
28971
|
+
ref: menuRef,
|
|
28972
|
+
id,
|
|
28973
|
+
role: "listbox",
|
|
28974
|
+
"aria-label": ariaLabel ?? title,
|
|
28975
|
+
className: "dxw-menu-select-menu",
|
|
28976
|
+
"data-dxw-menu-select-menu": "",
|
|
28977
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
28978
|
+
onKeyDown: onMenuKeyDown,
|
|
28979
|
+
style: {
|
|
28980
|
+
position: "fixed",
|
|
28981
|
+
left: position.left,
|
|
28982
|
+
top: position.top,
|
|
28983
|
+
zIndex: "var(--dxw-toolbar-z-index, 100)",
|
|
28984
|
+
width: position.width,
|
|
28985
|
+
maxHeight: `min(var(--dxw-select-menu-max-height, 320px), ${position.maxHeight}px)`,
|
|
28986
|
+
overflowY: "auto",
|
|
28987
|
+
overscrollBehavior: "contain",
|
|
28988
|
+
boxSizing: "border-box",
|
|
28989
|
+
padding: "var(--dxw-select-menu-padding, 5px)",
|
|
28990
|
+
border: "1px solid var(--dxw-select-menu-border, var(--dxw-toolbar-border, #dadce0))",
|
|
28991
|
+
borderRadius: "var(--dxw-select-menu-radius, 8px)",
|
|
28992
|
+
background: "var(--dxw-select-menu-bg, var(--dxw-popover-bg, #fff))",
|
|
28993
|
+
boxShadow: "var(--dxw-select-menu-shadow, var(--dxw-popover-shadow, 0 4px 16px rgba(0,0,0,.15)))"
|
|
28994
|
+
},
|
|
28995
|
+
children: options.map((option) => {
|
|
28996
|
+
const groupChanged = option.group !== previousGroup;
|
|
28997
|
+
previousGroup = option.group;
|
|
28998
|
+
const active = option.value === value;
|
|
28999
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
29000
|
+
groupChanged && option.group && /* @__PURE__ */ jsx("div", { className: "dxw-menu-select-group", style: { padding: "6px 8px 3px", color: T.muted, font: "600 10.5px system-ui, sans-serif" }, children: option.group }),
|
|
29001
|
+
/* @__PURE__ */ jsxs(
|
|
29002
|
+
"button",
|
|
29003
|
+
{
|
|
29004
|
+
type: "button",
|
|
29005
|
+
role: "option",
|
|
29006
|
+
"aria-selected": active,
|
|
29007
|
+
disabled: option.disabled,
|
|
29008
|
+
tabIndex: -1,
|
|
29009
|
+
className: "dxw-menu-select-option",
|
|
29010
|
+
"data-dxw-menu-select-option": option.value,
|
|
29011
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
29012
|
+
onClick: () => pick(option.value),
|
|
29013
|
+
style: {
|
|
29014
|
+
width: "100%",
|
|
29015
|
+
minHeight: 30,
|
|
29016
|
+
border: 0,
|
|
29017
|
+
borderRadius: 6,
|
|
29018
|
+
padding: "5px 8px",
|
|
29019
|
+
display: "flex",
|
|
29020
|
+
alignItems: "center",
|
|
29021
|
+
gap: 8,
|
|
29022
|
+
background: active ? T.activeBg : "transparent",
|
|
29023
|
+
color: option.disabled ? T.muted : T.fg,
|
|
29024
|
+
textAlign: "left",
|
|
29025
|
+
cursor: option.disabled ? "default" : "pointer",
|
|
29026
|
+
font: "13px system-ui, sans-serif",
|
|
29027
|
+
fontFamily: option.fontFamily
|
|
29028
|
+
},
|
|
29029
|
+
onMouseEnter: (event) => {
|
|
29030
|
+
if (!active && !option.disabled) event.currentTarget.style.background = T.hoverBg;
|
|
29031
|
+
},
|
|
29032
|
+
onMouseLeave: (event) => {
|
|
29033
|
+
if (!active) event.currentTarget.style.background = "transparent";
|
|
29034
|
+
},
|
|
29035
|
+
children: [
|
|
29036
|
+
/* @__PURE__ */ jsx("span", { style: { flex: 1 }, children: option.label }),
|
|
29037
|
+
active && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { color: T.accent, fontWeight: 700 }, children: "\u2713" })
|
|
29038
|
+
]
|
|
29039
|
+
}
|
|
29040
|
+
)
|
|
29041
|
+
] }, option.value);
|
|
29042
|
+
})
|
|
29043
|
+
}
|
|
29044
|
+
)
|
|
29045
|
+
]
|
|
29046
|
+
}
|
|
29047
|
+
);
|
|
29048
|
+
}
|
|
27634
29049
|
function ActionMenu({
|
|
27635
29050
|
label,
|
|
27636
29051
|
title,
|
|
@@ -27638,22 +29053,21 @@ function ActionMenu({
|
|
|
27638
29053
|
onPick,
|
|
27639
29054
|
width
|
|
27640
29055
|
}) {
|
|
27641
|
-
return /* @__PURE__ */
|
|
27642
|
-
|
|
29056
|
+
return /* @__PURE__ */ jsx(
|
|
29057
|
+
ToolbarMenuSelect,
|
|
27643
29058
|
{
|
|
27644
29059
|
title,
|
|
29060
|
+
triggerAriaLabel: title,
|
|
27645
29061
|
value: "",
|
|
27646
|
-
|
|
27647
|
-
|
|
27648
|
-
|
|
27649
|
-
|
|
27650
|
-
|
|
27651
|
-
|
|
27652
|
-
|
|
27653
|
-
|
|
27654
|
-
|
|
27655
|
-
)
|
|
27656
|
-
]
|
|
29062
|
+
placeholder: label,
|
|
29063
|
+
width,
|
|
29064
|
+
menuWidth: Math.max(width ?? 0, 190),
|
|
29065
|
+
options: groups.flatMap((group) => group.items.map(([value, text]) => ({
|
|
29066
|
+
value,
|
|
29067
|
+
label: text,
|
|
29068
|
+
group: group.label
|
|
29069
|
+
}))),
|
|
29070
|
+
onChange: onPick
|
|
27657
29071
|
}
|
|
27658
29072
|
);
|
|
27659
29073
|
}
|
|
@@ -27733,6 +29147,183 @@ function HighlightMenu({ current, onPick }) {
|
|
|
27733
29147
|
)
|
|
27734
29148
|
] });
|
|
27735
29149
|
}
|
|
29150
|
+
var COLOR_SWATCHES = [
|
|
29151
|
+
"#000000",
|
|
29152
|
+
"#434343",
|
|
29153
|
+
"#666666",
|
|
29154
|
+
"#999999",
|
|
29155
|
+
"#b7b7b7",
|
|
29156
|
+
"#cccccc",
|
|
29157
|
+
"#d9d9d9",
|
|
29158
|
+
"#ffffff",
|
|
29159
|
+
"#980000",
|
|
29160
|
+
"#ff0000",
|
|
29161
|
+
"#ff9900",
|
|
29162
|
+
"#ffff00",
|
|
29163
|
+
"#00ff00",
|
|
29164
|
+
"#00ffff",
|
|
29165
|
+
"#4a86e8",
|
|
29166
|
+
"#0000ff",
|
|
29167
|
+
"#9900ff",
|
|
29168
|
+
"#ff00ff",
|
|
29169
|
+
"#e6b8af",
|
|
29170
|
+
"#f4cccc",
|
|
29171
|
+
"#fce5cd",
|
|
29172
|
+
"#fff2cc",
|
|
29173
|
+
"#d9ead3",
|
|
29174
|
+
"#d0e0e3",
|
|
29175
|
+
"#c9daf8",
|
|
29176
|
+
"#cfe2f3",
|
|
29177
|
+
"#d9d2e9",
|
|
29178
|
+
"#ead1dc",
|
|
29179
|
+
"#a61c00",
|
|
29180
|
+
"#cc0000",
|
|
29181
|
+
"#e69138",
|
|
29182
|
+
"#6aa84f"
|
|
29183
|
+
];
|
|
29184
|
+
function normalizedColor(value) {
|
|
29185
|
+
const match = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(value.trim());
|
|
29186
|
+
if (!match) return null;
|
|
29187
|
+
const digits = match[1].length === 3 ? match[1].split("").map((digit) => digit + digit).join("") : match[1];
|
|
29188
|
+
return `#${digits.toLowerCase()}`;
|
|
29189
|
+
}
|
|
29190
|
+
function ColorMenu({
|
|
29191
|
+
current,
|
|
29192
|
+
title,
|
|
29193
|
+
trigger,
|
|
29194
|
+
onPick
|
|
29195
|
+
}) {
|
|
29196
|
+
const [open, setOpen] = useState(false);
|
|
29197
|
+
const [custom, setCustom] = useState(current);
|
|
29198
|
+
const [position, setPosition] = useState({ left: 8, top: 8 });
|
|
29199
|
+
const rootRef = useRef(null);
|
|
29200
|
+
const triggerRef = useRef(null);
|
|
29201
|
+
const menuRef = useRef(null);
|
|
29202
|
+
const valid = normalizedColor(custom);
|
|
29203
|
+
useLayoutEffect(() => {
|
|
29204
|
+
if (!open) return;
|
|
29205
|
+
setCustom(current);
|
|
29206
|
+
const update = () => {
|
|
29207
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
29208
|
+
if (!rect) return;
|
|
29209
|
+
const width = Math.min(236, window.innerWidth - 16);
|
|
29210
|
+
const menuHeight = menuRef.current?.offsetHeight ?? 188;
|
|
29211
|
+
const top = window.innerHeight - rect.bottom >= menuHeight + 8 ? rect.bottom + 4 : Math.max(8, rect.top - menuHeight - 4);
|
|
29212
|
+
setPosition({ left: Math.max(8, Math.min(rect.left, window.innerWidth - width - 8)), top });
|
|
29213
|
+
};
|
|
29214
|
+
update();
|
|
29215
|
+
const frame = requestAnimationFrame(update);
|
|
29216
|
+
const close = (event) => {
|
|
29217
|
+
if (!rootRef.current?.contains(event.target)) setOpen(false);
|
|
29218
|
+
};
|
|
29219
|
+
const keydown = (event) => {
|
|
29220
|
+
if (event.key === "Escape") {
|
|
29221
|
+
setOpen(false);
|
|
29222
|
+
requestAnimationFrame(() => triggerRef.current?.focus({ preventScroll: true }));
|
|
29223
|
+
}
|
|
29224
|
+
};
|
|
29225
|
+
document.addEventListener("mousedown", close);
|
|
29226
|
+
document.addEventListener("keydown", keydown);
|
|
29227
|
+
window.addEventListener("resize", update);
|
|
29228
|
+
window.addEventListener("scroll", update, true);
|
|
29229
|
+
return () => {
|
|
29230
|
+
cancelAnimationFrame(frame);
|
|
29231
|
+
document.removeEventListener("mousedown", close);
|
|
29232
|
+
document.removeEventListener("keydown", keydown);
|
|
29233
|
+
window.removeEventListener("resize", update);
|
|
29234
|
+
window.removeEventListener("scroll", update, true);
|
|
29235
|
+
};
|
|
29236
|
+
}, [open, current]);
|
|
29237
|
+
const pick = (value) => {
|
|
29238
|
+
onPick(value);
|
|
29239
|
+
setOpen(false);
|
|
29240
|
+
};
|
|
29241
|
+
return /* @__PURE__ */ jsxs("span", { ref: rootRef, className: "dxw-color-control", style: { position: "relative", display: "inline-flex" }, children: [
|
|
29242
|
+
/* @__PURE__ */ jsx(
|
|
29243
|
+
"button",
|
|
29244
|
+
{
|
|
29245
|
+
ref: triggerRef,
|
|
29246
|
+
type: "button",
|
|
29247
|
+
title,
|
|
29248
|
+
"aria-haspopup": "dialog",
|
|
29249
|
+
"aria-expanded": open,
|
|
29250
|
+
className: "dxw-color-trigger",
|
|
29251
|
+
"data-dxw-color-trigger": "",
|
|
29252
|
+
style: { ...btnStyle(open), display: "inline-flex", alignItems: "center", gap: 5 },
|
|
29253
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
29254
|
+
onClick: () => setOpen(!open),
|
|
29255
|
+
children: trigger
|
|
29256
|
+
}
|
|
29257
|
+
),
|
|
29258
|
+
open && /* @__PURE__ */ jsxs(
|
|
29259
|
+
"div",
|
|
29260
|
+
{
|
|
29261
|
+
ref: menuRef,
|
|
29262
|
+
role: "dialog",
|
|
29263
|
+
"aria-label": title,
|
|
29264
|
+
className: "dxw-color-menu",
|
|
29265
|
+
"data-dxw-color-menu": "",
|
|
29266
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
29267
|
+
style: {
|
|
29268
|
+
position: "fixed",
|
|
29269
|
+
left: position.left,
|
|
29270
|
+
top: position.top,
|
|
29271
|
+
zIndex: "var(--dxw-toolbar-z-index, 100)",
|
|
29272
|
+
width: "min(var(--dxw-color-menu-width, 236px), calc(100vw - 16px))",
|
|
29273
|
+
boxSizing: "border-box",
|
|
29274
|
+
padding: 8,
|
|
29275
|
+
border: `1px solid ${T.border}`,
|
|
29276
|
+
borderRadius: 8,
|
|
29277
|
+
background: T.popoverBg,
|
|
29278
|
+
boxShadow: T.popoverShadow
|
|
29279
|
+
},
|
|
29280
|
+
children: [
|
|
29281
|
+
/* @__PURE__ */ jsx("div", { className: "dxw-color-swatches", style: { display: "grid", gridTemplateColumns: "repeat(8, 1fr)", gap: 4 }, children: COLOR_SWATCHES.map((color) => /* @__PURE__ */ jsx(
|
|
29282
|
+
"button",
|
|
29283
|
+
{
|
|
29284
|
+
type: "button",
|
|
29285
|
+
title: color,
|
|
29286
|
+
"aria-label": `Choose ${color}`,
|
|
29287
|
+
className: "dxw-color-swatch",
|
|
29288
|
+
"data-dxw-color": color,
|
|
29289
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
29290
|
+
onClick: () => pick(color),
|
|
29291
|
+
style: {
|
|
29292
|
+
width: 23,
|
|
29293
|
+
height: 23,
|
|
29294
|
+
padding: 0,
|
|
29295
|
+
borderRadius: 4,
|
|
29296
|
+
cursor: "pointer",
|
|
29297
|
+
border: color.toLowerCase() === current.toLowerCase() ? `2px solid ${T.accent}` : `1px solid ${T.border}`,
|
|
29298
|
+
background: color
|
|
29299
|
+
}
|
|
29300
|
+
},
|
|
29301
|
+
color
|
|
29302
|
+
)) }),
|
|
29303
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, marginTop: 8 }, children: [
|
|
29304
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { width: 24, height: 24, borderRadius: 4, border: `1px solid ${T.border}`, background: valid ?? current, flexShrink: 0 } }),
|
|
29305
|
+
/* @__PURE__ */ jsx(
|
|
29306
|
+
"input",
|
|
29307
|
+
{
|
|
29308
|
+
"aria-label": "Custom hex color",
|
|
29309
|
+
className: "dxw-color-value",
|
|
29310
|
+
value: custom,
|
|
29311
|
+
onChange: (event) => setCustom(event.target.value),
|
|
29312
|
+
onKeyDown: (event) => {
|
|
29313
|
+
if (event.key === "Enter" && valid) pick(valid);
|
|
29314
|
+
},
|
|
29315
|
+
spellCheck: false,
|
|
29316
|
+
placeholder: "#1a73e8",
|
|
29317
|
+
style: { minWidth: 0, flex: 1, height: 28, boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 5, padding: "3px 6px", color: T.fg, background: T.popoverBg }
|
|
29318
|
+
}
|
|
29319
|
+
),
|
|
29320
|
+
/* @__PURE__ */ jsx("button", { type: "button", disabled: !valid, onClick: () => valid && pick(valid), style: pillBtn, children: "Apply" })
|
|
29321
|
+
] })
|
|
29322
|
+
]
|
|
29323
|
+
}
|
|
29324
|
+
)
|
|
29325
|
+
] });
|
|
29326
|
+
}
|
|
27736
29327
|
function BulletListIcon() {
|
|
27737
29328
|
return /* @__PURE__ */ jsxs("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
|
|
27738
29329
|
/* @__PURE__ */ jsx("circle", { cx: "3", cy: "4", r: "1.1", fill: "currentColor", stroke: "none" }),
|
|
@@ -28095,7 +29686,18 @@ function CrossReferenceMenu({ api }) {
|
|
|
28095
29686
|
return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
|
|
28096
29687
|
/* @__PURE__ */ jsx("button", { title: "Insert cross-reference", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Cross-reference" }),
|
|
28097
29688
|
open && /* @__PURE__ */ jsx("div", { style: { position: "absolute", top: 28, left: 0, zIndex: 100, width: 260, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: bookmarks.length === 0 ? /* @__PURE__ */ jsx("div", { style: { color: T.muted, fontSize: 12 }, children: "Add a bookmark first, then reference its text or page." }) : /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
28098
|
-
/* @__PURE__ */ jsx(
|
|
29689
|
+
/* @__PURE__ */ jsx(
|
|
29690
|
+
ToolbarMenuSelect,
|
|
29691
|
+
{
|
|
29692
|
+
value: selected,
|
|
29693
|
+
ariaLabel: "Bookmark to reference",
|
|
29694
|
+
width: "100%",
|
|
29695
|
+
menuWidth: 240,
|
|
29696
|
+
options: bookmarks.map((name) => ({ value: name, label: name })),
|
|
29697
|
+
onChange: setBookmark,
|
|
29698
|
+
style: { borderColor: T.border }
|
|
29699
|
+
}
|
|
29700
|
+
),
|
|
28099
29701
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 8 }, children: [
|
|
28100
29702
|
/* @__PURE__ */ jsx("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => insert("page"), children: "Page number" }),
|
|
28101
29703
|
/* @__PURE__ */ jsx("button", { style: pillBtn, onClick: () => insert("text"), children: "Bookmark text" })
|
|
@@ -28202,6 +29804,7 @@ function SymbolMenu({ api }) {
|
|
|
28202
29804
|
] });
|
|
28203
29805
|
}
|
|
28204
29806
|
var SHAPES = [
|
|
29807
|
+
["line", "Line", "\u2015"],
|
|
28205
29808
|
["rectangle", "Rectangle", "\u25AD"],
|
|
28206
29809
|
["roundedRectangle", "Rounded rectangle", "\u25A2"],
|
|
28207
29810
|
["ellipse", "Ellipse", "\u25EF"],
|
|
@@ -28373,12 +29976,23 @@ function ChartMenu({ api }) {
|
|
|
28373
29976
|
return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
|
|
28374
29977
|
/* @__PURE__ */ jsx("button", { title: "Insert or edit chart", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Chart" }),
|
|
28375
29978
|
open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 320, padding: 10, display: "grid", gap: 7, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
|
|
28376
|
-
/* @__PURE__ */
|
|
28377
|
-
|
|
28378
|
-
|
|
28379
|
-
|
|
28380
|
-
|
|
28381
|
-
|
|
29979
|
+
/* @__PURE__ */ jsx(
|
|
29980
|
+
ToolbarMenuSelect,
|
|
29981
|
+
{
|
|
29982
|
+
value: type,
|
|
29983
|
+
ariaLabel: "Chart type",
|
|
29984
|
+
width: "100%",
|
|
29985
|
+
menuWidth: 300,
|
|
29986
|
+
options: [
|
|
29987
|
+
{ value: "column", label: "Column" },
|
|
29988
|
+
{ value: "bar", label: "Bar" },
|
|
29989
|
+
{ value: "line", label: "Line" },
|
|
29990
|
+
{ value: "pie", label: "Pie" }
|
|
29991
|
+
],
|
|
29992
|
+
onChange: (value) => setType(value),
|
|
29993
|
+
style: fieldStyle
|
|
29994
|
+
}
|
|
29995
|
+
),
|
|
28382
29996
|
/* @__PURE__ */ jsx("input", { "aria-label": "Chart title", value: title, onChange: (event) => setTitle(event.target.value), placeholder: "Chart title", style: fieldStyle }),
|
|
28383
29997
|
/* @__PURE__ */ jsx("input", { "aria-label": "Chart categories", value: categories, onChange: (event) => setCategories(event.target.value), placeholder: "Q1, Q2, Q3, Q4", style: fieldStyle }),
|
|
28384
29998
|
/* @__PURE__ */ jsx("textarea", { "aria-label": "Chart series", rows: 3, value: series, onChange: (event) => setSeries(event.target.value), style: { ...fieldStyle, resize: "vertical" } }),
|
|
@@ -28411,12 +30025,23 @@ function SmartArtMenu({ api }) {
|
|
|
28411
30025
|
return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
|
|
28412
30026
|
/* @__PURE__ */ jsx("button", { title: "Insert or edit SmartArt", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "SmartArt" }),
|
|
28413
30027
|
open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 280, padding: 10, display: "grid", gap: 7, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
|
|
28414
|
-
/* @__PURE__ */
|
|
28415
|
-
|
|
28416
|
-
|
|
28417
|
-
|
|
28418
|
-
|
|
28419
|
-
|
|
30028
|
+
/* @__PURE__ */ jsx(
|
|
30029
|
+
ToolbarMenuSelect,
|
|
30030
|
+
{
|
|
30031
|
+
value: layout,
|
|
30032
|
+
ariaLabel: "SmartArt layout",
|
|
30033
|
+
width: "100%",
|
|
30034
|
+
menuWidth: 260,
|
|
30035
|
+
options: [
|
|
30036
|
+
{ value: "process", label: "Process" },
|
|
30037
|
+
{ value: "cycle", label: "Cycle" },
|
|
30038
|
+
{ value: "hierarchy", label: "Hierarchy" },
|
|
30039
|
+
{ value: "list", label: "List" }
|
|
30040
|
+
],
|
|
30041
|
+
onChange: (value) => setLayout(value),
|
|
30042
|
+
style: fieldStyle
|
|
30043
|
+
}
|
|
30044
|
+
),
|
|
28420
30045
|
/* @__PURE__ */ jsx("textarea", { "aria-label": "SmartArt items", rows: 5, value: items, onChange: (event) => setItems(event.target.value), style: { ...fieldStyle, resize: "vertical" } }),
|
|
28421
30046
|
/* @__PURE__ */ jsx("div", { style: { color: T.muted, font: "11.5px system-ui, sans-serif" }, children: "One diagram item per line." }),
|
|
28422
30047
|
/* @__PURE__ */ jsx("button", { disabled: !items.trim(), onClick: submit, style: { border: 0, borderRadius: 6, padding: "7px 10px", background: items.trim() ? T.accent : T.border, color: T.accentFg, cursor: items.trim() ? "pointer" : "default", font: "600 12px system-ui, sans-serif" }, children: "Insert or update SmartArt" })
|
|
@@ -28474,19 +30099,18 @@ function DrawTab({ api }) {
|
|
|
28474
30099
|
/* @__PURE__ */ jsx(Btn, { label: "Eraser", title: "Stroke eraser", active: active === "eraser", onClick: () => api?.setDrawingTool({ kind: "eraser", size: 14 }) }),
|
|
28475
30100
|
/* @__PURE__ */ jsx(Btn, { label: "Lasso", title: "Lasso ink", active: active === "lasso", onClick: () => api?.setDrawingTool({ kind: "lasso" }) }),
|
|
28476
30101
|
/* @__PURE__ */ jsx(Sep, {}),
|
|
28477
|
-
/* @__PURE__ */
|
|
28478
|
-
|
|
28479
|
-
|
|
28480
|
-
|
|
28481
|
-
|
|
28482
|
-
|
|
28483
|
-
|
|
28484
|
-
|
|
28485
|
-
|
|
28486
|
-
|
|
28487
|
-
|
|
28488
|
-
|
|
28489
|
-
] }),
|
|
30102
|
+
/* @__PURE__ */ jsx(
|
|
30103
|
+
ColorMenu,
|
|
30104
|
+
{
|
|
30105
|
+
current: color,
|
|
30106
|
+
title: "Pen color",
|
|
30107
|
+
trigger: /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
30108
|
+
/* @__PURE__ */ jsx("span", { style: { font: "12px system-ui, sans-serif" }, children: "Color" }),
|
|
30109
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { width: 18, height: 18, borderRadius: 4, border: `1px solid ${T.border}`, background: color } })
|
|
30110
|
+
] }),
|
|
30111
|
+
onPick: (value) => activate(active === "highlighter" ? "highlighter" : "pen", value, width)
|
|
30112
|
+
}
|
|
30113
|
+
),
|
|
28490
30114
|
/* @__PURE__ */ jsx(
|
|
28491
30115
|
ActionMenu,
|
|
28492
30116
|
{
|
|
@@ -29064,9 +30688,8 @@ function MarginMenu({
|
|
|
29064
30688
|
"input",
|
|
29065
30689
|
{
|
|
29066
30690
|
"aria-label": `${label} margin (inches)`,
|
|
29067
|
-
type: "
|
|
29068
|
-
|
|
29069
|
-
step: "0.01",
|
|
30691
|
+
type: "text",
|
|
30692
|
+
inputMode: "decimal",
|
|
29070
30693
|
required: true,
|
|
29071
30694
|
autoFocus: side === "top",
|
|
29072
30695
|
value: values[side],
|
|
@@ -29191,9 +30814,8 @@ function PageSizeMenu({
|
|
|
29191
30814
|
"input",
|
|
29192
30815
|
{
|
|
29193
30816
|
"aria-label": `Page ${side} (inches)`,
|
|
29194
|
-
type: "
|
|
29195
|
-
|
|
29196
|
-
step: "0.01",
|
|
30817
|
+
type: "text",
|
|
30818
|
+
inputMode: "decimal",
|
|
29197
30819
|
required: true,
|
|
29198
30820
|
autoFocus: side === "width",
|
|
29199
30821
|
value: values[side],
|
|
@@ -29291,19 +30913,20 @@ function LayoutTab({ api, showArrange }) {
|
|
|
29291
30913
|
"data-dxw-layout-ribbon": "",
|
|
29292
30914
|
style: { display: "flex", flex: "1 1 640px", minWidth: 0, alignItems: "center", flexWrap: "wrap", gap: 2 },
|
|
29293
30915
|
children: [
|
|
29294
|
-
/* @__PURE__ */
|
|
29295
|
-
|
|
30916
|
+
/* @__PURE__ */ jsx(
|
|
30917
|
+
ToolbarMenuSelect,
|
|
29296
30918
|
{
|
|
29297
30919
|
title: "Apply layout changes to",
|
|
29298
|
-
|
|
30920
|
+
ariaLabel: "Apply layout changes to",
|
|
29299
30921
|
value: scope,
|
|
29300
|
-
|
|
29301
|
-
|
|
29302
|
-
|
|
29303
|
-
|
|
29304
|
-
|
|
29305
|
-
|
|
29306
|
-
|
|
30922
|
+
width: 118,
|
|
30923
|
+
menuWidth: 170,
|
|
30924
|
+
options: [
|
|
30925
|
+
{ value: "document", label: "Whole document" },
|
|
30926
|
+
{ value: "section", label: "This section" }
|
|
30927
|
+
],
|
|
30928
|
+
onChange: (value) => setScope(value),
|
|
30929
|
+
style: { maxWidth: "100%" }
|
|
29307
30930
|
}
|
|
29308
30931
|
),
|
|
29309
30932
|
/* @__PURE__ */ jsx(Sep, {}),
|
|
@@ -29530,42 +31153,44 @@ function DocxToolbar({
|
|
|
29530
31153
|
if (on("styles"))
|
|
29531
31154
|
groups.push({
|
|
29532
31155
|
key: "styles",
|
|
29533
|
-
node: /* @__PURE__ */
|
|
29534
|
-
|
|
31156
|
+
node: /* @__PURE__ */ jsx(
|
|
31157
|
+
ToolbarMenuSelect,
|
|
29535
31158
|
{
|
|
29536
31159
|
title: "Paragraph style",
|
|
29537
31160
|
value: curStyle ?? "__normal",
|
|
29538
|
-
|
|
29539
|
-
|
|
29540
|
-
|
|
29541
|
-
|
|
31161
|
+
width: 92,
|
|
31162
|
+
menuWidth: 190,
|
|
31163
|
+
options: [
|
|
31164
|
+
{ value: "__normal", label: "Normal" },
|
|
31165
|
+
...(api?.listParagraphStyles() ?? []).filter((style2) => !/^normal$/i.test(style2.name)).map((style2) => ({ value: style2.id, label: style2.name })),
|
|
31166
|
+
...curStyle !== null && !(api?.listParagraphStyles() ?? []).some((style2) => style2.id === curStyle) ? [{ value: curStyle, label: api?.document.styles.byId.get(curStyle)?.name ?? curStyle }] : []
|
|
31167
|
+
],
|
|
31168
|
+
onChange: (value) => {
|
|
31169
|
+
if (value) {
|
|
31170
|
+
api?.setParagraphStyle(value === "__normal" ? null : value);
|
|
29542
31171
|
setCurStyle(api?.getParagraphStyleId?.() ?? null);
|
|
29543
31172
|
}
|
|
29544
|
-
}
|
|
29545
|
-
style: { ...selectStyle, width: 92 },
|
|
29546
|
-
children: [
|
|
29547
|
-
/* @__PURE__ */ jsx("option", { value: "__normal", children: "Normal" }),
|
|
29548
|
-
(api?.listParagraphStyles() ?? []).filter((s) => !/^normal$/i.test(s.name)).map((s) => /* @__PURE__ */ jsx("option", { value: s.id, children: s.name }, s.id)),
|
|
29549
|
-
curStyle !== null && !(api?.listParagraphStyles() ?? []).some((s) => s.id === curStyle) && /* @__PURE__ */ jsx("option", { value: curStyle, children: api?.document.styles.byId.get(curStyle)?.name ?? curStyle })
|
|
29550
|
-
]
|
|
31173
|
+
}
|
|
29551
31174
|
}
|
|
29552
31175
|
)
|
|
29553
31176
|
});
|
|
29554
31177
|
if (on("font"))
|
|
29555
31178
|
groups.push({
|
|
29556
31179
|
key: "font",
|
|
29557
|
-
node: /* @__PURE__ */
|
|
29558
|
-
|
|
31180
|
+
node: /* @__PURE__ */ jsx(
|
|
31181
|
+
ToolbarMenuSelect,
|
|
29559
31182
|
{
|
|
29560
31183
|
title: "Font",
|
|
29561
31184
|
value: fmt?.fontFamily ?? "",
|
|
29562
|
-
|
|
29563
|
-
|
|
29564
|
-
|
|
29565
|
-
|
|
29566
|
-
|
|
29567
|
-
|
|
29568
|
-
|
|
31185
|
+
placeholder: "Font",
|
|
31186
|
+
width: 130,
|
|
31187
|
+
menuWidth: 210,
|
|
31188
|
+
options: (fmt?.fontFamily && !detectFonts().includes(fmt.fontFamily) ? [fmt.fontFamily, ...detectFonts()] : detectFonts()).map((font) => ({
|
|
31189
|
+
value: font,
|
|
31190
|
+
label: font,
|
|
31191
|
+
fontFamily: font
|
|
31192
|
+
})),
|
|
31193
|
+
onChange: (value) => value && apply({ fontFamily: value })
|
|
29569
31194
|
}
|
|
29570
31195
|
)
|
|
29571
31196
|
});
|
|
@@ -29573,18 +31198,16 @@ function DocxToolbar({
|
|
|
29573
31198
|
groups.push({
|
|
29574
31199
|
key: "size",
|
|
29575
31200
|
node: /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
29576
|
-
/* @__PURE__ */
|
|
29577
|
-
|
|
31201
|
+
/* @__PURE__ */ jsx(
|
|
31202
|
+
ToolbarMenuSelect,
|
|
29578
31203
|
{
|
|
29579
31204
|
title: "Font size",
|
|
29580
|
-
value: fmt?.fontSizePt
|
|
29581
|
-
|
|
29582
|
-
|
|
29583
|
-
|
|
29584
|
-
|
|
29585
|
-
|
|
29586
|
-
SIZES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: s }, s))
|
|
29587
|
-
]
|
|
31205
|
+
value: fmt?.fontSizePt === void 0 ? "" : String(fmt.fontSizePt),
|
|
31206
|
+
placeholder: "Size",
|
|
31207
|
+
width: 58,
|
|
31208
|
+
menuWidth: 92,
|
|
31209
|
+
options: SIZES.map((size) => ({ value: String(size), label: String(size) })),
|
|
31210
|
+
onChange: (value) => value && apply({ fontSizePt: parseFloat(value) })
|
|
29588
31211
|
}
|
|
29589
31212
|
),
|
|
29590
31213
|
/* @__PURE__ */ jsx(Sep, {})
|
|
@@ -29641,19 +31264,15 @@ function DocxToolbar({
|
|
|
29641
31264
|
if (on("color"))
|
|
29642
31265
|
groups.push({
|
|
29643
31266
|
key: "color",
|
|
29644
|
-
node: /* @__PURE__ */
|
|
29645
|
-
|
|
29646
|
-
|
|
29647
|
-
"
|
|
29648
|
-
|
|
29649
|
-
|
|
29650
|
-
|
|
29651
|
-
|
|
29652
|
-
|
|
29653
|
-
style: { width: 0, height: 0, opacity: 0, border: "none", padding: 0 }
|
|
29654
|
-
}
|
|
29655
|
-
)
|
|
29656
|
-
] })
|
|
31267
|
+
node: /* @__PURE__ */ jsx(
|
|
31268
|
+
ColorMenu,
|
|
31269
|
+
{
|
|
31270
|
+
current: fmt?.color && fmt.color !== "auto" ? fmt.color : "#000000",
|
|
31271
|
+
title: "Text color",
|
|
31272
|
+
trigger: /* @__PURE__ */ jsx("span", { style: { fontSize: 13, borderBottom: `3px solid ${fmt?.color && fmt.color !== "auto" ? fmt.color : "#000"}`, padding: "0 3px", color: T.fg }, children: "A" }),
|
|
31273
|
+
onPick: (value) => apply({ color: value })
|
|
31274
|
+
}
|
|
31275
|
+
)
|
|
29657
31276
|
});
|
|
29658
31277
|
if (on("highlight"))
|
|
29659
31278
|
groups.push({
|
|
@@ -30325,20 +31944,25 @@ function DocxView({
|
|
|
30325
31944
|
"Calibri",
|
|
30326
31945
|
"Calibri Light",
|
|
30327
31946
|
"Tahoma",
|
|
30328
|
-
"Franklin Gothic Medium"
|
|
30329
|
-
// Complex-script faces gate layout too (advances must be real
|
|
30330
|
-
// before line breaking): Mangal (Devanagari), Latha (Tamil),
|
|
30331
|
-
// Noto Sans Lao Looped (Lao — bundled OFL webfont).
|
|
30332
|
-
"Mangal",
|
|
30333
|
-
"Latha",
|
|
30334
|
-
"Noto Sans Lao Looped"
|
|
31947
|
+
"Franklin Gothic Medium"
|
|
30335
31948
|
];
|
|
30336
31949
|
for (const fam of latin) {
|
|
30337
31950
|
for (const variant of ["", "italic ", "bold ", "bold italic "]) {
|
|
30338
31951
|
loads.push(document.fonts.load(`${variant}16px "${fam}"`).catch(() => []));
|
|
30339
31952
|
}
|
|
30340
31953
|
}
|
|
31954
|
+
const complex = [
|
|
31955
|
+
["Mangal", "\u0905"],
|
|
31956
|
+
["Latha", "\u0B85"],
|
|
31957
|
+
["Noto Sans Lao Looped", "\u0E81"]
|
|
31958
|
+
];
|
|
31959
|
+
for (const [fam, sample] of complex) {
|
|
31960
|
+
for (const variant of ["", "bold "]) {
|
|
31961
|
+
loads.push(document.fonts.load(`${variant}16px "${fam}"`, sample).catch(() => []));
|
|
31962
|
+
}
|
|
31963
|
+
}
|
|
30341
31964
|
loads.push(document.fonts.load('16px "Cambria Math"').catch(() => []));
|
|
31965
|
+
loads.push(document.fonts.load('16px "Segoe UI Emoji"', "\u{1F680}").catch(() => []));
|
|
30342
31966
|
const cjk = [
|
|
30343
31967
|
"MS Mincho",
|
|
30344
31968
|
"MS Gothic",
|
|
@@ -30353,7 +31977,7 @@ function DocxView({
|
|
|
30353
31977
|
];
|
|
30354
31978
|
for (const fam of cjk) {
|
|
30355
31979
|
for (const variant of ["", "bold "]) {
|
|
30356
|
-
loads.push(document.fonts.load(`${variant}16px "${fam}"
|
|
31980
|
+
loads.push(document.fonts.load(`${variant}16px "${fam}"`, "A\u6F22").catch(() => []));
|
|
30357
31981
|
}
|
|
30358
31982
|
}
|
|
30359
31983
|
await Promise.all(loads);
|
|
@@ -30400,7 +32024,39 @@ function DocxView({
|
|
|
30400
32024
|
else if (formatted.length > 0) editor?.selectRanges(formatted);
|
|
30401
32025
|
document.dispatchEvent(new CustomEvent("dxw-selection"));
|
|
30402
32026
|
},
|
|
30403
|
-
onStyleShortcut: (styleId) => applyStyleShortcut?.(styleId)
|
|
32027
|
+
onStyleShortcut: (styleId) => applyStyleShortcut?.(styleId),
|
|
32028
|
+
onTextCommand: (command) => {
|
|
32029
|
+
const current = apiRef.current;
|
|
32030
|
+
if (!current) return;
|
|
32031
|
+
if (command === "link") {
|
|
32032
|
+
const anchor = containerRef.current;
|
|
32033
|
+
if (!anchor) return;
|
|
32034
|
+
void requestTextInputDialog(anchor, {
|
|
32035
|
+
title: "Link address",
|
|
32036
|
+
label: "URL",
|
|
32037
|
+
value: current.getLinkAt() ?? "https://"
|
|
32038
|
+
}).then((next) => {
|
|
32039
|
+
if (next !== null) current.setLink(next.trim() || null);
|
|
32040
|
+
});
|
|
32041
|
+
} else if (command === "comment") {
|
|
32042
|
+
const anchor = containerRef.current;
|
|
32043
|
+
if (!anchor) return;
|
|
32044
|
+
void requestTextInputDialog(anchor, {
|
|
32045
|
+
title: "New comment",
|
|
32046
|
+
label: "Comment",
|
|
32047
|
+
submitLabel: "Comment",
|
|
32048
|
+
multiline: true
|
|
32049
|
+
}).then((text) => {
|
|
32050
|
+
if (text?.trim()) current.addComment(text.trim());
|
|
32051
|
+
});
|
|
32052
|
+
} else if (command === "bullet" || command === "number") {
|
|
32053
|
+
current.toggleList(command);
|
|
32054
|
+
} else {
|
|
32055
|
+
current.setAlignment(
|
|
32056
|
+
command === "alignLeft" ? "left" : command === "alignCenter" ? "center" : command === "alignRight" ? "right" : "justify"
|
|
32057
|
+
);
|
|
32058
|
+
}
|
|
32059
|
+
}
|
|
30404
32060
|
};
|
|
30405
32061
|
editor = new DocxEditor(editorConfig);
|
|
30406
32062
|
editor.attach();
|
|
@@ -31019,7 +32675,8 @@ function DocxView({
|
|
|
31019
32675
|
alignItems: "center"
|
|
31020
32676
|
},
|
|
31021
32677
|
children: [
|
|
31022
|
-
/* @__PURE__ */ jsx2("span", { style: { font: "600 11.5px system-ui, sans-serif", color: "#5f6368", padding: "0 4px" }, children: "Header & footer" }),
|
|
32678
|
+
/* @__PURE__ */ jsx2("span", { style: { font: "600 11.5px system-ui, sans-serif", color: "#5f6368", padding: "0 4px" }, children: "Header & footer \xB7 repeats on pages" }),
|
|
32679
|
+
hotBtn("Line", "Insert a reusable line in the repeating page layer", () => apiRef.current?.insertShape("line")),
|
|
31023
32680
|
hotBtn("Page number", "Insert a dynamic page number at the caret", () => apiRef.current?.insertPageNumber("page")),
|
|
31024
32681
|
hotBtn("Page X of Y", "Insert 'Page X of Y' at the caret", () => apiRef.current?.insertPageNumber("pageOfTotal")),
|
|
31025
32682
|
hotBtn("Close", "Return to the document body", () => {
|
|
@@ -31035,6 +32692,7 @@ export {
|
|
|
31035
32692
|
DocxDocument,
|
|
31036
32693
|
DocxToolbar,
|
|
31037
32694
|
DocxView,
|
|
32695
|
+
ToolbarMenuSelect,
|
|
31038
32696
|
layoutDocument,
|
|
31039
32697
|
printPages,
|
|
31040
32698
|
renderToDom
|