@univerjs/docs 1.0.0-alpha.1 → 1.0.0-alpha.2

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/lib/cjs/facade.js CHANGED
@@ -3,210 +3,6 @@ let _univerjs_core = require("@univerjs/core");
3
3
  let _univerjs_core_facade = require("@univerjs/core/facade");
4
4
  let _univerjs_docs = require("@univerjs/docs");
5
5
 
6
- //#region src/facade/f-document-element.ts
7
- /**
8
- * A generic top-level document body element.
9
- *
10
- * Use this wrapper when you need to inspect an element type first, navigate to
11
- * neighboring elements, or cast the element to a more specific facade wrapper.
12
- *
13
- * Paragraph keys are persisted `paragraphId` values. Tables, block ranges, and
14
- * custom blocks use their persisted ids.
15
- *
16
- * @hideconstructor
17
- */
18
- var FDocumentElement = class extends _univerjs_core_facade.FBase {
19
- constructor(_body, _bodyEdit, _info, _injector) {
20
- super();
21
- this._body = _body;
22
- this._bodyEdit = _bodyEdit;
23
- this._info = _info;
24
- this._injector = _injector;
25
- }
26
- /**
27
- * Get the document element type.
28
- * @returns {DocumentBlockType} The element type, such as `paragraph`, `table`, `blockRange`, or `customBlock`.
29
- * @example
30
- * ```ts
31
- * const fDocument = univerAPI.getActiveDocument();
32
- * const fDocumentBody = fDocument.getBody();
33
- * const element = fDocumentBody.getElement(0);
34
- * console.log(element?.getType());
35
- * ```
36
- */
37
- getType() {
38
- return this._info.type;
39
- }
40
- /**
41
- * Whether this element is a paragraph.
42
- * @returns {boolean} `true` if this element is a paragraph.
43
- * @example
44
- * ```ts
45
- * const fDocument = univerAPI.getActiveDocument();
46
- * const fDocumentBody = fDocument.getBody();
47
- * const element = fDocumentBody.getElement(0);
48
- * console.log(element?.isParagraph());
49
- * ```
50
- */
51
- isParagraph() {
52
- return this._info.type === _univerjs_core.DocumentBlockType.PARAGRAPH;
53
- }
54
- /**
55
- * Whether this element is a table.
56
- * @returns {boolean} `true` if this element is a table.
57
- * @example
58
- * ```ts
59
- * const fDocument = univerAPI.getActiveDocument();
60
- * const fDocumentBody = fDocument.getBody();
61
- * const element = fDocumentBody.getElement(0);
62
- * console.log(element?.isTable());
63
- * ```
64
- */
65
- isTable() {
66
- return this._info.type === _univerjs_core.DocumentBlockType.TABLE;
67
- }
68
- /**
69
- * Whether this element is a block range, such as a callout, quote, or code block.
70
- * @returns {boolean} `true` if this element is a block range.
71
- * @example
72
- * ```ts
73
- * const fDocument = univerAPI.getActiveDocument();
74
- * const fDocumentBody = fDocument.getBody();
75
- * const element = fDocumentBody.getElement(0);
76
- * console.log(element?.isBlockRange());
77
- * ```
78
- */
79
- isBlockRange() {
80
- return this._info.type === _univerjs_core.DocumentBlockType.BLOCK_RANGE;
81
- }
82
- /**
83
- * Whether this element is a custom block.
84
- * @returns {boolean} `true` if this element is a custom block.
85
- * @example
86
- * ```ts
87
- * const fDocument = univerAPI.getActiveDocument();
88
- * const fDocumentBody = fDocument.getBody();
89
- * const element = fDocumentBody.getElement(0);
90
- * console.log(element?.isCustomBlock());
91
- * ```
92
- */
93
- isCustomBlock() {
94
- return this._info.type === _univerjs_core.DocumentBlockType.CUSTOM_BLOCK;
95
- }
96
- /**
97
- * Get the facade key used to resolve this element.
98
- * @returns {string} The paragraph `paragraphId` or persisted table/block/custom block id.
99
- * @example
100
- * ```ts
101
- * const fDocument = univerAPI.getActiveDocument();
102
- * const fDocumentBody = fDocument.getBody();
103
- * const element = fDocumentBody.getElement(0);
104
- * console.log(element?.getKey());
105
- * ```
106
- */
107
- getKey() {
108
- return this._info.key;
109
- }
110
- /**
111
- * Get the parent body facade that owns this element.
112
- * @returns {FDocumentBody} The document body facade.
113
- * @example
114
- * ```ts
115
- * const fDocument = univerAPI.getActiveDocument();
116
- * const fDocumentBody = fDocument.getBody();
117
- * const element = fDocumentBody.getElement(0);
118
- * console.log(element?.getParent());
119
- * ```
120
- */
121
- getParent() {
122
- return this._body;
123
- }
124
- /**
125
- * Get the resolved element info for this wrapper.
126
- * @returns {IFDocumentElementInfo} The resolved element info, including type, key, position, and priority.
127
- * @example
128
- * ```ts
129
- * const fDocument = univerAPI.getActiveDocument();
130
- * const fDocumentBody = fDocument.getBody();
131
- * const element = fDocumentBody.getElement(0);
132
- * console.log(element?.getResolvedInfo());
133
- * ```
134
- */
135
- getResolvedInfo() {
136
- return this._info;
137
- }
138
- /**
139
- * Get the next sibling element in the current body order.
140
- * @returns {FDocumentElement | null} The next sibling wrapper, or `null` when this is the last child.
141
- * @example
142
- * ```ts
143
- * const fDocument = univerAPI.getActiveDocument();
144
- * const fDocumentBody = fDocument.getBody();
145
- * const element = fDocumentBody.getElement(0);
146
- * console.log(element?.getNextSibling());
147
- * ```
148
- */
149
- getNextSibling() {
150
- return this._createSibling(1);
151
- }
152
- /**
153
- * Get the previous sibling element in the current body order.
154
- * @returns {FDocumentElement | null} The previous sibling wrapper, or `null` when this is the first child.
155
- * @example
156
- * ```ts
157
- * const fDocument = univerAPI.getActiveDocument();
158
- * const fDocumentBody = fDocument.getBody();
159
- * const element = fDocumentBody.getElement(1);
160
- * console.log(element?.getPreviousSibling());
161
- * ```
162
- */
163
- getPreviousSibling() {
164
- return this._createSibling(-1);
165
- }
166
- /**
167
- * Get the sibling element at a relative offset from this element.
168
- * @param {number} offset The relative offset from this element. Use `1` for the next sibling, `-1` for the previous sibling, and so on.
169
- * @returns {FDocumentElement | null} The sibling wrapper at the specified offset, or `null` when the offset is out of range.
170
- * @example
171
- * ```ts
172
- * const fDocument = univerAPI.getActiveDocument();
173
- * const fDocumentBody = fDocument.getBody();
174
- * const element = fDocumentBody.getElement(0);
175
- *
176
- * // Get the third sibling after this element
177
- * const nextThirdSibling = element?.getSibling(3);
178
- * console.log(nextThirdSibling?.getType());
179
- * ```
180
- */
181
- getSibling(offset) {
182
- return this._createSibling(offset);
183
- }
184
- /**
185
- * Remove this element from its parent body.
186
- * @returns {boolean} `true` if the element content was removed.
187
- * @example
188
- * ```ts
189
- * const fDocument = univerAPI.getActiveDocument();
190
- * const fDocumentBody = fDocument.getBody();
191
- * const element = fDocumentBody.getElement(0);
192
- * const removed = element?.remove();
193
- * console.log(removed);
194
- * ```
195
- */
196
- remove() {
197
- if (this.isParagraph()) return this._body.removeParagraph(this.asParagraph());
198
- if (this.isBlockRange()) return this._body.removeBlockRange(this.asBlockRange());
199
- if (this.isTable()) return this._body.removeTable(this.asTable());
200
- return this._body.removeCustomBlock(this.asCustomBlock());
201
- }
202
- _createSibling(offset) {
203
- if (offset === 0) throw new Error("Offset cannot be zero.");
204
- const index = this._body.getElementIndex(this);
205
- return this._body.getElement(index + offset);
206
- }
207
- };
208
-
209
- //#endregion
210
6
  //#region src/facade/utils.ts
211
7
  function cloneParagraphStyle(paragraphStyle) {
212
8
  return paragraphStyle == null ? paragraphStyle : JSON.parse(JSON.stringify(paragraphStyle));
@@ -237,6 +33,70 @@ function buildPlainTextInsertBody(dataStream, options = {}) {
237
33
  if (paragraphs.length > 0) body.paragraphs = paragraphs;
238
34
  return body;
239
35
  }
36
+ function replaceBodyRange(range, insertBody, docDataModel, injector) {
37
+ const { startOffset, endOffset, segmentId } = range;
38
+ const textX = new _univerjs_core.TextX();
39
+ if (startOffset > 0) textX.push({
40
+ t: _univerjs_core.TextXActionType.RETAIN,
41
+ len: startOffset
42
+ });
43
+ if (endOffset > startOffset) textX.push({
44
+ t: _univerjs_core.TextXActionType.DELETE,
45
+ len: endOffset - startOffset
46
+ });
47
+ if (insertBody.dataStream.length > 0) textX.push({
48
+ t: _univerjs_core.TextXActionType.INSERT,
49
+ body: insertBody,
50
+ len: insertBody.dataStream.length
51
+ });
52
+ const actions = _univerjs_core.JSONX.getInstance().editOp(textX.serialize(), (0, _univerjs_core.getRichTextEditPath)(docDataModel, segmentId));
53
+ const result = injector.get(_univerjs_core.ICommandService).syncExecuteCommand(_univerjs_docs.RichTextEditingMutation.id, {
54
+ unitId: docDataModel.getUnitId(),
55
+ segmentId,
56
+ actions,
57
+ textRanges: [],
58
+ isEditing: false
59
+ });
60
+ return Boolean((result === null || result === void 0 ? void 0 : result.actions) && result.actions.length > 0);
61
+ }
62
+ function retainBodyRange(range, updateBody, coverType, docDataModel, injector) {
63
+ var _updateBody$textRuns, _docDataModel$getSelf;
64
+ const { startOffset, endOffset, segmentId } = range;
65
+ const commandService = injector.get(_univerjs_core.ICommandService);
66
+ if (((_updateBody$textRuns = updateBody.textRuns) === null || _updateBody$textRuns === void 0 ? void 0 : _updateBody$textRuns.length) && ((_docDataModel$getSelf = docDataModel.getSelfOrHeaderFooterModel(segmentId)) === null || _docDataModel$getSelf === void 0 || (_docDataModel$getSelf = _docDataModel$getSelf.getBody()) === null || _docDataModel$getSelf === void 0 ? void 0 : _docDataModel$getSelf.textRuns) == null) {
67
+ const actions = _univerjs_core.JSONX.getInstance().replaceOp([...(0, _univerjs_core.getRichTextEditPath)(docDataModel, segmentId), "textRuns"], void 0, []);
68
+ commandService.syncExecuteCommand(_univerjs_docs.RichTextEditingMutation.id, {
69
+ unitId: docDataModel.getUnitId(),
70
+ segmentId,
71
+ actions,
72
+ textRanges: [],
73
+ isEditing: false
74
+ });
75
+ }
76
+ const textX = new _univerjs_core.TextX();
77
+ if (startOffset > 0) textX.push({
78
+ t: _univerjs_core.TextXActionType.RETAIN,
79
+ len: startOffset
80
+ });
81
+ textX.push({
82
+ t: _univerjs_core.TextXActionType.RETAIN,
83
+ body: updateBody,
84
+ coverType,
85
+ len: endOffset - startOffset
86
+ });
87
+ const actions = _univerjs_core.JSONX.getInstance().editOp(textX.serialize(), (0, _univerjs_core.getRichTextEditPath)(docDataModel, segmentId));
88
+ const result = commandService.syncExecuteCommand(_univerjs_docs.RichTextEditingMutation.id, {
89
+ unitId: docDataModel.getUnitId(),
90
+ segmentId,
91
+ actions,
92
+ textRanges: [],
93
+ isEditing: false
94
+ });
95
+ return Boolean((result === null || result === void 0 ? void 0 : result.actions) && result.actions.length > 0);
96
+ }
97
+ function stripBlockTokens(text) {
98
+ return Array.from(text).map((char) => char === _univerjs_core.DataStreamTreeTokenType.PARAGRAPH ? "\n" : char).filter((char) => char !== _univerjs_core.DataStreamTreeTokenType.BLOCK_START && char !== _univerjs_core.DataStreamTreeTokenType.BLOCK_END && char !== _univerjs_core.DataStreamTreeTokenType.SECTION_BREAK).join("").replace(/\n$/, "");
99
+ }
240
100
 
241
101
  //#endregion
242
102
  //#region src/facade/f-document-paragraph.ts
@@ -249,14 +109,12 @@ function buildPlainTextInsertBody(dataStream, options = {}) {
249
109
  *
250
110
  * @hideconstructor
251
111
  */
252
- var FDocumentParagraph = class extends FDocumentElement {
253
- constructor(body, bodyEdit, info, injector) {
254
- super(body, bodyEdit, info, injector);
255
- this.body = body;
256
- this.bodyEdit = bodyEdit;
257
- this.info = info;
258
- this.injector = injector;
259
- if (this.getType() !== _univerjs_core.DocumentBlockType.PARAGRAPH) throw new Error(`Element type is not a paragraph: ${this.getType()}`);
112
+ var FDocumentParagraph = class {
113
+ constructor(_document, _paragraphId, _segmentId = "", _injector) {
114
+ this._document = _document;
115
+ this._paragraphId = _paragraphId;
116
+ this._segmentId = _segmentId;
117
+ this._injector = _injector;
260
118
  }
261
119
  /**
262
120
  * Get the persisted paragraph id.
@@ -264,41 +122,46 @@ var FDocumentParagraph = class extends FDocumentElement {
264
122
  * @example
265
123
  * ```ts
266
124
  * const fDocument = univerAPI.getActiveDocument();
267
- * const fDocumentBody = fDocument.getBody();
268
- * const element = fDocumentBody.getElement(0);
269
- *
270
- * if (element?.isParagraph()) {
271
- * const paragraph = element.asParagraph();
272
- * console.log(paragraph.getParagraphId());
273
- * }
125
+ * const paragraph = fDocument.getParagraphs()[0];
126
+ * console.log(paragraph?.getId());
274
127
  * ```
275
128
  */
276
- getParagraphId() {
277
- return this.getKey();
129
+ getId() {
130
+ return this._paragraphId;
278
131
  }
279
132
  /**
280
- * Get the resolved paragraph info for this wrapper.
281
- * @returns {IFDocumentResolvedParagraph} The resolved paragraph info, including the paragraph object, its index, and its text range.
133
+ * Get the segment id of this paragraph.
134
+ * The main body paragraphs have an empty string segment id.
135
+ * The header and footer paragraphs have a non-empty string segment id.
136
+ * @returns {string} The segment id.
282
137
  * @example
283
138
  * ```ts
284
139
  * const fDocument = univerAPI.getActiveDocument();
285
- * const fDocumentBody = fDocument.getBody();
286
- * const element = fDocumentBody.getElement(0);
287
- *
288
- * if (element?.isParagraph()) {
289
- * const paragraph = element.asParagraph();
290
- * console.log(paragraph.getResolvedParagraphInfo());
291
- * }
140
+ * const paragraph = fDocument.getParagraphs()[0];
141
+ * console.log(paragraph?.getSegmentId());
292
142
  * ```
293
143
  */
294
- getResolvedParagraphInfo() {
295
- const { paragraphs = [] } = this._body.getBody();
144
+ getSegmentId() {
145
+ return this._segmentId;
146
+ }
147
+ /**
148
+ * Get this paragraph's metadata.
149
+ * @returns {IFDocumentParagraphInfo} The paragraph info.
150
+ * @example
151
+ * ```ts
152
+ * const fDocument = univerAPI.getActiveDocument();
153
+ * const paragraph = fDocument.getParagraphs()[0];
154
+ * console.log(paragraph?.getInfo());
155
+ * ```
156
+ */
157
+ getInfo() {
158
+ const { paragraphs = [] } = this._document.getBody(this._segmentId);
296
159
  const matches = paragraphs.map((paragraph, paragraphIndex) => ({
297
160
  paragraph,
298
161
  paragraphIndex
299
- })).filter(({ paragraph }) => paragraph.paragraphId === this.getKey());
300
- if (matches.length === 0) throw new Error(`Document paragraph with id ${this.getKey()} not found`);
301
- if (matches.length > 1) throw new Error(`Multiple document paragraphs with id ${this.getKey()} found`);
162
+ })).filter(({ paragraph }) => paragraph.paragraphId === this._paragraphId);
163
+ if (matches.length === 0) throw new Error(`Document paragraph with id ${this._paragraphId} not found`);
164
+ if (matches.length > 1) throw new Error(`Multiple document paragraphs with id ${this._paragraphId} found`);
302
165
  const { paragraph, paragraphIndex } = matches[0];
303
166
  return {
304
167
  paragraph,
@@ -313,22 +176,16 @@ var FDocumentParagraph = class extends FDocumentElement {
313
176
  * @example
314
177
  * ```ts
315
178
  * const fDocument = univerAPI.getActiveDocument();
316
- * const fDocumentBody = fDocument.getBody();
317
- * const element = fDocumentBody.getElement(0);
318
- *
319
- * if (element?.isParagraph()) {
320
- * const paragraph = element.asParagraph();
321
- * const range = paragraph.getRange();
322
- * fDocumentBody.setTextStyle(range, { bl: 1 });
323
- * }
179
+ * const paragraph = fDocument.getParagraphs()[0];
180
+ * console.log(paragraph?.getRange());
324
181
  * ```
325
182
  */
326
183
  getRange() {
327
- const { startOffset, endOffset } = this.getResolvedParagraphInfo();
184
+ const { startOffset, endOffset } = this.getInfo();
328
185
  return {
329
186
  startOffset,
330
187
  endOffset,
331
- segmentId: this._body.getSegmentId()
188
+ segmentId: this._segmentId
332
189
  };
333
190
  }
334
191
  /**
@@ -337,18 +194,13 @@ var FDocumentParagraph = class extends FDocumentElement {
337
194
  * @example
338
195
  * ```ts
339
196
  * const fDocument = univerAPI.getActiveDocument();
340
- * const fDocumentBody = fDocument.getBody();
341
- * const element = fDocumentBody.getElement(0);
342
- *
343
- * if (element?.isParagraph()) {
344
- * const paragraph = element.asParagraph();
345
- * console.log(paragraph.getText());
346
- * }
197
+ * const paragraph = fDocument.getParagraphs()[0];
198
+ * console.log(paragraph?.getText());
347
199
  * ```
348
200
  */
349
201
  getText() {
350
- const { dataStream } = this._body.getBody();
351
- const { startOffset, endOffset } = this.getResolvedParagraphInfo();
202
+ const { dataStream } = this._document.getBody(this._segmentId);
203
+ const { startOffset, endOffset } = this.getInfo();
352
204
  return dataStream.slice(startOffset, endOffset);
353
205
  }
354
206
  /**
@@ -358,22 +210,18 @@ var FDocumentParagraph = class extends FDocumentElement {
358
210
  * @example
359
211
  * ```ts
360
212
  * const fDocument = univerAPI.getActiveDocument();
361
- * const fDocumentBody = fDocument.getBody();
362
- * const element = fDocumentBody.getElement(0);
363
- *
364
- * if (element?.isParagraph()) {
365
- * const paragraph = element.asParagraph();
366
- * const success = paragraph.setText('Updated title');
367
- * console.log(success ? 'Text updated' : 'Failed to update text');
368
- * }
213
+ * const paragraph = fDocument.getParagraphs()[0];
214
+ * paragraph?.setText('New text');
215
+ * console.log(paragraph?.getText());
369
216
  * ```
370
217
  */
371
218
  setText(text) {
372
- const { startOffset, endOffset } = this.getResolvedParagraphInfo();
373
- return this._bodyEdit.replaceRange({
219
+ const { startOffset, endOffset } = this.getInfo();
220
+ return replaceBodyRange({
374
221
  startOffset,
375
- endOffset
376
- }, buildPlainTextInsertBody(text));
222
+ endOffset,
223
+ segmentId: this._segmentId
224
+ }, buildPlainTextInsertBody(text), this._document.getDocumentDataModel(), this._injector);
377
225
  }
378
226
  /**
379
227
  * Append plain text before this paragraph's trailing paragraph break.
@@ -382,19 +230,14 @@ var FDocumentParagraph = class extends FDocumentElement {
382
230
  * @example
383
231
  * ```ts
384
232
  * const fDocument = univerAPI.getActiveDocument();
385
- * const fDocumentBody = fDocument.getBody();
386
- * const element = fDocumentBody.getElement(0);
387
- *
388
- * if (element?.isParagraph()) {
389
- * const paragraph = element.asParagraph();
390
- * const success = paragraph.appendText(' Appended text');
391
- * console.log(success ? 'Text appended' : 'Failed to append text');
392
- * }
233
+ * const paragraph = fDocument.getParagraphs()[0];
234
+ * paragraph?.appendText(' Appended text');
235
+ * console.log(paragraph?.getText());
393
236
  * ```
394
237
  */
395
238
  appendText(text) {
396
- const { endOffset } = this.getResolvedParagraphInfo();
397
- return this._body.insertText(endOffset, text);
239
+ const { endOffset } = this.getInfo();
240
+ return this._document.insertText(endOffset, text, this._segmentId);
398
241
  }
399
242
  /**
400
243
  * Apply paragraph style to a paragraph handle or text range.
@@ -403,17 +246,35 @@ var FDocumentParagraph = class extends FDocumentElement {
403
246
  * @example
404
247
  * ```ts
405
248
  * const fDocument = univerAPI.getActiveDocument();
406
- * const fDocumentBody = fDocument.getBody();
407
- * const element = fDocumentBody.getElement(0);
408
- *
409
- * if (element?.isParagraph()) {
410
- * const paragraph = element.asParagraph();
411
- * paragraph.setStyle({ horizontalAlign: 2 });
412
- * }
249
+ * const paragraph = fDocument.getParagraphs()[0];
250
+ * paragraph?.setText('Styled text');
251
+ * paragraph?.setStyle({
252
+ * textStyle: {
253
+ * cl: {
254
+ * rgb: '#FF0000',
255
+ * },
256
+ * fs: 14,
257
+ * },
258
+ * horizontalAlign: 2,
259
+ * });
260
+ * console.log(paragraph?.getInfo().paragraph.paragraphStyle);
413
261
  * ```
414
262
  */
415
263
  setStyle(style) {
416
- const { paragraph, endOffset } = this.getResolvedParagraphInfo();
264
+ const { paragraph, startOffset, endOffset } = this.getInfo();
265
+ let result = true;
266
+ if (style.textStyle && startOffset < endOffset) result = retainBodyRange({
267
+ startOffset,
268
+ endOffset,
269
+ segmentId: this._segmentId
270
+ }, {
271
+ dataStream: "",
272
+ textRuns: [{
273
+ st: 0,
274
+ ed: endOffset - startOffset,
275
+ ts: style.textStyle
276
+ }]
277
+ }, _univerjs_core.UpdateDocsAttributeType.COVER, this._document.getDocumentDataModel(), this._injector);
417
278
  const updateBody = {
418
279
  dataStream: "",
419
280
  paragraphs: [{
@@ -426,10 +287,11 @@ var FDocumentParagraph = class extends FDocumentElement {
426
287
  }]
427
288
  };
428
289
  this._preserveExplicitParagraphIds(updateBody);
429
- return this._bodyEdit.retainRange({
290
+ return retainBodyRange({
430
291
  startOffset: endOffset,
431
- endOffset: endOffset + 1
432
- }, updateBody, _univerjs_core.UpdateDocsAttributeType.REPLACE);
292
+ endOffset: endOffset + 1,
293
+ segmentId: this._segmentId
294
+ }, updateBody, _univerjs_core.UpdateDocsAttributeType.REPLACE, this._document.getDocumentDataModel(), this._injector) && result;
433
295
  }
434
296
  /**
435
297
  * Check whether this paragraph is a bullet, ordered, or checklist item.
@@ -437,17 +299,12 @@ var FDocumentParagraph = class extends FDocumentElement {
437
299
  * @example
438
300
  * ```ts
439
301
  * const fDocument = univerAPI.getActiveDocument();
440
- * const fDocumentBody = fDocument.getBody();
441
- * const element = fDocumentBody.getElement(0);
442
- *
443
- * if (element?.isParagraph()) {
444
- * const paragraph = element.asParagraph();
445
- * console.log(paragraph.isListItem() ? 'This is a list item' : 'This is not a list item');
446
- * }
302
+ * const paragraph = fDocument.getParagraphs()[0];
303
+ * console.log(paragraph?.isListItem());
447
304
  * ```
448
305
  */
449
306
  isListItem() {
450
- const { paragraph } = this.getResolvedParagraphInfo();
307
+ const { paragraph } = this.getInfo();
451
308
  return Boolean(paragraph.bullet);
452
309
  }
453
310
  /**
@@ -456,18 +313,13 @@ var FDocumentParagraph = class extends FDocumentElement {
456
313
  * @example
457
314
  * ```ts
458
315
  * const fDocument = univerAPI.getActiveDocument();
459
- * const fDocumentBody = fDocument.getBody();
460
- * const element = fDocumentBody.getElement(0);
461
- *
462
- * if (element?.isParagraph()) {
463
- * const paragraph = element.asParagraph();
464
- * console.log(paragraph.isTask() ? 'This is a task item' : 'This is not a task item');
465
- * }
316
+ * const paragraph = fDocument.getParagraphs()[0];
317
+ * console.log(paragraph?.isTask());
466
318
  * ```
467
319
  */
468
320
  isTask() {
469
321
  var _paragraph$bullet;
470
- const { paragraph } = this.getResolvedParagraphInfo();
322
+ const { paragraph } = this.getInfo();
471
323
  const listType = (_paragraph$bullet = paragraph.bullet) === null || _paragraph$bullet === void 0 ? void 0 : _paragraph$bullet.listType;
472
324
  return listType === _univerjs_core.PresetListType.CHECK_LIST || listType === _univerjs_core.PresetListType.CHECK_LIST_CHECKED;
473
325
  }
@@ -478,22 +330,17 @@ var FDocumentParagraph = class extends FDocumentElement {
478
330
  * @example
479
331
  * ```ts
480
332
  * const fDocument = univerAPI.getActiveDocument();
481
- * const fDocumentBody = fDocument.getBody();
482
- * const element = fDocumentBody.getElement(0);
483
- *
484
- * if (element?.isParagraph()) {
485
- * const paragraph = element.asParagraph();
333
+ * const paragraph = fDocument.getParagraphs()[0];
486
334
  *
487
- * if (paragraph.isTask()) {
488
- * const success = paragraph.setTaskChecked(true);
489
- * console.log(success ? 'Task checked' : 'Failed to check task');
490
- * }
335
+ * if (paragraph.isTask()) {
336
+ * const success = paragraph.setTaskChecked(true);
337
+ * console.log(success ? 'Task checked' : 'Failed to check task');
491
338
  * }
492
339
  * ```
493
340
  */
494
341
  setTaskChecked(checked) {
495
342
  if (!this.isTask()) return false;
496
- const { paragraph, endOffset } = this.getResolvedParagraphInfo();
343
+ const { paragraph, endOffset } = this.getInfo();
497
344
  const bullet = paragraph.bullet;
498
345
  const updateBody = {
499
346
  dataStream: "",
@@ -507,22 +354,39 @@ var FDocumentParagraph = class extends FDocumentElement {
507
354
  }]
508
355
  };
509
356
  this._preserveExplicitParagraphIds(updateBody);
510
- return this._bodyEdit.retainRange({
357
+ return retainBodyRange({
511
358
  startOffset: endOffset,
512
- endOffset: endOffset + 1
513
- }, updateBody, _univerjs_core.UpdateDocsAttributeType.REPLACE);
359
+ endOffset: endOffset + 1,
360
+ segmentId: this._segmentId
361
+ }, updateBody, _univerjs_core.UpdateDocsAttributeType.REPLACE, this._document.getDocumentDataModel(), this._injector);
362
+ }
363
+ /**
364
+ * Remove this paragraph.
365
+ * @returns {boolean} `true` if the paragraph was removed.
366
+ * @example
367
+ * ```ts
368
+ * const fDocument = univerAPI.getActiveDocument();
369
+ * const paragraph = fDocument.getParagraphs()[0];
370
+ * const success = paragraph?.remove();
371
+ * console.log(success ? 'Paragraph removed' : 'Failed to remove paragraph');
372
+ * ```
373
+ */
374
+ remove() {
375
+ const { startOffset, endOffset } = this.getInfo();
376
+ return this._document.deleteRange({
377
+ startOffset,
378
+ endOffset: endOffset + 1,
379
+ segmentId: this._segmentId
380
+ });
514
381
  }
515
382
  _preserveExplicitParagraphIds(body) {
516
383
  body[_univerjs_core.RESTORE_INSERTED_PARAGRAPH_IDS] = true;
517
384
  }
518
385
  };
519
- var FDocumentParagraphMixin = class extends FDocumentElement {
520
- asParagraph() {
521
- if (this.getType() !== _univerjs_core.DocumentBlockType.PARAGRAPH) throw new Error(`Element type is not a paragraph: ${this.getType()}`);
522
- return this._injector.createInstance(FDocumentParagraph, this._body, this._bodyEdit, this.getResolvedInfo(), this._injector);
523
- }
524
- };
525
- FDocumentElement.extend(FDocumentParagraphMixin);
386
+ function isParagraphFacade(value) {
387
+ if (typeof value !== "object" || value === null) return false;
388
+ return typeof value.getId === "function" && typeof value.getSegmentId === "function" && typeof value.getInfo === "function" && typeof value.getRange === "function";
389
+ }
526
390
 
527
391
  //#endregion
528
392
  //#region \0@oxc-project+runtime@0.137.0/helpers/esm/typeof.js
@@ -566,435 +430,6 @@ function _defineProperty(e, r, t) {
566
430
  }) : e[r] = t, e;
567
431
  }
568
432
 
569
- //#endregion
570
- //#region src/facade/f-document-body.ts
571
- /**
572
- * A Facade API object bounded to a document body or header/footer segment.
573
- * It provides Google Docs-like element access and range editing methods.
574
- *
575
- * Paragraph elements use their persisted `paragraphId`. Tables, block ranges, and
576
- * custom blocks use their persisted ids.
577
- *
578
- * @hideconstructor
579
- */
580
- var FDocumentBody = class {
581
- constructor(_documentDataModel, _injector, _segmentId = "") {
582
- this._documentDataModel = _documentDataModel;
583
- this._injector = _injector;
584
- this._segmentId = _segmentId;
585
- _defineProperty(this, "_bodyEdit", void 0);
586
- this._bodyEdit = {
587
- replaceRange: this._replaceBodyRange.bind(this),
588
- retainRange: this._retainBodyRange.bind(this)
589
- };
590
- }
591
- /**
592
- * Get the segment id of this document body facade.
593
- * The main body has an empty string segment id.
594
- * The header and footer FDocumentBody instances have their respective segment ids.
595
- * @returns {string} The segment id of this document body facade.
596
- * @example
597
- * ```ts
598
- * const fDocument = univerAPI.getActiveDocument();
599
- * const fDocumentBody = fDocument.getBody();
600
- * console.log(fDocumentBody.getSegmentId());
601
- * ```
602
- */
603
- getSegmentId() {
604
- return this._segmentId;
605
- }
606
- /**
607
- * Get the underlying document body snapshot.
608
- * @returns {IDocumentBody} The document body snapshot.
609
- * @example
610
- * ```ts
611
- * const fDocument = univerAPI.getActiveDocument();
612
- * const fDocumentBody = fDocument.getBody();
613
- * console.log(fDocumentBody.getBody());
614
- * ```
615
- */
616
- getBody() {
617
- const body = this._documentDataModel.getSelfOrHeaderFooterModel(this._segmentId).getBody();
618
- if (!body) throw new Error("The document body is empty");
619
- return body;
620
- }
621
- /**
622
- * Get a list of top-level child elements in the body.
623
- * @returns {FDocumentElement[]} The list of top-level document elements.
624
- * @example
625
- * ```ts
626
- * const fDocument = univerAPI.getActiveDocument();
627
- * const fDocumentBody = fDocument.getBody();
628
- * const elements = fDocumentBody.getElements();
629
- * console.log(elements);
630
- * ```
631
- */
632
- getElements() {
633
- return this._getChildren().map((child) => {
634
- return this._injector.createInstance(FDocumentElement, this, this._bodyEdit, child, this._injector);
635
- });
636
- }
637
- /**
638
- * Get a top-level child element by child index.
639
- * @param {number} index The zero-based child index.
640
- * @returns {FDocumentElement} The top-level child element wrapper.
641
- * @example
642
- * ```ts
643
- * const fDocument = univerAPI.getActiveDocument();
644
- * const fDocumentBody = fDocument.getBody();
645
- * const element = fDocumentBody.getElement(0);
646
- * console.log(element);
647
- * ```
648
- */
649
- getElement(index) {
650
- var _this$getElements$ind;
651
- return (_this$getElements$ind = this.getElements()[index]) !== null && _this$getElements$ind !== void 0 ? _this$getElements$ind : null;
652
- }
653
- /**
654
- * Get the current child index of an element handle.
655
- * The index is resolved from the element key, so a paragraph handle keeps pointing
656
- * to the same paragraph after facade edits insert content before it.
657
- * @param {FDocumentElement} element The element handle to locate.
658
- * @returns {number} The current zero-based child index.
659
- * @example
660
- * ```ts
661
- * const fDocument = univerAPI.getActiveDocument();
662
- * const fDocumentBody = fDocument.getBody();
663
- * const element = fDocumentBody.getElement(0);
664
- * console.log(fDocumentBody.getElementIndex(element));
665
- * ```
666
- */
667
- getElementIndex(element) {
668
- const { type, key } = element.getResolvedInfo();
669
- const index = this._getChildren().findIndex((child) => child.type === type && child.key === key);
670
- if (index < 0) throw new Error("Doc element is stale");
671
- return index;
672
- }
673
- /**
674
- * Insert plain text at a document body offset.
675
- * @param {number} index The zero-based insertion offset.
676
- * @param {string} text The plain text to insert.
677
- * @returns {boolean} `true` if the edit was applied.
678
- * @example
679
- * ```ts
680
- * const fDocument = univerAPI.getActiveDocument();
681
- * const fDocumentBody = fDocument.getBody();
682
- * fDocumentBody.insertText(0, 'Hello ');
683
- * ```
684
- */
685
- insertText(index, text) {
686
- return this._replaceBodyRange({
687
- startOffset: index,
688
- endOffset: index
689
- }, buildPlainTextInsertBody(text));
690
- }
691
- /**
692
- * Apply text style to a body range.
693
- * @param {IFDocumentTextRange} range The range to style.
694
- * @param {ITextStyle} style The Univer text style patch.
695
- * @returns {boolean} `true` if the style was applied.
696
- * @example
697
- * ```ts
698
- * const fDocument = univerAPI.getActiveDocument();
699
- * const fDocumentBody = fDocument.getBody();
700
- * fDocumentBody.setTextStyle({ startOffset: 0, endOffset: 5 }, { bl: 1 });
701
- * ```
702
- */
703
- setTextStyle(range, style) {
704
- const updateBody = {
705
- dataStream: "",
706
- textRuns: [{
707
- st: 0,
708
- ed: range.endOffset - range.startOffset,
709
- ts: style
710
- }]
711
- };
712
- return this._retainBodyRange(range, updateBody, _univerjs_core.UpdateDocsAttributeType.COVER);
713
- }
714
- /**
715
- * Insert a plain-text paragraph before the paragraph at the given paragraph index.
716
- * @param {number} index The zero-based paragraph insertion index.
717
- * @param {string} text The paragraph text. Defaults to an empty paragraph.
718
- * @returns {FDocumentParagraph} The inserted paragraph wrapper.
719
- * @example
720
- * ```ts
721
- * const fDocument = univerAPI.getActiveDocument();
722
- * const fDocumentBody = fDocument.getBody();
723
- * const paragraph = fDocumentBody.insertParagraph(0, 'Document title');
724
- * paragraph.appendText(' suffix');
725
- * ```
726
- */
727
- insertParagraph(index, text = "") {
728
- var _paragraphs;
729
- const offset = this._getParagraphInsertOffset(index);
730
- if (!this._replaceBodyRange({
731
- startOffset: offset,
732
- endOffset: offset
733
- }, buildPlainTextInsertBody(`${text}\r`))) throw new Error("Failed to insert paragraph.");
734
- const { paragraphs = [] } = this.getBody();
735
- const paragraph = paragraphs[index];
736
- if (!paragraph) throw new Error("Failed to insert paragraph.");
737
- const info = this._resolveParagraphInfo(paragraph, index, (_paragraphs = paragraphs[index - 1]) === null || _paragraphs === void 0 ? void 0 : _paragraphs.startIndex);
738
- return this._injector.createInstance(FDocumentParagraph, this, this._bodyEdit, info, this._injector);
739
- }
740
- /**
741
- * Append a plain-text paragraph at the end of the body.
742
- * @param {string} text The paragraph text. Defaults to an empty paragraph.
743
- * @returns {FDocumentParagraph} The appended paragraph wrapper.
744
- * @example
745
- * ```ts
746
- * const fDocument = univerAPI.getActiveDocument();
747
- * const fDocumentBody = fDocument.getBody();
748
- * const paragraph = fDocumentBody.appendParagraph('Summary');
749
- * console.log(paragraph.getText());
750
- * ```
751
- */
752
- appendParagraph(text = "") {
753
- const { paragraphs = [] } = this.getBody();
754
- return this.insertParagraph(paragraphs.length, text);
755
- }
756
- /**
757
- * Delete a range from the body.
758
- * @param {IFDocumentTextRange} range The text range to delete.
759
- * @returns {boolean} `true` if the range was deleted.
760
- * @example
761
- * ```ts
762
- * const fDocument = univerAPI.getActiveDocument();
763
- * const fDocumentBody = fDocument.getBody();
764
- * fDocumentBody.deleteRange({ startOffset: 0, endOffset: 5 });
765
- * ```
766
- */
767
- deleteRange(range) {
768
- return this._replaceBodyRange(range, { dataStream: "" });
769
- }
770
- /**
771
- * Remove a paragraph by paragraph id.
772
- * @param {FDocumentParagraph} paragraph The paragraph handle to remove.
773
- * @returns {boolean} `true` if the paragraph was removed.
774
- * @example
775
- * ```ts
776
- * const fDocument = univerAPI.getActiveDocument();
777
- * const fDocumentBody = fDocument.getBody();
778
- * const element = fDocumentBody.getElement(0);
779
- *
780
- * if (element?.isParagraph()) {
781
- * const paragraph = element.asParagraph();
782
- * const removed = fDocumentBody.removeParagraph(paragraph);
783
- * console.log(removed ? 'Paragraph removed' : 'Failed to remove paragraph');
784
- * }
785
- * ```
786
- */
787
- removeParagraph(paragraph) {
788
- const { startOffset, endOffset } = paragraph.getResolvedParagraphInfo();
789
- return this.deleteRange({
790
- startOffset,
791
- endOffset: endOffset + 1
792
- });
793
- }
794
- /**
795
- * Remove a callout, quote, or code block range and its content.
796
- * @param {FDocumentBlockRange} blockRange The block range handle to remove.
797
- * @returns {boolean} `true` if the block range content was removed.
798
- * @example
799
- * ```ts
800
- * const fDocument = univerAPI.getActiveDocument();
801
- * const fDocumentBody = fDocument.getBody();
802
- * const element = fDocumentBody.getElement(0);
803
- *
804
- * if (element?.isBlockRange()) {
805
- * const blockRange = element.asBlockRange();
806
- * const removed = fDocumentBody.removeBlockRange(blockRange);
807
- * console.log(removed ? 'Block range removed' : 'Failed to remove block range');
808
- * }
809
- * ```
810
- */
811
- removeBlockRange(blockRange) {
812
- const { startIndex, endIndex } = blockRange.getBlockRange();
813
- return this.deleteRange({
814
- startOffset: startIndex,
815
- endOffset: endIndex + 1
816
- });
817
- }
818
- /**
819
- * Remove a table marker and its content range.
820
- * @returns {boolean} `true` if the table range was removed.
821
- * @example
822
- * ```ts
823
- * const fDocument = univerAPI.getActiveDocument();
824
- * const fDocumentBody = fDocument.getBody();
825
- * const element = fDocumentBody.getElement(0);
826
- *
827
- * if (element?.isTable()) {
828
- * const table = element.asTable();
829
- * const removed = fDocumentBody.removeTable(table);
830
- * console.log(removed ? 'Table removed' : 'Failed to remove table');
831
- * }
832
- * ```
833
- */
834
- removeTable(table) {
835
- const { startIndex, endIndex } = table.getTable();
836
- return this.deleteRange({
837
- startOffset: startIndex,
838
- endOffset: endIndex + 1
839
- });
840
- }
841
- /**
842
- * Remove a custom block marker and its placeholder character.
843
- * @param {FDocumentCustomBlock} customBlock The custom block handle to remove.
844
- * @returns {boolean} `true` if the custom block placeholder was removed.
845
- * @example
846
- * ```ts
847
- * const fDocument = univerAPI.getActiveDocument();
848
- * const fDocumentBody = fDocument.getBody();
849
- * const element = fDocumentBody.getElement(0);
850
- *
851
- * if (element?.isCustomBlock()) {
852
- * const customBlock = element.asCustomBlock();
853
- * const removed = fDocumentBody.removeCustomBlock(customBlock);
854
- * console.log(removed ? 'Custom block removed' : 'Failed to remove custom block');
855
- * }
856
- * ```
857
- */
858
- removeCustomBlock(customBlock) {
859
- const { startIndex } = customBlock.getCustomBlock();
860
- return this.deleteRange({
861
- startOffset: startIndex,
862
- endOffset: startIndex + 1
863
- });
864
- }
865
- /**
866
- * Resolve an element key to its current child metadata.
867
- * @param {FDocumentElement} element The element handle to resolve.
868
- * @returns {IFDocumentElementInfo} The current child metadata used by the facade.
869
- * @example
870
- * ```ts
871
- * const fDocument = univerAPI.getActiveDocument();
872
- * const fDocumentBody = fDocument.getBody();
873
- * const element = fDocumentBody.getElement(0);
874
- * const resolved = fDocumentBody.resolveElement(element);
875
- * console.log(resolved);
876
- * ```
877
- */
878
- resolveElement(element) {
879
- const { type, key } = element.getResolvedInfo();
880
- const child = this._getChildren().find((item) => item.type === type && item.key === key);
881
- if (!child) throw new Error("Doc element is stale");
882
- return child;
883
- }
884
- _getChildren() {
885
- const { paragraphs, blockRanges, tables, customBlocks } = this.getBody();
886
- const children = [];
887
- if (paragraphs) for (let i = 0; i < paragraphs.length; i++) {
888
- var _paragraphs2;
889
- const paragraph = paragraphs[i];
890
- const info = this._resolveParagraphInfo(paragraph, i, (_paragraphs2 = paragraphs[i - 1]) === null || _paragraphs2 === void 0 ? void 0 : _paragraphs2.startIndex);
891
- children.push(info);
892
- }
893
- if (blockRanges) for (let i = 0; i < blockRanges.length; i++) {
894
- const blockRange = blockRanges[i];
895
- children.push({
896
- type: _univerjs_core.DocumentBlockType.BLOCK_RANGE,
897
- key: blockRange.blockId,
898
- position: blockRange.startIndex,
899
- priority: 0
900
- });
901
- }
902
- if (tables) for (let i = 0; i < tables.length; i++) {
903
- const table = tables[i];
904
- children.push({
905
- type: _univerjs_core.DocumentBlockType.TABLE,
906
- key: table.tableId,
907
- position: table.startIndex,
908
- priority: 1
909
- });
910
- }
911
- if (customBlocks) for (let i = 0; i < customBlocks.length; i++) {
912
- const customBlock = customBlocks[i];
913
- children.push({
914
- type: _univerjs_core.DocumentBlockType.CUSTOM_BLOCK,
915
- key: customBlock.blockId,
916
- position: customBlock.startIndex,
917
- priority: 2
918
- });
919
- }
920
- return children.sort((a, b) => a.position - b.position || a.priority - b.priority);
921
- }
922
- _resolveParagraphInfo(paragraph, paragraphIndex, previousParagraphStartIndex) {
923
- return {
924
- type: _univerjs_core.DocumentBlockType.PARAGRAPH,
925
- key: this._getParagraphId(paragraph, paragraphIndex),
926
- position: paragraphIndex > 0 ? previousParagraphStartIndex + 1 : 0,
927
- priority: 3
928
- };
929
- }
930
- _getParagraphId(paragraph, paragraphIndex) {
931
- if (!paragraph) throw new Error(`Paragraph index ${paragraphIndex} is out of range.`);
932
- if (!paragraph.paragraphId) throw new Error(`Paragraph at index ${paragraphIndex} is missing paragraphId.`);
933
- return paragraph.paragraphId;
934
- }
935
- _getParagraphInsertOffset(index) {
936
- if (index <= 0) return 0;
937
- const { dataStream, paragraphs = [] } = this.getBody();
938
- if (paragraphs.length === 0) return Math.max(0, dataStream.length - 1);
939
- if (index >= paragraphs.length) return paragraphs[paragraphs.length - 1].startIndex + 1;
940
- return paragraphs[index - 1].startIndex + 1;
941
- }
942
- _replaceBodyRange(range, insertBody) {
943
- const { startOffset, endOffset } = range;
944
- const textX = new _univerjs_core.TextX();
945
- if (startOffset > 0) textX.push({
946
- t: _univerjs_core.TextXActionType.RETAIN,
947
- len: startOffset
948
- });
949
- if (endOffset > startOffset) textX.push({
950
- t: _univerjs_core.TextXActionType.DELETE,
951
- len: endOffset - startOffset
952
- });
953
- if (insertBody.dataStream.length > 0) textX.push({
954
- t: _univerjs_core.TextXActionType.INSERT,
955
- body: insertBody,
956
- len: insertBody.dataStream.length
957
- });
958
- return this._executeTextX(textX);
959
- }
960
- _retainBodyRange(range, body, coverType) {
961
- var _body$textRuns;
962
- if (((_body$textRuns = body.textRuns) === null || _body$textRuns === void 0 ? void 0 : _body$textRuns.length) && this.getBody().textRuns == null) this._ensureTextRuns();
963
- const textX = new _univerjs_core.TextX();
964
- if (range.startOffset > 0) textX.push({
965
- t: _univerjs_core.TextXActionType.RETAIN,
966
- len: range.startOffset
967
- });
968
- textX.push({
969
- t: _univerjs_core.TextXActionType.RETAIN,
970
- body,
971
- coverType,
972
- len: range.endOffset - range.startOffset
973
- });
974
- return this._executeTextX(textX);
975
- }
976
- _ensureTextRuns() {
977
- const actions = _univerjs_core.JSONX.getInstance().replaceOp([...(0, _univerjs_core.getRichTextEditPath)(this._documentDataModel, this._segmentId), "textRuns"], void 0, []);
978
- this._injector.get(_univerjs_core.ICommandService).syncExecuteCommand(_univerjs_docs.RichTextEditingMutation.id, {
979
- unitId: this._documentDataModel.getUnitId(),
980
- segmentId: this._segmentId,
981
- actions,
982
- textRanges: [],
983
- isEditing: false
984
- });
985
- }
986
- _executeTextX(textX) {
987
- const actions = _univerjs_core.JSONX.getInstance().editOp(textX.serialize(), (0, _univerjs_core.getRichTextEditPath)(this._documentDataModel, this._segmentId));
988
- return this._injector.get(_univerjs_core.ICommandService).syncExecuteCommand(_univerjs_docs.RichTextEditingMutation.id, {
989
- unitId: this._documentDataModel.getUnitId(),
990
- segmentId: this._segmentId,
991
- actions,
992
- textRanges: [],
993
- isEditing: false
994
- }) !== false;
995
- }
996
- };
997
-
998
433
  //#endregion
999
434
  //#region \0@oxc-project+runtime@0.137.0/helpers/esm/decorateParam.js
1000
435
  function __decorateParam(paramIndex, decorator) {
@@ -1027,42 +462,42 @@ let FDocument = class FDocument extends _univerjs_core_facade.FBaseInitialable {
1027
462
  }
1028
463
  /**
1029
464
  * Get the document data model of the document.
465
+ * @param {string} segmentId The segment id used to get the header/footer data model. Defaults to an empty string for the document data model of the document.
1030
466
  * @returns {DocumentDataModel} The document data model.
1031
467
  * @example
1032
468
  * ```typescript
1033
469
  * const fDocument = univerAPI.getActiveDocument();
1034
- * const documentDataModel = fDocument.getDocumentDataModel();
1035
- * console.log(documentDataModel);
470
+ * console.log(fDocument.getDocumentDataModel());
471
+ *
472
+ * const headerSegmentId = fDocument.ensurePageHeader();
473
+ * console.log(fDocument.getDocumentDataModel(headerSegmentId));
1036
474
  * ```
1037
475
  */
1038
- getDocumentDataModel() {
1039
- return this._documentDataModel;
476
+ getDocumentDataModel(segmentId = "") {
477
+ const documentDataModel = this._documentDataModel.getSelfOrHeaderFooterModel(segmentId);
478
+ if (!documentDataModel) throw new Error(segmentId === "" ? "Document data model is not found." : `Document data model is not found in the segment: ${segmentId}`);
479
+ return documentDataModel;
1040
480
  }
1041
481
  /**
1042
- * Get the document body facade.
1043
- *
1044
- * The returned body facade provides synchronous Google Docs-like element APIs
1045
- * for reading and editing top-level document body elements. Paragraph elements
1046
- * use their persisted `paragraphId` values. Persisted elements, such as tables
1047
- * and custom blocks, use their existing ids.
1048
- *
1049
- * @returns {FDocumentBody} The document body API instance.
482
+ * Get the document body or header/footer body by the segment id.
483
+ * The main body has an empty segment id.
484
+ * The header and footer body have their respective segment ids.
485
+ * @param {string} segmentId The segment id of the body. Defaults to an empty string for the main body.
486
+ * @returns {IDocumentBody} The document body.
1050
487
  * @example
1051
488
  * ```typescript
1052
489
  * const fDocument = univerAPI.getActiveDocument();
1053
- * const fDocumentBody = fDocument.getBody();
1054
- * console.log(fDocumentBody.getBody());
490
+ * console.log(fDocument.getBody()); // Get the main body
1055
491
  *
1056
- * const element = fDocumentBody.getElement(0);
1057
- * if (element.isParagraph()) {
1058
- * const paragraph = element.asParagraph();
1059
- * paragraph.appendText(' updated');
1060
- * console.log(paragraph.getText());
1061
- * }
492
+ * const footerSegmentId = fDocument.ensurePageFooter();
493
+ * console.log(fDocument.getBody(footerSegmentId)); // Get the footer body
1062
494
  * ```
1063
495
  */
1064
- getBody() {
1065
- return this._injector.createInstance(FDocumentBody, this._documentDataModel, this._injector);
496
+ getBody(segmentId = "") {
497
+ var _this$_documentDataMo;
498
+ const body = (_this$_documentDataMo = this._documentDataModel.getSelfOrHeaderFooterModel(segmentId)) === null || _this$_documentDataMo === void 0 ? void 0 : _this$_documentDataMo.getBody();
499
+ if (!body) throw new Error(segmentId === "" ? "Body is not found in the document." : `Body is not found in the segment: ${segmentId}`);
500
+ return body;
1066
501
  }
1067
502
  dispose() {
1068
503
  super.dispose();
@@ -1073,8 +508,7 @@ let FDocument = class FDocument extends _univerjs_core_facade.FBaseInitialable {
1073
508
  * @example
1074
509
  * ```typescript
1075
510
  * const fDocument = univerAPI.getActiveDocument();
1076
- * const unitId = fDocument.getId();
1077
- * console.log(unitId);
511
+ * console.log(fDocument.getId());
1078
512
  * ```
1079
513
  */
1080
514
  getId() {
@@ -1086,14 +520,25 @@ let FDocument = class FDocument extends _univerjs_core_facade.FBaseInitialable {
1086
520
  * @example
1087
521
  * ```typescript
1088
522
  * const fDocument = univerAPI.getActiveDocument();
1089
- * const name = fDocument.getName();
1090
- * console.log(name);
523
+ * console.log(fDocument.getName());
1091
524
  * ```
1092
525
  */
1093
526
  getName() {
1094
527
  return this._documentDataModel.getTitle() || "";
1095
528
  }
1096
529
  /**
530
+ * Whether the document is a modern document or not.
531
+ * @returns {boolean} `true` if the document is a modern document, or `false` if it is not.
532
+ * @example
533
+ * ```typescript
534
+ * const fDocument = univerAPI.getActiveDocument();
535
+ * console.log(fDocument.isModern());
536
+ * ```
537
+ */
538
+ isModern() {
539
+ return this._documentDataModel.getSnapshot().documentStyle.documentFlavor === _univerjs_core.DocumentFlavor.MODERN;
540
+ }
541
+ /**
1097
542
  * Save the document snapshot data, including the document content and resource data, etc.
1098
543
  * @returns {IDocumentData} The document snapshot data.
1099
544
  * @example
@@ -1134,264 +579,302 @@ let FDocument = class FDocument extends _univerjs_core_facade.FBaseInitialable {
1134
579
  this._univerInstanceService.focusUnit(this.id);
1135
580
  return this._commandService.syncExecuteCommand(_univerjs_core.RedoCommand.id);
1136
581
  }
1137
- };
1138
- FDocument = __decorate([
1139
- __decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_core.Injector)),
1140
- __decorateParam(2, _univerjs_core.IUniverInstanceService),
1141
- __decorateParam(3, (0, _univerjs_core.Inject)(_univerjs_core.IResourceLoaderService)),
1142
- __decorateParam(4, _univerjs_core.ICommandService)
1143
- ], FDocument);
1144
-
1145
- //#endregion
1146
- //#region src/facade/f-univer.ts
1147
- var FUniverDocsMixin = class extends _univerjs_core_facade.FUniver {
1148
- createDocument(data) {
1149
- const document = this._injector.get(_univerjs_core.IUniverInstanceService).createUnit(_univerjs_core.UniverInstanceType.UNIVER_DOC, data);
1150
- return this._injector.createInstance(FDocument, document);
1151
- }
1152
- getActiveDocument() {
1153
- const document = this._univerInstanceService.getCurrentUnitOfType(_univerjs_core.UniverInstanceType.UNIVER_DOC);
1154
- if (!document) return null;
1155
- return this._injector.createInstance(FDocument, document);
1156
- }
1157
- getDocument(id) {
1158
- const document = this._univerInstanceService.getUnit(id, _univerjs_core.UniverInstanceType.UNIVER_DOC);
1159
- if (!document) return null;
1160
- return this._injector.createInstance(FDocument, document);
582
+ /**
583
+ * Ensure the page header segment exists and return its segment id.
584
+ * @param {number} pageIndex The zero-based page index. Defaults to the first page.
585
+ * @returns {string} The header segment id.
586
+ * @example
587
+ * ```ts
588
+ * const fDocument = univerAPI.getActiveDocument();
589
+ * const headerSegmentId = fDocument.ensurePageHeader();
590
+ * fDocument.insertText(0, 'Header text', headerSegmentId);
591
+ * ```
592
+ */
593
+ ensurePageHeader(pageIndex = 0) {
594
+ return this._ensureHeaderFooter("header", pageIndex);
1161
595
  }
1162
- };
1163
- _univerjs_core_facade.FUniver.extend(FUniverDocsMixin);
1164
-
1165
- //#endregion
1166
- //#region src/facade/f-document-block-range.ts
1167
- /**
1168
- * A facade wrapper for document block ranges, such as callout, quote, and code blocks.
1169
- *
1170
- * Block range identity is backed by the persisted `IDocumentBlockRange.blockId`,
1171
- * so wrappers can be re-resolved after text is inserted before the block range.
1172
- *
1173
- * @hideconstructor
1174
- */
1175
- var FDocumentBlockRange = class extends FDocumentElement {
1176
- constructor(body, bodyEdit, info, injector) {
1177
- super(body, bodyEdit, info, injector);
1178
- this.body = body;
1179
- this.bodyEdit = bodyEdit;
1180
- this.info = info;
1181
- this.injector = injector;
1182
- if (this.getType() !== _univerjs_core.DocumentBlockType.BLOCK_RANGE) throw new Error(`Element type is not a block range: ${this.getType()}`);
596
+ /**
597
+ * Ensure the page footer segment exists and return its segment id.
598
+ * @param {number} pageIndex The zero-based page index. Defaults to the first page.
599
+ * @returns {string} The footer segment id.
600
+ * @example
601
+ * ```ts
602
+ * const fDocument = univerAPI.getActiveDocument();
603
+ * const footerSegmentId = fDocument.ensurePageFooter();
604
+ * fDocument.insertText(0, 'Footer text', footerSegmentId);
605
+ * ```
606
+ */
607
+ ensurePageFooter(pageIndex = 0) {
608
+ return this._ensureHeaderFooter("footer", pageIndex);
1183
609
  }
1184
610
  /**
1185
- * Get the top-level block range data model.
1186
- * @returns {IDocumentBlockRange} The block range data model.
611
+ * Insert plain text at a document body offset.
612
+ * @param {number} index The zero-based insertion offset.
613
+ * @param {string} text The plain text to insert.
614
+ * @param {string} segmentId The segment id of the body. Defaults to an empty string for the main body.
615
+ * @returns {boolean} `true` if the edit was applied.
1187
616
  * @example
1188
617
  * ```ts
1189
618
  * const fDocument = univerAPI.getActiveDocument();
1190
- * const fDocumentBody = fDocument.getBody();
1191
- * const element = fDocumentBody.getElement(0);
619
+ * fDocument.insertText(0, 'Hello ');
1192
620
  *
1193
- * if (element?.isBlockRange()) {
1194
- * const blockRange = element.asBlockRange();
1195
- * console.log(blockRange.getBlockRange());
1196
- * }
621
+ * const headerSegmentId = fDocument.ensurePageHeader();
622
+ * fDocument.insertText(0, 'Header text', headerSegmentId);
1197
623
  * ```
1198
624
  */
1199
- getBlockRange() {
1200
- const { blockRanges = [] } = this._body.getBody();
1201
- const blockRange = blockRanges.find((blockRange) => blockRange.blockId === this.getKey());
1202
- if (!blockRange) throw new Error(`Block range not found: ${this.getKey()}`);
1203
- return blockRange;
625
+ insertText(index, text, segmentId = "") {
626
+ return replaceBodyRange({
627
+ startOffset: index,
628
+ endOffset: index,
629
+ segmentId
630
+ }, buildPlainTextInsertBody(text), this._documentDataModel, this._injector);
1204
631
  }
1205
632
  /**
1206
- * Get the block range type.
1207
- * @returns {DocumentBlockRangeType} The block type, such as callout, quote, or code.
633
+ * Get all paragraphs in the document body or header/footer body by the segment id.
634
+ * @param {string} segmentId The segment id of the body. Defaults to an empty string for the main body.
635
+ * @returns {FDocumentParagraph[]} An array of paragraph facade instances.
1208
636
  * @example
1209
637
  * ```ts
1210
638
  * const fDocument = univerAPI.getActiveDocument();
1211
- * const fDocumentBody = fDocument.getBody();
1212
- * const element = fDocumentBody.getElement(0);
639
+ * const paragraphs = fDocument.getParagraphs();
640
+ * console.log(paragraphs);
1213
641
  *
1214
- * if (element?.isBlockRange()) {
1215
- * const blockRange = element.asBlockRange();
1216
- * console.log(blockRange.getBlockType());
1217
- * }
642
+ * const headerSegmentId = fDocument.ensurePageHeader();
643
+ * const headerParagraphs = fDocument.getParagraphs(headerSegmentId);
644
+ * console.log(headerParagraphs);
1218
645
  * ```
1219
646
  */
1220
- getBlockType() {
1221
- return this.getBlockRange().blockType;
647
+ getParagraphs(segmentId = "") {
648
+ const { paragraphs = [] } = this.getBody(segmentId);
649
+ return paragraphs.map((paragraph) => this._createFDocumentParagraph(paragraph.paragraphId, segmentId));
1222
650
  }
1223
651
  /**
1224
- * Get the plain text inside this block range.
1225
- * @returns {string} The block range text.
652
+ * Get a paragraph by its paragraph id and segment id.
653
+ * @param {string} paragraphId The paragraph id.
654
+ * @param {string} segmentId The segment id of the body. Defaults to an empty string for the main body.
655
+ * @returns {FDocumentParagraph | null} The paragraph facade instance, or `null` if the paragraph is not found.
1226
656
  * @example
1227
657
  * ```ts
1228
658
  * const fDocument = univerAPI.getActiveDocument();
1229
- * const fDocumentBody = fDocument.getBody();
1230
- * const element = fDocumentBody.getElement(0);
659
+ * const paragraph = fDocument.getParagraph('paragraph-01');
660
+ * console.log(paragraph);
1231
661
  *
1232
- * if (element?.isBlockRange()) {
1233
- * const blockRange = element.asBlockRange();
1234
- * console.log(blockRange.getText());
1235
- * }
662
+ * const headerSegmentId = fDocument.ensurePageHeader();
663
+ * const headerParagraph = fDocument.getParagraph('header-paragraph-01', headerSegmentId);
664
+ * console.log(headerParagraph);
1236
665
  * ```
1237
666
  */
1238
- getText() {
1239
- const { dataStream } = this._body.getBody();
1240
- const { startIndex, endIndex } = this.getBlockRange();
1241
- return dataStream.slice(startIndex, endIndex);
667
+ getParagraph(paragraphId, segmentId = "") {
668
+ const { paragraphs = [] } = this.getBody(segmentId);
669
+ if (!paragraphs.find((paragraph) => paragraph.paragraphId === paragraphId)) return null;
670
+ return this._createFDocumentParagraph(paragraphId, segmentId);
1242
671
  }
1243
672
  /**
1244
- * Replace the plain text inside this block range.
1245
- * @param {string} text The replacement text.
1246
- * @returns {boolean} `true` if the block range text was replaced.
673
+ * Find a paragraph by its text content and segment id.
674
+ * @param {string} text The text content to search for.
675
+ * @param {string} segmentId The segment id of the body. Defaults to an empty string for the main body.
676
+ * @returns {FDocumentParagraph | null} The paragraph facade instance, or `null` if the paragraph is not found.
1247
677
  * @example
1248
678
  * ```ts
1249
679
  * const fDocument = univerAPI.getActiveDocument();
1250
- * const fDocumentBody = fDocument.getBody();
1251
- * const element = fDocumentBody.getElement(0);
680
+ * const paragraph = fDocument.findParagraphByText('Hello');
681
+ * console.log(paragraph);
1252
682
  *
1253
- * if (element?.isBlockRange()) {
1254
- * const blockRange = element.asBlockRange();
1255
- * blockRange.setText('Updated block text');
1256
- * console.log(blockRange.getText());
1257
- * }
683
+ * const footerSegmentId = fDocument.ensurePageFooter();
684
+ * const footerParagraph = fDocument.findParagraphByText('Page', footerSegmentId);
685
+ * console.log(footerParagraph);
1258
686
  * ```
1259
687
  */
1260
- setText(text) {
1261
- const blockRange = this.getBlockRange();
1262
- const { startIndex, endIndex } = blockRange;
1263
- const updateBody = buildPlainTextInsertBody(`${text}\r`);
1264
- updateBody.blockRanges = [{
1265
- ...blockRange,
1266
- startIndex: 0,
1267
- endIndex: text.length
1268
- }];
1269
- return this._bodyEdit.replaceRange({
1270
- startOffset: startIndex,
1271
- endOffset: endIndex + 1
1272
- }, updateBody);
688
+ findParagraphByText(text, segmentId = "") {
689
+ return this.findParagraphs({
690
+ text,
691
+ segmentId
692
+ })[0] || null;
1273
693
  }
1274
694
  /**
1275
- * Remove this block range wrapper from the body.
695
+ * Find paragraphs by a query object, which can include text content, paragraph id, and segment id.
696
+ * @param {string | IFDocumentParagraphQuery} query The query object or text content to search for.
697
+ * @returns {FDocumentParagraph[]} An array of paragraph facade instances that match the query.
698
+ * @example
699
+ * ```ts
700
+ * const fDocument = univerAPI.getActiveDocument();
701
+ * const paragraphsWithText = fDocument.findParagraphs('Hello');
702
+ * console.log(paragraphsWithText);
1276
703
  *
1277
- * This currently removes the block range and its content, matching
1278
- * `remove()`.
704
+ * const paragraphsWithId = fDocument.findParagraphs({ paragraphId: 'paragraph-01' });
705
+ * console.log(paragraphsWithId);
1279
706
  *
1280
- * @returns {boolean} `true` if the block range content was removed.
707
+ * const headerSegmentId = fDocument.ensurePageHeader();
708
+ * const paragraphsWithSegment = fDocument.findParagraphs({ segmentId: headerSegmentId });
709
+ * console.log(paragraphsWithSegment);
710
+ * ```
711
+ */
712
+ findParagraphs(query) {
713
+ const { text, paragraphId, segmentId = "" } = typeof query === "string" ? { text: query } : query;
714
+ return this.getParagraphs(segmentId).filter((paragraph) => {
715
+ if (paragraphId && paragraph.getId() !== paragraphId) return false;
716
+ if (text && !paragraph.getText().includes(text)) return false;
717
+ return true;
718
+ });
719
+ }
720
+ /**
721
+ * Insert a plain-text paragraph before the paragraph at the given paragraph index.
722
+ * @param {number} index The zero-based paragraph insertion index.
723
+ * @param {string} text The paragraph text. Defaults to an empty paragraph.
724
+ * @param {string} segmentId The segment id of the body. Defaults to an empty string for the main body.
725
+ * @returns {FDocumentParagraph} The inserted paragraph facade instance.
1281
726
  * @example
1282
727
  * ```ts
1283
728
  * const fDocument = univerAPI.getActiveDocument();
1284
- * const fDocumentBody = fDocument.getBody();
1285
- * const element = fDocumentBody.getElement(0);
729
+ * const paragraph = fDocument.insertParagraph(0, 'Document title');
730
+ * paragraph.appendText(' suffix');
1286
731
  *
1287
- * if (element?.isBlockRange()) {
1288
- * const blockRange = element.asBlockRange();
1289
- * const removed = blockRange.unwrap();
1290
- * console.log(removed ? 'Block range removed' : 'Failed to remove block range');
1291
- * }
732
+ * const headerSegmentId = fDocument.ensurePageHeader();
733
+ * const headerParagraph = fDocument.insertParagraph(0, 'Header title', headerSegmentId);
734
+ * headerParagraph.appendText(' suffix');
1292
735
  * ```
1293
736
  */
1294
- unwrap() {
1295
- return this.remove();
1296
- }
1297
- };
1298
- var FDocumentBlockRangeMixin = class extends FDocumentElement {
1299
- asBlockRange() {
1300
- if (this.getType() !== _univerjs_core.DocumentBlockType.BLOCK_RANGE) throw new Error(`Element type is not a block range: ${this.getType()}`);
1301
- return this._injector.createInstance(FDocumentBlockRange, this._body, this._bodyEdit, this.getResolvedInfo(), this._injector);
1302
- }
1303
- };
1304
- FDocumentElement.extend(FDocumentBlockRangeMixin);
1305
-
1306
- //#endregion
1307
- //#region src/facade/f-document-custom-block.ts
1308
- /**
1309
- * A facade wrapper for document top-level custom blocks.
1310
- * @hideconstructor
1311
- */
1312
- var FDocumentCustomBlock = class extends FDocumentElement {
1313
- constructor(body, bodyEdit, info, injector) {
1314
- super(body, bodyEdit, info, injector);
1315
- this.body = body;
1316
- this.bodyEdit = bodyEdit;
1317
- this.info = info;
1318
- this.injector = injector;
1319
- if (this.getType() !== _univerjs_core.DocumentBlockType.CUSTOM_BLOCK) throw new Error(`Element type is not a custom block: ${this.getType()}`);
737
+ insertParagraph(index, text = "", segmentId = "") {
738
+ const offset = this._getParagraphInsertOffset(index, segmentId);
739
+ if (!replaceBodyRange({
740
+ startOffset: offset,
741
+ endOffset: offset,
742
+ segmentId
743
+ }, buildPlainTextInsertBody(`${text}\r`), this._documentDataModel, this._injector)) throw new Error("Failed to insert paragraph.");
744
+ const { paragraphs = [] } = this.getBody(segmentId);
745
+ const paragraph = paragraphs[index];
746
+ if (!paragraph) throw new Error("Failed to insert paragraph.");
747
+ return this._createFDocumentParagraph(paragraph.paragraphId, segmentId);
1320
748
  }
1321
749
  /**
1322
- * Get the custom block marker.
1323
- * @returns {ICustomBlock} The custom block marker.
750
+ * Append a plain-text paragraph at the end of the body.
751
+ * @param {string} text The paragraph text. Defaults to an empty paragraph.
752
+ * @returns {FDocumentParagraph} The appended paragraph wrapper.
1324
753
  * @example
1325
754
  * ```ts
1326
755
  * const fDocument = univerAPI.getActiveDocument();
1327
- * const fDocumentBody = fDocument.getBody();
1328
- * const element = fDocumentBody.getElement(0);
756
+ * const paragraph = fDocument.appendParagraph('Summary');
757
+ * console.log(paragraph.getText());
1329
758
  *
1330
- * if (element?.isCustomBlock()) {
1331
- * const customBlock = element.asCustomBlock();
1332
- * console.log(customBlock.getCustomBlock());
1333
- * }
759
+ * const footerSegmentId = fDocument.ensurePageFooter();
760
+ * const footerParagraph = fDocument.appendParagraph('Confidential', footerSegmentId);
761
+ * console.log(footerParagraph.getText());
1334
762
  * ```
1335
763
  */
1336
- getCustomBlock() {
1337
- const { customBlocks = [] } = this._body.getBody();
1338
- const block = customBlocks.find((item) => item.blockId === this.getKey());
1339
- if (!block) throw new Error("Doc custom block is stale");
1340
- return block;
1341
- }
1342
- };
1343
- var FDocumentCustomBlockMixin = class extends FDocumentElement {
1344
- asCustomBlock() {
1345
- if (this.getType() !== _univerjs_core.DocumentBlockType.CUSTOM_BLOCK) throw new Error(`Element type is not a custom block: ${this.getType()}`);
1346
- return this._injector.createInstance(FDocumentCustomBlock, this._body, this._bodyEdit, this.getResolvedInfo(), this._injector);
1347
- }
1348
- };
1349
- FDocumentElement.extend(FDocumentCustomBlockMixin);
1350
-
1351
- //#endregion
1352
- //#region src/facade/f-document-table.ts
1353
- /**
1354
- * A facade wrapper for document top-level tables.
1355
- * @hideconstructor
1356
- */
1357
- var FDocumentTable = class extends FDocumentElement {
1358
- constructor(body, bodyEdit, info, injector) {
1359
- super(body, bodyEdit, info, injector);
1360
- this.body = body;
1361
- this.bodyEdit = bodyEdit;
1362
- this.info = info;
1363
- this.injector = injector;
1364
- if (this.getType() !== _univerjs_core.DocumentBlockType.TABLE) throw new Error(`Element type is not a table: ${this.getType()}`);
764
+ appendParagraph(text = "", segmentId = "") {
765
+ const { paragraphs = [] } = this.getBody(segmentId);
766
+ return this.insertParagraph(paragraphs.length, text, segmentId);
1365
767
  }
1366
768
  /**
1367
- * Get the table marker.
1368
- * @returns {ICustomTable} The table marker.
769
+ * Delete a range from the body.
770
+ * @param {IFDocumentTextRange} range The text range to delete.
771
+ * @returns {boolean} `true` if the range was deleted.
1369
772
  * @example
1370
773
  * ```ts
1371
774
  * const fDocument = univerAPI.getActiveDocument();
1372
- * const fDocumentBody = fDocument.getBody();
1373
- * const element = fDocumentBody.getElement(0);
775
+ * fDocument.deleteRange({ startOffset: 0, endOffset: 5 });
1374
776
  *
1375
- * if (element?.isTable()) {
1376
- * const table = element.asTable();
1377
- * console.log(table.getTable());
1378
- * }
777
+ * const headerSegmentId = fDocument.ensurePageHeader();
778
+ * fDocument.deleteRange({ startOffset: 0, endOffset: 5, segmentId: headerSegmentId });
1379
779
  * ```
1380
780
  */
1381
- getTable() {
1382
- const { tables = [] } = this._body.getBody();
1383
- const table = tables.find((item) => item.tableId === this.getKey());
1384
- if (!table) throw new Error("Doc table is stale");
1385
- return table;
781
+ deleteRange(range) {
782
+ const normalizedRange = this._normalizeDeleteRange(range);
783
+ if (normalizedRange.startOffset >= normalizedRange.endOffset) return false;
784
+ return replaceBodyRange(normalizedRange, { dataStream: "" }, this._documentDataModel, this._injector);
785
+ }
786
+ _createFDocumentParagraph(paragraphId, segmentId = "") {
787
+ return this._injector.createInstance(FDocumentParagraph, this, paragraphId, segmentId, this._injector);
788
+ }
789
+ _normalizeDeleteRange(range) {
790
+ const body = this.getBody(range.segmentId);
791
+ const protectedEndOffset = body.dataStream.endsWith("\r\n") ? Math.max(0, body.dataStream.length - 2) : body.dataStream.length;
792
+ const endOffset = Math.min(Math.max(range.endOffset, 0), protectedEndOffset);
793
+ return {
794
+ ...range,
795
+ startOffset: Math.min(Math.max(range.startOffset, 0), endOffset),
796
+ endOffset
797
+ };
798
+ }
799
+ _getParagraphInsertOffset(index, segmentId = "") {
800
+ if (index <= 0) return 0;
801
+ const { dataStream, paragraphs = [] } = this.getBody(segmentId);
802
+ if (paragraphs.length === 0) return Math.max(0, dataStream.length - 1);
803
+ if (index >= paragraphs.length) return paragraphs[paragraphs.length - 1].startIndex + 1;
804
+ return paragraphs[index - 1].startIndex + 1;
805
+ }
806
+ _ensureHeaderFooter(kind, pageIndex) {
807
+ if (this.isModern()) throw new Error("The document is a modern document, header/footer is not supported.");
808
+ const { createType, segmentId: existingSegmentId } = this._getHeaderFooterCreateInfo(kind, pageIndex);
809
+ if (existingSegmentId) return existingSegmentId;
810
+ const segmentId = (0, _univerjs_core.generateRandomId)(6);
811
+ if (!this._commandService.syncExecuteCommand(_univerjs_docs.CreateHeaderFooterCommand.id, {
812
+ unitId: this.getId(),
813
+ segmentId,
814
+ createType
815
+ })) throw new Error(`Failed to create page ${kind}.`);
816
+ return segmentId;
817
+ }
818
+ _getHeaderFooterCreateInfo(kind, pageIndex) {
819
+ var _documentStyle$defaul, _documentStyle$defaul2;
820
+ const { documentStyle } = this._documentDataModel.getSnapshot();
821
+ const isFirstPage = pageIndex === 0;
822
+ const isEvenPage = (pageIndex + 1) % 2 === 0;
823
+ if (isFirstPage && documentStyle.useFirstPageHeaderFooter === _univerjs_core.BooleanNumber.TRUE) {
824
+ var _documentStyle$firstP, _documentStyle$firstP2;
825
+ return kind === "header" ? {
826
+ createType: _univerjs_docs.HeaderFooterType.FIRST_PAGE_HEADER,
827
+ segmentId: (_documentStyle$firstP = documentStyle.firstPageHeaderId) !== null && _documentStyle$firstP !== void 0 ? _documentStyle$firstP : ""
828
+ } : {
829
+ createType: _univerjs_docs.HeaderFooterType.FIRST_PAGE_FOOTER,
830
+ segmentId: (_documentStyle$firstP2 = documentStyle.firstPageFooterId) !== null && _documentStyle$firstP2 !== void 0 ? _documentStyle$firstP2 : ""
831
+ };
832
+ }
833
+ if (isEvenPage && documentStyle.evenAndOddHeaders === _univerjs_core.BooleanNumber.TRUE) {
834
+ var _documentStyle$evenPa, _documentStyle$evenPa2;
835
+ return kind === "header" ? {
836
+ createType: _univerjs_docs.HeaderFooterType.EVEN_PAGE_HEADER,
837
+ segmentId: (_documentStyle$evenPa = documentStyle.evenPageHeaderId) !== null && _documentStyle$evenPa !== void 0 ? _documentStyle$evenPa : ""
838
+ } : {
839
+ createType: _univerjs_docs.HeaderFooterType.EVEN_PAGE_FOOTER,
840
+ segmentId: (_documentStyle$evenPa2 = documentStyle.evenPageFooterId) !== null && _documentStyle$evenPa2 !== void 0 ? _documentStyle$evenPa2 : ""
841
+ };
842
+ }
843
+ return kind === "header" ? {
844
+ createType: _univerjs_docs.HeaderFooterType.DEFAULT_HEADER,
845
+ segmentId: (_documentStyle$defaul = documentStyle.defaultHeaderId) !== null && _documentStyle$defaul !== void 0 ? _documentStyle$defaul : ""
846
+ } : {
847
+ createType: _univerjs_docs.HeaderFooterType.DEFAULT_FOOTER,
848
+ segmentId: (_documentStyle$defaul2 = documentStyle.defaultFooterId) !== null && _documentStyle$defaul2 !== void 0 ? _documentStyle$defaul2 : ""
849
+ };
1386
850
  }
1387
851
  };
1388
- var FDocumentTableMixin = class extends FDocumentElement {
1389
- asTable() {
1390
- if (this.getType() !== _univerjs_core.DocumentBlockType.TABLE) throw new Error(`Element type is not a table: ${this.getType()}`);
1391
- return this._injector.createInstance(FDocumentTable, this._body, this._bodyEdit, this.getResolvedInfo(), this._injector);
852
+ FDocument = __decorate([
853
+ __decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_core.Injector)),
854
+ __decorateParam(2, _univerjs_core.IUniverInstanceService),
855
+ __decorateParam(3, (0, _univerjs_core.Inject)(_univerjs_core.IResourceLoaderService)),
856
+ __decorateParam(4, _univerjs_core.ICommandService)
857
+ ], FDocument);
858
+
859
+ //#endregion
860
+ //#region src/facade/f-univer.ts
861
+ var FUniverDocsMixin = class extends _univerjs_core_facade.FUniver {
862
+ createDocument(data) {
863
+ const document = this._injector.get(_univerjs_core.IUniverInstanceService).createUnit(_univerjs_core.UniverInstanceType.UNIVER_DOC, data);
864
+ return this._injector.createInstance(FDocument, document);
865
+ }
866
+ getActiveDocument() {
867
+ const document = this._univerInstanceService.getCurrentUnitOfType(_univerjs_core.UniverInstanceType.UNIVER_DOC);
868
+ if (!document) return null;
869
+ return this._injector.createInstance(FDocument, document);
870
+ }
871
+ getDocument(id) {
872
+ const document = this._univerInstanceService.getUnit(id, _univerjs_core.UniverInstanceType.UNIVER_DOC);
873
+ if (!document) return null;
874
+ return this._injector.createInstance(FDocument, document);
1392
875
  }
1393
876
  };
1394
- FDocumentElement.extend(FDocumentTableMixin);
877
+ _univerjs_core_facade.FUniver.extend(FUniverDocsMixin);
1395
878
 
1396
879
  //#endregion
1397
880
  Object.defineProperty(exports, 'FDocument', {
@@ -1400,9 +883,6 @@ Object.defineProperty(exports, 'FDocument', {
1400
883
  return FDocument;
1401
884
  }
1402
885
  });
1403
- exports.FDocumentBlockRange = FDocumentBlockRange;
1404
- exports.FDocumentBody = FDocumentBody;
1405
- exports.FDocumentCustomBlock = FDocumentCustomBlock;
1406
- exports.FDocumentElement = FDocumentElement;
1407
886
  exports.FDocumentParagraph = FDocumentParagraph;
1408
- exports.FDocumentTable = FDocumentTable;
887
+ exports.isParagraphFacade = isParagraphFacade;
888
+ exports.stripBlockTokens = stripBlockTokens;