@univerjs/docs-toc 1.0.0

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.
@@ -0,0 +1,597 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ let _univerjs_core = require("@univerjs/core");
3
+ let _univerjs_docs = require("@univerjs/docs");
4
+ let _univerjs_engine_render = require("@univerjs/engine-render");
5
+ let rxjs = require("rxjs");
6
+
7
+ //#region src/commands/table-of-contents.command.ts
8
+ const FIELD_START = "";
9
+ const FIELD_END = "";
10
+ async function replaceBodyRange(accessor, doc, unitId, selection, body, historyAction, historyGroupId = (0, _univerjs_core.generateRandomId)()) {
11
+ const textX = new _univerjs_core.TextX();
12
+ textX.push(..._univerjs_core.BuildTextUtils.selection.delete([selection], doc.getBody(), 0, body));
13
+ const caretOffset = selection.startOffset + body.dataStream.length;
14
+ accessor.get(_univerjs_docs.DocStateChangeManagerService).flushPendingChanges(unitId);
15
+ const group = accessor.get(_univerjs_core.IUndoRedoService).beginUndoRedoGroup(unitId, historyGroupId, "append");
16
+ try {
17
+ return Boolean(accessor.get(_univerjs_core.ICommandService).syncExecuteCommand(_univerjs_docs.RichTextEditingMutation.id, {
18
+ unitId,
19
+ historyAction,
20
+ actions: _univerjs_core.JSONX.getInstance().editOp(textX.serialize(), (0, _univerjs_core.getRichTextEditPath)(doc)),
21
+ textRanges: [{
22
+ startOffset: caretOffset,
23
+ endOffset: caretOffset,
24
+ collapsed: true
25
+ }],
26
+ debounce: false,
27
+ trigger: historyAction
28
+ }));
29
+ } finally {
30
+ group.dispose();
31
+ }
32
+ }
33
+ const UpdateTableOfContentsCommand = {
34
+ id: "doc.command.update-table-of-contents",
35
+ type: _univerjs_core.CommandType.COMMAND,
36
+ handler: (accessor, params) => updateTableOfContents(accessor, params)
37
+ };
38
+ async function updateTableOfContents(accessor, params, historyGroupId = (0, _univerjs_core.generateRandomId)()) {
39
+ var _body$customRanges, _toc$properties, _render$getInjector;
40
+ const instanceService = accessor.get(_univerjs_core.IUniverInstanceService);
41
+ const doc = (params === null || params === void 0 ? void 0 : params.unitId) ? instanceService.getUnit(params.unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC) : instanceService.getCurrentUnitOfType(_univerjs_core.UniverInstanceType.UNIVER_DOC);
42
+ const body = doc === null || doc === void 0 ? void 0 : doc.getBody();
43
+ const selection = accessor.get(_univerjs_docs.DocSelectionManagerService).getActiveTextRange();
44
+ const toc = (params === null || params === void 0 ? void 0 : params.rangeId) ? body === null || body === void 0 || (_body$customRanges = body.customRanges) === null || _body$customRanges === void 0 ? void 0 : _body$customRanges.find((range) => range.rangeId === params.rangeId && isTableOfContentsRange(range)) : findTableOfContentsAtOffset(body, selection === null || selection === void 0 ? void 0 : selection.startOffset);
45
+ const unitId = doc === null || doc === void 0 ? void 0 : doc.getUnitId();
46
+ if (!doc || !body || !toc || ((_toc$properties = toc.properties) === null || _toc$properties === void 0 ? void 0 : _toc$properties.locked) === _univerjs_core.BooleanNumber.TRUE || !unitId) return false;
47
+ const render = accessor.get(_univerjs_engine_render.IRenderManagerService).getRenderUnitById(unitId);
48
+ const renderInjector = render === null || render === void 0 || (_render$getInjector = render.getInjector) === null || _render$getInjector === void 0 ? void 0 : _render$getInjector.call(render);
49
+ if (!render || !(renderInjector === null || renderInjector === void 0 ? void 0 : renderInjector.has(_univerjs_docs.DocSkeletonManagerService))) return false;
50
+ const skeleton = render.with(_univerjs_docs.DocSkeletonManagerService).getSkeleton();
51
+ if (!await waitForCompleteLayout(skeleton)) return false;
52
+ let updated = false;
53
+ for (let iteration = 0; iteration < 3; iteration += 1) {
54
+ var _currentBody$customRa, _currentToc$propertie, _skeleton$getLayoutPr;
55
+ const currentBody = doc.getBody();
56
+ const currentToc = currentBody === null || currentBody === void 0 || (_currentBody$customRa = currentBody.customRanges) === null || _currentBody$customRa === void 0 ? void 0 : _currentBody$customRa.find((range) => range.rangeId === toc.rangeId && isTableOfContentsRange(range));
57
+ if (!currentBody || !currentToc || ((_currentToc$propertie = currentToc.properties) === null || _currentToc$propertie === void 0 ? void 0 : _currentToc$propertie.locked) === _univerjs_core.BooleanNumber.TRUE) return false;
58
+ const resolvePageNumber = (offset) => {
59
+ var _skeleton$getSkeleton;
60
+ const pageIndex = skeleton.findBodyPageIndexByCharIndex(offset);
61
+ return (_skeleton$getSkeleton = skeleton.getSkeletonData()) === null || _skeleton$getSkeleton === void 0 || (_skeleton$getSkeleton = _skeleton$getSkeleton.pages[pageIndex]) === null || _skeleton$getSkeleton === void 0 ? void 0 : _skeleton$getSkeleton.pageNumber;
62
+ };
63
+ const replacement = (params === null || params === void 0 ? void 0 : params.mode) === "pageNumbersOnly" ? buildPageNumberOnlyTableOfContentsBody(currentBody, currentToc, resolvePageNumber) : buildTableOfContentsBody(currentBody, currentToc, resolvePageNumber);
64
+ if (!replacement) return false;
65
+ if ((params === null || params === void 0 ? void 0 : params.mode) === "pageNumbersOnly" && _univerjs_core.Tools.diffValue((0, _univerjs_core.getBodySlice)(currentBody, currentToc.startIndex, currentToc.endIndex + 1, true, _univerjs_core.SliceBodyType.cut), replacement)) return true;
66
+ if (updated && currentBody.dataStream.slice(currentToc.startIndex, currentToc.endIndex + 1) === replacement.dataStream) return true;
67
+ const generation = ((_skeleton$getLayoutPr = skeleton.getLayoutProgress()) === null || _skeleton$getLayoutPr === void 0 ? void 0 : _skeleton$getLayoutPr.generation) ?? -1;
68
+ updated = await replaceBodyRange(accessor, doc, unitId, {
69
+ startOffset: currentToc.startIndex,
70
+ endOffset: currentToc.endIndex + 1,
71
+ collapsed: false
72
+ }, replacement, UpdateTableOfContentsCommand.id, historyGroupId);
73
+ if (!updated || iteration === 2) return updated;
74
+ if (!await waitForNextCompleteLayout(skeleton, generation)) return false;
75
+ }
76
+ return updated;
77
+ }
78
+ const DeleteTableOfContentsCommand = {
79
+ id: "doc.command.delete-table-of-contents",
80
+ type: _univerjs_core.CommandType.COMMAND,
81
+ async handler(accessor, params) {
82
+ var _body$customRanges2;
83
+ const instanceService = accessor.get(_univerjs_core.IUniverInstanceService);
84
+ const doc = (params === null || params === void 0 ? void 0 : params.unitId) ? instanceService.getUnit(params.unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC) : instanceService.getCurrentUnitOfType(_univerjs_core.UniverInstanceType.UNIVER_DOC);
85
+ const body = doc === null || doc === void 0 ? void 0 : doc.getBody();
86
+ const selection = accessor.get(_univerjs_docs.DocSelectionManagerService).getActiveTextRange();
87
+ const toc = (params === null || params === void 0 ? void 0 : params.rangeId) ? body === null || body === void 0 || (_body$customRanges2 = body.customRanges) === null || _body$customRanges2 === void 0 ? void 0 : _body$customRanges2.find((range) => range.rangeId === params.rangeId && isTableOfContentsRange(range)) : findTableOfContentsAtOffset(body, selection === null || selection === void 0 ? void 0 : selection.startOffset);
88
+ const unitId = doc === null || doc === void 0 ? void 0 : doc.getUnitId();
89
+ if (!toc || !unitId) return false;
90
+ return replaceBodyRange(accessor, doc, unitId, {
91
+ startOffset: toc.startIndex,
92
+ endOffset: toc.endIndex + 1,
93
+ collapsed: false
94
+ }, { dataStream: "" }, DeleteTableOfContentsCommand.id);
95
+ }
96
+ };
97
+ const InsertTableOfContentsCommand = {
98
+ id: "doc.command.insert-table-of-contents",
99
+ type: _univerjs_core.CommandType.COMMAND,
100
+ async handler(accessor, params) {
101
+ var _render$getInjector2;
102
+ const instanceService = accessor.get(_univerjs_core.IUniverInstanceService);
103
+ const doc = (params === null || params === void 0 ? void 0 : params.unitId) ? instanceService.getUnit(params.unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC) : instanceService.getCurrentUnitOfType(_univerjs_core.UniverInstanceType.UNIVER_DOC);
104
+ const selection = accessor.get(_univerjs_docs.DocSelectionManagerService).getActiveTextRange();
105
+ const body = doc === null || doc === void 0 ? void 0 : doc.getBody();
106
+ const unitId = doc === null || doc === void 0 ? void 0 : doc.getUnitId();
107
+ const render = unitId ? accessor.get(_univerjs_engine_render.IRenderManagerService).getRenderUnitById(unitId) : void 0;
108
+ const renderInjector = render === null || render === void 0 || (_render$getInjector2 = render.getInjector) === null || _render$getInjector2 === void 0 ? void 0 : _render$getInjector2.call(render);
109
+ if (!doc || !body || !unitId || !selection || selection.segmentId || selection.startOffset !== selection.endOffset || findTableOfContentsAtOffset(body, selection.startOffset) || !render || !(renderInjector === null || renderInjector === void 0 ? void 0 : renderInjector.has(_univerjs_docs.DocSkeletonManagerService))) return false;
110
+ const skeleton = render.with(_univerjs_docs.DocSkeletonManagerService).getSkeleton();
111
+ if (!await waitForCompleteLayout(skeleton)) return false;
112
+ const levels = Math.min(9, Math.max(1, Math.trunc((params === null || params === void 0 ? void 0 : params.levels) ?? 3)));
113
+ const showPageNumbers = (params === null || params === void 0 ? void 0 : params.showPageNumbers) ?? true;
114
+ const rightAlignPageNumbers = showPageNumbers && ((params === null || params === void 0 ? void 0 : params.rightAlignPageNumbers) ?? true);
115
+ const tabLeader = (params === null || params === void 0 ? void 0 : params.tabLeader) ?? "dots";
116
+ const format = (params === null || params === void 0 ? void 0 : params.format) ?? "fromTemplate";
117
+ const rangeId = (0, _univerjs_core.generateRandomId)();
118
+ const toc = {
119
+ rangeId,
120
+ rangeType: _univerjs_core.CustomRangeType.FIELD,
121
+ startIndex: selection.startOffset,
122
+ endIndex: selection.startOffset,
123
+ wholeEntity: false,
124
+ properties: {
125
+ fieldType: "TOC",
126
+ instruction: buildTableOfContentsInstruction({
127
+ levels,
128
+ showPageNumbers,
129
+ rightAlignPageNumbers
130
+ }),
131
+ sourceKind: "complex",
132
+ showPageNumbers,
133
+ rightAlignPageNumbers,
134
+ tabLeader,
135
+ format,
136
+ title: params === null || params === void 0 ? void 0 : params.title
137
+ }
138
+ };
139
+ const { pageSize, marginLeft = 0, marginRight = 0 } = doc.getDocumentStyle();
140
+ const replacement = buildTableOfContentsBody(body, toc, (offset) => {
141
+ var _skeleton$getSkeleton2;
142
+ const pageIndex = skeleton.findBodyPageIndexByCharIndex(offset);
143
+ return (_skeleton$getSkeleton2 = skeleton.getSkeletonData()) === null || _skeleton$getSkeleton2 === void 0 || (_skeleton$getSkeleton2 = _skeleton$getSkeleton2.pages[pageIndex]) === null || _skeleton$getSkeleton2 === void 0 ? void 0 : _skeleton$getSkeleton2.pageNumber;
144
+ }, _univerjs_core.generateRandomId, { tabStopOffset: Math.max(72, ((pageSize === null || pageSize === void 0 ? void 0 : pageSize.width) ?? 594.3) - marginLeft - marginRight) });
145
+ if (!replacement) return false;
146
+ const historyGroupId = (0, _univerjs_core.generateRandomId)();
147
+ if (!await replaceBodyRange(accessor, doc, unitId, {
148
+ startOffset: selection.startOffset,
149
+ endOffset: selection.startOffset,
150
+ collapsed: true
151
+ }, replacement, InsertTableOfContentsCommand.id, historyGroupId)) return false;
152
+ await updateTableOfContents(accessor, {
153
+ unitId,
154
+ rangeId,
155
+ mode: "entireTable"
156
+ }, historyGroupId);
157
+ return true;
158
+ }
159
+ };
160
+ function buildTableOfContentsInstruction(options = {}) {
161
+ const levels = Math.min(9, Math.max(1, Math.trunc(options.levels ?? 3)));
162
+ const showPageNumbers = options.showPageNumbers ?? true;
163
+ const rightAlignPageNumbers = showPageNumbers && (options.rightAlignPageNumbers ?? true);
164
+ return `TOC ${[
165
+ `\\o "1-${levels}"`,
166
+ "\\h",
167
+ "\\z",
168
+ "\\u",
169
+ ...!showPageNumbers ? ["\\n"] : [],
170
+ ...showPageNumbers && !rightAlignPageNumbers ? ["\\p \" \""] : []
171
+ ].join(" ")}`;
172
+ }
173
+ function isTableOfContentsRange(range) {
174
+ var _range$properties;
175
+ return range.rangeType === _univerjs_core.CustomRangeType.FIELD && ((_range$properties = range.properties) === null || _range$properties === void 0 ? void 0 : _range$properties.fieldType) === "TOC";
176
+ }
177
+ function findTableOfContentsAtOffset(body, offset) {
178
+ var _body$customRanges3;
179
+ if (offset == null) return;
180
+ return body === null || body === void 0 || (_body$customRanges3 = body.customRanges) === null || _body$customRanges3 === void 0 ? void 0 : _body$customRanges3.filter((range) => isTableOfContentsRange(range) && range.startIndex <= offset && offset <= range.endIndex).sort((left, right) => left.endIndex - left.startIndex - (right.endIndex - right.startIndex))[0];
181
+ }
182
+ async function waitForCompleteLayout(skeleton) {
183
+ const progress = skeleton.getLayoutProgress();
184
+ if (progress == null || progress.complete) return true;
185
+ try {
186
+ await (0, rxjs.firstValueFrom)(skeleton.layoutProgress$.pipe((0, rxjs.filter)((next) => next.complete), (0, rxjs.take)(1), (0, rxjs.timeout)({ first: 3e4 })));
187
+ return true;
188
+ } catch {
189
+ return false;
190
+ }
191
+ }
192
+ async function waitForNextCompleteLayout(skeleton, generation) {
193
+ try {
194
+ await (0, rxjs.firstValueFrom)(skeleton.layoutProgress$.pipe((0, rxjs.filter)((next) => next.generation > generation && next.complete), (0, rxjs.take)(1), (0, rxjs.timeout)({ first: 3e4 })));
195
+ return true;
196
+ } catch {
197
+ return false;
198
+ }
199
+ }
200
+ function buildPageNumberOnlyTableOfContentsBody(body, toc, resolvePageNumber) {
201
+ var _toc$properties2, _result$customRanges, _result$customRanges2;
202
+ if (((_toc$properties2 = toc.properties) === null || _toc$properties2 === void 0 ? void 0 : _toc$properties2.locked) === _univerjs_core.BooleanNumber.TRUE) return null;
203
+ const result = _univerjs_core.Tools.deepClone((0, _univerjs_core.getBodySlice)(body, toc.startIndex, toc.endIndex + 1, true, _univerjs_core.SliceBodyType.cut));
204
+ const pageFields = ((_result$customRanges = result.customRanges) === null || _result$customRanges === void 0 ? void 0 : _result$customRanges.filter((range) => {
205
+ var _range$properties2, _range$properties3;
206
+ return range.rangeType === _univerjs_core.CustomRangeType.FIELD && ((_range$properties2 = range.properties) === null || _range$properties2 === void 0 ? void 0 : _range$properties2.fieldType) === "PAGEREF" && ((_range$properties3 = range.properties) === null || _range$properties3 === void 0 ? void 0 : _range$properties3.locked) !== _univerjs_core.BooleanNumber.TRUE;
207
+ }).sort((left, right) => right.startIndex - left.startIndex)) ?? [];
208
+ for (const pageField of pageFields) {
209
+ var _body$customRanges4;
210
+ const originalField = (_body$customRanges4 = body.customRanges) === null || _body$customRanges4 === void 0 ? void 0 : _body$customRanges4.find((range) => range.rangeId === pageField.rangeId);
211
+ const targetOffset = originalField && resolvePageReferenceOffset(body, originalField);
212
+ const pageNumber = targetOffset == null ? void 0 : resolvePageNumber(targetOffset);
213
+ if (pageNumber == null) return null;
214
+ replaceFieldResult(result, pageField, String(pageNumber));
215
+ }
216
+ const outer = (_result$customRanges2 = result.customRanges) === null || _result$customRanges2 === void 0 ? void 0 : _result$customRanges2.find((range) => range.rangeId === toc.rangeId);
217
+ if (outer === null || outer === void 0 ? void 0 : outer.properties) outer.properties.cachedResult = (0, _univerjs_core.getPlainText)(result.dataStream.slice(1, -1)).replaceAll(FIELD_START, "").replaceAll(FIELD_END, "");
218
+ return result;
219
+ }
220
+ function resolvePageReferenceOffset(body, pageField) {
221
+ var _String$match, _pageField$properties, _body$customRanges6, _link$properties, _body$paragraphs;
222
+ const targetId = (_String$match = String(((_pageField$properties = pageField.properties) === null || _pageField$properties === void 0 ? void 0 : _pageField$properties.instruction) ?? "").match(/PAGEREF\s+"?([^"\s\\]+)"?/i)) === null || _String$match === void 0 ? void 0 : _String$match[1];
223
+ if (targetId) {
224
+ var _body$customRanges5;
225
+ const bookmark = (_body$customRanges5 = body.customRanges) === null || _body$customRanges5 === void 0 ? void 0 : _body$customRanges5.find((range) => {
226
+ var _range$properties4;
227
+ return range.rangeType === _univerjs_core.CustomRangeType.BOOKMARK && ((_range$properties4 = range.properties) === null || _range$properties4 === void 0 ? void 0 : _range$properties4.bookmarkId) === targetId;
228
+ });
229
+ if (bookmark) return bookmark.startIndex;
230
+ }
231
+ const link = (_body$customRanges6 = body.customRanges) === null || _body$customRanges6 === void 0 ? void 0 : _body$customRanges6.find((range) => range.rangeType === _univerjs_core.CustomRangeType.HYPERLINK && range.startIndex <= pageField.startIndex && pageField.endIndex <= range.endIndex);
232
+ const headingId = link === null || link === void 0 || (_link$properties = link.properties) === null || _link$properties === void 0 ? void 0 : _link$properties.headingId;
233
+ return (_body$paragraphs = body.paragraphs) === null || _body$paragraphs === void 0 || (_body$paragraphs = _body$paragraphs.find((paragraph) => {
234
+ var _paragraph$paragraphS;
235
+ return ((_paragraph$paragraphS = paragraph.paragraphStyle) === null || _paragraph$paragraphS === void 0 ? void 0 : _paragraph$paragraphS.headingId) === headingId;
236
+ })) === null || _body$paragraphs === void 0 ? void 0 : _body$paragraphs.startIndex;
237
+ }
238
+ function replaceFieldResult(body, field, value) {
239
+ var _body$paragraphs2, _body$customRanges7;
240
+ const start = field.startIndex + 1;
241
+ const end = field.endIndex;
242
+ if (field.properties) field.properties.cachedResult = value;
243
+ if (body.dataStream.slice(start, end) === value) return;
244
+ const delta = value.length - (end - start);
245
+ body.dataStream = `${body.dataStream.slice(0, start)}${value}${body.dataStream.slice(end)}`;
246
+ shiftRuns(body.textRuns, start, end, delta);
247
+ (_body$paragraphs2 = body.paragraphs) === null || _body$paragraphs2 === void 0 || _body$paragraphs2.forEach((paragraph) => {
248
+ if (paragraph.startIndex >= end) paragraph.startIndex += delta;
249
+ });
250
+ (_body$customRanges7 = body.customRanges) === null || _body$customRanges7 === void 0 || _body$customRanges7.forEach((range) => {
251
+ if (range.startIndex >= end) {
252
+ range.startIndex += delta;
253
+ range.endIndex += delta;
254
+ } else if (range.endIndex >= end) range.endIndex += delta;
255
+ });
256
+ }
257
+ function shiftRuns(runs, start, end, delta) {
258
+ runs === null || runs === void 0 || runs.forEach((run) => {
259
+ if (run.st >= end) {
260
+ run.st += delta;
261
+ run.ed += delta;
262
+ } else if (run.ed > start) run.ed += delta;
263
+ });
264
+ }
265
+ function buildTableOfContentsBody(body, toc, resolvePageNumber, idFactory = _univerjs_core.generateRandomId, options) {
266
+ var _toc$properties3, _toc$properties4, _toc$properties5, _toc$properties6, _toc$properties7, _toc$properties8, _body$customRanges8, _body$paragraphs3, _toc$properties9;
267
+ if (((_toc$properties3 = toc.properties) === null || _toc$properties3 === void 0 ? void 0 : _toc$properties3.locked) === _univerjs_core.BooleanNumber.TRUE) return null;
268
+ const instruction = String(((_toc$properties4 = toc.properties) === null || _toc$properties4 === void 0 ? void 0 : _toc$properties4.instruction) ?? "");
269
+ if (/\\c\s+/i.test(instruction)) return null;
270
+ const [minLevel, maxLevel] = parseOutlineLevelRange(instruction);
271
+ const headings = collectHeadings(body, toc, minLevel, maxLevel);
272
+ if (headings.length === 0) return null;
273
+ const showPageNumbers = ((_toc$properties5 = toc.properties) === null || _toc$properties5 === void 0 ? void 0 : _toc$properties5.showPageNumbers) !== false && !/\\n(?:\s|$)/i.test(instruction);
274
+ const rightAlignPageNumbers = showPageNumbers && ((_toc$properties6 = toc.properties) === null || _toc$properties6 === void 0 ? void 0 : _toc$properties6.rightAlignPageNumbers) !== false && !/\\p\s+/i.test(instruction);
275
+ const tabLeader = normalizeTabLeader((_toc$properties7 = toc.properties) === null || _toc$properties7 === void 0 ? void 0 : _toc$properties7.tabLeader);
276
+ const format = normalizeFormat((_toc$properties8 = toc.properties) === null || _toc$properties8 === void 0 ? void 0 : _toc$properties8.format);
277
+ const oldParagraphs = ((_body$customRanges8 = body.customRanges) === null || _body$customRanges8 === void 0 ? void 0 : _body$customRanges8.some((range) => range.rangeId === toc.rangeId)) ?? false ? ((_body$paragraphs3 = body.paragraphs) === null || _body$paragraphs3 === void 0 ? void 0 : _body$paragraphs3.filter((paragraph) => paragraph.startIndex >= toc.startIndex && paragraph.startIndex <= toc.endIndex)) ?? [] : [];
278
+ const title = typeof ((_toc$properties9 = toc.properties) === null || _toc$properties9 === void 0 ? void 0 : _toc$properties9.title) === "string" ? toc.properties.title.trim() : getExistingTableOfContentsTitle(body, oldParagraphs);
279
+ const result = {
280
+ dataStream: FIELD_START,
281
+ paragraphs: [],
282
+ customRanges: []
283
+ };
284
+ const ranges = result.customRanges;
285
+ const oldTitleParagraph = oldParagraphs.find((paragraph) => {
286
+ var _paragraph$styleId;
287
+ return ((_paragraph$styleId = paragraph.styleId) === null || _paragraph$styleId === void 0 ? void 0 : _paragraph$styleId.toLowerCase()) === "tocheading";
288
+ });
289
+ const oldEntryParagraphs = oldParagraphs.filter((paragraph) => paragraph !== oldTitleParagraph);
290
+ const usedParagraphIds = /* @__PURE__ */ new Set();
291
+ let cachedResult = "";
292
+ if (title) {
293
+ result.dataStream += `${title}\r`;
294
+ cachedResult += `${title}\r`;
295
+ result.paragraphs.push((0, _univerjs_core.cloneParagraphWithId)({
296
+ startIndex: result.dataStream.length - 1,
297
+ paragraphId: (oldTitleParagraph === null || oldTitleParagraph === void 0 ? void 0 : oldTitleParagraph.paragraphId) ?? "",
298
+ styleId: "TOCHeading"
299
+ }, usedParagraphIds));
300
+ }
301
+ for (const [index, heading] of headings.entries()) {
302
+ const pageNumber = showPageNumbers ? resolvePageNumber(heading.startOffset) : void 0;
303
+ if (showPageNumbers && pageNumber == null) return null;
304
+ const entryStart = result.dataStream.length;
305
+ const separator = showPageNumbers ? rightAlignPageNumbers ? " " : " " : "";
306
+ const visibleEntry = `${heading.text}${separator}${pageNumber ?? ""}`;
307
+ result.dataStream += `${heading.text}${separator}`;
308
+ const targetId = heading.bookmarkId ?? heading.headingId;
309
+ const link = {
310
+ startIndex: entryStart,
311
+ endIndex: result.dataStream.length - 1,
312
+ rangeId: idFactory(),
313
+ rangeType: _univerjs_core.CustomRangeType.HYPERLINK,
314
+ wholeEntity: false,
315
+ properties: {
316
+ ...heading.bookmarkId ? { bookmarkId: targetId } : { headingId: targetId },
317
+ textStyleMode: "text"
318
+ }
319
+ };
320
+ ranges.push(link);
321
+ if (showPageNumbers) {
322
+ const pageFieldStart = result.dataStream.length;
323
+ result.dataStream += `${FIELD_START}${pageNumber}${FIELD_END}`;
324
+ const pageFieldEnd = result.dataStream.length - 1;
325
+ link.endIndex = pageFieldEnd;
326
+ ranges.push({
327
+ startIndex: pageFieldStart,
328
+ endIndex: pageFieldEnd,
329
+ rangeId: idFactory(),
330
+ rangeType: _univerjs_core.CustomRangeType.FIELD,
331
+ wholeEntity: false,
332
+ properties: {
333
+ fieldType: "PAGEREF",
334
+ instruction: `PAGEREF ${targetId} \\h`,
335
+ cachedResult: String(pageNumber),
336
+ sourceKind: "complex"
337
+ }
338
+ });
339
+ }
340
+ result.dataStream += "\r";
341
+ cachedResult += `${visibleEntry}\r`;
342
+ result.paragraphs.push(copyTocParagraph(oldEntryParagraphs, index, heading.level, result.dataStream.length - 1, usedParagraphIds, rightAlignPageNumbers ? options === null || options === void 0 ? void 0 : options.tabStopOffset : void 0, tabLeader, format));
343
+ }
344
+ result.dataStream += FIELD_END;
345
+ ranges.push({
346
+ startIndex: 0,
347
+ endIndex: result.dataStream.length - 1,
348
+ rangeId: toc.rangeId,
349
+ rangeType: _univerjs_core.CustomRangeType.FIELD,
350
+ wholeEntity: false,
351
+ properties: {
352
+ ..._univerjs_core.Tools.deepClone(toc.properties ?? {}),
353
+ fieldType: "TOC",
354
+ instruction,
355
+ cachedResult
356
+ }
357
+ });
358
+ ranges.sort((left, right) => left.startIndex - right.startIndex || right.endIndex - left.endIndex);
359
+ return result;
360
+ }
361
+ function getExistingTableOfContentsTitle(body, paragraphs) {
362
+ const titleParagraph = paragraphs.find((paragraph) => {
363
+ var _paragraph$styleId2;
364
+ return ((_paragraph$styleId2 = paragraph.styleId) === null || _paragraph$styleId2 === void 0 ? void 0 : _paragraph$styleId2.toLowerCase()) === "tocheading";
365
+ });
366
+ if (!titleParagraph) return "";
367
+ const allParagraphs = [...body.paragraphs ?? []].sort((left, right) => left.startIndex - right.startIndex);
368
+ const index = allParagraphs.findIndex((paragraph) => paragraph === titleParagraph || paragraph.paragraphId === titleParagraph.paragraphId);
369
+ let start = index > 0 ? allParagraphs[index - 1].startIndex + 1 : 0;
370
+ while (body.dataStream[start] === FIELD_START || body.dataStream[start] === FIELD_END) start += 1;
371
+ return (0, _univerjs_core.getPlainText)(body.dataStream.slice(start, titleParagraph.startIndex)).trim();
372
+ }
373
+ function countTableOfContentsHeadings(body, levels = 3) {
374
+ if (!body) return 0;
375
+ return collectHeadings(body, void 0, 1, Math.min(9, Math.max(1, Math.trunc(levels)))).length;
376
+ }
377
+ function parseOutlineLevelRange(instruction) {
378
+ const match = instruction.match(/\\o\s+"(\d+)\s*-\s*(\d+)"/i);
379
+ const min = Math.max(1, Number((match === null || match === void 0 ? void 0 : match[1]) ?? 1));
380
+ return [min, Math.min(9, Math.max(min, Number((match === null || match === void 0 ? void 0 : match[2]) ?? 3)))];
381
+ }
382
+ function collectHeadings(body, toc, minLevel, maxLevel) {
383
+ const paragraphs = [...body.paragraphs ?? []].sort((left, right) => left.startIndex - right.startIndex);
384
+ let paragraphStart = 0;
385
+ return paragraphs.flatMap((paragraph) => {
386
+ var _paragraph$paragraphS2, _body$customRanges9, _bookmark$properties;
387
+ let startOffset = paragraphStart;
388
+ while (body.dataStream[startOffset] === FIELD_START || body.dataStream[startOffset] === FIELD_END) startOffset += 1;
389
+ paragraphStart = paragraph.startIndex + 1;
390
+ const level = getOutlineLevel(paragraph);
391
+ const headingId = (_paragraph$paragraphS2 = paragraph.paragraphStyle) === null || _paragraph$paragraphS2 === void 0 ? void 0 : _paragraph$paragraphS2.headingId;
392
+ if (!headingId || level == null || level < minLevel || level > maxLevel || toc && startOffset >= toc.startIndex && paragraph.startIndex <= toc.endIndex) return [];
393
+ const text = (0, _univerjs_core.getPlainText)(body.dataStream.slice(startOffset, paragraph.startIndex)).trim();
394
+ if (!text) return [];
395
+ const bookmark = (_body$customRanges9 = body.customRanges) === null || _body$customRanges9 === void 0 ? void 0 : _body$customRanges9.find((range) => {
396
+ var _range$properties5;
397
+ return range.rangeType === _univerjs_core.CustomRangeType.BOOKMARK && range.startIndex <= paragraph.startIndex && range.endIndex >= startOffset && ((_range$properties5 = range.properties) === null || _range$properties5 === void 0 ? void 0 : _range$properties5.bookmarkId);
398
+ });
399
+ return [{
400
+ bookmarkId: bookmark === null || bookmark === void 0 || (_bookmark$properties = bookmark.properties) === null || _bookmark$properties === void 0 ? void 0 : _bookmark$properties.bookmarkId,
401
+ headingId,
402
+ level,
403
+ paragraph,
404
+ startOffset,
405
+ text
406
+ }];
407
+ });
408
+ }
409
+ function getOutlineLevel(paragraph) {
410
+ var _paragraph$paragraphS3, _paragraph$paragraphS4;
411
+ const outlineLevel = (_paragraph$paragraphS3 = paragraph.paragraphStyle) === null || _paragraph$paragraphS3 === void 0 ? void 0 : _paragraph$paragraphS3.outlineLevel;
412
+ if (outlineLevel != null && outlineLevel >= 0 && outlineLevel <= 8) return outlineLevel + 1;
413
+ const namedStyle = (_paragraph$paragraphS4 = paragraph.paragraphStyle) === null || _paragraph$paragraphS4 === void 0 ? void 0 : _paragraph$paragraphS4.namedStyleType;
414
+ if (namedStyle != null && namedStyle >= _univerjs_core.NamedStyleType.HEADING_1 && namedStyle <= _univerjs_core.NamedStyleType.HEADING_5) return namedStyle - _univerjs_core.NamedStyleType.HEADING_1 + 1;
415
+ }
416
+ function copyTocParagraph(oldParagraphs, index, level, startIndex, usedParagraphIds, tabStopOffset, tabLeader = "dots", format = "fromTemplate") {
417
+ const source = oldParagraphs.find((paragraph) => {
418
+ var _paragraph$styleId3;
419
+ return ((_paragraph$styleId3 = paragraph.styleId) === null || _paragraph$styleId3 === void 0 || (_paragraph$styleId3 = _paragraph$styleId3.match(/TOC(\d+)/i)) === null || _paragraph$styleId3 === void 0 ? void 0 : _paragraph$styleId3[1]) === String(level);
420
+ }) ?? oldParagraphs[Math.min(index, oldParagraphs.length - 1)];
421
+ if (source) {
422
+ var _oldParagraphs$index;
423
+ return (0, _univerjs_core.cloneParagraphWithId)({
424
+ ...source,
425
+ startIndex,
426
+ paragraphId: ((_oldParagraphs$index = oldParagraphs[index]) === null || _oldParagraphs$index === void 0 ? void 0 : _oldParagraphs$index.paragraphId) ?? ""
427
+ }, usedParagraphIds);
428
+ }
429
+ return {
430
+ startIndex,
431
+ paragraphId: (0, _univerjs_core.createParagraphId)(usedParagraphIds),
432
+ styleId: `TOC${level}`,
433
+ paragraphStyle: {
434
+ indentStart: { v: Math.max(0, level - 1) * getFormatIndent(format) },
435
+ spaceBelow: format === "modern" ? { v: 4 } : format === "classic" ? { v: 2 } : void 0,
436
+ tabStops: tabStopOffset == null ? void 0 : [{
437
+ offset: tabStopOffset,
438
+ alignment: _univerjs_core.TabStopAlignment.END,
439
+ leader: getTabStopLeader(tabLeader)
440
+ }]
441
+ }
442
+ };
443
+ }
444
+ function normalizeTabLeader(value) {
445
+ return value === "none" || value === "dashes" || value === "underline" ? value : "dots";
446
+ }
447
+ function getTabStopLeader(value) {
448
+ return {
449
+ none: _univerjs_core.TabStopLeader.NONE,
450
+ dots: _univerjs_core.TabStopLeader.DOT,
451
+ dashes: _univerjs_core.TabStopLeader.HYPHEN,
452
+ underline: _univerjs_core.TabStopLeader.UNDERSCORE
453
+ }[value];
454
+ }
455
+ function normalizeFormat(value) {
456
+ return value === "classic" || value === "modern" || value === "simple" ? value : "fromTemplate";
457
+ }
458
+ function getFormatIndent(format) {
459
+ return {
460
+ fromTemplate: 18,
461
+ classic: 14,
462
+ modern: 20,
463
+ simple: 12
464
+ }[format];
465
+ }
466
+
467
+ //#endregion
468
+ //#region package.json
469
+ var name = "@univerjs/docs-toc";
470
+ var version = "1.0.0";
471
+
472
+ //#endregion
473
+ //#region src/config/config.ts
474
+ /**
475
+ * Copyright 2023-present DreamNum Co., Ltd.
476
+ *
477
+ * Licensed under the Apache License, Version 2.0 (the "License");
478
+ * you may not use this file except in compliance with the License.
479
+ * You may obtain a copy of the License at
480
+ *
481
+ * http://www.apache.org/licenses/LICENSE-2.0
482
+ *
483
+ * Unless required by applicable law or agreed to in writing, software
484
+ * distributed under the License is distributed on an "AS IS" BASIS,
485
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
486
+ * See the License for the specific language governing permissions and
487
+ * limitations under the License.
488
+ */
489
+ const DOCS_TOC_PLUGIN_CONFIG_KEY = "docs-toc.config";
490
+ const configSymbol = Symbol(DOCS_TOC_PLUGIN_CONFIG_KEY);
491
+ const defaultPluginConfig = {};
492
+
493
+ //#endregion
494
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorateParam.js
495
+ function __decorateParam(paramIndex, decorator) {
496
+ return function(target, key) {
497
+ decorator(target, key, paramIndex);
498
+ };
499
+ }
500
+
501
+ //#endregion
502
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorate.js
503
+ function __decorate(decorators, target, key, desc) {
504
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
505
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
506
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
507
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
508
+ }
509
+
510
+ //#endregion
511
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/typeof.js
512
+ function _typeof(o) {
513
+ "@babel/helpers - typeof";
514
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
515
+ return typeof o;
516
+ } : function(o) {
517
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
518
+ }, _typeof(o);
519
+ }
520
+
521
+ //#endregion
522
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/toPrimitive.js
523
+ function toPrimitive(t, r) {
524
+ if ("object" != _typeof(t) || !t) return t;
525
+ var e = t[Symbol.toPrimitive];
526
+ if (void 0 !== e) {
527
+ var i = e.call(t, r || "default");
528
+ if ("object" != _typeof(i)) return i;
529
+ throw new TypeError("@@toPrimitive must return a primitive value.");
530
+ }
531
+ return ("string" === r ? String : Number)(t);
532
+ }
533
+
534
+ //#endregion
535
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/toPropertyKey.js
536
+ function toPropertyKey(t) {
537
+ var i = toPrimitive(t, "string");
538
+ return "symbol" == _typeof(i) ? i : i + "";
539
+ }
540
+
541
+ //#endregion
542
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/defineProperty.js
543
+ function _defineProperty(e, r, t) {
544
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
545
+ value: t,
546
+ enumerable: !0,
547
+ configurable: !0,
548
+ writable: !0
549
+ }) : e[r] = t, e;
550
+ }
551
+
552
+ //#endregion
553
+ //#region src/plugin.ts
554
+ let UniverDocsTocPlugin = class UniverDocsTocPlugin extends _univerjs_core.Plugin {
555
+ constructor(_config = defaultPluginConfig, _injector, _configService, _commandService) {
556
+ super();
557
+ this._config = _config;
558
+ this._injector = _injector;
559
+ this._configService = _configService;
560
+ this._commandService = _commandService;
561
+ const { ...rest } = (0, _univerjs_core.merge)({}, defaultPluginConfig, this._config);
562
+ this._configService.setConfig(DOCS_TOC_PLUGIN_CONFIG_KEY, rest);
563
+ }
564
+ onStarting() {
565
+ [
566
+ InsertTableOfContentsCommand,
567
+ UpdateTableOfContentsCommand,
568
+ DeleteTableOfContentsCommand
569
+ ].forEach((command) => this.disposeWithMe(this._commandService.registerCommand(command)));
570
+ }
571
+ };
572
+ _defineProperty(UniverDocsTocPlugin, "pluginName", "DOCS_TOC_PLUGIN");
573
+ _defineProperty(UniverDocsTocPlugin, "packageName", name);
574
+ _defineProperty(UniverDocsTocPlugin, "version", version);
575
+ _defineProperty(UniverDocsTocPlugin, "type", _univerjs_core.UniverInstanceType.UNIVER_DOC);
576
+ UniverDocsTocPlugin = __decorate([
577
+ (0, _univerjs_core.DependentOn)(_univerjs_docs.UniverDocsPlugin, _univerjs_engine_render.UniverRenderEnginePlugin),
578
+ __decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_core.Injector)),
579
+ __decorateParam(2, _univerjs_core.IConfigService),
580
+ __decorateParam(3, _univerjs_core.ICommandService)
581
+ ], UniverDocsTocPlugin);
582
+
583
+ //#endregion
584
+ exports.DeleteTableOfContentsCommand = DeleteTableOfContentsCommand;
585
+ exports.InsertTableOfContentsCommand = InsertTableOfContentsCommand;
586
+ Object.defineProperty(exports, 'UniverDocsTocPlugin', {
587
+ enumerable: true,
588
+ get: function () {
589
+ return UniverDocsTocPlugin;
590
+ }
591
+ });
592
+ exports.UpdateTableOfContentsCommand = UpdateTableOfContentsCommand;
593
+ exports.buildPageNumberOnlyTableOfContentsBody = buildPageNumberOnlyTableOfContentsBody;
594
+ exports.buildTableOfContentsBody = buildTableOfContentsBody;
595
+ exports.buildTableOfContentsInstruction = buildTableOfContentsInstruction;
596
+ exports.countTableOfContentsHeadings = countTableOfContentsHeadings;
597
+ exports.findTableOfContentsAtOffset = findTableOfContentsAtOffset;