oasis-editor 0.0.11 → 0.0.13

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.
Files changed (36) hide show
  1. package/dist/{OasisEditorApp-BgOoWqpC.js → OasisEditorApp-DYcAe_1n.js} +568 -41
  2. package/dist/app/controllers/EditorCommandsController.d.ts +4 -0
  3. package/dist/app/controllers/useEditorLayout.d.ts +2 -1
  4. package/dist/assets/{importDocxWorker-DbiKelzX.js → importDocxWorker-cjz15bhS.js} +1 -1
  5. package/dist/core/commands/builtinCommands.d.ts +1 -1
  6. package/dist/core/commands/image.d.ts +2 -0
  7. package/dist/core/commands/publicCommandTypes.d.ts +1 -0
  8. package/dist/core/document/imageCaptions.d.ts +13 -0
  9. package/dist/core/editorState.d.ts +1 -0
  10. package/dist/core/model/index.d.ts +1 -0
  11. package/dist/core/model/types/document.d.ts +7 -0
  12. package/dist/core/model/types/documentComments.d.ts +50 -0
  13. package/dist/export/docx/commentsXml.d.ts +34 -0
  14. package/dist/export/docx/docxTypes.d.ts +7 -0
  15. package/dist/i18n/locales/en.d.ts +4 -0
  16. package/dist/i18n/locales/pt-BR.d.ts +4 -0
  17. package/dist/import/docx/comments.d.ts +12 -0
  18. package/dist/import/docx/commentsXml.d.ts +14 -0
  19. package/dist/import/docx/runs/types.d.ts +10 -0
  20. package/dist/import/docx/runs.d.ts +5 -1
  21. package/dist/{index-L71R0x7D.js → index-CWev1Jg0.js} +723 -304
  22. package/dist/oasis-editor.css +1 -1
  23. package/dist/oasis-editor.js +54 -54
  24. package/dist/oasis-editor.umd.cjs +4 -4
  25. package/dist/plugins/internal/createEssentialsPlugin.d.ts +1 -0
  26. package/dist/ui/OasisEditorEditor.d.ts +2 -1
  27. package/dist/ui/app/EditorDialogsLayer.d.ts +1 -0
  28. package/dist/ui/app/buildEditorViewProps.d.ts +2 -1
  29. package/dist/ui/app/useEditorDialogs.d.ts +8 -0
  30. package/dist/ui/canvas/CanvasCommentGeometry.d.ts +13 -0
  31. package/dist/ui/components/CommentHighlightOverlay.d.ts +16 -0
  32. package/dist/ui/components/Dialogs/ImageCaptionDialog.d.ts +8 -0
  33. package/dist/ui/components/Menubar/builtinMenuIds.d.ts +1 -0
  34. package/dist/ui/components/Toolbar/presets/builtinToolbarIds.d.ts +1 -0
  35. package/dist/ui/editorUiTypes.d.ts +8 -0
  36. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { n as normalizeSelection, g as getParagraphs, c as createEditorParagraphFromRuns, a as createEditorStyledRun, b as getParagraphLength, d as getParagraphText, e as getActiveZone, f as getDocumentSections, h as getActiveSectionIndex, p as positionToParagraphOffset, i as paragraphOffsetToPosition, j as clampPosition, k as findParagraphIndex, l as createCollapsedSelection, m as isSelectionCollapsed, o as createEditorParagraph, q as getBlockParagraphs, r as findParagraphTableLocation, s as buildTableCellLayout, t as createEditorTableCell, u as createEditorTable, v as createEditorTableRow, w as underlineStyleToCssDecorationStyle, x as resolveImageSrc, y as createEditorFootnote, z as createFootnoteReferenceRun, A as renumberFootnotes, B as iterateFootnoteReferenceRuns, C as getFootnoteDisplayMarker, D as createSignal, E as createEffect, F as onCleanup, G as buildCanvasLayoutSnapshot, H as on, I as onMount, J as debounce, K as unwrap, L as getDocumentParagraphs, M as getDocumentSectionsCanonical, N as createEditorDocument, O as getPageContentWidth, P as getDocumentPageSettings, Q as getTableCellContentWidthForParagraph, R as resolveResizedDimensions, S as resolveTextBoxRenderHeight, T as resolveEffectiveParagraphStyle, U as resolveEffectiveTextStyleForParagraph, V as iterateEndnoteReferenceRuns, W as JSZip, X as imageContentTypeDefaults, Y as imageExtensionFromMime, Z as pxToPt$1, _ as buildSegmentTable, $ as buildCanvasTableLayout, a0 as resolveFloatingObjectRect, a1 as getTextBoxFloatingGeometry, a2 as getPresetPathSegments, a3 as projectBlocksLayout, a4 as textStyleToFontSizePt, a5 as PX_PER_POINT, a6 as DEFAULT_FONT_SIZE_PX, a7 as isDoubleUnderlineStyle, a8 as isWavyUnderlineStyle, a9 as underlineStyleLineWidthPx, aa as underlineStyleDashArray, ab as getListLabelInset, ac as getParagraphBorderInsets, ad as normalizeFamily, ae as ROBOTO_FONT_FILES, af as loadFontAsset, ag as OFFICE_COMPAT_FONT_FAMILIES, ah as buildSfnt, ai as defaultFontDecoderRegistry, aj as SfntFontProgram, ak as collectPdfFontFamilies, al as projectDocumentLayout, am as getPageHeaderZoneTop, an as getPageBodyTop, ao as findFootnoteReference, ap as FOOTNOTE_MARKER_GUTTER_PX, aq as resolveImporterForFile, ar as createEditorStateFromDocument, as as getDocumentParagraphsCanonical, at as getToolbarStyleState, au as STANDARD_FONT_SIZES_PT, av as fontSizePxToPt, aw as probeLocalFontFamilies, ax as createInitialEditorState, ay as parseFontSizePtToPx, az as formatFontSizePt, aA as listKindForTag, aB as isParagraphTag, aC as collectInlineRuns, aD as parseParagraphStyle, aE as t, aF as preciseFontModeVersion, aG as isPreciseFontModeEnabled, aH as togglePreciseFontMode, aI as nextFontSizePt, aJ as previousFontSizePt, aK as fontSizePtToPx, aL as createDefaultToolbarPreset, aM as defaultMenuItems, aN as MenuRegistry, aO as createToolbarRegistry, aP as Editor, aQ as resolveCommandRef, aR as commandRefName, aS as InlineShell, aT as BalloonShell, aU as DocumentShell, aV as createMemo, aW as getCaretRectFromSnapshot, aX as getParagraphRectFromSnapshot, aY as createComponent, aZ as CaretOverlay, a_ as Show, a$ as createRenderEffect, b0 as style, b1 as setAttribute, b2 as setStyleProperty, b3 as memo, b4 as template, b5 as insert, b6 as use, b7 as addEventListener, b8 as Dialog, b9 as delegateEvents, ba as className, bb as For, bc as UNDERLINE_STYLE_OPTIONS, bd as Tabs, be as measureParagraphMinContentWidthPx, bf as getEditableBlocksForZone, bg as findParagraphLocation, bh as createSectionBoundaryParagraph, bi as normalizePageSettings, bj as DEFAULT_EDITOR_PAGE_SETTINGS, bk as markStart, bl as markEnd, bm as getParagraphEntries, bn as getParagraphById, bo as PluginUiHost, bp as OasisEditorEditor, bq as perfTimer, br as OasisBrandMark, bs as setPreciseFontPreference, bt as setWelcomeSeen, bu as enablePreciseFontMode, bv as createOasisEditorClient, bw as setLocale, bx as startLongTaskObserver, by as installGlobalReport, bz as applyStoredPreciseFontPreference, bA as getWelcomeSeen, bB as isLocalFontAccessSupported, bC as EDITOR_SCROLL_PADDING_PX, bD as Toolbar, bE as OasisEditorLoading, bF as createEditorLogger, bG as getCachedCanvasImage, bH as registerDomStatsSurface } from "./index-L71R0x7D.js";
4
+ import { n as normalizeSelection, g as getParagraphs, c as createEditorParagraphFromRuns, a as getParagraphLength, b as createEditorRun, d as getDocumentSections, e as createEditorStyledRun, f as getParagraphText, h as getActiveZone, i as getActiveSectionIndex, p as positionToParagraphOffset, j as paragraphOffsetToPosition, k as clampPosition, l as findParagraphIndex, m as createCollapsedSelection, o as isSelectionCollapsed, q as createEditorParagraph, r as getBlockParagraphs, s as findParagraphTableLocation, t as buildTableCellLayout, u as createEditorTableCell, v as createEditorTable, w as createEditorTableRow, x as underlineStyleToCssDecorationStyle, y as resolveImageSrc, z as createEditorFootnote, A as createFootnoteReferenceRun, B as renumberFootnotes, C as iterateFootnoteReferenceRuns, D as getFootnoteDisplayMarker, E as createSignal, F as createEffect, G as onCleanup, H as buildCanvasLayoutSnapshot, I as on, J as onMount, K as debounce, L as unwrap, M as getDocumentParagraphs, N as getDocumentSectionsCanonical, O as createEditorDocument, P as getPageContentWidth, Q as getDocumentPageSettings, R as getTableCellContentWidthForParagraph, S as resolveResizedDimensions, T as resolveTextBoxRenderHeight, U as resolveEffectiveParagraphStyle, V as resolveEffectiveTextStyleForParagraph, W as iterateEndnoteReferenceRuns, X as JSZip, Y as imageContentTypeDefaults, Z as imageExtensionFromMime, _ as pxToPt$1, $ as buildSegmentTable, a0 as buildCanvasTableLayout, a1 as resolveFloatingObjectRect, a2 as getTextBoxFloatingGeometry, a3 as getPresetPathSegments, a4 as projectBlocksLayout, a5 as textStyleToFontSizePt, a6 as PX_PER_POINT, a7 as DEFAULT_FONT_SIZE_PX, a8 as isDoubleUnderlineStyle, a9 as isWavyUnderlineStyle, aa as underlineStyleLineWidthPx, ab as underlineStyleDashArray, ac as getListLabelInset, ad as getParagraphBorderInsets, ae as normalizeFamily, af as ROBOTO_FONT_FILES, ag as loadFontAsset, ah as OFFICE_COMPAT_FONT_FAMILIES, ai as buildSfnt, aj as defaultFontDecoderRegistry, ak as SfntFontProgram, al as collectPdfFontFamilies, am as projectDocumentLayout, an as getPageHeaderZoneTop, ao as getPageBodyTop, ap as findFootnoteReference, aq as FOOTNOTE_MARKER_GUTTER_PX, ar as resolveImporterForFile, as as createEditorStateFromDocument, at as getDocumentParagraphsCanonical, au as getToolbarStyleState, av as STANDARD_FONT_SIZES_PT, aw as fontSizePxToPt, ax as probeLocalFontFamilies, ay as createInitialEditorState, az as parseFontSizePtToPx, aA as formatFontSizePt, aB as listKindForTag, aC as isParagraphTag, aD as collectInlineRuns, aE as parseParagraphStyle, aF as t, aG as preciseFontModeVersion, aH as isPreciseFontModeEnabled, aI as togglePreciseFontMode, aJ as nextFontSizePt, aK as previousFontSizePt, aL as fontSizePtToPx, aM as createDefaultToolbarPreset, aN as defaultMenuItems, aO as MenuRegistry, aP as createToolbarRegistry, aQ as Editor, aR as resolveCommandRef, aS as commandRefName, aT as InlineShell, aU as BalloonShell, aV as DocumentShell, aW as createMemo, aX as getCaretRectFromSnapshot, aY as getParagraphRectFromSnapshot, aZ as createComponent, a_ as CaretOverlay, a$ as Show, b0 as createRenderEffect, b1 as style, b2 as setAttribute, b3 as setStyleProperty, b4 as memo, b5 as template, b6 as insert, b7 as use, b8 as addEventListener, b9 as Dialog, ba as delegateEvents, bb as className, bc as For, bd as UNDERLINE_STYLE_OPTIONS, be as Tabs, bf as measureParagraphMinContentWidthPx, bg as getEditableBlocksForZone, bh as findParagraphLocation, bi as createSectionBoundaryParagraph, bj as normalizePageSettings, bk as DEFAULT_EDITOR_PAGE_SETTINGS, bl as markStart, bm as markEnd, bn as getParagraphEntries, bo as getParagraphById, bp as PluginUiHost, bq as OasisEditorEditor, br as perfTimer, bs as OasisBrandMark, bt as setPreciseFontPreference, bu as setWelcomeSeen, bv as enablePreciseFontMode, bw as createOasisEditorClient, bx as setLocale, by as startLongTaskObserver, bz as installGlobalReport, bA as applyStoredPreciseFontPreference, bB as getWelcomeSeen, bC as isLocalFontAccessSupported, bD as EDITOR_SCROLL_PADDING_PX, bE as Toolbar, bF as OasisEditorLoading, bG as createEditorLogger, bH as getCachedCanvasImage, bI as registerDomStatsSurface } from "./index-CWev1Jg0.js";
5
5
  function getSelectedObjectRun(state, predicate) {
6
6
  const normalized = normalizeSelection(state);
7
7
  if (normalized.isCollapsed || normalized.startIndex !== normalized.endIndex || normalized.endParagraphOffset - normalized.startParagraphOffset !== 1) {
@@ -135,6 +135,7 @@ function cloneRun(run) {
135
135
  image: run.image ? { ...run.image } : void 0,
136
136
  textBox: run.textBox ? cloneTextBox(run.textBox) : void 0,
137
137
  field: run.field ? { ...run.field } : void 0,
138
+ fieldChar: run.fieldChar ? { ...run.fieldChar } : void 0,
138
139
  revision: run.revision ? { ...run.revision } : void 0,
139
140
  footnoteReference: run.footnoteReference ? { ...run.footnoteReference } : void 0,
140
141
  endnoteReference: run.endnoteReference ? { ...run.endnoteReference } : void 0
@@ -186,6 +187,164 @@ function cloneBlocks(blocks) {
186
187
  };
187
188
  });
188
189
  }
190
+ const IMAGE_CAPTION_STYLE_ID = "Caption";
191
+ const IMAGE_CAPTION_FIELD_IDENTIFIER = "Figure";
192
+ const IMAGE_CAPTION_FIELD_INSTRUCTION = " SEQ Figure \\* ARABIC ";
193
+ function createFieldCharRun(kind) {
194
+ const run = createEditorRun("");
195
+ run.fieldChar = { kind };
196
+ return run;
197
+ }
198
+ function createFieldInstructionRun(instruction) {
199
+ const run = createEditorRun("");
200
+ run.fieldInstruction = instruction;
201
+ return run;
202
+ }
203
+ function createImageCaptionParagraph(captionText, label, sequenceNumber) {
204
+ const paragraph = createEditorParagraphFromRuns([
205
+ { text: `${label} ` },
206
+ { text: String(sequenceNumber) },
207
+ { text: captionText ? `: ${captionText}` : "" }
208
+ ]);
209
+ paragraph.style = { styleId: IMAGE_CAPTION_STYLE_ID, align: "center" };
210
+ paragraph.runs = [
211
+ paragraph.runs[0],
212
+ createFieldCharRun("begin"),
213
+ createFieldInstructionRun(IMAGE_CAPTION_FIELD_INSTRUCTION),
214
+ createFieldCharRun("separate"),
215
+ paragraph.runs[1],
216
+ createFieldCharRun("end"),
217
+ paragraph.runs[2]
218
+ ];
219
+ return paragraph;
220
+ }
221
+ function isImageCaptionParagraph(paragraph) {
222
+ var _a, _b;
223
+ if (!paragraph) {
224
+ return false;
225
+ }
226
+ const styleId = (_b = (_a = paragraph.style) == null ? void 0 : _a.styleId) == null ? void 0 : _b.toLowerCase();
227
+ if (styleId !== "caption") {
228
+ return false;
229
+ }
230
+ return paragraph.runs.some(
231
+ (run) => run.fieldInstruction !== void 0 && new RegExp(`\\bSEQ\\s+${IMAGE_CAPTION_FIELD_IDENTIFIER}\\b`, "i").test(
232
+ run.fieldInstruction
233
+ )
234
+ );
235
+ }
236
+ function getImageCaptionText(paragraph) {
237
+ var _a;
238
+ if (!isImageCaptionParagraph(paragraph)) {
239
+ return "";
240
+ }
241
+ let afterField = false;
242
+ let value = "";
243
+ for (const run of paragraph.runs) {
244
+ if (afterField) {
245
+ value += run.text;
246
+ continue;
247
+ }
248
+ if (((_a = run.fieldChar) == null ? void 0 : _a.kind) === "end") {
249
+ afterField = true;
250
+ }
251
+ }
252
+ return value.replace(/^[:\-\s]+/, "");
253
+ }
254
+ function updateImageCaptionParagraph(paragraph, captionText, label) {
255
+ var _a;
256
+ const currentNumber = ((_a = paragraph.runs.find((run) => /^\d+$/.test(run.text))) == null ? void 0 : _a.text) ?? "1";
257
+ const next = createImageCaptionParagraph(
258
+ captionText,
259
+ label,
260
+ Number.parseInt(currentNumber, 10) || 1
261
+ );
262
+ next.id = paragraph.id;
263
+ return next;
264
+ }
265
+ function renumberCaptionParagraph(paragraph, sequenceNumber) {
266
+ if (!isImageCaptionParagraph(paragraph)) {
267
+ return cloneParagraph(paragraph);
268
+ }
269
+ let insideSeqResult = false;
270
+ let changed = false;
271
+ const nextRuns = paragraph.runs.map((run) => {
272
+ var _a, _b;
273
+ if (((_a = run.fieldChar) == null ? void 0 : _a.kind) === "separate") {
274
+ insideSeqResult = true;
275
+ return { ...run, fieldChar: { ...run.fieldChar } };
276
+ }
277
+ if (((_b = run.fieldChar) == null ? void 0 : _b.kind) === "end") {
278
+ insideSeqResult = false;
279
+ return { ...run, fieldChar: { ...run.fieldChar } };
280
+ }
281
+ if (insideSeqResult && run.text !== "") {
282
+ if (run.text === String(sequenceNumber)) {
283
+ return { ...run };
284
+ }
285
+ changed = true;
286
+ return { ...run, text: String(sequenceNumber) };
287
+ }
288
+ return { ...run };
289
+ });
290
+ if (!changed) {
291
+ return cloneParagraph(paragraph);
292
+ }
293
+ return {
294
+ ...cloneParagraph(paragraph),
295
+ runs: nextRuns
296
+ };
297
+ }
298
+ function renumberImageCaptionParagraphs(paragraphs) {
299
+ let nextSequence = 1;
300
+ return paragraphs.map((paragraph) => {
301
+ if (!isImageCaptionParagraph(paragraph)) {
302
+ return cloneParagraph(paragraph);
303
+ }
304
+ return renumberCaptionParagraph(paragraph, nextSequence++);
305
+ });
306
+ }
307
+ function renumberBlocks(blocks, sequence) {
308
+ return blocks.map((block) => {
309
+ if (block.type === "paragraph") {
310
+ if (!isImageCaptionParagraph(block)) {
311
+ return cloneParagraph(block);
312
+ }
313
+ return renumberCaptionParagraph(block, sequence.next++);
314
+ }
315
+ return {
316
+ ...block,
317
+ rows: block.rows.map((row) => ({
318
+ ...row,
319
+ cells: row.cells.map((cell) => ({
320
+ ...cell,
321
+ blocks: renumberBlocks(
322
+ cell.blocks,
323
+ sequence
324
+ )
325
+ }))
326
+ }))
327
+ };
328
+ });
329
+ }
330
+ function renumberImageCaptionsInDocument(document2) {
331
+ const sequence = { next: 1 };
332
+ const sections = getDocumentSections(document2).map(
333
+ (section) => ({
334
+ ...section,
335
+ blocks: renumberBlocks(section.blocks, sequence),
336
+ header: section.header ? cloneBlocks(section.header) : void 0,
337
+ footer: section.footer ? cloneBlocks(section.footer) : void 0
338
+ })
339
+ );
340
+ return {
341
+ ...document2,
342
+ sections
343
+ };
344
+ }
345
+ function getCaptionSelectionOffset(paragraph) {
346
+ return getParagraphLength(paragraph);
347
+ }
189
348
  function isObjectRun(run) {
190
349
  return Boolean(run.image || run.textBox);
191
350
  }
@@ -983,6 +1142,48 @@ function setSelectedImageAlt(state, alt) {
983
1142
  )
984
1143
  );
985
1144
  }
1145
+ function getSelectedImageCaption(state) {
1146
+ const selectedImage = getSelectedImageRun(state);
1147
+ if (!(selectedImage == null ? void 0 : selectedImage.run.image)) {
1148
+ return null;
1149
+ }
1150
+ const paragraphs = getParagraphs(state);
1151
+ return getImageCaptionText(paragraphs[selectedImage.paragraphIndex + 1]);
1152
+ }
1153
+ function setSelectedImageCaption(state, captionText, label) {
1154
+ const selectedImage = getSelectedImageRun(state);
1155
+ if (!(selectedImage == null ? void 0 : selectedImage.run.image)) {
1156
+ return state;
1157
+ }
1158
+ const paragraphs = getParagraphs(state);
1159
+ const captionIndex = selectedImage.paragraphIndex + 1;
1160
+ const nextParagraph = captionIndex < paragraphs.length && isImageCaptionParagraph(paragraphs[captionIndex]) ? updateImageCaptionParagraph(
1161
+ paragraphs[captionIndex],
1162
+ captionText,
1163
+ label
1164
+ ) : createImageCaptionParagraph(captionText, label, 1);
1165
+ const nextParagraphs = captionIndex < paragraphs.length && isImageCaptionParagraph(paragraphs[captionIndex]) ? [
1166
+ ...cloneParagraphs(paragraphs.slice(0, captionIndex)),
1167
+ nextParagraph,
1168
+ ...cloneParagraphs(paragraphs.slice(captionIndex + 1))
1169
+ ] : [
1170
+ ...cloneParagraphs(paragraphs.slice(0, captionIndex)),
1171
+ nextParagraph,
1172
+ ...cloneParagraphs(paragraphs.slice(captionIndex))
1173
+ ];
1174
+ const renumberedParagraphs = renumberImageCaptionParagraphs(nextParagraphs);
1175
+ const insertedCaption = renumberedParagraphs[captionIndex] ?? nextParagraph;
1176
+ return cloneStateWithParagraphs(
1177
+ state,
1178
+ renumberedParagraphs,
1179
+ withSelection(
1180
+ paragraphOffsetToPosition(
1181
+ insertedCaption,
1182
+ getCaptionSelectionOffset(insertedCaption)
1183
+ )
1184
+ )
1185
+ );
1186
+ }
986
1187
  function moveSelectedImageToPosition(state, targetPosition) {
987
1188
  const selectedImage = getSelectedImageRun(state);
988
1189
  if (!selectedImage) {
@@ -4254,6 +4455,26 @@ function createEditorCommandsController(deps) {
4254
4455
  const currentAlt = ((_a = run.run.image) == null ? void 0 : _a.alt) ?? "";
4255
4456
  deps.openImageAltDialog(currentAlt);
4256
4457
  };
4458
+ const applyImageCaptionCommand = (caption) => {
4459
+ const run = selectedImageRun();
4460
+ if (!run) {
4461
+ return;
4462
+ }
4463
+ clearPreferredColumn();
4464
+ resetTransactionGrouping();
4465
+ applyTransactionalState(
4466
+ (current) => setSelectedImageCaption(current, caption, deps.imageCaptionLabel()),
4467
+ { mergeKey: "imageCaption" }
4468
+ );
4469
+ focusInput();
4470
+ };
4471
+ const promptForImageCaption = () => {
4472
+ const run = selectedImageRun();
4473
+ if (!run) {
4474
+ return;
4475
+ }
4476
+ deps.openImageCaptionDialog(getSelectedImageCaption(state) ?? "");
4477
+ };
4257
4478
  return {
4258
4479
  applyBooleanStyleCommand,
4259
4480
  applyValueStyleCommand,
@@ -4280,6 +4501,8 @@ function createEditorCommandsController(deps) {
4280
4501
  removeLinkCommand,
4281
4502
  applyImageAltCommand,
4282
4503
  promptForImageAlt,
4504
+ applyImageCaptionCommand,
4505
+ promptForImageCaption,
4283
4506
  handleListTab,
4284
4507
  handleListEnter,
4285
4508
  handleListBoundaryBackspace
@@ -5169,6 +5392,63 @@ function computeCanvasSelectionGeometry(snapshot, state) {
5169
5392
  selectedTextBoxBox
5170
5393
  };
5171
5394
  }
5395
+ function computeCommentHighlights(snapshot, state) {
5396
+ const registry = state.document.comments;
5397
+ if (!registry || registry.order.length === 0) {
5398
+ return [];
5399
+ }
5400
+ const surfaceRect = snapshot.surfaceRect;
5401
+ const paragraphIndexById = new Map(
5402
+ getParagraphs(state).map(
5403
+ (paragraph, index) => [paragraph.id, index]
5404
+ )
5405
+ );
5406
+ const boxes = [];
5407
+ for (const id of registry.order) {
5408
+ const comment = registry.items[id];
5409
+ if (!(comment == null ? void 0 : comment.start) || !(comment == null ? void 0 : comment.end)) {
5410
+ continue;
5411
+ }
5412
+ const startIndex = paragraphIndexById.get(comment.start.paragraphId);
5413
+ const endIndex = paragraphIndexById.get(comment.end.paragraphId);
5414
+ if (startIndex === void 0 || endIndex === void 0) {
5415
+ continue;
5416
+ }
5417
+ for (const segment of snapshot.paragraphs) {
5418
+ const segmentIndex = paragraphIndexById.get(segment.paragraphId);
5419
+ if (segmentIndex === void 0 || segmentIndex < startIndex || segmentIndex > endIndex) {
5420
+ continue;
5421
+ }
5422
+ const rangeStart = segmentIndex === startIndex ? comment.start.offset : 0;
5423
+ const rangeEnd = segmentIndex === endIndex ? comment.end.offset : Number.POSITIVE_INFINITY;
5424
+ const segStart = Math.max(rangeStart, segment.startOffset);
5425
+ const segEnd = Math.min(rangeEnd, segment.endOffset);
5426
+ if (segStart >= segEnd) {
5427
+ continue;
5428
+ }
5429
+ for (const line of segment.lines) {
5430
+ const lineStart = Math.max(segStart, line.startOffset);
5431
+ const lineEnd = Math.min(segEnd, line.endOffset);
5432
+ if (lineStart >= lineEnd) {
5433
+ continue;
5434
+ }
5435
+ const startSlot = line.slots.find((slot) => slot.offset === lineStart);
5436
+ const endSlot = line.slots.find((slot) => slot.offset === lineEnd) ?? line.slots[line.slots.length - 1];
5437
+ if (!startSlot || !endSlot) {
5438
+ continue;
5439
+ }
5440
+ boxes.push({
5441
+ commentId: id,
5442
+ left: startSlot.left - surfaceRect.left,
5443
+ top: line.top - surfaceRect.top,
5444
+ width: Math.max(1, endSlot.left - startSlot.left),
5445
+ height: line.height
5446
+ });
5447
+ }
5448
+ }
5449
+ }
5450
+ return boxes;
5451
+ }
5172
5452
  function scheduleFrame(callback) {
5173
5453
  if (typeof window !== "undefined" && typeof window.requestAnimationFrame === "function") {
5174
5454
  return window.requestAnimationFrame(() => callback());
@@ -5194,6 +5474,7 @@ function useEditorLayout(props) {
5194
5474
  height: 28
5195
5475
  });
5196
5476
  const [selectionBoxes, setSelectionBoxes] = createSignal([]);
5477
+ const [commentHighlights, setCommentHighlights] = createSignal([]);
5197
5478
  const [selectedImageBox, setSelectedImageBox] = createSignal(null);
5198
5479
  const [selectedTextBoxBox, setSelectedTextBoxBox] = createSignal(null);
5199
5480
  const [caretBox, setCaretBox] = createSignal({
@@ -5210,6 +5491,7 @@ function useEditorLayout(props) {
5210
5491
  const surface = props.surfaceRef();
5211
5492
  if (!surface) {
5212
5493
  setSelectionBoxes([]);
5494
+ setCommentHighlights([]);
5213
5495
  setSelectedImageBox(null);
5214
5496
  setSelectedTextBoxBox(null);
5215
5497
  setCaretBox((current) => ({ ...current, visible: false }));
@@ -5223,6 +5505,7 @@ function useEditorLayout(props) {
5223
5505
  });
5224
5506
  if (!snapshot) {
5225
5507
  setSelectionBoxes([]);
5508
+ setCommentHighlights([]);
5226
5509
  setSelectedImageBox(null);
5227
5510
  setSelectedTextBoxBox(null);
5228
5511
  setCaretBox((current) => ({ ...current, visible: false }));
@@ -5230,6 +5513,7 @@ function useEditorLayout(props) {
5230
5513
  }
5231
5514
  const geometry = computeCanvasSelectionGeometry(snapshot, props.state);
5232
5515
  setSelectionBoxes(geometry.selectionBoxes);
5516
+ setCommentHighlights(computeCommentHighlights(snapshot, props.state));
5233
5517
  setSelectedImageBox(geometry.selectedImageBox);
5234
5518
  setSelectedTextBoxBox(geometry.selectedTextBoxBox);
5235
5519
  setInputBox(geometry.inputBox);
@@ -5329,6 +5613,7 @@ function useEditorLayout(props) {
5329
5613
  measuredParagraphLayouts,
5330
5614
  inputBox,
5331
5615
  selectionBoxes,
5616
+ commentHighlights,
5332
5617
  selectedImageBox,
5333
5618
  selectedTextBoxBox,
5334
5619
  caretBox,
@@ -7564,6 +7849,105 @@ function serializeBookmarkEvent(event) {
7564
7849
  event.name ?? ""
7565
7850
  )}"${col}/>`;
7566
7851
  }
7852
+ const WORD15_NS = "http://schemas.microsoft.com/office/word/2012/wordml";
7853
+ function buildCommentExportPlan(document2) {
7854
+ const registry = document2.comments;
7855
+ if (!registry || registry.order.length === 0) {
7856
+ return void 0;
7857
+ }
7858
+ const assignedId = /* @__PURE__ */ new Map();
7859
+ const used = /* @__PURE__ */ new Set();
7860
+ for (const id of registry.order) {
7861
+ const c = registry.items[id];
7862
+ if (!c) continue;
7863
+ const hint = c.docxIdHint;
7864
+ if (hint !== void 0 && hint >= 0 && !used.has(hint)) {
7865
+ assignedId.set(id, hint);
7866
+ used.add(hint);
7867
+ }
7868
+ }
7869
+ let next = 0;
7870
+ for (const id of registry.order) {
7871
+ if (assignedId.has(id)) continue;
7872
+ while (used.has(next)) next += 1;
7873
+ assignedId.set(id, next);
7874
+ used.add(next);
7875
+ next += 1;
7876
+ }
7877
+ const eventsByParagraph = /* @__PURE__ */ new Map();
7878
+ const push = (paragraphId, event) => {
7879
+ const list = eventsByParagraph.get(paragraphId);
7880
+ if (list) {
7881
+ list.push(event);
7882
+ } else {
7883
+ eventsByParagraph.set(paragraphId, [event]);
7884
+ }
7885
+ };
7886
+ const comments = [];
7887
+ registry.order.forEach((id, index) => {
7888
+ const comment = registry.items[id];
7889
+ if (!comment) return;
7890
+ const wId = assignedId.get(id);
7891
+ const paraId = (1073741824 + index).toString(16).toUpperCase();
7892
+ comments.push({ comment, wId, paraId });
7893
+ if (comment.start) {
7894
+ push(comment.start.paragraphId, {
7895
+ kind: "start",
7896
+ offset: comment.start.offset,
7897
+ seq: comment.start.seq ?? 0,
7898
+ wId
7899
+ });
7900
+ }
7901
+ if (comment.end) {
7902
+ push(comment.end.paragraphId, {
7903
+ kind: "end",
7904
+ offset: comment.end.offset,
7905
+ seq: comment.end.seq ?? 0,
7906
+ wId
7907
+ });
7908
+ push(comment.end.paragraphId, {
7909
+ kind: "reference",
7910
+ offset: comment.end.offset,
7911
+ seq: (comment.end.seq ?? 0) + 0.5,
7912
+ wId
7913
+ });
7914
+ }
7915
+ });
7916
+ return { eventsByParagraph, comments };
7917
+ }
7918
+ function serializeCommentRangeEvent(event) {
7919
+ switch (event.kind) {
7920
+ case "start":
7921
+ return `<w:commentRangeStart w:id="${event.wId}"/>`;
7922
+ case "end":
7923
+ return `<w:commentRangeEnd w:id="${event.wId}"/>`;
7924
+ case "reference":
7925
+ return `<w:r><w:commentReference w:id="${event.wId}"/></w:r>`;
7926
+ }
7927
+ }
7928
+ const COMMENTS_XMLNS = `xmlns:w="${WORD_NS$1}" xmlns:w14="${WORD14_NS}" xmlns:w15="${WORD15_NS}"`;
7929
+ function serializeCommentBody(text) {
7930
+ const lines = text.split("\n");
7931
+ const runs = lines.map((line, i) => {
7932
+ const brk = i > 0 ? "<w:br/>" : "";
7933
+ return `${brk}<w:t xml:space="preserve">${escapeXml(line)}</w:t>`;
7934
+ }).join("");
7935
+ return `<w:r>${runs}</w:r>`;
7936
+ }
7937
+ function buildCommentsPartXml(plan) {
7938
+ const body = plan.comments.map(({ comment, wId, paraId }) => {
7939
+ const dateAttr = comment.date !== void 0 ? ` w:date="${new Date(comment.date).toISOString().replace(/\.\d{3}Z$/, "Z")}"` : "";
7940
+ const initialsAttr = comment.initials ? ` w:initials="${escapeXml(comment.initials)}"` : "";
7941
+ return `<w:comment w:id="${wId}" w:author="${escapeXml(comment.author)}"${dateAttr}${initialsAttr}><w:p w14:paraId="${paraId}">${serializeCommentBody(comment.text)}</w:p></w:comment>`;
7942
+ }).join("");
7943
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:comments ${COMMENTS_XMLNS}>${body}</w:comments>`;
7944
+ }
7945
+ function buildCommentsExtendedPartXml(plan) {
7946
+ const body = plan.comments.map(
7947
+ ({ comment, paraId }) => `<w15:commentEx w15:paraId="${paraId}" w15:done="${comment.resolved ? "1" : "0"}"/>`
7948
+ ).join("");
7949
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w15:commentsEx ${COMMENTS_XMLNS}>${body}</w15:commentsEx>`;
7950
+ }
7567
7951
  function serializeDocxBorderAttrs(border, colorFallback = "000000") {
7568
7952
  if (border.type === "none" || border.width <= 0) {
7569
7953
  return 'w:val="nil"/>';
@@ -8058,10 +8442,13 @@ function serializeParagraphStyleXml(style2) {
8058
8442
  return parts.length > 0 ? `<w:pPr>${parts.join("")}</w:pPr>` : "";
8059
8443
  }
8060
8444
  function serializeParagraphProperties(paragraph, numberingInfo, styles, overrides) {
8061
- var _a;
8445
+ var _a, _b;
8062
8446
  const parts = [];
8063
8447
  const style2 = materializeParagraphStyle(paragraph, styles);
8064
8448
  const align = ((_a = paragraph.style) == null ? void 0 : _a.align) ?? (overrides == null ? void 0 : overrides.align) ?? style2.align;
8449
+ if ((_b = paragraph.style) == null ? void 0 : _b.styleId) {
8450
+ parts.push(`<w:pStyle w:val="${escapeXml(paragraph.style.styleId)}"/>`);
8451
+ }
8065
8452
  if (align) {
8066
8453
  parts.push(`<w:jc w:val="${align}"/>`);
8067
8454
  }
@@ -8732,8 +9119,8 @@ function stripRpr(rPr) {
8732
9119
  function isSplittableTextRun(run) {
8733
9120
  return !run.image && !run.textBox && !run.field && !run.fieldChar && run.fieldInstruction === void 0 && !run.footnoteReference && !run.endnoteReference;
8734
9121
  }
8735
- function serializeRunsWithBookmarks(runs, events, context, paragraphStyleId, styles) {
8736
- const sorted = [...events].sort(
9122
+ function serializeRunsWithBoundaries(runs, tokens, context, paragraphStyleId, styles) {
9123
+ const sorted = [...tokens].sort(
8737
9124
  (a, b) => a.offset - b.offset || a.seq - b.seq
8738
9125
  );
8739
9126
  let ei = 0;
@@ -8741,7 +9128,7 @@ function serializeRunsWithBookmarks(runs, events, context, paragraphStyleId, sty
8741
9128
  let out = "";
8742
9129
  const flushUpTo = (limit) => {
8743
9130
  while (ei < sorted.length && sorted[ei].offset <= limit) {
8744
- out += serializeBookmarkEvent(sorted[ei]);
9131
+ out += sorted[ei].xml;
8745
9132
  ei += 1;
8746
9133
  }
8747
9134
  };
@@ -8752,21 +9139,21 @@ function serializeRunsWithBookmarks(runs, events, context, paragraphStyleId, sty
8752
9139
  if (isSplittableTextRun(run) && run.text.length > 0) {
8753
9140
  let cursor = runStart;
8754
9141
  while (ei < sorted.length && sorted[ei].offset < runEnd) {
8755
- const event = sorted[ei];
8756
- if (event.offset > cursor) {
9142
+ const token = sorted[ei];
9143
+ if (token.offset > cursor) {
8757
9144
  out += serializeRunWithRelationships(
8758
9145
  {
8759
9146
  ...run,
8760
- text: run.text.slice(cursor - runStart, event.offset - runStart)
9147
+ text: run.text.slice(cursor - runStart, token.offset - runStart)
8761
9148
  },
8762
9149
  context,
8763
9150
  paragraphStyleId,
8764
9151
  styles
8765
9152
  );
8766
9153
  }
8767
- out += serializeBookmarkEvent(event);
9154
+ out += token.xml;
8768
9155
  ei += 1;
8769
- cursor = event.offset;
9156
+ cursor = token.offset;
8770
9157
  }
8771
9158
  if (cursor < runEnd) {
8772
9159
  out += serializeRunWithRelationships(
@@ -8808,15 +9195,28 @@ function serializeBlocksXml(blocks, context, styles) {
8808
9195
  }).join("");
8809
9196
  }
8810
9197
  function serializeParagraphXml(paragraph, context, styles, overrides) {
8811
- var _a, _b;
9198
+ var _a, _b, _c;
8812
9199
  const runs = paragraph.runs.length > 0 ? paragraph.runs : [{ id: "", text: "" }];
8813
9200
  const dropCapFrame = paragraph.dropCap ? serializeDropCapFrameParagraph(paragraph.dropCap) : "";
8814
9201
  const bookmarkEvents = (_a = context.bookmarkEventsByParagraph) == null ? void 0 : _a.get(paragraph.id);
8815
- const runsXml = bookmarkEvents && bookmarkEvents.length > 0 ? serializeRunsWithBookmarks(
9202
+ const commentEvents = (_b = context.commentEventsByParagraph) == null ? void 0 : _b.get(paragraph.id);
9203
+ const boundaryTokens = [
9204
+ ...(bookmarkEvents ?? []).map((e) => ({
9205
+ offset: e.offset,
9206
+ seq: e.seq,
9207
+ xml: serializeBookmarkEvent(e)
9208
+ })),
9209
+ ...(commentEvents ?? []).map((e) => ({
9210
+ offset: e.offset,
9211
+ seq: e.seq,
9212
+ xml: serializeCommentRangeEvent(e)
9213
+ }))
9214
+ ];
9215
+ const runsXml = boundaryTokens.length > 0 ? serializeRunsWithBoundaries(
8816
9216
  runs,
8817
- bookmarkEvents,
9217
+ boundaryTokens,
8818
9218
  context,
8819
- (_b = paragraph.style) == null ? void 0 : _b.styleId,
9219
+ (_c = paragraph.style) == null ? void 0 : _c.styleId,
8820
9220
  styles
8821
9221
  ) : runs.map(
8822
9222
  (run) => {
@@ -9310,14 +9710,24 @@ function buildPartContext(blocks, numberingContext, state, document2) {
9310
9710
  };
9311
9711
  }
9312
9712
  function buildNumberingXml(definitions) {
9313
- const abstractNums = definitions.map(({ kind, level, abstractNumId, format, startAt, bulletGlyph, bulletFont }) => {
9314
- const numFmtVal = kind === "bullet" ? "bullet" : format ?? "decimal";
9315
- const levelText = kind === "bullet" ? bulletGlyph ?? "" : `%${level + 1}.`;
9316
- const startVal = startAt ?? 1;
9317
- const fontName = kind === "bullet" ? bulletFont ?? "Symbol" : void 0;
9318
- const runFonts = fontName ? `<w:rPr><w:rFonts w:ascii="${escapeXml(fontName)}" w:hAnsi="${escapeXml(fontName)}" w:hint="default"/></w:rPr>` : "";
9319
- return `<w:abstractNum w:abstractNumId="${abstractNumId}"><w:lvl w:ilvl="${level}"><w:start w:val="${startVal}"/><w:numFmt w:val="${numFmtVal}"/><w:lvlText w:val="${escapeXml(levelText)}"/><w:lvlJc w:val="left"/>${runFonts}</w:lvl></w:abstractNum>`;
9320
- }).join("");
9713
+ const abstractNums = definitions.map(
9714
+ ({
9715
+ kind,
9716
+ level,
9717
+ abstractNumId,
9718
+ format,
9719
+ startAt,
9720
+ bulletGlyph,
9721
+ bulletFont
9722
+ }) => {
9723
+ const numFmtVal = kind === "bullet" ? "bullet" : format ?? "decimal";
9724
+ const levelText = kind === "bullet" ? bulletGlyph ?? "" : `%${level + 1}.`;
9725
+ const startVal = startAt ?? 1;
9726
+ const fontName = kind === "bullet" ? bulletFont ?? "Symbol" : void 0;
9727
+ const runFonts = fontName ? `<w:rPr><w:rFonts w:ascii="${escapeXml(fontName)}" w:hAnsi="${escapeXml(fontName)}" w:hint="default"/></w:rPr>` : "";
9728
+ return `<w:abstractNum w:abstractNumId="${abstractNumId}"><w:lvl w:ilvl="${level}"><w:start w:val="${startVal}"/><w:numFmt w:val="${numFmtVal}"/><w:lvlText w:val="${escapeXml(levelText)}"/><w:lvlJc w:val="left"/>${runFonts}</w:lvl></w:abstractNum>`;
9729
+ }
9730
+ ).join("");
9321
9731
  const nums = definitions.map(
9322
9732
  ({ abstractNumId, numId }) => `<w:num w:numId="${numId}"><w:abstractNumId w:val="${abstractNumId}"/></w:num>`
9323
9733
  ).join("");
@@ -9343,19 +9753,19 @@ function buildHeaderFooterXml(kind, blocks, context, styles) {
9343
9753
  const tag = kind === "header" ? "hdr" : "ftr";
9344
9754
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:${tag} ${DOCUMENT_XMLNS}>${serializeBlocksXml(blocks, context, styles)}</w:${tag}>`;
9345
9755
  }
9346
- function buildContentTypesXml(hasNumbering, imageExtensions, hasSettings, parts, hasFootnotes, hasEndnotes, hasStyles) {
9756
+ function buildContentTypesXml(hasNumbering, imageExtensions, hasSettings, parts, hasFootnotes, hasEndnotes, hasStyles, hasComments) {
9347
9757
  const overrides = parts.map((part) => {
9348
9758
  const contentType = part.kind === "header" ? "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml" : "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml";
9349
9759
  return `<Override PartName="/word/${part.path}" ContentType="${contentType}"/>`;
9350
9760
  }).join("");
9351
9761
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/>${imageContentTypeDefaults(
9352
9762
  imageExtensions
9353
- )}<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>${hasStyles ? '<Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>' : ""}${hasNumbering ? '<Override PartName="/word/numbering.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"/>' : ""}${hasSettings ? '<Override PartName="/word/settings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"/>' : ""}${hasFootnotes ? '<Override PartName="/word/footnotes.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml"/>' : ""}${hasEndnotes ? '<Override PartName="/word/endnotes.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml"/>' : ""}${overrides}</Types>`;
9763
+ )}<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>${hasStyles ? '<Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>' : ""}${hasNumbering ? '<Override PartName="/word/numbering.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"/>' : ""}${hasSettings ? '<Override PartName="/word/settings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"/>' : ""}${hasFootnotes ? '<Override PartName="/word/footnotes.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml"/>' : ""}${hasEndnotes ? '<Override PartName="/word/endnotes.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml"/>' : ""}${hasComments ? '<Override PartName="/word/comments.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml"/><Override PartName="/word/commentsExtended.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml"/>' : ""}${overrides}</Types>`;
9354
9764
  }
9355
9765
  function buildRootRelationshipsXml() {
9356
9766
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="${PACKAGE_REL_NS}"><Relationship Id="rId1" Type="${OFFICE_REL_NS}/officeDocument" Target="word/document.xml"/></Relationships>`;
9357
9767
  }
9358
- function buildDocumentRelationshipsXml(hasNumbering, hasSettings, images, hyperlinks, parts, hasFootnotes, hasEndnotes, hasStyles) {
9768
+ function buildDocumentRelationshipsXml(hasNumbering, hasSettings, images, hyperlinks, parts, hasFootnotes, hasEndnotes, hasStyles, hasComments) {
9359
9769
  let rels = "";
9360
9770
  if (hasStyles)
9361
9771
  rels += `<Relationship Id="rIdStyles" Type="${OFFICE_REL_NS}/styles" Target="styles.xml"/>`;
@@ -9380,6 +9790,10 @@ function buildDocumentRelationshipsXml(hasNumbering, hasSettings, images, hyperl
9380
9790
  if (hasEndnotes) {
9381
9791
  rels += `<Relationship Id="rIdEndnotes" Type="${OFFICE_REL_NS}/endnotes" Target="endnotes.xml"/>`;
9382
9792
  }
9793
+ if (hasComments) {
9794
+ rels += `<Relationship Id="rIdComments" Type="${OFFICE_REL_NS}/comments" Target="comments.xml"/>`;
9795
+ rels += `<Relationship Id="rIdCommentsExtended" Type="http://schemas.microsoft.com/office/2011/relationships/commentsExtended" Target="commentsExtended.xml"/>`;
9796
+ }
9383
9797
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="${PACKAGE_REL_NS}">${rels}</Relationships>`;
9384
9798
  }
9385
9799
  function buildSettingsXml(hasEvenAndOddHeaders, defaultTabStop, footnoteSettings, endnoteSettings) {
@@ -9442,6 +9856,7 @@ function buildPartRelationshipsXml(images, hyperlinks) {
9442
9856
  }
9443
9857
  async function exportEditorDocumentToDocx(document2) {
9444
9858
  var _a, _b, _c, _d, _e, _f;
9859
+ document2 = renumberImageCaptionsInDocument(document2);
9445
9860
  const zip = new JSZip();
9446
9861
  const numberingContext = buildNumberingContext(document2);
9447
9862
  const buildState = {
@@ -9466,6 +9881,9 @@ async function exportEditorDocumentToDocx(document2) {
9466
9881
  bodyContext.endnoteIdMap = endnoteIdMap;
9467
9882
  const bookmarkEvents = buildBookmarkExportPlan(document2);
9468
9883
  bodyContext.bookmarkEventsByParagraph = bookmarkEvents;
9884
+ const commentPlan = buildCommentExportPlan(document2);
9885
+ bodyContext.commentEventsByParagraph = commentPlan == null ? void 0 : commentPlan.eventsByParagraph;
9886
+ const hasComments = commentPlan !== void 0;
9469
9887
  const parts = [];
9470
9888
  const sectionReferences = sections.map(
9471
9889
  () => ({})
@@ -9491,6 +9909,7 @@ async function exportEditorDocumentToDocx(document2) {
9491
9909
  context.footnoteIdMap = footnoteIdMap;
9492
9910
  context.endnoteIdMap = endnoteIdMap;
9493
9911
  context.bookmarkEventsByParagraph = bookmarkEvents;
9912
+ context.commentEventsByParagraph = commentPlan == null ? void 0 : commentPlan.eventsByParagraph;
9494
9913
  parts.push({
9495
9914
  kind,
9496
9915
  type,
@@ -9564,7 +9983,8 @@ async function exportEditorDocumentToDocx(document2) {
9564
9983
  parts,
9565
9984
  hasFootnotes,
9566
9985
  hasEndnotes,
9567
- hasStyles
9986
+ hasStyles,
9987
+ hasComments
9568
9988
  )
9569
9989
  );
9570
9990
  zip.file("_rels/.rels", buildRootRelationshipsXml());
@@ -9581,7 +10001,7 @@ async function exportEditorDocumentToDocx(document2) {
9581
10001
  buildNumberingXml(numberingContext.definitions)
9582
10002
  );
9583
10003
  }
9584
- if (hasStyles || hasNumbering || hasDocumentSettings || bodyContext.images.length > 0 || bodyContext.hyperlinks.length > 0 || parts.length > 0 || hasFootnotes || hasEndnotes) {
10004
+ if (hasStyles || hasNumbering || hasDocumentSettings || bodyContext.images.length > 0 || bodyContext.hyperlinks.length > 0 || parts.length > 0 || hasFootnotes || hasEndnotes || hasComments) {
9585
10005
  zip.file(
9586
10006
  "word/_rels/document.xml.rels",
9587
10007
  buildDocumentRelationshipsXml(
@@ -9592,7 +10012,8 @@ async function exportEditorDocumentToDocx(document2) {
9592
10012
  parts,
9593
10013
  hasFootnotes,
9594
10014
  hasEndnotes,
9595
- hasStyles
10015
+ hasStyles,
10016
+ hasComments
9596
10017
  )
9597
10018
  );
9598
10019
  }
@@ -9648,6 +10069,13 @@ async function exportEditorDocumentToDocx(document2) {
9648
10069
  );
9649
10070
  }
9650
10071
  }
10072
+ if (commentPlan) {
10073
+ zip.file("word/comments.xml", buildCommentsPartXml(commentPlan));
10074
+ zip.file(
10075
+ "word/commentsExtended.xml",
10076
+ buildCommentsExtendedPartXml(commentPlan)
10077
+ );
10078
+ }
9651
10079
  for (const img of allImages) {
9652
10080
  if (img.kind === "embedded" && img.base64) {
9653
10081
  zip.file(`word/${img.target}`, img.base64, { base64: true });
@@ -11891,6 +12319,7 @@ endobj
11891
12319
  }
11892
12320
  const FOOTNOTE_BLOCK_GAP_PX = 2;
11893
12321
  async function exportEditorDocumentToPdf(document2) {
12322
+ document2 = renumberImageCaptionsInDocument(document2);
11894
12323
  const fontRegistry = new PdfFontRegistry();
11895
12324
  await fontRegistry.loadBundledUnicodeFaces({
11896
12325
  families: collectPdfFontFamilies(document2)
@@ -38993,6 +39422,10 @@ function createEditorDialogs() {
38993
39422
  isOpen: false,
38994
39423
  initialAlt: ""
38995
39424
  });
39425
+ const [imageCaptionDialog, setImageCaptionDialog] = createSignal({
39426
+ isOpen: false,
39427
+ initialCaption: ""
39428
+ });
38996
39429
  const [contextMenu, setContextMenu] = createSignal({ isOpen: false, x: 0, y: 0 });
38997
39430
  const [fontDialog, setFontDialog] = createSignal({
38998
39431
  isOpen: false,
@@ -39090,6 +39523,8 @@ function createEditorDialogs() {
39090
39523
  setLinkDialog,
39091
39524
  imageAltDialog,
39092
39525
  setImageAltDialog,
39526
+ imageCaptionDialog,
39527
+ setImageCaptionDialog,
39093
39528
  contextMenu,
39094
39529
  setContextMenu,
39095
39530
  fontDialog,
@@ -40634,6 +41069,14 @@ function buildDocumentAndBrowserCommands({
40634
41069
  isEnabled: image.isSelected(),
40635
41070
  isActive: image.isSelected()
40636
41071
  })
41072
+ ),
41073
+ insertImageCaption: actionCommand(
41074
+ "insertImageCaption",
41075
+ () => image.promptCaption(),
41076
+ () => ({
41077
+ isEnabled: image.isSelected(),
41078
+ isActive: image.isSelected()
41079
+ })
40637
41080
  )
40638
41081
  };
40639
41082
  }
@@ -41037,6 +41480,7 @@ function createEditorEssentialsRuntimePlugin(options) {
41037
41480
  };
41038
41481
  const essentialsImage = {
41039
41482
  promptAlt: () => options.commandsController.promptForImageAlt(),
41483
+ promptCaption: () => options.commandsController.promptForImageCaption(),
41040
41484
  isSelected: () => Boolean(options.selectedImageRun())
41041
41485
  };
41042
41486
  const essentialsBrowser = {
@@ -41579,14 +42023,14 @@ function DropCaret(props) {
41579
42023
  })
41580
42024
  });
41581
42025
  }
41582
- var _tmpl$$d = /* @__PURE__ */ template(`<div class=oasis-editor-table-resize-guide>`), _tmpl$2$8 = /* @__PURE__ */ template(`<img class=oasis-editor-image-ghost>`), _tmpl$3$6 = /* @__PURE__ */ template(`<div class=oasis-editor-table-ghost>`);
42026
+ var _tmpl$$e = /* @__PURE__ */ template(`<div class=oasis-editor-table-resize-guide>`), _tmpl$2$9 = /* @__PURE__ */ template(`<img class=oasis-editor-image-ghost>`), _tmpl$3$7 = /* @__PURE__ */ template(`<div class=oasis-editor-table-ghost>`);
41583
42027
  function EditorDragLayers(props) {
41584
42028
  return [createComponent(Show, {
41585
42029
  get when() {
41586
42030
  return props.tableResize.resizing();
41587
42031
  },
41588
42032
  children: (resizing) => (() => {
41589
- var _el$ = _tmpl$$d();
42033
+ var _el$ = _tmpl$$e();
41590
42034
  createRenderEffect((_p$) => {
41591
42035
  var _v$ = !!(resizing().type === "column"), _v$2 = !!(resizing().type === "row"), _v$3 = {
41592
42036
  ...resizing().type === "column" ? {
@@ -41617,7 +42061,7 @@ function EditorDragLayers(props) {
41617
42061
  return memo(() => !!props.imageOps.dragging())() && props.imageOps.draggedImageInfo();
41618
42062
  },
41619
42063
  children: (info) => (() => {
41620
- var _el$2 = _tmpl$2$8();
42064
+ var _el$2 = _tmpl$2$9();
41621
42065
  createRenderEffect((_p$) => {
41622
42066
  var _v$4 = info().src, _v$5 = `${info().width}px`, _v$6 = `${info().height}px`, _v$7 = `${props.imageOps.mousePos().x - info().offsetX}px`, _v$8 = `${props.imageOps.mousePos().y - info().offsetY}px`;
41623
42067
  _v$4 !== _p$.e && setAttribute(_el$2, "src", _p$.e = _v$4);
@@ -41640,7 +42084,7 @@ function EditorDragLayers(props) {
41640
42084
  return memo(() => !!props.tableDrag.dragging())() && props.tableDrag.draggedTableInfo();
41641
42085
  },
41642
42086
  children: (info) => (() => {
41643
- var _el$3 = _tmpl$3$6();
42087
+ var _el$3 = _tmpl$3$7();
41644
42088
  createRenderEffect((_p$) => {
41645
42089
  var _v$9 = `${info().width}px`, _v$0 = `${info().height}px`, _v$1 = `${props.tableDrag.mousePos().x - info().offsetX}px`, _v$10 = `${props.tableDrag.mousePos().y - info().offsetY}px`;
41646
42090
  _v$9 !== _p$.e && setStyleProperty(_el$3, "width", _p$.e = _v$9);
@@ -41703,7 +42147,7 @@ function EditorDragLayers(props) {
41703
42147
  })
41704
42148
  })];
41705
42149
  }
41706
- var _tmpl$$c = /* @__PURE__ */ template(`<div class=oasis-editor-dialog-input-group><label class=oasis-editor-dialog-label></label><input type=text class=oasis-editor-dialog-input data-testid=editor-link-dialog-input>`), _tmpl$2$7 = /* @__PURE__ */ template(`<button class="oasis-editor-dialog-button oasis-editor-dialog-button-secondary"data-testid=editor-link-dialog-cancel>`), _tmpl$3$5 = /* @__PURE__ */ template(`<button class="oasis-editor-dialog-button oasis-editor-dialog-button-primary"data-testid=editor-link-dialog-apply>`);
42150
+ var _tmpl$$d = /* @__PURE__ */ template(`<div class=oasis-editor-dialog-input-group><label class=oasis-editor-dialog-label></label><input type=text class=oasis-editor-dialog-input data-testid=editor-link-dialog-input>`), _tmpl$2$8 = /* @__PURE__ */ template(`<button class="oasis-editor-dialog-button oasis-editor-dialog-button-secondary"data-testid=editor-link-dialog-cancel>`), _tmpl$3$6 = /* @__PURE__ */ template(`<button class="oasis-editor-dialog-button oasis-editor-dialog-button-primary"data-testid=editor-link-dialog-apply>`);
41707
42151
  function LinkDialog(props) {
41708
42152
  const [href, setHref] = createSignal(props.initialHref);
41709
42153
  let inputRef;
@@ -41729,19 +42173,19 @@ function LinkDialog(props) {
41729
42173
  },
41730
42174
  get footer() {
41731
42175
  return [(() => {
41732
- var _el$4 = _tmpl$2$7();
42176
+ var _el$4 = _tmpl$2$8();
41733
42177
  addEventListener(_el$4, "click", props.onClose, true);
41734
42178
  insert(_el$4, () => t("generic.cancel"));
41735
42179
  return _el$4;
41736
42180
  })(), (() => {
41737
- var _el$5 = _tmpl$3$5();
42181
+ var _el$5 = _tmpl$3$6();
41738
42182
  _el$5.$$click = handleConfirm;
41739
42183
  insert(_el$5, () => t("generic.apply"));
41740
42184
  return _el$5;
41741
42185
  })()];
41742
42186
  },
41743
42187
  get children() {
41744
- var _el$ = _tmpl$$c(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
42188
+ var _el$ = _tmpl$$d(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
41745
42189
  insert(_el$2, () => t("dialog.link.label"));
41746
42190
  _el$3.$$keydown = (e) => e.key === "Enter" && handleConfirm();
41747
42191
  _el$3.$$input = (e) => setHref(e.currentTarget.value);
@@ -41754,7 +42198,7 @@ function LinkDialog(props) {
41754
42198
  });
41755
42199
  }
41756
42200
  delegateEvents(["input", "keydown", "click"]);
41757
- var _tmpl$$b = /* @__PURE__ */ template(`<div class=oasis-editor-dialog-input-group><label class=oasis-editor-dialog-label></label><input type=text class=oasis-editor-dialog-input>`), _tmpl$2$6 = /* @__PURE__ */ template(`<button class="oasis-editor-dialog-button oasis-editor-dialog-button-secondary">`), _tmpl$3$4 = /* @__PURE__ */ template(`<button class="oasis-editor-dialog-button oasis-editor-dialog-button-primary">`);
42201
+ var _tmpl$$c = /* @__PURE__ */ template(`<div class=oasis-editor-dialog-input-group><label class=oasis-editor-dialog-label></label><input type=text class=oasis-editor-dialog-input>`), _tmpl$2$7 = /* @__PURE__ */ template(`<button class="oasis-editor-dialog-button oasis-editor-dialog-button-secondary">`), _tmpl$3$5 = /* @__PURE__ */ template(`<button class="oasis-editor-dialog-button oasis-editor-dialog-button-primary">`);
41758
42202
  function ImageAltDialog(props) {
41759
42203
  const [alt, setAlt] = createSignal(props.initialAlt);
41760
42204
  let inputRef;
@@ -41780,19 +42224,19 @@ function ImageAltDialog(props) {
41780
42224
  },
41781
42225
  get footer() {
41782
42226
  return [(() => {
41783
- var _el$4 = _tmpl$2$6();
42227
+ var _el$4 = _tmpl$2$7();
41784
42228
  addEventListener(_el$4, "click", props.onClose, true);
41785
42229
  insert(_el$4, () => t("generic.cancel"));
41786
42230
  return _el$4;
41787
42231
  })(), (() => {
41788
- var _el$5 = _tmpl$3$4();
42232
+ var _el$5 = _tmpl$3$5();
41789
42233
  _el$5.$$click = handleConfirm;
41790
42234
  insert(_el$5, () => t("generic.save"));
41791
42235
  return _el$5;
41792
42236
  })()];
41793
42237
  },
41794
42238
  get children() {
41795
- var _el$ = _tmpl$$b(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
42239
+ var _el$ = _tmpl$$c(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
41796
42240
  insert(_el$2, () => t("dialog.imageAlt.label"));
41797
42241
  _el$3.$$keydown = (e) => e.key === "Enter" && handleConfirm();
41798
42242
  _el$3.$$input = (e) => setAlt(e.currentTarget.value);
@@ -41805,6 +42249,57 @@ function ImageAltDialog(props) {
41805
42249
  });
41806
42250
  }
41807
42251
  delegateEvents(["input", "keydown", "click"]);
42252
+ var _tmpl$$b = /* @__PURE__ */ template(`<div class=oasis-editor-dialog-input-group><label class=oasis-editor-dialog-label></label><input type=text class=oasis-editor-dialog-input>`), _tmpl$2$6 = /* @__PURE__ */ template(`<button class="oasis-editor-dialog-button oasis-editor-dialog-button-secondary">`), _tmpl$3$4 = /* @__PURE__ */ template(`<button class="oasis-editor-dialog-button oasis-editor-dialog-button-primary">`);
42253
+ function ImageCaptionDialog(props) {
42254
+ const [caption, setCaption] = createSignal(props.initialCaption);
42255
+ let inputRef;
42256
+ createEffect(() => {
42257
+ if (props.isOpen) {
42258
+ setCaption(props.initialCaption);
42259
+ setTimeout(() => inputRef == null ? void 0 : inputRef.focus(), 50);
42260
+ }
42261
+ });
42262
+ const handleConfirm = () => {
42263
+ props.onConfirm(caption());
42264
+ props.onClose();
42265
+ };
42266
+ return createComponent(Dialog, {
42267
+ get isOpen() {
42268
+ return props.isOpen;
42269
+ },
42270
+ get title() {
42271
+ return t("dialog.imageCaption.title");
42272
+ },
42273
+ get onClose() {
42274
+ return props.onClose;
42275
+ },
42276
+ get footer() {
42277
+ return [(() => {
42278
+ var _el$4 = _tmpl$2$6();
42279
+ addEventListener(_el$4, "click", props.onClose, true);
42280
+ insert(_el$4, () => t("generic.cancel"));
42281
+ return _el$4;
42282
+ })(), (() => {
42283
+ var _el$5 = _tmpl$3$4();
42284
+ _el$5.$$click = handleConfirm;
42285
+ insert(_el$5, () => t("generic.save"));
42286
+ return _el$5;
42287
+ })()];
42288
+ },
42289
+ get children() {
42290
+ var _el$ = _tmpl$$b(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
42291
+ insert(_el$2, () => t("dialog.imageCaption.label"));
42292
+ _el$3.$$keydown = (e) => e.key === "Enter" && handleConfirm();
42293
+ _el$3.$$input = (e) => setCaption(e.currentTarget.value);
42294
+ var _ref$ = inputRef;
42295
+ typeof _ref$ === "function" ? use(_ref$, _el$3) : inputRef = _el$3;
42296
+ createRenderEffect(() => setAttribute(_el$3, "placeholder", t("dialog.imageCaption.placeholder")));
42297
+ createRenderEffect(() => _el$3.value = caption());
42298
+ return _el$;
42299
+ }
42300
+ });
42301
+ }
42302
+ delegateEvents(["input", "keydown", "click"]);
41808
42303
  const DEFAULT_COLOR = "#111827";
41809
42304
  const DEFAULT_HIGHLIGHT = "#fef08a";
41810
42305
  const DEFAULT_SHADING = "#fef3c7";
@@ -43308,6 +43803,8 @@ function EditorDialogsLayer(props) {
43308
43803
  setLinkDialog,
43309
43804
  imageAltDialog,
43310
43805
  setImageAltDialog,
43806
+ imageCaptionDialog,
43807
+ setImageCaptionDialog,
43311
43808
  contextMenu,
43312
43809
  fontDialog,
43313
43810
  setFontDialog,
@@ -43346,6 +43843,21 @@ function EditorDialogsLayer(props) {
43346
43843
  props.focusInput();
43347
43844
  },
43348
43845
  onConfirm: (alt) => props.applyImageAltCommand(alt.trim())
43846
+ }), createComponent(ImageCaptionDialog, {
43847
+ get isOpen() {
43848
+ return imageCaptionDialog().isOpen;
43849
+ },
43850
+ get initialCaption() {
43851
+ return imageCaptionDialog().initialCaption;
43852
+ },
43853
+ onClose: () => {
43854
+ setImageCaptionDialog({
43855
+ ...imageCaptionDialog(),
43856
+ isOpen: false
43857
+ });
43858
+ props.focusInput();
43859
+ },
43860
+ onConfirm: (caption) => props.applyImageCaptionCommand(caption.trim())
43349
43861
  }), createComponent(FindReplaceDialog, {
43350
43862
  get fr() {
43351
43863
  return props.findReplace;
@@ -45377,6 +45889,7 @@ function buildEditorViewProps(ctx) {
45377
45889
  };
45378
45890
  const overlays = {
45379
45891
  selectionBoxes: ctx.selectionBoxes,
45892
+ commentHighlights: ctx.commentHighlights,
45380
45893
  selectedImageBox: ctx.selectedImageBox,
45381
45894
  selectedTextBoxBox: ctx.selectedTextBoxBox,
45382
45895
  layoutOptions: ctx.layoutOptions,
@@ -45782,6 +46295,8 @@ function OasisEditorApp(props = {}) {
45782
46295
  setLinkDialog,
45783
46296
  imageAltDialog,
45784
46297
  setImageAltDialog,
46298
+ imageCaptionDialog,
46299
+ setImageCaptionDialog,
45785
46300
  contextMenu,
45786
46301
  setContextMenu,
45787
46302
  fontDialog,
@@ -45818,6 +46333,7 @@ function OasisEditorApp(props = {}) {
45818
46333
  measuredParagraphLayouts,
45819
46334
  inputBox,
45820
46335
  selectionBoxes,
46336
+ commentHighlights,
45821
46337
  selectedImageBox,
45822
46338
  selectedTextBoxBox,
45823
46339
  caretBox,
@@ -46081,7 +46597,12 @@ function OasisEditorApp(props = {}) {
46081
46597
  openImageAltDialog: (initialAlt) => setImageAltDialog({
46082
46598
  isOpen: true,
46083
46599
  initialAlt
46084
- })
46600
+ }),
46601
+ openImageCaptionDialog: (initialCaption) => setImageCaptionDialog({
46602
+ isOpen: true,
46603
+ initialCaption
46604
+ }),
46605
+ imageCaptionLabel: () => (ui().locale ?? "pt-BR").startsWith("en") ? "Figure" : "Figura"
46085
46606
  });
46086
46607
  const keyboardCommandsController = {
46087
46608
  ...commandsController,
@@ -46333,6 +46854,7 @@ function OasisEditorApp(props = {}) {
46333
46854
  className: ui().class,
46334
46855
  style: ui().style,
46335
46856
  selectionBoxes,
46857
+ commentHighlights,
46336
46858
  selectedImageBox,
46337
46859
  selectedTextBoxBox,
46338
46860
  layoutOptions: layoutOptionsOverlay,
@@ -46409,6 +46931,8 @@ function OasisEditorApp(props = {}) {
46409
46931
  setLinkDialog,
46410
46932
  imageAltDialog,
46411
46933
  setImageAltDialog,
46934
+ imageCaptionDialog,
46935
+ setImageCaptionDialog,
46412
46936
  contextMenu,
46413
46937
  setContextMenu,
46414
46938
  fontDialog,
@@ -46429,6 +46953,9 @@ function OasisEditorApp(props = {}) {
46429
46953
  get applyImageAltCommand() {
46430
46954
  return commandsController.applyImageAltCommand;
46431
46955
  },
46956
+ get applyImageCaptionCommand() {
46957
+ return commandsController.applyImageCaptionCommand;
46958
+ },
46432
46959
  applyFontDialogValues,
46433
46960
  applyParagraphDialogValues,
46434
46961
  applyTablePropertiesDialogValues,