wordinweb 0.1.20 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -0
- package/dist/index.js +237 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1281,6 +1281,10 @@ declare class DocxDocument {
|
|
|
1281
1281
|
before: Paragraph;
|
|
1282
1282
|
after: Paragraph;
|
|
1283
1283
|
} | null;
|
|
1284
|
+
/** Insert a new paragraph immediately before a retained body paragraph
|
|
1285
|
+
* without rebuilding the complete document model. Used by Enter at the
|
|
1286
|
+
* exact paragraph start, where the existing paragraph itself is unchanged. */
|
|
1287
|
+
insertDirectBodyParagraphBefore(referenceSource: XmlElement, insertedSource: XmlElement): Paragraph | null;
|
|
1284
1288
|
/** Reparse a body paragraph plus several new siblings created by
|
|
1285
1289
|
* click-and-type without rebuilding the complete document model. */
|
|
1286
1290
|
reparseDirectBodyParagraphSplits(beforeSource: XmlElement, afterSources: XmlElement[]): Paragraph[] | null;
|
|
@@ -1530,6 +1534,8 @@ interface TextItem {
|
|
|
1530
1534
|
* the bookmark's page number (Word recomputes PAGEREF on open; the docx
|
|
1531
1535
|
* cached result is stale in real TOCs). */
|
|
1532
1536
|
pageRef?: string;
|
|
1537
|
+
/** DOCX bookmarks that begin on this text item. */
|
|
1538
|
+
bookmarks?: string[];
|
|
1533
1539
|
/** Source m:oMath element when this text is a piece of an equation. */
|
|
1534
1540
|
mathSrc?: XmlElement;
|
|
1535
1541
|
href?: string;
|
package/dist/index.js
CHANGED
|
@@ -6364,6 +6364,45 @@ var DocxDocument = class _DocxDocument {
|
|
|
6364
6364
|
const parsed = this.reparseDirectBodyParagraphSplits(beforeSource, [afterSource]);
|
|
6365
6365
|
return parsed ? { before: parsed[0], after: parsed[1] } : null;
|
|
6366
6366
|
}
|
|
6367
|
+
/** Insert a new paragraph immediately before a retained body paragraph
|
|
6368
|
+
* without rebuilding the complete document model. Used by Enter at the
|
|
6369
|
+
* exact paragraph start, where the existing paragraph itself is unchanged. */
|
|
6370
|
+
insertDirectBodyParagraphBefore(referenceSource, insertedSource) {
|
|
6371
|
+
const parent = this.findParentOf(referenceSource);
|
|
6372
|
+
if (!parent) return null;
|
|
6373
|
+
const referenceIndex = parent.children.indexOf(referenceSource);
|
|
6374
|
+
if (referenceIndex < 1 || parent.children[referenceIndex - 1] !== insertedSource) return null;
|
|
6375
|
+
if (localName(referenceSource.name) !== "p" || localName(insertedSource.name) !== "p") return null;
|
|
6376
|
+
const findBlockList = (blocks) => {
|
|
6377
|
+
const index = blocks.findIndex((block) => block.type === "paragraph" && block.src === referenceSource);
|
|
6378
|
+
if (index >= 0) return { blocks, index };
|
|
6379
|
+
for (const block of blocks) {
|
|
6380
|
+
if (block.type !== "table") continue;
|
|
6381
|
+
for (const row of block.rows) {
|
|
6382
|
+
for (const cell of row.cells) {
|
|
6383
|
+
const found = findBlockList(cell.blocks);
|
|
6384
|
+
if (found) return found;
|
|
6385
|
+
}
|
|
6386
|
+
}
|
|
6387
|
+
}
|
|
6388
|
+
return null;
|
|
6389
|
+
};
|
|
6390
|
+
let location = null;
|
|
6391
|
+
for (const section of this.sections) {
|
|
6392
|
+
location = findBlockList(section.blocks);
|
|
6393
|
+
if (location) break;
|
|
6394
|
+
}
|
|
6395
|
+
if (!location || location.blocks.some((block) => block.src === insertedSource)) return null;
|
|
6396
|
+
const paragraph = parseParagraph(insertedSource, {
|
|
6397
|
+
...this.ctxBase,
|
|
6398
|
+
rels: this.documentRels,
|
|
6399
|
+
readPart: (part) => this.readXmlOptional(part),
|
|
6400
|
+
independentTextboxStories: true
|
|
6401
|
+
});
|
|
6402
|
+
if (paragraph.revisionHidden || paragraph.sectionBreak) return null;
|
|
6403
|
+
location.blocks.splice(location.index, 0, paragraph);
|
|
6404
|
+
return paragraph;
|
|
6405
|
+
}
|
|
6367
6406
|
/** Reparse a body paragraph plus several new siblings created by
|
|
6368
6407
|
* click-and-type without rebuilding the complete document model. */
|
|
6369
6408
|
reparseDirectBodyParagraphSplits(beforeSource, afterSources) {
|
|
@@ -6687,6 +6726,8 @@ var DocxDocument = class _DocxDocument {
|
|
|
6687
6726
|
}
|
|
6688
6727
|
markNumberingChanged() {
|
|
6689
6728
|
this.numberingDirty = true;
|
|
6729
|
+
this.numbering = parseNumbering(this.numberingRoot ?? void 0, this.ctxBase);
|
|
6730
|
+
this._layoutGlobalSig = null;
|
|
6690
6731
|
}
|
|
6691
6732
|
/**
|
|
6692
6733
|
* Retained footnotes tree. With create=true, a missing footnotes.xml part
|
|
@@ -11719,6 +11760,7 @@ var Engine = class {
|
|
|
11719
11760
|
/** Per top-level block content signature, recorded during a captured layout
|
|
11720
11761
|
* so the next incremental layout can find the first changed block. */
|
|
11721
11762
|
this.incrSigs = null;
|
|
11763
|
+
this.incrLastNumberingUse = null;
|
|
11722
11764
|
/** Reuse points captured at clean page tops: the block index that starts the
|
|
11723
11765
|
* page and a snapshot of engine state to resume from. */
|
|
11724
11766
|
this.incrPoints = null;
|
|
@@ -11871,7 +11913,9 @@ var Engine = class {
|
|
|
11871
11913
|
}
|
|
11872
11914
|
startRun() {
|
|
11873
11915
|
if (this.incrEligible()) {
|
|
11874
|
-
|
|
11916
|
+
const blocks = this.doc.sections[0].blocks;
|
|
11917
|
+
this.incrSigs = blocks.map((b) => this.blockSig(b));
|
|
11918
|
+
this.incrLastNumberingUse = this.lastNumberingUse(blocks);
|
|
11875
11919
|
this.incrPoints = [];
|
|
11876
11920
|
}
|
|
11877
11921
|
this.assignNoteNumbers();
|
|
@@ -11945,6 +11989,7 @@ var Engine = class {
|
|
|
11945
11989
|
result._incr = {
|
|
11946
11990
|
sigs: this.incrSigs,
|
|
11947
11991
|
points: this.incrPoints,
|
|
11992
|
+
lastNumberingUse: this.incrLastNumberingUse,
|
|
11948
11993
|
pages: this.pages,
|
|
11949
11994
|
bookmarks: this.bookmarkPages,
|
|
11950
11995
|
bookmarkPageIndices: this.bookmarkPageIndices,
|
|
@@ -12055,6 +12100,43 @@ var Engine = class {
|
|
|
12055
12100
|
blockSig(block) {
|
|
12056
12101
|
return block.src ? hashXml(block.src) : "\0nosrc";
|
|
12057
12102
|
}
|
|
12103
|
+
blockNumberingKeys(block, keys) {
|
|
12104
|
+
if (block.type === "paragraph") {
|
|
12105
|
+
const numbering = this.doc.effectiveParaProps(block).numbering;
|
|
12106
|
+
const instance = numbering ? this.doc.numberingInstance(numbering.numId) : void 0;
|
|
12107
|
+
if (instance) keys.add(instance.abstractNumId);
|
|
12108
|
+
return;
|
|
12109
|
+
}
|
|
12110
|
+
for (const row of block.rows) {
|
|
12111
|
+
for (const cell of row.cells) {
|
|
12112
|
+
for (const nested of cell.blocks) this.blockNumberingKeys(nested, keys);
|
|
12113
|
+
}
|
|
12114
|
+
}
|
|
12115
|
+
}
|
|
12116
|
+
lastNumberingUse(blocks) {
|
|
12117
|
+
const lastUse = /* @__PURE__ */ new Map();
|
|
12118
|
+
for (let index = 0; index < blocks.length; index++) {
|
|
12119
|
+
const keys = /* @__PURE__ */ new Set();
|
|
12120
|
+
this.blockNumberingKeys(blocks[index], keys);
|
|
12121
|
+
for (const key of keys) lastUse.set(key, index);
|
|
12122
|
+
}
|
|
12123
|
+
return lastUse;
|
|
12124
|
+
}
|
|
12125
|
+
numberingCountersAffectLabels(abstractNumId) {
|
|
12126
|
+
const abstract = this.doc.numbering.abstract.get(abstractNumId);
|
|
12127
|
+
if (!abstract) return true;
|
|
12128
|
+
for (const level of abstract.levels.values()) {
|
|
12129
|
+
if (level.format !== "bullet" && level.format !== "none") return true;
|
|
12130
|
+
}
|
|
12131
|
+
for (const instance of this.doc.numbering.instances.values()) {
|
|
12132
|
+
if (instance.abstractNumId !== abstractNumId) continue;
|
|
12133
|
+
for (const override of instance.overrides.values()) {
|
|
12134
|
+
const format = override.level?.format;
|
|
12135
|
+
if (format && format !== "bullet" && format !== "none") return true;
|
|
12136
|
+
}
|
|
12137
|
+
}
|
|
12138
|
+
return false;
|
|
12139
|
+
}
|
|
12058
12140
|
/** PAGEREF rewrite: replace stale cached field text with the bookmark's real
|
|
12059
12141
|
* page. The right edge stays fixed so TOC right-tab page numbers keep align. */
|
|
12060
12142
|
rewritePageRefs(pages) {
|
|
@@ -12122,7 +12204,7 @@ var Engine = class {
|
|
|
12122
12204
|
if (this.incrPrevPoints && blockIdx > this.incrFirstDirty) {
|
|
12123
12205
|
const pp = this.incrPrevPoints.get(blockIdx);
|
|
12124
12206
|
const pageShift = pp ? globalPageIdx - pp.pageCount : 0;
|
|
12125
|
-
if (pp && this.statesMatch(pp.state, pageShift)) {
|
|
12207
|
+
if (pp && this.statesMatch(pp.state, pageShift, blockIdx)) {
|
|
12126
12208
|
__incrStats.convergedBlock = blockIdx;
|
|
12127
12209
|
__incrStats.convergedPage = globalPageIdx;
|
|
12128
12210
|
__incrStats.pageShift = pageShift;
|
|
@@ -12152,17 +12234,27 @@ var Engine = class {
|
|
|
12152
12234
|
/** True when the current engine state at a clean page top exactly matches a
|
|
12153
12235
|
* prev-layout capture point — i.e. the relaid tail has re-converged and the
|
|
12154
12236
|
* rest of the layout is guaranteed identical. */
|
|
12155
|
-
statesMatch(s, pageShift = 0) {
|
|
12237
|
+
statesMatch(s, pageShift = 0, blockIdx = 0) {
|
|
12156
12238
|
const p = this.cur;
|
|
12157
12239
|
if (this.col !== s.col || this.y !== s.y || this.sectionFirstPagePhys !== s.sectionFirstPagePhys || this.lastParaSpacingAfter !== s.lastParaSpacingAfter || this.lastParaAfterPad !== s.lastParaAfterPad || this.lastParaWasEmpty !== s.lastParaWasEmpty || this.trailingSectionBreakMarkGap !== s.trailingSectionBreakMarkGap || this.suppressNextSpaceBefore !== s.suppressNextSpaceBefore || this.docGridDropBefore !== s.docGridDropBefore || this.gridResyncPending !== s.gridResyncPending || this.verticalGridFlow !== s.verticalGridFlow || this.bannerSlotUsed !== s.bannerSlotUsed || p.physIndex !== s.page.physIndex + pageShift || p.displayNumber !== s.page.displayNumber + pageShift || p.bodyTop !== s.page.bodyTop || p.bodyBottom !== s.page.bodyBottom) {
|
|
12158
12240
|
return false;
|
|
12159
12241
|
}
|
|
12160
|
-
|
|
12161
|
-
|
|
12162
|
-
|
|
12163
|
-
|
|
12164
|
-
|
|
12165
|
-
|
|
12242
|
+
const numberingActive = (abstractNumId) => this.numberingCountersAffectLabels(abstractNumId) && (!this.incrLastNumberingUse || (this.incrLastNumberingUse.get(abstractNumId) ?? -1) >= blockIdx);
|
|
12243
|
+
const numIdActive = (numId) => {
|
|
12244
|
+
const instance = this.doc.numberingInstance(numId);
|
|
12245
|
+
return !instance || numberingActive(instance.abstractNumId);
|
|
12246
|
+
};
|
|
12247
|
+
const oldSeen = s.seenNumIds.filter(numIdActive);
|
|
12248
|
+
const newSeen = [...this.seenNumIds].filter(numIdActive);
|
|
12249
|
+
if (oldSeen.length !== newSeen.length) return false;
|
|
12250
|
+
for (const id of oldSeen) if (!this.seenNumIds.has(id)) return false;
|
|
12251
|
+
const oldCounters = new Map(s.counters);
|
|
12252
|
+
const counterKeys = /* @__PURE__ */ new Set([...oldCounters.keys(), ...this.counters.keys()]);
|
|
12253
|
+
for (const key of counterKeys) {
|
|
12254
|
+
if (!numberingActive(key)) continue;
|
|
12255
|
+
const w = oldCounters.get(key);
|
|
12256
|
+
const v = this.counters.get(key);
|
|
12257
|
+
if (!v || !w || w.length !== v.length) return false;
|
|
12166
12258
|
for (let i = 0; i < v.length; i++) if (v[i] !== w[i]) return false;
|
|
12167
12259
|
}
|
|
12168
12260
|
return true;
|
|
@@ -12366,6 +12458,20 @@ var Engine = class {
|
|
|
12366
12458
|
__incrStats.blocksHashed = blocks.length;
|
|
12367
12459
|
__incrStats.firstDirty = firstDirty;
|
|
12368
12460
|
}
|
|
12461
|
+
this.incrLastNumberingUse = new Map(
|
|
12462
|
+
[...inc.lastNumberingUse].map(([key, index]) => [
|
|
12463
|
+
key,
|
|
12464
|
+
index > this.incrBlockShiftAfter ? index + this.incrBlockDelta : index
|
|
12465
|
+
])
|
|
12466
|
+
);
|
|
12467
|
+
const changedEnd = Math.min(blocks.length - 1, firstDirty + Math.max(0, this.incrBlockDelta));
|
|
12468
|
+
for (let index = firstDirty; index <= changedEnd; index++) {
|
|
12469
|
+
const keys = /* @__PURE__ */ new Set();
|
|
12470
|
+
this.blockNumberingKeys(blocks[index], keys);
|
|
12471
|
+
for (const key of keys) {
|
|
12472
|
+
this.incrLastNumberingUse.set(key, Math.max(index, this.incrLastNumberingUse.get(key) ?? -1));
|
|
12473
|
+
}
|
|
12474
|
+
}
|
|
12369
12475
|
let rp;
|
|
12370
12476
|
for (const pt of inc.points) {
|
|
12371
12477
|
if (pt.blockIdx <= firstDirty) rp = pt;
|
|
@@ -12504,6 +12610,7 @@ var Engine = class {
|
|
|
12504
12610
|
_incr: {
|
|
12505
12611
|
sigs: newSigs,
|
|
12506
12612
|
points,
|
|
12613
|
+
lastNumberingUse: this.incrLastNumberingUse,
|
|
12507
12614
|
pages: outInternal,
|
|
12508
12615
|
bookmarks: mergedBookmarks,
|
|
12509
12616
|
bookmarkPageIndices: mergedBookmarkPageIndices,
|
|
@@ -14427,6 +14534,7 @@ var Engine = class {
|
|
|
14427
14534
|
}
|
|
14428
14535
|
floatOffset = clearBannerForLine(line2, li, floatOffset);
|
|
14429
14536
|
this.y += floatOffset;
|
|
14537
|
+
const lineItemStart = this.cur.items.length;
|
|
14430
14538
|
this.emitLine(line2, this.cur, this.colX, this.y);
|
|
14431
14539
|
if (props.tabs) {
|
|
14432
14540
|
for (const t of props.tabs) {
|
|
@@ -14448,12 +14556,16 @@ var Engine = class {
|
|
|
14448
14556
|
if (li === 0 && para.bookmarks) {
|
|
14449
14557
|
const pg = this.cur.physIndex === -1 ? this.lastRealPage : this.cur;
|
|
14450
14558
|
if (pg) {
|
|
14559
|
+
const target = this.cur.physIndex === -1 ? void 0 : this.cur.items.slice(lineItemStart).find((item) => item.kind === "text");
|
|
14560
|
+
const targets = [];
|
|
14451
14561
|
for (const bm of para.bookmarks) {
|
|
14452
14562
|
if (!this.bookmarkPages.has(bm)) {
|
|
14453
14563
|
this.bookmarkPages.set(bm, formatNumber(pg.displayNumber, PAGE_FMT[pg.sp.pageNumberFormat ?? "decimal"] ?? "decimal"));
|
|
14454
14564
|
this.bookmarkPageIndices.set(bm, pg.physIndex - 1);
|
|
14565
|
+
targets.push(bm);
|
|
14455
14566
|
}
|
|
14456
14567
|
}
|
|
14568
|
+
if (target && targets.length > 0) target.bookmarks = targets;
|
|
14457
14569
|
}
|
|
14458
14570
|
}
|
|
14459
14571
|
if (li === 0 && this.styleRefTrack && this.styleRefTrack.size > 0) {
|
|
@@ -17797,6 +17909,12 @@ function renderPageShell(page, zoom, options) {
|
|
|
17797
17909
|
el16.dataset.bodyTop = String(page.bodyTop);
|
|
17798
17910
|
el16.dataset.bodyBottom = String(page.bodyBottom);
|
|
17799
17911
|
el16.dataset.columnBands = JSON.stringify(page.columnBands);
|
|
17912
|
+
const bookmarks = {};
|
|
17913
|
+
for (const item of page.items) {
|
|
17914
|
+
if (item.kind !== "text" || !item.bookmarks) continue;
|
|
17915
|
+
for (const name of item.bookmarks) bookmarks[name] = (item.glyphTop ?? item.lineTop) * zoom;
|
|
17916
|
+
}
|
|
17917
|
+
if (Object.keys(bookmarks).length > 0) el16.dataset.bookmarks = JSON.stringify(bookmarks);
|
|
17800
17918
|
return el16;
|
|
17801
17919
|
}
|
|
17802
17920
|
function renderEmptyPageRecord(page, zoom, options) {
|
|
@@ -19431,17 +19549,22 @@ function renderText(item, interactive) {
|
|
|
19431
19549
|
}
|
|
19432
19550
|
if (item.href) {
|
|
19433
19551
|
const anchor = el16;
|
|
19552
|
+
const bookmark = item.href.startsWith("#") ? item.href.slice(1) : void 0;
|
|
19434
19553
|
anchor.href = item.href;
|
|
19435
|
-
|
|
19436
|
-
|
|
19554
|
+
if (!bookmark) {
|
|
19555
|
+
anchor.target = "_blank";
|
|
19556
|
+
anchor.rel = "noreferrer noopener";
|
|
19557
|
+
}
|
|
19437
19558
|
anchor.title = item.href;
|
|
19438
|
-
if (interactive) {
|
|
19559
|
+
if (interactive || bookmark) {
|
|
19439
19560
|
anchor.addEventListener("mouseup", (event) => {
|
|
19440
19561
|
if (event.metaKey || event.ctrlKey) event.stopPropagation();
|
|
19441
19562
|
});
|
|
19442
19563
|
anchor.addEventListener("click", (event) => {
|
|
19443
19564
|
event.preventDefault();
|
|
19444
|
-
if (event.metaKey || event.ctrlKey) {
|
|
19565
|
+
if (bookmark && (!interactive || event.metaKey || event.ctrlKey)) {
|
|
19566
|
+
scrollToBookmark(anchor, bookmark);
|
|
19567
|
+
} else if (!bookmark && (event.metaKey || event.ctrlKey)) {
|
|
19445
19568
|
window.open(anchor.href, "_blank", "noopener,noreferrer");
|
|
19446
19569
|
}
|
|
19447
19570
|
});
|
|
@@ -19456,6 +19579,20 @@ function renderText(item, interactive) {
|
|
|
19456
19579
|
setItemLayer(el16, item);
|
|
19457
19580
|
return el16;
|
|
19458
19581
|
}
|
|
19582
|
+
function scrollToBookmark(anchor, bookmark) {
|
|
19583
|
+
const root = anchor.closest(".dxw-pages");
|
|
19584
|
+
const container = root?.parentElement;
|
|
19585
|
+
if (!root || !container) return;
|
|
19586
|
+
for (const page of Array.from(root.children)) {
|
|
19587
|
+
if (!(page instanceof HTMLElement) || !page.dataset.bookmarks) continue;
|
|
19588
|
+
const bookmarks = JSON.parse(page.dataset.bookmarks);
|
|
19589
|
+
const y = bookmarks[bookmark];
|
|
19590
|
+
if (y === void 0) continue;
|
|
19591
|
+
const pageTop = page.getBoundingClientRect().top - container.getBoundingClientRect().top + container.scrollTop;
|
|
19592
|
+
container.scrollTo({ top: Math.max(0, pageTop + y - 24) });
|
|
19593
|
+
return;
|
|
19594
|
+
}
|
|
19595
|
+
}
|
|
19459
19596
|
function renderEdge(x1, y1, x2, y2, border, rotate) {
|
|
19460
19597
|
const el16 = document.createElement("div");
|
|
19461
19598
|
el16.dataset.dxwEdge = "1";
|
|
@@ -20927,13 +21064,7 @@ function listTypeAt(doc, target) {
|
|
|
20927
21064
|
const lvl = doc.numberingLevel(id, parseInt(attr(ilvl ?? { name: "", attrs: {}, children: [], text: "" }, "val") ?? "0", 10) || 0);
|
|
20928
21065
|
return lvl?.format === "bullet" ? "bullet" : "number";
|
|
20929
21066
|
}
|
|
20930
|
-
function
|
|
20931
|
-
for (const [numId2, inst] of doc.numbering.instances) {
|
|
20932
|
-
const lvl = doc.numberingLevel(numId2, 0);
|
|
20933
|
-
if (!lvl) continue;
|
|
20934
|
-
if (kind === "bullet" ? lvl.format === "bullet" : lvl.format === "decimal") return numId2;
|
|
20935
|
-
void inst;
|
|
20936
|
-
}
|
|
21067
|
+
function createListNum(doc, kind) {
|
|
20937
21068
|
const root = doc.numberingTree(true);
|
|
20938
21069
|
if (!root) return null;
|
|
20939
21070
|
const w = prefixOf6(root);
|
|
@@ -21007,7 +21138,7 @@ function setListType(doc, targets, kind) {
|
|
|
21007
21138
|
if (p) paragraphs.add(p);
|
|
21008
21139
|
}
|
|
21009
21140
|
if (paragraphs.size === 0) return false;
|
|
21010
|
-
const numId = kind === null ? null :
|
|
21141
|
+
const numId = kind === null ? null : createListNum(doc, kind);
|
|
21011
21142
|
if (kind !== null && numId === null) return false;
|
|
21012
21143
|
let touched = false;
|
|
21013
21144
|
for (const pEl of paragraphs) {
|
|
@@ -21037,7 +21168,17 @@ function setListType(doc, targets, kind) {
|
|
|
21037
21168
|
}
|
|
21038
21169
|
touched = true;
|
|
21039
21170
|
}
|
|
21040
|
-
if (touched)
|
|
21171
|
+
if (touched) {
|
|
21172
|
+
let reparsed = true;
|
|
21173
|
+
for (const paragraph of paragraphs) {
|
|
21174
|
+
if (!doc.reparseBodyParagraph(paragraph)) {
|
|
21175
|
+
reparsed = false;
|
|
21176
|
+
break;
|
|
21177
|
+
}
|
|
21178
|
+
invalidateParagraphSignature(paragraph);
|
|
21179
|
+
}
|
|
21180
|
+
if (!reparsed) doc.refresh();
|
|
21181
|
+
}
|
|
21041
21182
|
return touched;
|
|
21042
21183
|
}
|
|
21043
21184
|
|
|
@@ -28524,11 +28665,39 @@ var _DocxEditor = class _DocxEditor {
|
|
|
28524
28665
|
if (this.caret) {
|
|
28525
28666
|
const paragraph = paragraphOf(this.host.doc, this.caret.t);
|
|
28526
28667
|
if (paragraph && textElements(paragraph).every((text) => text.text.length === 0) && clearListParagraphFormatting(this.host.doc, paragraph)) {
|
|
28527
|
-
this.
|
|
28668
|
+
const reparsed2 = this.host.doc.reparseBodyParagraph(paragraph);
|
|
28669
|
+
if (reparsed2) {
|
|
28670
|
+
for (const child4 of reparsed2.children) {
|
|
28671
|
+
const runs = child4.type === "run" ? [child4] : child4.runs;
|
|
28672
|
+
const run = runs.find(
|
|
28673
|
+
(candidate) => candidate.content.some((content) => content.kind === "text" && content.srcT === this.caret.t)
|
|
28674
|
+
);
|
|
28675
|
+
if (run) {
|
|
28676
|
+
this.caret.run = run;
|
|
28677
|
+
break;
|
|
28678
|
+
}
|
|
28679
|
+
}
|
|
28680
|
+
invalidateParagraphSignature(paragraph);
|
|
28681
|
+
}
|
|
28682
|
+
this.commit(false, "local", !!reparsed2);
|
|
28528
28683
|
this.focusText();
|
|
28529
28684
|
return;
|
|
28530
28685
|
}
|
|
28531
28686
|
}
|
|
28687
|
+
const insertedBefore = this.insertBlankParagraphBeforeAtStart();
|
|
28688
|
+
if (insertedBefore) {
|
|
28689
|
+
const reparsed2 = this.host.doc.insertDirectBodyParagraphBefore(insertedBefore.reference, insertedBefore.blank);
|
|
28690
|
+
if (reparsed2) {
|
|
28691
|
+
const run = reparsed2.children.flatMap((child4) => child4.type === "run" ? [child4] : child4.runs).find(
|
|
28692
|
+
(candidate) => candidate.content.some((content) => content.kind === "text" && content.srcT === insertedBefore.text)
|
|
28693
|
+
);
|
|
28694
|
+
if (run) this.caret = { t: insertedBefore.text, run, offset: 0 };
|
|
28695
|
+
invalidateParagraphSignature(insertedBefore.blank);
|
|
28696
|
+
}
|
|
28697
|
+
this.commit(false, "local", !!reparsed2);
|
|
28698
|
+
this.focusText();
|
|
28699
|
+
return;
|
|
28700
|
+
}
|
|
28532
28701
|
const split = this.splitParagraphCore();
|
|
28533
28702
|
const reparsed = split ? this.host.doc.reparseDirectBodyParagraphSplit(split.before, split.after) : null;
|
|
28534
28703
|
if (reparsed && split && this.caret) {
|
|
@@ -28548,6 +28717,49 @@ var _DocxEditor = class _DocxEditor {
|
|
|
28548
28717
|
this.commit(false, "local", !!reparsed);
|
|
28549
28718
|
this.focusText();
|
|
28550
28719
|
}
|
|
28720
|
+
/** Enter at the exact paragraph start only needs a blank paragraph before
|
|
28721
|
+
* the existing content. Retaining the original paragraph keeps its parsed
|
|
28722
|
+
* model, fields, and bookmarks valid for incremental pagination. */
|
|
28723
|
+
insertBlankParagraphBeforeAtStart() {
|
|
28724
|
+
const caret = this.caret;
|
|
28725
|
+
if (!caret || caret.offset !== 0) return null;
|
|
28726
|
+
const rEl = this.host.doc.findParentOf(caret.t);
|
|
28727
|
+
if (!rEl || localName(rEl.name) !== "r") return null;
|
|
28728
|
+
let pEl = this.host.doc.findParentOf(rEl);
|
|
28729
|
+
while (pEl && localName(pEl.name) !== "p") pEl = this.host.doc.findParentOf(pEl);
|
|
28730
|
+
if (!pEl) return null;
|
|
28731
|
+
const texts = textElements(pEl);
|
|
28732
|
+
const textIndex = texts.indexOf(caret.t);
|
|
28733
|
+
if (textIndex < 0 || texts.slice(0, textIndex).some((text) => text.text.length > 0)) return null;
|
|
28734
|
+
const parent = this.host.doc.findParentOf(pEl);
|
|
28735
|
+
if (!parent) return null;
|
|
28736
|
+
const prefix = pEl.name.includes(":") ? pEl.name.slice(0, pEl.name.indexOf(":") + 1) : "";
|
|
28737
|
+
const pPr = pEl.children.find((child4) => localName(child4.name) === "pPr");
|
|
28738
|
+
const blankPPr = pPr ? cloneXml(pPr) : void 0;
|
|
28739
|
+
if (blankPPr) blankPPr.children = blankPPr.children.filter((child4) => localName(child4.name) !== "sectPr");
|
|
28740
|
+
const rPr = rEl.children.find((child4) => localName(child4.name) === "rPr");
|
|
28741
|
+
const blankText = {
|
|
28742
|
+
name: caret.t.name,
|
|
28743
|
+
attrs: { ...caret.t.attrs, "xml:space": "preserve" },
|
|
28744
|
+
text: "",
|
|
28745
|
+
children: []
|
|
28746
|
+
};
|
|
28747
|
+
const blankRun = {
|
|
28748
|
+
name: rEl.name,
|
|
28749
|
+
attrs: { ...rEl.attrs },
|
|
28750
|
+
text: "",
|
|
28751
|
+
children: [...rPr ? [cloneXml(rPr)] : [], blankText]
|
|
28752
|
+
};
|
|
28753
|
+
const blank = {
|
|
28754
|
+
name: prefix + "p",
|
|
28755
|
+
attrs: {},
|
|
28756
|
+
text: "",
|
|
28757
|
+
children: [...blankPPr ? [blankPPr] : [], blankRun]
|
|
28758
|
+
};
|
|
28759
|
+
parent.children.splice(parent.children.indexOf(pEl), 0, blank);
|
|
28760
|
+
if (this.suggesting) markParagraphGlyph(blank, "ins", this.revMeta());
|
|
28761
|
+
return { blank, reference: pEl, text: blankText };
|
|
28762
|
+
}
|
|
28551
28763
|
/** Split the paragraph at the caret without history or commit — shared by
|
|
28552
28764
|
* Enter and multi-line paste. */
|
|
28553
28765
|
splitParagraphCore() {
|
|
@@ -35344,9 +35556,10 @@ function DocxView({
|
|
|
35344
35556
|
const targets = segs.length > 0 ? segs.map((sg) => sg.t).filter((t) => !!t) : caret ? [caret.t] : [];
|
|
35345
35557
|
if (targets.length === 0) return;
|
|
35346
35558
|
const current = listTypeAt(doc, targets[0]);
|
|
35559
|
+
const dirtyBlock = targets.length === 1 ? topLevelBlockOf(doc, targets[0]) ?? void 0 : void 0;
|
|
35347
35560
|
history.checkpoint();
|
|
35348
35561
|
if (setListType(doc, targets, current === kind ? null : kind)) {
|
|
35349
|
-
pages = rerender(doc);
|
|
35562
|
+
pages = rerender(doc, dirtyBlock);
|
|
35350
35563
|
document.dispatchEvent(new CustomEvent("dxw-selection"));
|
|
35351
35564
|
}
|
|
35352
35565
|
},
|