oasis-editor 0.0.10 → 0.0.12

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.
@@ -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 textStyleToFontSizePt, $ as PX_PER_POINT, a0 as DEFAULT_FONT_SIZE_PX, a1 as isDoubleUnderlineStyle, a2 as isWavyUnderlineStyle, a3 as underlineStyleLineWidthPx, a4 as underlineStyleDashArray, a5 as getListLabelInset, a6 as getParagraphBorderInsets, a7 as buildSegmentTable, a8 as buildCanvasTableLayout, a9 as normalizeFamily, aa as ROBOTO_FONT_FILES, ab as loadFontAsset, ac as OFFICE_COMPAT_FONT_FAMILIES, ad as buildSfnt, ae as defaultFontDecoderRegistry, af as SfntFontProgram, ag as collectPdfFontFamilies, ah as projectDocumentLayout, ai as getPageHeaderZoneTop, aj as getPageBodyTop, ak as findFootnoteReference, al as FOOTNOTE_MARKER_GUTTER_PX, am as resolveImporterForFile, an as createEditorStateFromDocument, ao as getDocumentParagraphsCanonical, ap as getToolbarStyleState, aq as STANDARD_FONT_SIZES_PT, ar as fontSizePxToPt, as as probeLocalFontFamilies, at as createInitialEditorState, au as parseFontSizePtToPx, av as formatFontSizePt, aw as listKindForTag, ax as isParagraphTag, ay as collectInlineRuns, az as parseParagraphStyle, aA as t, aB as preciseFontModeVersion, aC as isPreciseFontModeEnabled, aD as togglePreciseFontMode, aE as nextFontSizePt, aF as previousFontSizePt, aG as fontSizePtToPx, aH as createDefaultToolbarPreset, aI as defaultMenuItems, aJ as MenuRegistry, aK as createToolbarRegistry, aL as Editor, aM as resolveCommandRef, aN as commandRefName, aO as InlineShell, aP as BalloonShell, aQ as DocumentShell, aR as createMemo, aS as getCaretRectFromSnapshot, aT as getParagraphRectFromSnapshot, aU as createComponent, aV as CaretOverlay, aW as Show, aX as createRenderEffect, aY as style, aZ as setAttribute, a_ as setStyleProperty, a$ as memo, b0 as template, b1 as insert, b2 as use, b3 as addEventListener, b4 as Dialog, b5 as delegateEvents, b6 as className, b7 as For, b8 as UNDERLINE_STYLE_OPTIONS, b9 as Tabs, ba as measureParagraphMinContentWidthPx, bb as getEditableBlocksForZone, bc as findParagraphLocation, bd as createSectionBoundaryParagraph, be as normalizePageSettings, bf as DEFAULT_EDITOR_PAGE_SETTINGS, bg as markStart, bh as markEnd, bi as getParagraphEntries, bj as getParagraphById, bk as PluginUiHost, bl as OasisEditorEditor, bm as perfTimer, bn as OasisBrandMark, bo as setPreciseFontPreference, bp as setWelcomeSeen, bq as enablePreciseFontMode, br as createOasisEditorClient, bs as setLocale, bt as startLongTaskObserver, bu as installGlobalReport, bv as applyStoredPreciseFontPreference, bw as getWelcomeSeen, bx as isLocalFontAccessSupported, by as EDITOR_SCROLL_PADDING_PX, bz as Toolbar, bA as OasisEditorLoading, bB as createEditorLogger, bC as getCachedCanvasImage, bD as registerDomStatsSurface } from "./index--RsWcVrx.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-BUOuw27s.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) {
@@ -1240,6 +1441,43 @@ function resizeSelectedTextBox(state, width, height, options = {}) {
1240
1441
  )
1241
1442
  );
1242
1443
  }
1444
+ const SHAPE_DEFAULT_WIDTH = 150;
1445
+ const SHAPE_DEFAULT_HEIGHT = 100;
1446
+ const SHAPE_DEFAULT_FILL = "#4472C4";
1447
+ const SHAPE_DEFAULT_BORDER_COLOR = "#2F528F";
1448
+ const SHAPE_DEFAULT_BORDER_WIDTH_PT = 1;
1449
+ function insertShapeAtSelection(state, preset) {
1450
+ const collapsedState = isSelectionCollapsed(state.selection) ? state : deleteSelectionRange(state);
1451
+ const { paragraph, index, offset } = getFocusParagraph(collapsedState);
1452
+ const textBox = {
1453
+ width: SHAPE_DEFAULT_WIDTH,
1454
+ height: SHAPE_DEFAULT_HEIGHT,
1455
+ blocks: [createEditorParagraph("")],
1456
+ shape: {
1457
+ preset,
1458
+ fill: SHAPE_DEFAULT_FILL,
1459
+ borderColor: SHAPE_DEFAULT_BORDER_COLOR,
1460
+ borderWidthPt: SHAPE_DEFAULT_BORDER_WIDTH_PT
1461
+ },
1462
+ floating: wrapPresetToFloating(void 0, "front")
1463
+ };
1464
+ const insertedRun = createEditorStyledRun(
1465
+ "",
1466
+ getStyleAtOffset(paragraph, offset),
1467
+ void 0,
1468
+ textBox
1469
+ );
1470
+ const nextParagraph = insertRunsAtOffset(paragraph, offset, [insertedRun]);
1471
+ const paragraphs = getParagraphs(collapsedState);
1472
+ const nextParagraphs = paragraphs.map(
1473
+ (candidate, candidateIndex) => candidateIndex === index ? nextParagraph : cloneParagraph(candidate)
1474
+ );
1475
+ return cloneStateWithParagraphs(
1476
+ collapsedState,
1477
+ nextParagraphs,
1478
+ withSelection(paragraphOffsetToPosition(nextParagraph, offset + 1))
1479
+ );
1480
+ }
1243
1481
  function cloneFragmentRuns(runs) {
1244
1482
  return runs.map(cloneRun);
1245
1483
  }
@@ -4217,6 +4455,26 @@ function createEditorCommandsController(deps) {
4217
4455
  const currentAlt = ((_a = run.run.image) == null ? void 0 : _a.alt) ?? "";
4218
4456
  deps.openImageAltDialog(currentAlt);
4219
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
+ };
4220
4478
  return {
4221
4479
  applyBooleanStyleCommand,
4222
4480
  applyValueStyleCommand,
@@ -4243,6 +4501,8 @@ function createEditorCommandsController(deps) {
4243
4501
  removeLinkCommand,
4244
4502
  applyImageAltCommand,
4245
4503
  promptForImageAlt,
4504
+ applyImageCaptionCommand,
4505
+ promptForImageCaption,
4246
4506
  handleListTab,
4247
4507
  handleListEnter,
4248
4508
  handleListBoundaryBackspace
@@ -8021,10 +8281,13 @@ function serializeParagraphStyleXml(style2) {
8021
8281
  return parts.length > 0 ? `<w:pPr>${parts.join("")}</w:pPr>` : "";
8022
8282
  }
8023
8283
  function serializeParagraphProperties(paragraph, numberingInfo, styles, overrides) {
8024
- var _a;
8284
+ var _a, _b;
8025
8285
  const parts = [];
8026
8286
  const style2 = materializeParagraphStyle(paragraph, styles);
8027
8287
  const align = ((_a = paragraph.style) == null ? void 0 : _a.align) ?? (overrides == null ? void 0 : overrides.align) ?? style2.align;
8288
+ if ((_b = paragraph.style) == null ? void 0 : _b.styleId) {
8289
+ parts.push(`<w:pStyle w:val="${escapeXml(paragraph.style.styleId)}"/>`);
8290
+ }
8028
8291
  if (align) {
8029
8292
  parts.push(`<w:jc w:val="${align}"/>`);
8030
8293
  }
@@ -9273,14 +9536,24 @@ function buildPartContext(blocks, numberingContext, state, document2) {
9273
9536
  };
9274
9537
  }
9275
9538
  function buildNumberingXml(definitions) {
9276
- const abstractNums = definitions.map(({ kind, level, abstractNumId, format, startAt, bulletGlyph, bulletFont }) => {
9277
- const numFmtVal = kind === "bullet" ? "bullet" : format ?? "decimal";
9278
- const levelText = kind === "bullet" ? bulletGlyph ?? "" : `%${level + 1}.`;
9279
- const startVal = startAt ?? 1;
9280
- const fontName = kind === "bullet" ? bulletFont ?? "Symbol" : void 0;
9281
- const runFonts = fontName ? `<w:rPr><w:rFonts w:ascii="${escapeXml(fontName)}" w:hAnsi="${escapeXml(fontName)}" w:hint="default"/></w:rPr>` : "";
9282
- 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>`;
9283
- }).join("");
9539
+ const abstractNums = definitions.map(
9540
+ ({
9541
+ kind,
9542
+ level,
9543
+ abstractNumId,
9544
+ format,
9545
+ startAt,
9546
+ bulletGlyph,
9547
+ bulletFont
9548
+ }) => {
9549
+ const numFmtVal = kind === "bullet" ? "bullet" : format ?? "decimal";
9550
+ const levelText = kind === "bullet" ? bulletGlyph ?? "" : `%${level + 1}.`;
9551
+ const startVal = startAt ?? 1;
9552
+ const fontName = kind === "bullet" ? bulletFont ?? "Symbol" : void 0;
9553
+ const runFonts = fontName ? `<w:rPr><w:rFonts w:ascii="${escapeXml(fontName)}" w:hAnsi="${escapeXml(fontName)}" w:hint="default"/></w:rPr>` : "";
9554
+ 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>`;
9555
+ }
9556
+ ).join("");
9284
9557
  const nums = definitions.map(
9285
9558
  ({ abstractNumId, numId }) => `<w:num w:numId="${numId}"><w:abstractNumId w:val="${abstractNumId}"/></w:num>`
9286
9559
  ).join("");
@@ -9405,6 +9678,7 @@ function buildPartRelationshipsXml(images, hyperlinks) {
9405
9678
  }
9406
9679
  async function exportEditorDocumentToDocx(document2) {
9407
9680
  var _a, _b, _c, _d, _e, _f;
9681
+ document2 = renumberImageCaptionsInDocument(document2);
9408
9682
  const zip = new JSZip();
9409
9683
  const numberingContext = buildNumberingContext(document2);
9410
9684
  const buildState = {
@@ -9634,6 +9908,268 @@ function borderDashArray(type) {
9634
9908
  return void 0;
9635
9909
  }
9636
9910
  }
9911
+ function drawCellEdge(writer, pageIndex, border, x1, y1, x2, y2) {
9912
+ if (border.type === "none" || border.width <= 0) {
9913
+ return;
9914
+ }
9915
+ writer.drawLine(pageIndex, {
9916
+ x1: pxToPt$1(x1),
9917
+ y1: pxToPt$1(y1),
9918
+ x2: pxToPt$1(x2),
9919
+ y2: pxToPt$1(y2),
9920
+ stroke: border.color,
9921
+ lineWidth: pxToPt$1(border.width),
9922
+ dashArray: borderDashArray(border.type)
9923
+ });
9924
+ }
9925
+ function drawCellBorders(writer, pageIndex, cell, originX, originY) {
9926
+ const left = originX + cell.left;
9927
+ const top = originY + cell.top;
9928
+ const right = left + cell.width;
9929
+ const bottom = top + cell.height;
9930
+ drawCellEdge(writer, pageIndex, cell.borders.top, left, top, right, top);
9931
+ drawCellEdge(
9932
+ writer,
9933
+ pageIndex,
9934
+ cell.borders.right,
9935
+ right,
9936
+ top,
9937
+ right,
9938
+ bottom
9939
+ );
9940
+ drawCellEdge(
9941
+ writer,
9942
+ pageIndex,
9943
+ cell.borders.bottom,
9944
+ left,
9945
+ bottom,
9946
+ right,
9947
+ bottom
9948
+ );
9949
+ drawCellEdge(writer, pageIndex, cell.borders.left, left, top, left, bottom);
9950
+ }
9951
+ async function drawTableBlock(writer, pageIndex, block, document2, originX, originY, contentWidth, fontRegistry, listOrdinals) {
9952
+ if (block.sourceBlock.type !== "table") {
9953
+ return;
9954
+ }
9955
+ const sourceTable = block.sourceBlock;
9956
+ const segmentTable = block.tableSegment ? buildSegmentTable(sourceTable, block.tableSegment) : sourceTable;
9957
+ if (segmentTable.rows.length === 0) {
9958
+ return;
9959
+ }
9960
+ const stateStub = { document: document2 };
9961
+ const tableLayout = buildCanvasTableLayout({
9962
+ table: segmentTable,
9963
+ state: stateStub,
9964
+ pageIndex: 0,
9965
+ originX: 0,
9966
+ originY: 0,
9967
+ contentWidth,
9968
+ estimatedHeight: block.estimatedHeight
9969
+ });
9970
+ for (const cell of tableLayout.cells) {
9971
+ if (!cell.shading) continue;
9972
+ writer.drawRect(pageIndex, {
9973
+ x: pxToPt$1(originX + cell.left),
9974
+ y: pxToPt$1(originY + cell.top),
9975
+ width: pxToPt$1(cell.width),
9976
+ height: pxToPt$1(cell.height),
9977
+ fill: cell.shading
9978
+ });
9979
+ }
9980
+ for (const cell of tableLayout.cells) {
9981
+ drawCellBorders(writer, pageIndex, cell, originX, originY);
9982
+ }
9983
+ for (const cell of tableLayout.cells) {
9984
+ for (const paragraphLayout of cell.paragraphs) {
9985
+ await drawParagraph(
9986
+ writer,
9987
+ pageIndex,
9988
+ paragraphLayout.paragraph,
9989
+ paragraphLayout.lines,
9990
+ document2,
9991
+ originX + paragraphLayout.originX,
9992
+ originY + paragraphLayout.originY,
9993
+ fontRegistry,
9994
+ listOrdinals
9995
+ );
9996
+ }
9997
+ }
9998
+ }
9999
+ function getPadding(textBox) {
10000
+ var _a, _b, _c, _d;
10001
+ return {
10002
+ left: ((_a = textBox.body) == null ? void 0 : _a.paddingLeft) ?? 0,
10003
+ top: ((_b = textBox.body) == null ? void 0 : _b.paddingTop) ?? 0,
10004
+ right: ((_c = textBox.body) == null ? void 0 : _c.paddingRight) ?? 0,
10005
+ bottom: ((_d = textBox.body) == null ? void 0 : _d.paddingBottom) ?? 0
10006
+ };
10007
+ }
10008
+ function drawShapeGeometry(writer, pageIndex, textBox, xPx, yPx, widthPx, heightPx) {
10009
+ var _a, _b, _c, _d;
10010
+ const segments = getPresetPathSegments(
10011
+ (_a = textBox.shape) == null ? void 0 : _a.preset,
10012
+ pxToPt$1(xPx),
10013
+ pxToPt$1(yPx),
10014
+ pxToPt$1(widthPx),
10015
+ pxToPt$1(heightPx)
10016
+ );
10017
+ const fill = (_b = textBox.shape) == null ? void 0 : _b.fill;
10018
+ const borderColor = (_c = textBox.shape) == null ? void 0 : _c.borderColor;
10019
+ const borderWidthPt = ((_d = textBox.shape) == null ? void 0 : _d.borderWidthPt) ?? (borderColor ? 0.75 : 0);
10020
+ writer.drawPath(pageIndex, {
10021
+ segments,
10022
+ fill,
10023
+ stroke: borderColor && borderWidthPt > 0 ? borderColor : void 0,
10024
+ lineWidth: borderWidthPt
10025
+ });
10026
+ }
10027
+ async function drawTextBoxContent(writer, textBox, ctx, xPx, yPx, widthPx, heightPx) {
10028
+ var _a;
10029
+ if (textBox.blocks.length === 0) {
10030
+ return;
10031
+ }
10032
+ const padding = getPadding(textBox);
10033
+ const innerX = xPx + padding.left;
10034
+ const innerY = yPx + padding.top;
10035
+ const innerWidth = Math.max(1, widthPx - padding.left - padding.right);
10036
+ const innerHeight = Math.max(1, heightPx - padding.top - padding.bottom);
10037
+ const pages = projectBlocksLayout({
10038
+ blocks: textBox.blocks,
10039
+ pageSettings: {
10040
+ width: innerWidth,
10041
+ height: innerHeight,
10042
+ orientation: "portrait",
10043
+ margins: {
10044
+ top: 0,
10045
+ right: 0,
10046
+ bottom: 0,
10047
+ left: 0,
10048
+ header: 0,
10049
+ footer: 0,
10050
+ gutter: 0
10051
+ }
10052
+ },
10053
+ maxPageHeight: innerHeight,
10054
+ styles: ctx.document.styles,
10055
+ pageOffset: ctx.pageIndex
10056
+ });
10057
+ const blocks = ((_a = pages[0]) == null ? void 0 : _a.blocks) ?? [];
10058
+ if (blocks.length === 0) {
10059
+ return;
10060
+ }
10061
+ const listOrdinals = /* @__PURE__ */ new Map();
10062
+ writer.saveGraphicsState(ctx.pageIndex);
10063
+ writer.clipRect(
10064
+ ctx.pageIndex,
10065
+ pxToPt$1(innerX),
10066
+ pxToPt$1(innerY),
10067
+ pxToPt$1(innerWidth),
10068
+ pxToPt$1(innerHeight)
10069
+ );
10070
+ let cursorY = innerY;
10071
+ for (const block of blocks) {
10072
+ if (block.sourceBlock.type === "paragraph" && block.layout) {
10073
+ await drawParagraph(
10074
+ writer,
10075
+ ctx.pageIndex,
10076
+ block.sourceBlock,
10077
+ block.layout.lines,
10078
+ ctx.document,
10079
+ innerX,
10080
+ cursorY,
10081
+ ctx.fontRegistry,
10082
+ listOrdinals
10083
+ );
10084
+ } else if (block.sourceBlock.type === "table") {
10085
+ await drawTableBlock(
10086
+ writer,
10087
+ ctx.pageIndex,
10088
+ block,
10089
+ ctx.document,
10090
+ innerX,
10091
+ cursorY,
10092
+ innerWidth,
10093
+ ctx.fontRegistry,
10094
+ listOrdinals
10095
+ );
10096
+ }
10097
+ cursorY += Math.max(0, block.estimatedHeight);
10098
+ }
10099
+ writer.restoreGraphicsState(ctx.pageIndex);
10100
+ }
10101
+ async function paintTextBox(writer, textBox, ctx, xPx, yPx, widthPx, heightPx) {
10102
+ const rotation = textBox.rotation;
10103
+ if (rotation) {
10104
+ writer.saveGraphicsState(ctx.pageIndex);
10105
+ writer.rotateAbout(
10106
+ ctx.pageIndex,
10107
+ pxToPt$1(xPx + widthPx / 2),
10108
+ pxToPt$1(yPx + heightPx / 2),
10109
+ rotation
10110
+ );
10111
+ }
10112
+ drawShapeGeometry(
10113
+ writer,
10114
+ ctx.pageIndex,
10115
+ textBox,
10116
+ xPx,
10117
+ yPx,
10118
+ widthPx,
10119
+ heightPx
10120
+ );
10121
+ await drawTextBoxContent(writer, textBox, ctx, xPx, yPx, widthPx, heightPx);
10122
+ if (rotation) {
10123
+ writer.restoreGraphicsState(ctx.pageIndex);
10124
+ }
10125
+ }
10126
+ async function drawFloatingTextBoxesForParagraph(options) {
10127
+ const {
10128
+ writer,
10129
+ document: document2,
10130
+ fontRegistry,
10131
+ pageIndex,
10132
+ lines,
10133
+ pageSettings,
10134
+ contentLeft,
10135
+ contentTop,
10136
+ contentWidth,
10137
+ paragraphTop
10138
+ } = options;
10139
+ for (const line of lines) {
10140
+ const slotByOffset = new Map(
10141
+ line.slots.map((slot) => [slot.offset, slot])
10142
+ );
10143
+ for (const fragment of line.fragments) {
10144
+ const textBox = fragment.textBox;
10145
+ if (!(textBox == null ? void 0 : textBox.floating)) {
10146
+ continue;
10147
+ }
10148
+ const slot = slotByOffset.get(fragment.startOffset);
10149
+ const anchorLeft = contentLeft + ((slot == null ? void 0 : slot.left) ?? 0);
10150
+ const lineTop = paragraphTop + line.top;
10151
+ const rect = resolveFloatingObjectRect({
10152
+ object: getTextBoxFloatingGeometry(textBox),
10153
+ pageSettings,
10154
+ contentLeft,
10155
+ contentTop,
10156
+ contentWidth,
10157
+ paragraphTop,
10158
+ lineTop,
10159
+ anchorLeft
10160
+ });
10161
+ await paintTextBox(
10162
+ writer,
10163
+ textBox,
10164
+ { document: document2, fontRegistry, pageIndex },
10165
+ rect.x,
10166
+ rect.y,
10167
+ rect.width,
10168
+ rect.height
10169
+ );
10170
+ }
10171
+ }
10172
+ }
9637
10173
  const imageResourceCache = /* @__PURE__ */ new WeakMap();
9638
10174
  function parseDataUrl(src) {
9639
10175
  const match = /^data:([^;,]+)(;base64)?,(.*)$/i.exec(src);
@@ -10013,6 +10549,25 @@ function drawTabLeaders(writer, pageIndex, paragraph, line, fragment, document2,
10013
10549
  });
10014
10550
  }
10015
10551
  }
10552
+ async function drawInlineTextBoxFragment(writer, pageIndex, line, fragment, document2, originX, originY, fontRegistry) {
10553
+ const textBox = fragment.textBox;
10554
+ if (!textBox || textBox.floating) {
10555
+ return;
10556
+ }
10557
+ const slot = line.slots.find((candidate) => candidate.offset === fragment.startOffset) ?? line.slots.find((candidate) => candidate.offset >= fragment.startOffset);
10558
+ if (!slot) {
10559
+ return;
10560
+ }
10561
+ await paintTextBox(
10562
+ writer,
10563
+ textBox,
10564
+ { document: document2, fontRegistry, pageIndex },
10565
+ originX + slot.left,
10566
+ originY + line.top + line.height - textBox.height,
10567
+ textBox.width,
10568
+ textBox.height
10569
+ );
10570
+ }
10016
10571
  async function drawFragmentText(writer, pageIndex, paragraph, line, fragment, document2, originX, originY, fontRegistry) {
10017
10572
  var _a;
10018
10573
  if (fragment.image) {
@@ -10040,6 +10595,19 @@ async function drawFragmentText(writer, pageIndex, paragraph, line, fragment, do
10040
10595
  });
10041
10596
  return;
10042
10597
  }
10598
+ if (fragment.textBox) {
10599
+ await drawInlineTextBoxFragment(
10600
+ writer,
10601
+ pageIndex,
10602
+ line,
10603
+ fragment,
10604
+ document2,
10605
+ originX,
10606
+ originY,
10607
+ fontRegistry
10608
+ );
10609
+ return;
10610
+ }
10043
10611
  const styles = resolveEffectiveTextStyleForParagraph(
10044
10612
  fragment.styles,
10045
10613
  (_a = paragraph.style) == null ? void 0 : _a.styleId,
@@ -10385,98 +10953,11 @@ async function drawParagraph(writer, pageIndex, paragraph, lines, document2, ori
10385
10953
  }
10386
10954
  }
10387
10955
  }
10388
- function drawCellEdge(writer, pageIndex, border, x1, y1, x2, y2) {
10389
- if (border.type === "none" || border.width <= 0) {
10390
- return;
10391
- }
10392
- writer.drawLine(pageIndex, {
10393
- x1: pxToPt$1(x1),
10394
- y1: pxToPt$1(y1),
10395
- x2: pxToPt$1(x2),
10396
- y2: pxToPt$1(y2),
10397
- stroke: border.color,
10398
- lineWidth: pxToPt$1(border.width),
10399
- dashArray: borderDashArray(border.type)
10400
- });
10401
- }
10402
- function drawCellBorders(writer, pageIndex, cell, originX, originY) {
10403
- const left = originX + cell.left;
10404
- const top = originY + cell.top;
10405
- const right = left + cell.width;
10406
- const bottom = top + cell.height;
10407
- drawCellEdge(writer, pageIndex, cell.borders.top, left, top, right, top);
10408
- drawCellEdge(
10409
- writer,
10410
- pageIndex,
10411
- cell.borders.right,
10412
- right,
10413
- top,
10414
- right,
10415
- bottom
10416
- );
10417
- drawCellEdge(
10418
- writer,
10419
- pageIndex,
10420
- cell.borders.bottom,
10421
- left,
10422
- bottom,
10423
- right,
10424
- bottom
10425
- );
10426
- drawCellEdge(writer, pageIndex, cell.borders.left, left, top, left, bottom);
10427
- }
10428
- async function drawTableBlock(writer, pageIndex, block, document2, originX, originY, contentWidth, fontRegistry, listOrdinals) {
10429
- if (block.sourceBlock.type !== "table") {
10430
- return;
10431
- }
10432
- const sourceTable = block.sourceBlock;
10433
- const segmentTable = block.tableSegment ? buildSegmentTable(sourceTable, block.tableSegment) : sourceTable;
10434
- if (segmentTable.rows.length === 0) {
10435
- return;
10436
- }
10437
- const stateStub = { document: document2 };
10438
- const tableLayout = buildCanvasTableLayout({
10439
- table: segmentTable,
10440
- state: stateStub,
10441
- pageIndex: 0,
10442
- originX: 0,
10443
- originY: 0,
10444
- contentWidth,
10445
- estimatedHeight: block.estimatedHeight
10446
- });
10447
- for (const cell of tableLayout.cells) {
10448
- if (!cell.shading) continue;
10449
- writer.drawRect(pageIndex, {
10450
- x: pxToPt$1(originX + cell.left),
10451
- y: pxToPt$1(originY + cell.top),
10452
- width: pxToPt$1(cell.width),
10453
- height: pxToPt$1(cell.height),
10454
- fill: cell.shading
10455
- });
10456
- }
10457
- for (const cell of tableLayout.cells) {
10458
- drawCellBorders(writer, pageIndex, cell, originX, originY);
10459
- }
10460
- for (const cell of tableLayout.cells) {
10461
- for (const paragraphLayout of cell.paragraphs) {
10462
- await drawParagraph(
10463
- writer,
10464
- pageIndex,
10465
- paragraphLayout.paragraph,
10466
- paragraphLayout.lines,
10467
- document2,
10468
- originX + paragraphLayout.originX,
10469
- originY + paragraphLayout.originY,
10470
- fontRegistry,
10471
- listOrdinals
10472
- );
10473
- }
10474
- }
10475
- }
10476
- async function drawBlockList(writer, pageIndex, blocks, document2, originX, originY, contentWidth, fontRegistry, listOrdinals) {
10956
+ async function drawBlockList(writer, pageIndex, blocks, document2, originX, originY, contentWidth, fontRegistry, listOrdinals, pageSettings) {
10477
10957
  if (!blocks || blocks.length === 0) {
10478
10958
  return;
10479
10959
  }
10960
+ const contentTop = originY;
10480
10961
  let cursorY = originY;
10481
10962
  for (const block of blocks) {
10482
10963
  if (block.sourceBlock.type === "paragraph" && block.layout) {
@@ -10507,6 +10988,20 @@ async function drawBlockList(writer, pageIndex, blocks, document2, originX, orig
10507
10988
  fontRegistry,
10508
10989
  listOrdinals
10509
10990
  );
10991
+ if (pageSettings) {
10992
+ await drawFloatingTextBoxesForParagraph({
10993
+ writer,
10994
+ document: document2,
10995
+ fontRegistry,
10996
+ pageIndex,
10997
+ lines: block.layout.lines,
10998
+ pageSettings,
10999
+ contentLeft: originX,
11000
+ contentTop,
11001
+ contentWidth,
11002
+ paragraphTop: boxTop
11003
+ });
11004
+ }
10510
11005
  } else if (block.sourceBlock.type === "table") {
10511
11006
  await drawTableBlock(
10512
11007
  writer,
@@ -11207,6 +11702,103 @@ class OasisPdfWriter {
11207
11702
  );
11208
11703
  page.commands.push(commands.join("\n"));
11209
11704
  }
11705
+ // Fills/strokes an arbitrary path. Segment coordinates are in points with a
11706
+ // top-left origin (callers convert px→pt, like drawRect/drawLine); the y axis
11707
+ // is flipped here to the PDF bottom-left origin.
11708
+ drawPath(pageIndex, options) {
11709
+ const page = this.pages[pageIndex];
11710
+ if (!page || options.segments.length === 0) {
11711
+ return;
11712
+ }
11713
+ if (!options.fill && !options.stroke) {
11714
+ return;
11715
+ }
11716
+ const flip = (yy) => page.height - yy;
11717
+ const commands = ["q"];
11718
+ if (options.fill) {
11719
+ commands.push(colorCommand(options.fill, "rg", [1, 1, 1]));
11720
+ }
11721
+ if (options.stroke) {
11722
+ commands.push(colorCommand(options.stroke, "RG", [0, 0, 0]));
11723
+ commands.push(`${formatNumber(options.lineWidth ?? 1)} w`);
11724
+ }
11725
+ for (const segment of options.segments) {
11726
+ switch (segment.type) {
11727
+ case "move":
11728
+ commands.push(
11729
+ `${formatNumber(segment.x)} ${formatNumber(flip(segment.y))} m`
11730
+ );
11731
+ break;
11732
+ case "line":
11733
+ commands.push(
11734
+ `${formatNumber(segment.x)} ${formatNumber(flip(segment.y))} l`
11735
+ );
11736
+ break;
11737
+ case "cubic":
11738
+ commands.push(
11739
+ `${formatNumber(segment.x1)} ${formatNumber(flip(segment.y1))} ${formatNumber(segment.x2)} ${formatNumber(flip(segment.y2))} ${formatNumber(segment.x)} ${formatNumber(flip(segment.y))} c`
11740
+ );
11741
+ break;
11742
+ case "close":
11743
+ commands.push("h");
11744
+ break;
11745
+ }
11746
+ }
11747
+ if (options.fill && options.stroke) {
11748
+ commands.push("B");
11749
+ } else if (options.fill) {
11750
+ commands.push("f");
11751
+ } else {
11752
+ commands.push("S");
11753
+ }
11754
+ commands.push("Q");
11755
+ page.commands.push(commands.join("\n"));
11756
+ }
11757
+ // Saves the graphics state (`q`). Pair with restoreGraphicsState. Any draw
11758
+ // commands emitted in between inherit the current transform/clip.
11759
+ saveGraphicsState(pageIndex) {
11760
+ const page = this.pages[pageIndex];
11761
+ if (page) {
11762
+ page.commands.push("q");
11763
+ }
11764
+ }
11765
+ restoreGraphicsState(pageIndex) {
11766
+ const page = this.pages[pageIndex];
11767
+ if (page) {
11768
+ page.commands.push("Q");
11769
+ }
11770
+ }
11771
+ // Concatenates a clockwise rotation (in degrees, matching the canvas/editor
11772
+ // convention) about a top-left-origin point onto the current CTM. Must sit
11773
+ // inside a saveGraphicsState/restoreGraphicsState pair.
11774
+ rotateAbout(pageIndex, centerX, centerY, degrees) {
11775
+ const page = this.pages[pageIndex];
11776
+ if (!page || !degrees) {
11777
+ return;
11778
+ }
11779
+ const cyf = page.height - centerY;
11780
+ const radians = -degrees * Math.PI / 180;
11781
+ const cos = Math.cos(radians);
11782
+ const sin = Math.sin(radians);
11783
+ const e = centerX - centerX * cos + cyf * sin;
11784
+ const f = cyf - centerX * sin - cyf * cos;
11785
+ page.commands.push(
11786
+ `${formatNumber(cos)} ${formatNumber(sin)} ${formatNumber(-sin)} ${formatNumber(cos)} ${formatNumber(e)} ${formatNumber(f)} cm`
11787
+ );
11788
+ }
11789
+ // Intersects the clip path with a rectangle (top-left origin). Must sit inside
11790
+ // a saveGraphicsState/restoreGraphicsState pair so the clip can be undone.
11791
+ clipRect(pageIndex, x, y, width, height) {
11792
+ const page = this.pages[pageIndex];
11793
+ if (!page || width <= 0 || height <= 0) {
11794
+ return;
11795
+ }
11796
+ page.commands.push(
11797
+ `${formatNumber(x)} ${formatNumber(page.height - y - height)} ${formatNumber(width)} ${formatNumber(height)} re`,
11798
+ "W",
11799
+ "n"
11800
+ );
11801
+ }
11210
11802
  drawText(pageIndex, options) {
11211
11803
  const page = this.pages[pageIndex];
11212
11804
  if (!page || options.text.length === 0) {
@@ -11536,6 +12128,7 @@ endobj
11536
12128
  }
11537
12129
  const FOOTNOTE_BLOCK_GAP_PX = 2;
11538
12130
  async function exportEditorDocumentToPdf(document2) {
12131
+ document2 = renumberImageCaptionsInDocument(document2);
11539
12132
  const fontRegistry = new PdfFontRegistry();
11540
12133
  await fontRegistry.loadBundledUnicodeFaces({
11541
12134
  families: collectPdfFontFamilies(document2)
@@ -11559,7 +12152,8 @@ async function exportEditorDocumentToPdf(document2) {
11559
12152
  page.headerTop ?? getPageHeaderZoneTop(page.pageSettings),
11560
12153
  contentWidth,
11561
12154
  fontRegistry,
11562
- listOrdinals
12155
+ listOrdinals,
12156
+ page.pageSettings
11563
12157
  );
11564
12158
  await drawBlockList(
11565
12159
  writer,
@@ -11570,7 +12164,8 @@ async function exportEditorDocumentToPdf(document2) {
11570
12164
  page.bodyTop ?? getPageBodyTop(page.pageSettings),
11571
12165
  contentWidth,
11572
12166
  fontRegistry,
11573
- listOrdinals
12167
+ listOrdinals,
12168
+ page.pageSettings
11574
12169
  );
11575
12170
  await drawBlockList(
11576
12171
  writer,
@@ -11581,7 +12176,8 @@ async function exportEditorDocumentToPdf(document2) {
11581
12176
  page.footerTop ?? page.bodyBottom ?? page.pageSettings.height,
11582
12177
  contentWidth,
11583
12178
  fontRegistry,
11584
- listOrdinals
12179
+ listOrdinals,
12180
+ page.pageSettings
11585
12181
  );
11586
12182
  if (page.footnoteBlocks && page.footnoteBlocks.length > 0 && page.footnoteTop !== void 0) {
11587
12183
  if (page.footnoteSeparatorTop !== void 0) {
@@ -38635,6 +39231,10 @@ function createEditorDialogs() {
38635
39231
  isOpen: false,
38636
39232
  initialAlt: ""
38637
39233
  });
39234
+ const [imageCaptionDialog, setImageCaptionDialog] = createSignal({
39235
+ isOpen: false,
39236
+ initialCaption: ""
39237
+ });
38638
39238
  const [contextMenu, setContextMenu] = createSignal({ isOpen: false, x: 0, y: 0 });
38639
39239
  const [fontDialog, setFontDialog] = createSignal({
38640
39240
  isOpen: false,
@@ -38732,6 +39332,8 @@ function createEditorDialogs() {
38732
39332
  setLinkDialog,
38733
39333
  imageAltDialog,
38734
39334
  setImageAltDialog,
39335
+ imageCaptionDialog,
39336
+ setImageCaptionDialog,
38735
39337
  contextMenu,
38736
39338
  setContextMenu,
38737
39339
  fontDialog,
@@ -40257,6 +40859,10 @@ function buildDocumentAndBrowserCommands({
40257
40859
  () => document2.importDocument()
40258
40860
  ),
40259
40861
  insertImage: actionCommand("insertImage", () => document2.insertImage()),
40862
+ insertShape: actionCommand(
40863
+ "insertShape",
40864
+ (p) => document2.insertShape(String(p))
40865
+ ),
40260
40866
  unlink: actionCommand(
40261
40867
  "unlink",
40262
40868
  () => link.remove(),
@@ -40272,6 +40878,14 @@ function buildDocumentAndBrowserCommands({
40272
40878
  isEnabled: image.isSelected(),
40273
40879
  isActive: image.isSelected()
40274
40880
  })
40881
+ ),
40882
+ insertImageCaption: actionCommand(
40883
+ "insertImageCaption",
40884
+ () => image.promptCaption(),
40885
+ () => ({
40886
+ isEnabled: image.isSelected(),
40887
+ isActive: image.isSelected()
40888
+ })
40275
40889
  )
40276
40890
  };
40277
40891
  }
@@ -40663,7 +41277,10 @@ function createEditorEssentialsRuntimePlugin(options) {
40663
41277
  insertImage: () => {
40664
41278
  var _a;
40665
41279
  return (_a = options.imageInputRef()) == null ? void 0 : _a.click();
40666
- }
41280
+ },
41281
+ insertShape: (preset) => options.applyTransactionalState(
41282
+ (current) => insertShapeAtSelection(current, preset)
41283
+ )
40667
41284
  };
40668
41285
  const essentialsLink = {
40669
41286
  prompt: () => options.commandsController.promptForLink(),
@@ -40672,6 +41289,7 @@ function createEditorEssentialsRuntimePlugin(options) {
40672
41289
  };
40673
41290
  const essentialsImage = {
40674
41291
  promptAlt: () => options.commandsController.promptForImageAlt(),
41292
+ promptCaption: () => options.commandsController.promptForImageCaption(),
40675
41293
  isSelected: () => Boolean(options.selectedImageRun())
40676
41294
  };
40677
41295
  const essentialsBrowser = {
@@ -41214,14 +41832,14 @@ function DropCaret(props) {
41214
41832
  })
41215
41833
  });
41216
41834
  }
41217
- 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>`);
41835
+ 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>`);
41218
41836
  function EditorDragLayers(props) {
41219
41837
  return [createComponent(Show, {
41220
41838
  get when() {
41221
41839
  return props.tableResize.resizing();
41222
41840
  },
41223
41841
  children: (resizing) => (() => {
41224
- var _el$ = _tmpl$$d();
41842
+ var _el$ = _tmpl$$e();
41225
41843
  createRenderEffect((_p$) => {
41226
41844
  var _v$ = !!(resizing().type === "column"), _v$2 = !!(resizing().type === "row"), _v$3 = {
41227
41845
  ...resizing().type === "column" ? {
@@ -41252,7 +41870,7 @@ function EditorDragLayers(props) {
41252
41870
  return memo(() => !!props.imageOps.dragging())() && props.imageOps.draggedImageInfo();
41253
41871
  },
41254
41872
  children: (info) => (() => {
41255
- var _el$2 = _tmpl$2$8();
41873
+ var _el$2 = _tmpl$2$9();
41256
41874
  createRenderEffect((_p$) => {
41257
41875
  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`;
41258
41876
  _v$4 !== _p$.e && setAttribute(_el$2, "src", _p$.e = _v$4);
@@ -41275,7 +41893,7 @@ function EditorDragLayers(props) {
41275
41893
  return memo(() => !!props.tableDrag.dragging())() && props.tableDrag.draggedTableInfo();
41276
41894
  },
41277
41895
  children: (info) => (() => {
41278
- var _el$3 = _tmpl$3$6();
41896
+ var _el$3 = _tmpl$3$7();
41279
41897
  createRenderEffect((_p$) => {
41280
41898
  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`;
41281
41899
  _v$9 !== _p$.e && setStyleProperty(_el$3, "width", _p$.e = _v$9);
@@ -41338,7 +41956,7 @@ function EditorDragLayers(props) {
41338
41956
  })
41339
41957
  })];
41340
41958
  }
41341
- 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>`);
41959
+ 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>`);
41342
41960
  function LinkDialog(props) {
41343
41961
  const [href, setHref] = createSignal(props.initialHref);
41344
41962
  let inputRef;
@@ -41364,19 +41982,19 @@ function LinkDialog(props) {
41364
41982
  },
41365
41983
  get footer() {
41366
41984
  return [(() => {
41367
- var _el$4 = _tmpl$2$7();
41985
+ var _el$4 = _tmpl$2$8();
41368
41986
  addEventListener(_el$4, "click", props.onClose, true);
41369
41987
  insert(_el$4, () => t("generic.cancel"));
41370
41988
  return _el$4;
41371
41989
  })(), (() => {
41372
- var _el$5 = _tmpl$3$5();
41990
+ var _el$5 = _tmpl$3$6();
41373
41991
  _el$5.$$click = handleConfirm;
41374
41992
  insert(_el$5, () => t("generic.apply"));
41375
41993
  return _el$5;
41376
41994
  })()];
41377
41995
  },
41378
41996
  get children() {
41379
- var _el$ = _tmpl$$c(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
41997
+ var _el$ = _tmpl$$d(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
41380
41998
  insert(_el$2, () => t("dialog.link.label"));
41381
41999
  _el$3.$$keydown = (e) => e.key === "Enter" && handleConfirm();
41382
42000
  _el$3.$$input = (e) => setHref(e.currentTarget.value);
@@ -41389,7 +42007,7 @@ function LinkDialog(props) {
41389
42007
  });
41390
42008
  }
41391
42009
  delegateEvents(["input", "keydown", "click"]);
41392
- 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">`);
42010
+ 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">`);
41393
42011
  function ImageAltDialog(props) {
41394
42012
  const [alt, setAlt] = createSignal(props.initialAlt);
41395
42013
  let inputRef;
@@ -41415,19 +42033,19 @@ function ImageAltDialog(props) {
41415
42033
  },
41416
42034
  get footer() {
41417
42035
  return [(() => {
41418
- var _el$4 = _tmpl$2$6();
42036
+ var _el$4 = _tmpl$2$7();
41419
42037
  addEventListener(_el$4, "click", props.onClose, true);
41420
42038
  insert(_el$4, () => t("generic.cancel"));
41421
42039
  return _el$4;
41422
42040
  })(), (() => {
41423
- var _el$5 = _tmpl$3$4();
42041
+ var _el$5 = _tmpl$3$5();
41424
42042
  _el$5.$$click = handleConfirm;
41425
42043
  insert(_el$5, () => t("generic.save"));
41426
42044
  return _el$5;
41427
42045
  })()];
41428
42046
  },
41429
42047
  get children() {
41430
- var _el$ = _tmpl$$b(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
42048
+ var _el$ = _tmpl$$c(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
41431
42049
  insert(_el$2, () => t("dialog.imageAlt.label"));
41432
42050
  _el$3.$$keydown = (e) => e.key === "Enter" && handleConfirm();
41433
42051
  _el$3.$$input = (e) => setAlt(e.currentTarget.value);
@@ -41440,6 +42058,57 @@ function ImageAltDialog(props) {
41440
42058
  });
41441
42059
  }
41442
42060
  delegateEvents(["input", "keydown", "click"]);
42061
+ 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">`);
42062
+ function ImageCaptionDialog(props) {
42063
+ const [caption, setCaption] = createSignal(props.initialCaption);
42064
+ let inputRef;
42065
+ createEffect(() => {
42066
+ if (props.isOpen) {
42067
+ setCaption(props.initialCaption);
42068
+ setTimeout(() => inputRef == null ? void 0 : inputRef.focus(), 50);
42069
+ }
42070
+ });
42071
+ const handleConfirm = () => {
42072
+ props.onConfirm(caption());
42073
+ props.onClose();
42074
+ };
42075
+ return createComponent(Dialog, {
42076
+ get isOpen() {
42077
+ return props.isOpen;
42078
+ },
42079
+ get title() {
42080
+ return t("dialog.imageCaption.title");
42081
+ },
42082
+ get onClose() {
42083
+ return props.onClose;
42084
+ },
42085
+ get footer() {
42086
+ return [(() => {
42087
+ var _el$4 = _tmpl$2$6();
42088
+ addEventListener(_el$4, "click", props.onClose, true);
42089
+ insert(_el$4, () => t("generic.cancel"));
42090
+ return _el$4;
42091
+ })(), (() => {
42092
+ var _el$5 = _tmpl$3$4();
42093
+ _el$5.$$click = handleConfirm;
42094
+ insert(_el$5, () => t("generic.save"));
42095
+ return _el$5;
42096
+ })()];
42097
+ },
42098
+ get children() {
42099
+ var _el$ = _tmpl$$b(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
42100
+ insert(_el$2, () => t("dialog.imageCaption.label"));
42101
+ _el$3.$$keydown = (e) => e.key === "Enter" && handleConfirm();
42102
+ _el$3.$$input = (e) => setCaption(e.currentTarget.value);
42103
+ var _ref$ = inputRef;
42104
+ typeof _ref$ === "function" ? use(_ref$, _el$3) : inputRef = _el$3;
42105
+ createRenderEffect(() => setAttribute(_el$3, "placeholder", t("dialog.imageCaption.placeholder")));
42106
+ createRenderEffect(() => _el$3.value = caption());
42107
+ return _el$;
42108
+ }
42109
+ });
42110
+ }
42111
+ delegateEvents(["input", "keydown", "click"]);
41443
42112
  const DEFAULT_COLOR = "#111827";
41444
42113
  const DEFAULT_HIGHLIGHT = "#fef08a";
41445
42114
  const DEFAULT_SHADING = "#fef3c7";
@@ -42943,6 +43612,8 @@ function EditorDialogsLayer(props) {
42943
43612
  setLinkDialog,
42944
43613
  imageAltDialog,
42945
43614
  setImageAltDialog,
43615
+ imageCaptionDialog,
43616
+ setImageCaptionDialog,
42946
43617
  contextMenu,
42947
43618
  fontDialog,
42948
43619
  setFontDialog,
@@ -42981,6 +43652,21 @@ function EditorDialogsLayer(props) {
42981
43652
  props.focusInput();
42982
43653
  },
42983
43654
  onConfirm: (alt) => props.applyImageAltCommand(alt.trim())
43655
+ }), createComponent(ImageCaptionDialog, {
43656
+ get isOpen() {
43657
+ return imageCaptionDialog().isOpen;
43658
+ },
43659
+ get initialCaption() {
43660
+ return imageCaptionDialog().initialCaption;
43661
+ },
43662
+ onClose: () => {
43663
+ setImageCaptionDialog({
43664
+ ...imageCaptionDialog(),
43665
+ isOpen: false
43666
+ });
43667
+ props.focusInput();
43668
+ },
43669
+ onConfirm: (caption) => props.applyImageCaptionCommand(caption.trim())
42984
43670
  }), createComponent(FindReplaceDialog, {
42985
43671
  get fr() {
42986
43672
  return props.findReplace;
@@ -45417,6 +46103,8 @@ function OasisEditorApp(props = {}) {
45417
46103
  setLinkDialog,
45418
46104
  imageAltDialog,
45419
46105
  setImageAltDialog,
46106
+ imageCaptionDialog,
46107
+ setImageCaptionDialog,
45420
46108
  contextMenu,
45421
46109
  setContextMenu,
45422
46110
  fontDialog,
@@ -45716,7 +46404,12 @@ function OasisEditorApp(props = {}) {
45716
46404
  openImageAltDialog: (initialAlt) => setImageAltDialog({
45717
46405
  isOpen: true,
45718
46406
  initialAlt
45719
- })
46407
+ }),
46408
+ openImageCaptionDialog: (initialCaption) => setImageCaptionDialog({
46409
+ isOpen: true,
46410
+ initialCaption
46411
+ }),
46412
+ imageCaptionLabel: () => (ui().locale ?? "pt-BR").startsWith("en") ? "Figure" : "Figura"
45720
46413
  });
45721
46414
  const keyboardCommandsController = {
45722
46415
  ...commandsController,
@@ -46044,6 +46737,8 @@ function OasisEditorApp(props = {}) {
46044
46737
  setLinkDialog,
46045
46738
  imageAltDialog,
46046
46739
  setImageAltDialog,
46740
+ imageCaptionDialog,
46741
+ setImageCaptionDialog,
46047
46742
  contextMenu,
46048
46743
  setContextMenu,
46049
46744
  fontDialog,
@@ -46064,6 +46759,9 @@ function OasisEditorApp(props = {}) {
46064
46759
  get applyImageAltCommand() {
46065
46760
  return commandsController.applyImageAltCommand;
46066
46761
  },
46762
+ get applyImageCaptionCommand() {
46763
+ return commandsController.applyImageCaptionCommand;
46764
+ },
46067
46765
  applyFontDialogValues,
46068
46766
  applyParagraphDialogValues,
46069
46767
  applyTablePropertiesDialogValues,