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 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
- this.incrSigs = this.doc.sections[0].blocks.map((b) => this.blockSig(b));
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
- if (this.seenNumIds.size !== s.seenNumIds.length) return false;
12161
- for (const id of s.seenNumIds) if (!this.seenNumIds.has(id)) return false;
12162
- if (this.counters.size !== s.counters.length) return false;
12163
- for (const [k, w] of s.counters) {
12164
- const v = this.counters.get(k);
12165
- if (!v || w.length !== v.length) return false;
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
- anchor.target = "_blank";
19436
- anchor.rel = "noreferrer noopener";
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 ensureListNum(doc, kind) {
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 : ensureListNum(doc, kind);
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) doc.refresh();
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.commit();
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
  },