@windoc/core 0.3.23 → 0.3.24

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.js CHANGED
@@ -78,7 +78,7 @@ __export(index_exports, {
78
78
  module.exports = __toCommonJS(index_exports);
79
79
 
80
80
  // src/version.ts
81
- var version = "0.3.23";
81
+ var version = "0.3.24";
82
82
 
83
83
  // src/dataset/enum/Common.ts
84
84
  var MaxHeightRatio = /* @__PURE__ */ ((MaxHeightRatio2) => {
@@ -185,21 +185,6 @@ function debounce(func, delay) {
185
185
  }, delay);
186
186
  };
187
187
  }
188
- function deepCloneOmitKeys(obj, omitKeys) {
189
- if (!obj || typeof obj !== "object") {
190
- return obj;
191
- }
192
- let newObj = {};
193
- if (Array.isArray(obj)) {
194
- newObj = obj.map((item) => deepCloneOmitKeys(item, omitKeys));
195
- } else {
196
- Object.keys(obj).forEach((key) => {
197
- if (omitKeys.includes(key)) return;
198
- newObj[key] = deepCloneOmitKeys(obj[key], omitKeys);
199
- });
200
- }
201
- return newObj;
202
- }
203
188
  function deepClone(obj) {
204
189
  if (typeof structuredClone === "function") {
205
190
  return structuredClone(obj);
@@ -5023,9 +5008,7 @@ function mergeSplitTableRowsForZip(trList) {
5023
5008
  for (let t = trList.length - 1; t >= 0; t--) {
5024
5009
  const splitTr = trList[t];
5025
5010
  if (!splitTr.splitParentId) continue;
5026
- const parentTrIdx = trList.findIndex(
5027
- (tr) => tr.id === splitTr.splitParentId
5028
- );
5011
+ const parentTrIdx = trList.findIndex((tr) => tr.id === splitTr.splitParentId);
5029
5012
  if (!~parentTrIdx) continue;
5030
5013
  const parentTr = trList[parentTrIdx];
5031
5014
  parentTr.height += splitTr.height;
@@ -6071,10 +6054,184 @@ ${ulListStyleText || `${listIndex + 1}.`}${buildText(
6071
6054
  return buildText(zipElementList(elementList));
6072
6055
  }
6073
6056
  function getSlimCloneElementList(elementList) {
6074
- return deepCloneOmitKeys(elementList, [
6075
- "metrics",
6076
- "style"
6077
- ]);
6057
+ const snapshotElementList = [];
6058
+ let preSourceElement = null;
6059
+ let preSnapshotElement = null;
6060
+ for (let i = 0; i < elementList.length; i++) {
6061
+ const element = elementList[i];
6062
+ if (preSourceElement && preSnapshotElement && isHistoryTextSnapshotMergeable(preSourceElement, element)) {
6063
+ preSnapshotElement.value += element.value;
6064
+ preSourceElement = element;
6065
+ continue;
6066
+ }
6067
+ const snapshotElement = cloneHistorySnapshotElement(element);
6068
+ snapshotElementList.push(snapshotElement);
6069
+ preSourceElement = element;
6070
+ preSnapshotElement = snapshotElement;
6071
+ }
6072
+ return snapshotElementList;
6073
+ }
6074
+ var HISTORY_SNAPSHOT_OMIT_ATTR = /* @__PURE__ */ new Set([
6075
+ "metrics",
6076
+ "style",
6077
+ "rowList",
6078
+ "positionList",
6079
+ "x",
6080
+ "y",
6081
+ "trIndex",
6082
+ "tdIndex",
6083
+ "isLastRowTd",
6084
+ "isLastColTd",
6085
+ "isLastTd",
6086
+ "rowIndex",
6087
+ "colIndex",
6088
+ "mainHeight",
6089
+ "realHeight",
6090
+ "realMinHeight",
6091
+ "splitBoundaryTop",
6092
+ "splitBoundaryBottom",
6093
+ "actualSize"
6094
+ ]);
6095
+ function cloneHistorySnapshotValue(payload) {
6096
+ if (!payload || typeof payload !== "object") {
6097
+ return payload;
6098
+ }
6099
+ if (Array.isArray(payload)) {
6100
+ return payload.map((item) => cloneHistorySnapshotValue(item));
6101
+ }
6102
+ const snapshot = {};
6103
+ for (const key of Object.keys(payload)) {
6104
+ if (HISTORY_SNAPSHOT_OMIT_ATTR.has(String(key))) continue;
6105
+ snapshot[String(key)] = cloneHistorySnapshotValue(
6106
+ payload[key]
6107
+ );
6108
+ }
6109
+ return snapshot;
6110
+ }
6111
+ function cloneHistorySnapshotTd(td) {
6112
+ const snapshot = {};
6113
+ for (const key of Object.keys(td)) {
6114
+ if (HISTORY_SNAPSHOT_OMIT_ATTR.has(String(key))) continue;
6115
+ const value = td[key];
6116
+ if (key === "value") {
6117
+ snapshot.value = getSlimCloneElementList(value);
6118
+ continue;
6119
+ }
6120
+ snapshot[String(key)] = cloneHistorySnapshotValue(value);
6121
+ }
6122
+ return snapshot;
6123
+ }
6124
+ function cloneHistorySnapshotTr(tr) {
6125
+ const snapshot = {};
6126
+ for (const key of Object.keys(tr)) {
6127
+ if (HISTORY_SNAPSHOT_OMIT_ATTR.has(String(key))) continue;
6128
+ const value = tr[key];
6129
+ if (key === "tdList") {
6130
+ snapshot.tdList = value.map((td) => cloneHistorySnapshotTd(td));
6131
+ continue;
6132
+ }
6133
+ snapshot[String(key)] = cloneHistorySnapshotValue(value);
6134
+ }
6135
+ return snapshot;
6136
+ }
6137
+ function cloneHistorySnapshotElement(element) {
6138
+ const snapshot = {};
6139
+ for (const key of Object.keys(element)) {
6140
+ if (HISTORY_SNAPSHOT_OMIT_ATTR.has(String(key))) continue;
6141
+ const value = element[key];
6142
+ if (key === "trList" && Array.isArray(value)) {
6143
+ snapshot.trList = value.map((tr) => cloneHistorySnapshotTr(tr));
6144
+ continue;
6145
+ }
6146
+ if (key === "valueList" && Array.isArray(value)) {
6147
+ snapshot.valueList = getSlimCloneElementList(value);
6148
+ continue;
6149
+ }
6150
+ if (key === "control" && value && typeof value === "object") {
6151
+ snapshot.control = cloneHistorySnapshotControl(
6152
+ value
6153
+ );
6154
+ continue;
6155
+ }
6156
+ snapshot[String(key)] = cloneHistorySnapshotValue(value);
6157
+ }
6158
+ return snapshot;
6159
+ }
6160
+ function cloneHistorySnapshotControl(control) {
6161
+ const snapshot = {};
6162
+ for (const key of Object.keys(control)) {
6163
+ const value = control[key];
6164
+ if (key === "value" && Array.isArray(value)) {
6165
+ snapshot.value = getSlimCloneElementList(value);
6166
+ continue;
6167
+ }
6168
+ snapshot[String(key)] = cloneHistorySnapshotValue(value);
6169
+ }
6170
+ return snapshot;
6171
+ }
6172
+ function isHistoryTextSnapshotElement(element) {
6173
+ return !element.type || TEXTLIKE_ELEMENT_TYPE.includes(element.type);
6174
+ }
6175
+ function isHistoryTextSnapshotMergeable(source, target) {
6176
+ if (!isHistoryTextSnapshotElement(source) || !isHistoryTextSnapshotElement(target)) {
6177
+ return false;
6178
+ }
6179
+ return isSameHistoryElementExceptValue(source, target);
6180
+ }
6181
+ function isSameHistoryElementExceptValue(source, target) {
6182
+ const sourceKeys = Object.keys(source).filter(
6183
+ (key) => !HISTORY_SNAPSHOT_OMIT_ATTR.has(key)
6184
+ );
6185
+ const targetKeys = Object.keys(target).filter(
6186
+ (key) => !HISTORY_SNAPSHOT_OMIT_ATTR.has(key)
6187
+ );
6188
+ if (sourceKeys.length !== targetKeys.length) return false;
6189
+ for (let s = 0; s < sourceKeys.length; s++) {
6190
+ const key = sourceKeys[s];
6191
+ if (key === "value") continue;
6192
+ if (key === "groupIds" && Array.isArray(source[key]) && Array.isArray(target[key]) && isArrayEqual(source[key], target[key])) {
6193
+ continue;
6194
+ }
6195
+ if (source[key] !== target[key]) {
6196
+ return false;
6197
+ }
6198
+ }
6199
+ return true;
6200
+ }
6201
+ function inflateElementList(elementList) {
6202
+ let i = 0;
6203
+ while (i < elementList.length) {
6204
+ const element = elementList[i];
6205
+ if (element.trList?.length) {
6206
+ for (let t = 0; t < element.trList.length; t++) {
6207
+ const tr = element.trList[t];
6208
+ for (let d = 0; d < tr.tdList.length; d++) {
6209
+ inflateElementList(tr.tdList[d].value);
6210
+ }
6211
+ }
6212
+ }
6213
+ if (element.valueList?.length) {
6214
+ inflateElementList(element.valueList);
6215
+ }
6216
+ if (element.control?.value?.length) {
6217
+ inflateElementList(element.control.value);
6218
+ }
6219
+ if (isHistoryTextSnapshotElement(element) && element.value?.length > 1) {
6220
+ const textList = splitText(element.value);
6221
+ elementList.splice(
6222
+ i,
6223
+ 1,
6224
+ ...textList.map((value) => ({
6225
+ ...element,
6226
+ value
6227
+ }))
6228
+ );
6229
+ i += textList.length;
6230
+ continue;
6231
+ }
6232
+ i++;
6233
+ }
6234
+ return elementList;
6078
6235
  }
6079
6236
  function getIsBlockElement(element) {
6080
6237
  return !!element?.type && (BLOCK_ELEMENT_TYPE.includes(element.type) || element.imgDisplay === "inline" /* INLINE */);
@@ -7747,7 +7904,8 @@ function backspace(evt, host) {
7747
7904
  } else {
7748
7905
  rangeManager.setRange(curIndex, curIndex);
7749
7906
  draw.render({
7750
- curIndex
7907
+ curIndex,
7908
+ dirtyStartIndex: curIndex + 1
7751
7909
  });
7752
7910
  }
7753
7911
  }
@@ -7889,7 +8047,8 @@ function del(evt, host) {
7889
8047
  } else {
7890
8048
  rangeManager.setRange(curIndex, curIndex);
7891
8049
  draw.render({
7892
- curIndex
8050
+ curIndex,
8051
+ dirtyStartIndex: curIndex + 1
7893
8052
  });
7894
8053
  }
7895
8054
  }
@@ -8731,10 +8890,12 @@ function input(data2, host) {
8731
8890
  if (~curIndex) {
8732
8891
  rangeManager.setRange(curIndex, curIndex);
8733
8892
  const isWordBoundary = !isComposing && /[\s\p{P}]/u.test(data2);
8893
+ const dirtyStartIndex = startIndex + 1;
8734
8894
  draw.render({
8735
8895
  curIndex,
8736
8896
  isSubmitHistory: !isComposing,
8737
- isInputHistory: !isComposing && !isWordBoundary
8897
+ isInputHistory: !isComposing && !isWordBoundary,
8898
+ dirtyStartIndex
8738
8899
  });
8739
8900
  }
8740
8901
  if (isComposing && ~curIndex) {
@@ -9418,7 +9579,7 @@ var HistoryManager = class {
9418
9579
  const pop = this.undoStack.pop();
9419
9580
  this.redoStack.push(pop);
9420
9581
  if (this.undoStack.length) {
9421
- this.undoStack[this.undoStack.length - 1]();
9582
+ this.undoStack[this.undoStack.length - 1].restore();
9422
9583
  }
9423
9584
  }
9424
9585
  }
@@ -9426,11 +9587,11 @@ var HistoryManager = class {
9426
9587
  if (this.redoStack.length) {
9427
9588
  const pop = this.redoStack.pop();
9428
9589
  this.undoStack.push(pop);
9429
- pop();
9590
+ pop.restore();
9430
9591
  }
9431
9592
  }
9432
- execute(fn) {
9433
- this.undoStack.push(fn);
9593
+ execute(entry) {
9594
+ this.undoStack.push(this._normalizeEntry(entry));
9434
9595
  if (this.redoStack.length) {
9435
9596
  this.redoStack = [];
9436
9597
  }
@@ -9438,11 +9599,12 @@ var HistoryManager = class {
9438
9599
  this.undoStack.shift();
9439
9600
  }
9440
9601
  }
9441
- replaceLatest(fn) {
9602
+ replaceLatest(entry) {
9603
+ const normalizedEntry = this._normalizeEntry(entry);
9442
9604
  if (this.undoStack.length > 0) {
9443
- this.undoStack[this.undoStack.length - 1] = fn;
9605
+ this.undoStack[this.undoStack.length - 1] = normalizedEntry;
9444
9606
  } else {
9445
- this.execute(fn);
9607
+ this.execute(normalizedEntry);
9446
9608
  }
9447
9609
  if (this.redoStack.length) {
9448
9610
  this.redoStack = [];
@@ -9473,6 +9635,14 @@ var HistoryManager = class {
9473
9635
  popUndo() {
9474
9636
  return this.undoStack.pop();
9475
9637
  }
9638
+ _normalizeEntry(entry) {
9639
+ if (typeof entry === "function") {
9640
+ return {
9641
+ restore: entry
9642
+ };
9643
+ }
9644
+ return entry;
9645
+ }
9476
9646
  };
9477
9647
 
9478
9648
  // src/core/position/Position.ts
@@ -11680,6 +11850,7 @@ var ScrollObserver = class {
11680
11850
  const { intersectionPageNo, visiblePageNoList } = this.getPageVisibleInfo();
11681
11851
  this.draw.setIntersectionPageNo(intersectionPageNo);
11682
11852
  this.draw.setVisiblePageNoList(visiblePageNoList);
11853
+ this.draw.renderVisiblePages(visiblePageNoList);
11683
11854
  }, 150);
11684
11855
  this.draw = draw;
11685
11856
  this.options = draw.getOptions();
@@ -20487,6 +20658,9 @@ var Area = class {
20487
20658
  getAreaInfo() {
20488
20659
  return this.areaInfoMap;
20489
20660
  }
20661
+ clear() {
20662
+ this.areaInfoMap.clear();
20663
+ }
20490
20664
  getActiveAreaId() {
20491
20665
  if (!this.areaInfoMap.size) return null;
20492
20666
  const { startIndex } = this.range.getRange();
@@ -20878,6 +21052,7 @@ var Draw = class {
20878
21052
  this.container = this._wrapContainer(rootContainer);
20879
21053
  this.pageList = [];
20880
21054
  this.ctxList = [];
21055
+ this.pageRenderVersionList = [];
20881
21056
  this.pageNo = 0;
20882
21057
  this.renderCount = 0;
20883
21058
  this.pagePixelRatio = null;
@@ -20890,6 +21065,7 @@ var Draw = class {
20890
21065
  this._formatContainer();
20891
21066
  this.pageContainer = this._createPageContainer();
20892
21067
  this._createPage(0);
21068
+ this.measureCtx = this._createMeasureContext();
20893
21069
  this.i18n = new I18n(options.locale);
20894
21070
  this.historyManager = new HistoryManager(this);
20895
21071
  this.position = new Position(this);
@@ -20954,6 +21130,8 @@ var Draw = class {
20954
21130
  this.pageRowList = [];
20955
21131
  this.painterStyle = null;
20956
21132
  this.painterOptions = null;
21133
+ this.elementFontCache = /* @__PURE__ */ new WeakMap();
21134
+ this.elementRowMarginCache = /* @__PURE__ */ new WeakMap();
20957
21135
  this.visiblePageNoList = [];
20958
21136
  this.intersectionPageNo = 0;
20959
21137
  this.lazyRenderIntersectionObserver = null;
@@ -21120,7 +21298,9 @@ var Draw = class {
21120
21298
  getContextInnerWidth() {
21121
21299
  const positionContext = this.position.getPositionContext();
21122
21300
  if (positionContext.isTable) {
21123
- const td = this.resolveTableCellContext(this.getOriginalElementList())?.td;
21301
+ const td = this.resolveTableCellContext(
21302
+ this.getOriginalElementList()
21303
+ )?.td;
21124
21304
  if (!td) return this.getColumnWidth() / this.options.scale;
21125
21305
  const tdPadding = this.getTdPadding();
21126
21306
  return td.width - tdPadding[1] - tdPadding[3];
@@ -21173,6 +21353,7 @@ var Draw = class {
21173
21353
  return this.visiblePageNoList;
21174
21354
  }
21175
21355
  setVisiblePageNoList(payload) {
21356
+ if (isArrayEqual(this.visiblePageNoList, payload)) return;
21176
21357
  this.visiblePageNoList = payload;
21177
21358
  if (this.listener.visiblePageNoListChange) {
21178
21359
  this.listener.visiblePageNoListChange(this.visiblePageNoList);
@@ -21185,6 +21366,7 @@ var Draw = class {
21185
21366
  return this.intersectionPageNo;
21186
21367
  }
21187
21368
  setIntersectionPageNo(payload) {
21369
+ if (this.intersectionPageNo === payload) return;
21188
21370
  this.intersectionPageNo = payload;
21189
21371
  if (this.listener.intersectionPageNoChange) {
21190
21372
  this.listener.intersectionPageNoChange(this.intersectionPageNo);
@@ -21212,7 +21394,9 @@ var Draw = class {
21212
21394
  candidateIndexes.push(context.index);
21213
21395
  }
21214
21396
  if (context.tableId) {
21215
- const tableIndex = sourceElementList.findIndex((el) => el.id === context.tableId);
21397
+ const tableIndex = sourceElementList.findIndex(
21398
+ (el) => el.id === context.tableId
21399
+ );
21216
21400
  if (~tableIndex && !candidateIndexes.includes(tableIndex)) {
21217
21401
  candidateIndexes.push(tableIndex);
21218
21402
  }
@@ -21321,9 +21505,7 @@ var Draw = class {
21321
21505
  return this.header.getElementList();
21322
21506
  }
21323
21507
  getTableElementList(sourceElementList) {
21324
- const splitCellSelectionContext = this.getSplitCellSelectionContext(
21325
- sourceElementList
21326
- );
21508
+ const splitCellSelectionContext = this.getSplitCellSelectionContext(sourceElementList);
21327
21509
  if (splitCellSelectionContext) {
21328
21510
  return splitCellSelectionContext.value;
21329
21511
  }
@@ -21447,10 +21629,7 @@ var Draw = class {
21447
21629
  positionContext.trId = continuationTr.id;
21448
21630
  positionContext.tableId = tableId;
21449
21631
  this.position.setPositionContext(positionContext);
21450
- this.range.setRange(
21451
- continuationCursorIndex,
21452
- continuationCursorIndex
21453
- );
21632
+ this.range.setRange(continuationCursorIndex, continuationCursorIndex);
21454
21633
  this.pendingTableCursorIndex = continuationCursorIndex;
21455
21634
  return true;
21456
21635
  }
@@ -21510,7 +21689,10 @@ var Draw = class {
21510
21689
  });
21511
21690
  const splitCellSelection = this.range.getSplitCellSelection();
21512
21691
  if (splitCellSelection) {
21513
- const curIndex2 = this.replaceSplitCellSelection(payload, splitCellSelection);
21692
+ const curIndex2 = this.replaceSplitCellSelection(
21693
+ payload,
21694
+ splitCellSelection
21695
+ );
21514
21696
  if (~curIndex2) {
21515
21697
  this.range.setRange(curIndex2, curIndex2);
21516
21698
  this.render({
@@ -21640,12 +21822,7 @@ var Draw = class {
21640
21822
  trId: rootCellContext.tr.id,
21641
21823
  tdId: rootTd.id
21642
21824
  });
21643
- this.spliceElementList(
21644
- rootTd.value,
21645
- 1,
21646
- rootTd.value.length - 1,
21647
- payload
21648
- );
21825
+ this.spliceElementList(rootTd.value, 1, rootTd.value.length - 1, payload);
21649
21826
  rootTd.rowList = void 0;
21650
21827
  rootTd.positionList = void 0;
21651
21828
  rootTd.mainHeight = void 0;
@@ -22065,6 +22242,15 @@ var Draw = class {
22065
22242
  this._initPageContext(ctx);
22066
22243
  this.pageList.push(canvas);
22067
22244
  this.ctxList.push(ctx);
22245
+ this.pageRenderVersionList.push(0);
22246
+ }
22247
+ _createMeasureContext() {
22248
+ const canvas = document.createElement("canvas");
22249
+ const ctx = canvas.getContext("2d");
22250
+ ctx.letterSpacing = "0px";
22251
+ ctx.wordSpacing = "0px";
22252
+ ctx.direction = "ltr";
22253
+ return ctx;
22068
22254
  }
22069
22255
  _initPageContext(ctx) {
22070
22256
  const dpr = this.getPagePixelRatio();
@@ -22077,8 +22263,22 @@ var Draw = class {
22077
22263
  const { defaultSize, defaultFont } = this.options;
22078
22264
  const font = el.font || defaultFont;
22079
22265
  const size = el.actualSize || el.size || defaultSize;
22266
+ const cache = this.elementFontCache.get(el);
22267
+ if (cache && cache.scale === scale && cache.font === font && cache.size === size && cache.actualSize === el.actualSize && cache.bold === el.bold && cache.italic === el.italic) {
22268
+ return cache.style;
22269
+ }
22080
22270
  const sizePx = size * (96 / 72) * scale;
22081
- return `${el.italic ? "italic " : ""}${el.bold ? "bold " : ""}${sizePx}px ${font}`;
22271
+ const style = `${el.italic ? "italic " : ""}${el.bold ? "bold " : ""}${sizePx}px ${font}`;
22272
+ this.elementFontCache.set(el, {
22273
+ scale,
22274
+ font,
22275
+ size,
22276
+ actualSize: el.actualSize,
22277
+ bold: el.bold,
22278
+ italic: el.italic,
22279
+ style
22280
+ });
22281
+ return style;
22082
22282
  }
22083
22283
  getElementSize(el) {
22084
22284
  return el.actualSize || el.size || this.options.defaultSize;
@@ -22091,13 +22291,25 @@ var Draw = class {
22091
22291
  scale
22092
22292
  } = this.options;
22093
22293
  const fontSize = el.size || defaultSize;
22294
+ const rowMarginValue = el.rowMargin ?? defaultRowMargin;
22295
+ const cache = this.elementRowMarginCache.get(el);
22296
+ if (cache && cache.scale === scale && cache.size === fontSize && cache.rowMargin === rowMarginValue) {
22297
+ return cache.value;
22298
+ }
22094
22299
  let ratio = 1;
22095
22300
  if (fontSize < 12) {
22096
22301
  ratio = fontSize / 12;
22097
22302
  } else if (fontSize > 30) {
22098
22303
  ratio = 1 + (fontSize - 30) / 30;
22099
22304
  }
22100
- return defaultBasicRowMarginHeight * ratio * (el.rowMargin ?? defaultRowMargin) * scale;
22305
+ const value = defaultBasicRowMarginHeight * ratio * rowMarginValue * scale;
22306
+ this.elementRowMarginCache.set(el, {
22307
+ scale,
22308
+ size: fontSize,
22309
+ rowMargin: rowMarginValue,
22310
+ value
22311
+ });
22312
+ return value;
22101
22313
  }
22102
22314
  createListStateSeed(initialListState) {
22103
22315
  const listLevelIndex = /* @__PURE__ */ new Map();
@@ -22176,7 +22388,12 @@ var Draw = class {
22176
22388
  pageHeight = 0,
22177
22389
  mainOuterHeight = 0,
22178
22390
  surroundElementList = [],
22179
- initialListState
22391
+ initialListState,
22392
+ hasListElement = true,
22393
+ fromIndex = 0,
22394
+ initialY = startY,
22395
+ initialPageNo = 0,
22396
+ initialRowIndex = 0
22180
22397
  } = payload;
22181
22398
  const {
22182
22399
  defaultSize,
@@ -22185,27 +22402,62 @@ var Draw = class {
22185
22402
  defaultTabWidth
22186
22403
  } = this.options;
22187
22404
  const defaultBasicRowMarginHeight = this.getDefaultBasicRowMarginHeight();
22188
- const canvas = document.createElement("canvas");
22189
- const ctx = canvas.getContext("2d");
22190
- const listStyleMap = this.listParticle.computeListStyle(ctx, elementList);
22405
+ const ctx = this.measureCtx;
22406
+ ctx.save();
22407
+ ctx.font = "10px sans-serif";
22408
+ ctx.textAlign = "start";
22409
+ ctx.textBaseline = "alphabetic";
22410
+ const listStyleMap = hasListElement ? this.listParticle.computeListStyle(ctx, elementList) : /* @__PURE__ */ new Map();
22411
+ const wordMeasureCache = /* @__PURE__ */ new Map();
22412
+ const getWordMeasure = (curIndex, elementFont) => {
22413
+ const cache = wordMeasureCache.get(curIndex);
22414
+ if (cache) return cache;
22415
+ let endIndex = curIndex;
22416
+ while (endIndex < elementList.length) {
22417
+ const measureElement = elementList[endIndex];
22418
+ if (measureElement.type && measureElement.type !== "text" /* TEXT */ || !this.LETTER_REG.test(measureElement.value)) {
22419
+ break;
22420
+ }
22421
+ if (this.getElementFont(measureElement) !== elementFont) {
22422
+ const fallbackWord = this.textParticle.measureWord(
22423
+ ctx,
22424
+ elementList,
22425
+ curIndex
22426
+ );
22427
+ wordMeasureCache.set(curIndex, fallbackWord);
22428
+ return fallbackWord;
22429
+ }
22430
+ endIndex++;
22431
+ }
22432
+ const endElement = elementList[endIndex] || null;
22433
+ let suffixWidth = 0;
22434
+ for (let i = endIndex - 1; i >= curIndex; i--) {
22435
+ suffixWidth += this.textParticle.measureText(ctx, elementList[i]).width;
22436
+ wordMeasureCache.set(i, {
22437
+ width: suffixWidth,
22438
+ endElement
22439
+ });
22440
+ }
22441
+ return wordMeasureCache.get(curIndex);
22442
+ };
22191
22443
  const rowList = [];
22192
- if (elementList.length) {
22444
+ if (elementList.length && fromIndex < elementList.length) {
22193
22445
  rowList.push({
22194
22446
  width: 0,
22195
22447
  height: 0,
22196
22448
  ascent: 0,
22197
22449
  elementList: [],
22198
- startIndex: 0,
22199
- rowIndex: 0,
22200
- rowFlex: elementList?.[0]?.rowFlex || elementList?.[1]?.rowFlex
22450
+ startIndex: fromIndex,
22451
+ rowIndex: initialRowIndex,
22452
+ rowFlex: elementList?.[fromIndex]?.rowFlex || elementList?.[fromIndex + 1]?.rowFlex
22201
22453
  });
22202
22454
  }
22203
22455
  let x = startX;
22204
- let y = startY;
22205
- let pageNo = 0;
22456
+ let y = initialY;
22457
+ let pageNo = initialPageNo;
22206
22458
  const listState = this.createListStateSeed(initialListState);
22207
22459
  let controlRealWidth = 0;
22208
- for (let i = 0; i < elementList.length; i++) {
22460
+ for (let i = fromIndex; i < elementList.length; i++) {
22209
22461
  const curRow = rowList[rowList.length - 1];
22210
22462
  const element = elementList[i];
22211
22463
  const rowMargin = this.getElementRowMargin(element);
@@ -22251,9 +22503,7 @@ var Draw = class {
22251
22503
  } else if (element.type === "table" /* TABLE */) {
22252
22504
  let activeSplitRange;
22253
22505
  let mergedSplitFallback;
22254
- const logicalSplitCursor = this.getCollapsedSplitTableCursorContext(
22255
- element
22256
- );
22506
+ const logicalSplitCursor = this.getCollapsedSplitTableCursorContext(element);
22257
22507
  if (element.pagingId) {
22258
22508
  let tableIndex = i + 1;
22259
22509
  let combineCount = 0;
@@ -22858,16 +23108,14 @@ var Draw = class {
22858
23108
  element.actualSize = Math.ceil(size * 0.6);
22859
23109
  }
22860
23110
  metrics.height = (element.actualSize || size) * scale;
22861
- ctx.font = this.getElementFont(element);
23111
+ const elementFont = this.getElementFont(element);
23112
+ ctx.font = elementFont;
22862
23113
  const fontMetrics = this.textParticle.measureText(ctx, element);
22863
23114
  metrics.width = fontMetrics.width * scale;
22864
23115
  if (element.letterSpacing) {
22865
23116
  metrics.width += element.letterSpacing * scale;
22866
23117
  }
22867
- const basisMetrics = this.textParticle.measureBasisWord(
22868
- ctx,
22869
- element.font
22870
- );
23118
+ const basisMetrics = this.textParticle.measureBasisWord(ctx, elementFont);
22871
23119
  metrics.boundingBoxAscent = basisMetrics.fontBoundingBoxAscent * scale;
22872
23120
  metrics.boundingBoxDescent = basisMetrics.fontBoundingBoxDescent * scale;
22873
23121
  if (element.type === "superscript" /* SUPERSCRIPT */) {
@@ -22904,11 +23152,7 @@ var Draw = class {
22904
23152
  if ((!preElement?.type || preElement?.type === "text" /* TEXT */) && (!element.type || element.type === "text" /* TEXT */)) {
22905
23153
  const word = `${preElement?.value || ""}${element.value}`;
22906
23154
  if (this.WORD_LIKE_REG.test(word)) {
22907
- const { width, endElement } = this.textParticle.measureWord(
22908
- ctx,
22909
- elementList,
22910
- i
22911
- );
23155
+ const { width, endElement } = getWordMeasure(i, ctx.font);
22912
23156
  const wordWidth = width * scale;
22913
23157
  if (endElement && wordWidth <= availableWidth) {
22914
23158
  curRowWidth += wordWidth;
@@ -23041,6 +23285,7 @@ var Draw = class {
23041
23285
  x += metrics.width;
23042
23286
  }
23043
23287
  }
23288
+ ctx.restore();
23044
23289
  return rowList;
23045
23290
  }
23046
23291
  _applyRowSpacing() {
@@ -23633,30 +23878,11 @@ var Draw = class {
23633
23878
  if (this.isGraffitiMode()) {
23634
23879
  this.graffiti.render(ctx, pageNo);
23635
23880
  }
23881
+ this.pageRenderVersionList[pageNo] = this.renderCount;
23636
23882
  }
23637
23883
  _disconnectLazyRender() {
23638
23884
  this.lazyRenderIntersectionObserver?.disconnect();
23639
- }
23640
- _lazyRender() {
23641
- const positionList = this.position.getOriginalMainPositionList();
23642
- const elementList = this.getOriginalMainElementList();
23643
- this._disconnectLazyRender();
23644
- this.lazyRenderIntersectionObserver = new IntersectionObserver((entries) => {
23645
- entries.forEach((entry) => {
23646
- if (entry.isIntersecting) {
23647
- const index = Number(entry.target.dataset.index);
23648
- this._drawPage({
23649
- elementList,
23650
- positionList,
23651
- rowList: this.pageRowList[index],
23652
- pageNo: index
23653
- });
23654
- }
23655
- });
23656
- });
23657
- this.pageList.forEach((el) => {
23658
- this.lazyRenderIntersectionObserver.observe(el);
23659
- });
23885
+ this.lazyRenderIntersectionObserver = null;
23660
23886
  }
23661
23887
  _immediateRender() {
23662
23888
  const positionList = this.position.getOriginalMainPositionList();
@@ -23670,6 +23896,100 @@ var Draw = class {
23670
23896
  });
23671
23897
  }
23672
23898
  }
23899
+ _collectMainRenderMeta() {
23900
+ const surroundElementList = [];
23901
+ let hasAreaElement = false;
23902
+ let hasListElement = false;
23903
+ let hasStructuralElement = false;
23904
+ for (let i = 0; i < this.elementList.length; i++) {
23905
+ const element = this.elementList[i];
23906
+ if (!hasAreaElement && element.areaId) {
23907
+ hasAreaElement = true;
23908
+ }
23909
+ if (!hasListElement && element.listId) {
23910
+ hasListElement = true;
23911
+ }
23912
+ if (!hasStructuralElement && (element.type === "table" /* TABLE */ || element.type === "block" /* BLOCK */ || element.type === "pageBreak" /* PAGE_BREAK */ || element.type === "columnBreak" /* COLUMN_BREAK */ || element.type === "image" /* IMAGE */ || element.type === "latex" /* LATEX */ || element.type === "separator" /* SEPARATOR */)) {
23913
+ hasStructuralElement = true;
23914
+ }
23915
+ if (element.imgDisplay === "surround" /* SURROUND */) {
23916
+ surroundElementList.push(element);
23917
+ }
23918
+ }
23919
+ return {
23920
+ hasAreaElement,
23921
+ hasListElement,
23922
+ hasStructuralElement,
23923
+ surroundElementList
23924
+ };
23925
+ }
23926
+ _getIncrementalRestartState(dirtyStartIndex, rowList, pageRowList, startY) {
23927
+ if (!rowList.length || !pageRowList.length) return null;
23928
+ const searchIndex = Math.max(dirtyStartIndex - 1, 0);
23929
+ let restartRowIndex = -1;
23930
+ for (let i = 0; i < rowList.length; i++) {
23931
+ if (rowList[i].startIndex <= searchIndex) {
23932
+ restartRowIndex = i;
23933
+ } else {
23934
+ break;
23935
+ }
23936
+ }
23937
+ if (restartRowIndex < 0) return null;
23938
+ if (restartRowIndex > 0 && this.elementList[rowList[restartRowIndex].startIndex]?.value === ZERO && !this.elementList[rowList[restartRowIndex].startIndex]?.listWrap) {
23939
+ restartRowIndex -= 1;
23940
+ }
23941
+ const restartRow = rowList[restartRowIndex];
23942
+ const fromIndex = Math.min(restartRow.startIndex, this.elementList.length);
23943
+ let initialPageNo = 0;
23944
+ let initialY = startY;
23945
+ let absoluteRowIndex = 0;
23946
+ let isFound = false;
23947
+ for (let pageNo = 0; pageNo < pageRowList.length; pageNo++) {
23948
+ const rows = pageRowList[pageNo];
23949
+ let y = startY;
23950
+ for (let rowNo = 0; rowNo < rows.length; rowNo++) {
23951
+ if (absoluteRowIndex === restartRowIndex) {
23952
+ initialPageNo = pageNo;
23953
+ initialY = y;
23954
+ isFound = true;
23955
+ break;
23956
+ }
23957
+ const row = rows[rowNo];
23958
+ y += (row.offsetY || 0) + (row.spaceAbove || 0) + row.height + (row.spaceBelow || 0);
23959
+ absoluteRowIndex++;
23960
+ }
23961
+ if (isFound) break;
23962
+ }
23963
+ if (!isFound) return null;
23964
+ return {
23965
+ fromIndex,
23966
+ initialY,
23967
+ initialPageNo,
23968
+ initialRowIndex: restartRow.rowIndex,
23969
+ initialListState: this.getListStateBeforeIndex(this.elementList, fromIndex),
23970
+ prefixRows: rowList.slice(0, restartRowIndex)
23971
+ };
23972
+ }
23973
+ renderVisiblePages(pageNoList) {
23974
+ const positionList = this.position.getOriginalMainPositionList();
23975
+ const elementList = this.getOriginalMainElementList();
23976
+ const targetPageNoList = pageNoList ?? this.visiblePageNoList;
23977
+ if (!targetPageNoList?.length) return;
23978
+ const renderedPageNoSet = /* @__PURE__ */ new Set();
23979
+ for (let i = 0; i < targetPageNoList.length; i++) {
23980
+ const pageNo = targetPageNoList[i];
23981
+ if (renderedPageNoSet.has(pageNo) || pageNo < 0 || pageNo >= this.pageRowList.length || this.pageRenderVersionList[pageNo] === this.renderCount) {
23982
+ continue;
23983
+ }
23984
+ renderedPageNoSet.add(pageNo);
23985
+ this._drawPage({
23986
+ elementList,
23987
+ positionList,
23988
+ rowList: this.pageRowList[pageNo],
23989
+ pageNo
23990
+ });
23991
+ }
23992
+ }
23673
23993
  render(payload) {
23674
23994
  this.renderCount++;
23675
23995
  const { header, footer } = this.options;
@@ -23681,15 +24001,19 @@ var Draw = class {
23681
24001
  isLazy = true,
23682
24002
  isInit = false,
23683
24003
  isSourceHistory = false,
23684
- isFirstRender = false
24004
+ isFirstRender = false,
24005
+ dirtyStartIndex
23685
24006
  } = payload || {};
23686
24007
  let { curIndex } = payload || {};
23687
24008
  this.pendingTableCursorIndex = void 0;
23688
24009
  const innerWidth = this.getInnerWidth();
23689
24010
  const columnWidth = this.getColumnWidth();
23690
24011
  const isPagingMode = this.getIsPagingMode();
24012
+ const columnCount = this.getColumnCount();
23691
24013
  const oldPageSize = this.pageRowList.length;
23692
24014
  if (isCompute) {
24015
+ const oldRowList = this.rowList;
24016
+ const oldPageRowList = this.pageRowList;
23693
24017
  this.position.setFloatPositionList([]);
23694
24018
  if (isPagingMode) {
23695
24019
  if (!header.disabled) {
@@ -23705,8 +24029,13 @@ var Draw = class {
23705
24029
  const mainOuterHeight = this.getMainOuterHeight();
23706
24030
  const startX = margins[3];
23707
24031
  const startY = margins[0] + extraHeight;
23708
- const surroundElementList = pickSurroundElementList(this.elementList);
23709
- this.rowList = this.computeRowList({
24032
+ const {
24033
+ hasAreaElement,
24034
+ hasListElement,
24035
+ hasStructuralElement,
24036
+ surroundElementList
24037
+ } = this._collectMainRenderMeta();
24038
+ const rowListPayload = {
23710
24039
  startX,
23711
24040
  startY,
23712
24041
  pageHeight,
@@ -23714,12 +24043,41 @@ var Draw = class {
23714
24043
  isPagingMode,
23715
24044
  innerWidth: columnWidth,
23716
24045
  surroundElementList,
24046
+ hasListElement,
23717
24047
  elementList: this.elementList
23718
- });
24048
+ };
24049
+ const canUseIncrementalMainRows = dirtyStartIndex !== void 0 && dirtyStartIndex >= 0 && !isInit && !isSourceHistory && isPagingMode && columnCount === 1 && !hasAreaElement && !hasStructuralElement && surroundElementList.length === 0 && oldRowList.length > 0 && oldPageRowList.length > 0;
24050
+ if (canUseIncrementalMainRows) {
24051
+ const restartState = this._getIncrementalRestartState(
24052
+ dirtyStartIndex,
24053
+ oldRowList,
24054
+ oldPageRowList,
24055
+ startY
24056
+ );
24057
+ if (restartState) {
24058
+ const suffixRows = this.computeRowList({
24059
+ ...rowListPayload,
24060
+ fromIndex: restartState.fromIndex,
24061
+ initialY: restartState.initialY,
24062
+ initialPageNo: restartState.initialPageNo,
24063
+ initialRowIndex: restartState.initialRowIndex,
24064
+ initialListState: restartState.initialListState
24065
+ });
24066
+ this.rowList = restartState.prefixRows.concat(suffixRows);
24067
+ } else {
24068
+ this.rowList = this.computeRowList(rowListPayload);
24069
+ }
24070
+ } else {
24071
+ this.rowList = this.computeRowList(rowListPayload);
24072
+ }
23719
24073
  this._applyRowSpacing();
23720
24074
  this.pageRowList = this._computePageList();
23721
24075
  this.position.computePositionList();
23722
- this.area.compute();
24076
+ if (hasAreaElement) {
24077
+ this.area.compute();
24078
+ } else {
24079
+ this.area.clear();
24080
+ }
23723
24081
  if (!this.isPrintMode()) {
23724
24082
  const searchKeyword = this.search.getSearchKeyword();
23725
24083
  if (searchKeyword) {
@@ -23743,10 +24101,26 @@ var Draw = class {
23743
24101
  if (prePageCount > curPageCount) {
23744
24102
  const deleteCount = prePageCount - curPageCount;
23745
24103
  this.ctxList.splice(curPageCount, deleteCount);
24104
+ this.pageRenderVersionList.splice(curPageCount, deleteCount);
23746
24105
  this.pageList.splice(curPageCount, deleteCount).forEach((page) => page.remove());
23747
24106
  }
23748
24107
  if (isLazy && isPagingMode) {
23749
- this._lazyRender();
24108
+ let visiblePageNoList = this.visiblePageNoList.filter(
24109
+ (pageNo) => pageNo >= 0 && pageNo < curPageCount
24110
+ );
24111
+ let intersectionPageNo = Math.min(
24112
+ this.intersectionPageNo,
24113
+ Math.max(curPageCount - 1, 0)
24114
+ );
24115
+ if (!visiblePageNoList.length || oldPageSize !== curPageCount || intersectionPageNo >= curPageCount) {
24116
+ const visibleInfo = this.scrollObserver.getPageVisibleInfo();
24117
+ intersectionPageNo = visibleInfo.intersectionPageNo;
24118
+ visiblePageNoList = visibleInfo.visiblePageNoList;
24119
+ this.setIntersectionPageNo(intersectionPageNo);
24120
+ this.setVisiblePageNoList(visiblePageNoList);
24121
+ }
24122
+ const renderPageNoList = visiblePageNoList.length ? visiblePageNoList : [intersectionPageNo];
24123
+ this.renderVisiblePages(renderPageNoList);
23750
24124
  } else {
23751
24125
  this._immediateRender();
23752
24126
  }
@@ -23795,7 +24169,9 @@ var Draw = class {
23795
24169
  const positionContext = this.position.getPositionContext();
23796
24170
  const positionList = this.position.getPositionList();
23797
24171
  if (positionContext.isTable) {
23798
- const tablePositionList = this.resolveTableCellContext(this.getOriginalElementList())?.td.positionList;
24172
+ const tablePositionList = this.resolveTableCellContext(
24173
+ this.getOriginalElementList()
24174
+ )?.td.positionList;
23799
24175
  if (curIndex === void 0 && tablePositionList) {
23800
24176
  curIndex = tablePositionList.length - 1;
23801
24177
  }
@@ -23822,36 +24198,51 @@ var Draw = class {
23822
24198
  return curIndex;
23823
24199
  }
23824
24200
  submitHistory(curIndex, isInput = false) {
23825
- const positionContext = this.position.getPositionContext();
23826
- const oldElementList = getSlimCloneElementList(this.elementList);
23827
- const oldHeaderElementList = getSlimCloneElementList(
23828
- this.header.getElementList()
23829
- );
23830
- const oldFooterElementList = getSlimCloneElementList(
23831
- this.footer.getElementList()
23832
- );
23833
- const oldRange = deepClone(this.range.getRange());
23834
- const pageNo = this.pageNo;
23835
- const oldPositionContext = deepClone(positionContext);
23836
- const zone = this.zone.getZone();
23837
- const fn = () => {
23838
- this.zone.setZone(zone);
23839
- this.setPageNo(pageNo);
23840
- this.position.setPositionContext(deepClone(oldPositionContext));
23841
- this.header.setElementList(deepClone(oldHeaderElementList));
23842
- this.footer.setElementList(deepClone(oldFooterElementList));
23843
- this.elementList = deepClone(oldElementList);
23844
- this.range.replaceRange(deepClone(oldRange));
23845
- this.render({
23846
- curIndex,
23847
- isSubmitHistory: false,
23848
- isSourceHistory: true
23849
- });
24201
+ const snapshot = {
24202
+ elementList: getSlimCloneElementList(this.elementList),
24203
+ headerElementList: getSlimCloneElementList(this.header.getElementList()),
24204
+ footerElementList: getSlimCloneElementList(this.footer.getElementList()),
24205
+ range: deepClone(this.range.getRange()),
24206
+ pageNo: this.pageNo,
24207
+ positionContext: deepClone(this.position.getPositionContext()),
24208
+ zone: this.zone.getZone()
24209
+ };
24210
+ const entry = {
24211
+ restore: () => {
24212
+ const {
24213
+ elementList,
24214
+ headerElementList,
24215
+ footerElementList,
24216
+ range,
24217
+ pageNo,
24218
+ positionContext,
24219
+ zone
24220
+ } = snapshot;
24221
+ const restoredHeaderElementList = inflateElementList(
24222
+ deepClone(headerElementList)
24223
+ );
24224
+ const restoredFooterElementList = inflateElementList(
24225
+ deepClone(footerElementList)
24226
+ );
24227
+ const restoredMainElementList = inflateElementList(deepClone(elementList));
24228
+ this.zone.setZone(zone);
24229
+ this.setPageNo(pageNo);
24230
+ this.position.setPositionContext(deepClone(positionContext));
24231
+ this.header.setElementList(restoredHeaderElementList);
24232
+ this.footer.setElementList(restoredFooterElementList);
24233
+ this.elementList = restoredMainElementList;
24234
+ this.range.replaceRange(deepClone(range));
24235
+ this.render({
24236
+ curIndex,
24237
+ isSubmitHistory: false,
24238
+ isSourceHistory: true
24239
+ });
24240
+ }
23850
24241
  };
23851
24242
  if (isInput && this.historyManager.isInputGroupable()) {
23852
- this.historyManager.replaceLatest(fn);
24243
+ this.historyManager.replaceLatest(entry);
23853
24244
  } else {
23854
- this.historyManager.execute(fn);
24245
+ this.historyManager.execute(entry);
23855
24246
  }
23856
24247
  if (isInput) {
23857
24248
  this.historyManager.recordInputTime();