@superdoc/mcp 1.7.0-next.16 → 1.7.0-next.17

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 (2) hide show
  1. package/dist/index.js +1466 -232
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -31600,7 +31600,7 @@ var init_host = __esm(() => {
31600
31600
  });
31601
31601
 
31602
31602
  // ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
31603
- var SDK_VERSION = "2.20.0-next.16";
31603
+ var SDK_VERSION = "2.20.0-next.17";
31604
31604
 
31605
31605
  // ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
31606
31606
  import { accessSync, chmodSync, constants, existsSync, statSync } from "node:fs";
@@ -195996,7 +195996,8 @@ function renderParagraphProperties2(styleId, numberingProperties, paragraphPrope
195996
195996
  if (indent)
195997
195997
  parts.push(indent);
195998
195998
  if (paragraphProperties?.alignment) {
195999
- parts.push(`<w:jc w:val="${escapeXmlAttribute(paragraphProperties.alignment)}"/>`);
195999
+ const alignment = paragraphProperties.alignment === "justify" ? "both" : paragraphProperties.alignment;
196000
+ parts.push(`<w:jc w:val="${escapeXmlAttribute(alignment)}"/>`);
196000
196001
  }
196001
196002
  const markRunProps = renderRunPropertiesXml(paragraphProperties?.markRunProps);
196002
196003
  if (markRunProps)
@@ -196206,18 +196207,135 @@ function renderTrackedPasteRuns(runs, stamp) {
196206
196207
  return out.join("");
196207
196208
  }
196208
196209
  function renderPasteTableBlock(spec) {
196209
- const columnCount = Math.max(1, ...spec.rows.map((row) => row.cells.reduce((sum, cell) => sum + Math.max(1, cell.gridSpan ?? 1), 0)));
196210
- const columnWidth = Math.max(1, Math.floor(PASTE_TABLE_GRID_TWIPS / columnCount));
196211
- const grid = `<w:tblGrid>${`<w:gridCol w:w="${columnWidth}"/>`.repeat(columnCount)}</w:tblGrid>`;
196210
+ const grid = renderPasteTableGrid(spec);
196212
196211
  const rows = renderPasteTableRows(spec);
196213
196212
  return `<w:tbl>${renderPasteTableProperties(spec)}${grid}${rows}</w:tbl>`;
196214
196213
  }
196215
196214
  function renderTrackedPasteTableBlock(spec, stamp) {
196216
- const columnCount = tableColumnCount(spec);
196217
- const columnWidth = Math.max(1, Math.floor(PASTE_TABLE_GRID_TWIPS / columnCount));
196218
- const grid = `<w:tblGrid>${`<w:gridCol w:w="${columnWidth}"/>`.repeat(columnCount)}</w:tblGrid>`;
196215
+ const grid = renderPasteTableGrid(spec);
196219
196216
  return `<w:tbl>${renderPasteTableProperties(spec)}${grid}${renderTrackedPasteTableRows(spec, stamp)}</w:tbl>`;
196220
196217
  }
196218
+ function renderPasteTableGrid(spec) {
196219
+ const columnCount = tableColumnCount(spec);
196220
+ const widths = pasteTableColumnWidthsTwips(columnCount, spec.columnWidthShares, pasteTableGridWidthTwips(spec));
196221
+ return `<w:tblGrid>${widths.map((width) => `<w:gridCol w:w="${width}"/>`).join("")}</w:tblGrid>`;
196222
+ }
196223
+ function pasteTableGridWidthTwips(spec) {
196224
+ const width = spec.gridWidthTwips;
196225
+ return typeof width === "number" && Number.isFinite(width) && width >= 1 ? Math.floor(width) : PASTE_TABLE_GRID_TWIPS;
196226
+ }
196227
+ function pasteDestinationContentWidthTwipsFromPartXml(partXml, insertionOffset) {
196228
+ return readPasteDestinationContentWidth(partXml, { insertionOffset });
196229
+ }
196230
+ function splitPasteParagraphSectionProperties(propertiesXml, namespaceBindings) {
196231
+ if (!propertiesXml)
196232
+ return { ordinaryPropertiesXml: "", hasSection: false };
196233
+ const stack = [];
196234
+ const sections = [];
196235
+ const parsed = walkXmlElements(propertiesXml, {
196236
+ fragment: true,
196237
+ additionalNamespaces: { ...namespaceBindings },
196238
+ onOpenTag({ tag, start }) {
196239
+ stack.push({ tag, start });
196240
+ },
196241
+ onCloseTag({ end }) {
196242
+ const frame = stack.pop();
196243
+ if (stack.length === 1 && isWordTag(stack[0]?.tag, "pPr") && isWordTag(frame?.tag, "sectPr") && frame?.tag.namespaceUri === stack[0]?.tag.namespaceUri) {
196244
+ sections.push({ start: frame.start, end });
196245
+ }
196246
+ }
196247
+ });
196248
+ if (parsed.errors.length > 0 || sections.length > 1)
196249
+ return null;
196250
+ const section = sections[0];
196251
+ return {
196252
+ ordinaryPropertiesXml: section ? propertiesXml.slice(0, section.start) + propertiesXml.slice(section.end) : propertiesXml,
196253
+ hasSection: section !== undefined
196254
+ };
196255
+ }
196256
+ function readPasteDestinationContentWidth(xml, options) {
196257
+ const stack = [];
196258
+ const paragraphSections = [];
196259
+ const wrappers = new Set(["sdt", "sdtContent", "ins", "del", "moveFrom", "moveTo", "customXml", "smartTag", "hyperlink"]);
196260
+ let finalSection;
196261
+ const parsed = walkXmlElements(xml, {
196262
+ fragment: options.fragment ?? false,
196263
+ ...options.fragment ? { additionalNamespaces: { w: WORDPROCESSINGML_NAMESPACE3 } } : {},
196264
+ onOpenTag({ tag }) {
196265
+ const parent = stack[stack.length - 1];
196266
+ const paragraph = stack[stack.length - 2];
196267
+ const frame = { tag };
196268
+ if (isWordTag(tag, "sectPr")) {
196269
+ const bodySection = stack.length === 2 && isWordTag(stack[0]?.tag, "document") && isWordTag(parent?.tag, "body");
196270
+ const paragraphSection = isWordTag(parent?.tag, "pPr") && isWordTag(paragraph?.tag, "p") && isWordTag(stack[0]?.tag, "document") && isWordTag(stack[1]?.tag, "body") && stack.slice(2, -2).every((ancestor) => ancestor.tag.namespaceUri === parent?.tag.namespaceUri && wrappers.has(ancestor.tag.localName));
196271
+ if (bodySection || paragraphSection || options.fragment && stack.length === 0) {
196272
+ frame.section = { pageWidth: null, left: null, right: null, gutter: null };
196273
+ if (paragraphSection)
196274
+ paragraph.paragraphSection = frame.section;
196275
+ else
196276
+ finalSection = frame.section;
196277
+ }
196278
+ } else if (parent?.section) {
196279
+ if (isWordTag(tag, "pgSz"))
196280
+ parent.section.pageWidth = readOoxmlTwipAttribute(tag, "w");
196281
+ else if (isWordTag(tag, "pgMar")) {
196282
+ parent.section.left = readOoxmlTwipAttribute(tag, "left");
196283
+ parent.section.right = readOoxmlTwipAttribute(tag, "right");
196284
+ parent.section.gutter = readOoxmlTwipAttribute(tag, "gutter");
196285
+ }
196286
+ }
196287
+ stack.push(frame);
196288
+ },
196289
+ onCloseTag({ end }) {
196290
+ const frame = stack.pop();
196291
+ if (frame?.paragraphSection)
196292
+ paragraphSections.push({ geometry: frame.paragraphSection, end });
196293
+ }
196294
+ });
196295
+ if (parsed.errors.length > 0)
196296
+ return PASTE_TABLE_GRID_TWIPS;
196297
+ const section = options.insertionOffset === undefined ? finalSection : paragraphSections.find((candidate2) => options.insertionOffset < candidate2.end)?.geometry ?? finalSection;
196298
+ if (section?.pageWidth == null || section.pageWidth < 1)
196299
+ return PASTE_TABLE_GRID_TWIPS;
196300
+ const content = section.pageWidth - (section.left ?? DEFAULT_PAGE_MARGIN_TWIPS) - (section.right ?? DEFAULT_PAGE_MARGIN_TWIPS) - (section.gutter ?? 0);
196301
+ return content >= 1 ? content : PASTE_TABLE_GRID_TWIPS;
196302
+ }
196303
+ function isWordTag(tag, localName2) {
196304
+ return tag !== undefined && (tag.namespaceUri === WORDPROCESSINGML_NAMESPACE3 || tag.namespaceUri === NS_WSTRICT) && tag.localName === localName2;
196305
+ }
196306
+ function readOoxmlTwipAttribute(tag, localName2) {
196307
+ const value = readXmlAttribute(tag, tag.namespaceUri, localName2)?.value;
196308
+ if (value === undefined || !/^-?\d+$/.test(value))
196309
+ return null;
196310
+ const twips = Number(value);
196311
+ return Number.isSafeInteger(twips) ? twips : null;
196312
+ }
196313
+ function pasteTableColumnWidthsTwips(columnCount, shares, gridWidthTwips) {
196314
+ const gridWidth = Math.max(1, Math.floor(gridWidthTwips));
196315
+ if (!shares || shares.length !== columnCount || shares.some((share) => !Number.isFinite(share) || share <= 0)) {
196316
+ const equal = Math.max(1, Math.floor(gridWidth / columnCount));
196317
+ return Array.from({ length: columnCount }, () => equal);
196318
+ }
196319
+ const maximum = Math.max(...shares);
196320
+ const sourceTotal = shares.reduce((sum, share) => sum + share, 0);
196321
+ const needsScaling = !Number.isFinite(sourceTotal) || !Number.isFinite(gridWidth * maximum);
196322
+ const normalizedShares = needsScaling ? shares.map((share) => share / maximum) : shares;
196323
+ const total = needsScaling ? normalizedShares.reduce((sum, share) => sum + share, 0) : sourceTotal;
196324
+ if (!(total > 0)) {
196325
+ const equal = Math.max(1, Math.floor(gridWidth / columnCount));
196326
+ return Array.from({ length: columnCount }, () => equal);
196327
+ }
196328
+ const widths = normalizedShares.map((share) => Math.max(1, Math.floor(needsScaling ? share / total * gridWidth : gridWidth * share / total)));
196329
+ let remainder = gridWidth - widths.reduce((sum, width) => sum + width, 0);
196330
+ for (let index = widths.length - 1;remainder !== 0 && index >= 0; index -= 1) {
196331
+ const next = widths[index] + remainder;
196332
+ if (next >= 1) {
196333
+ widths[index] = next;
196334
+ remainder = 0;
196335
+ }
196336
+ }
196337
+ return widths;
196338
+ }
196221
196339
  function renderPasteTableRows(tableSpec) {
196222
196340
  return tableSpec.rows.map((row) => {
196223
196341
  const rowProperties = row.header ? "<w:trPr><w:tblHeader/></w:trPr>" : "";
@@ -196251,8 +196369,9 @@ function renderPasteTableCell(cell, renderParagraph = renderPasteParagraphBlock,
196251
196369
  return border ? [border.lineStyle === "nil" ? `<w:${side} w:val="nil"/>` : `<w:${side} w:val="${escapeXmlAttribute(border.lineStyle)}" w:sz="${Math.max(1, Math.round(border.lineWeightPt * 8))}" w:color="${escapeXmlAttribute(border.color.toUpperCase())}"/>`] : [];
196252
196370
  }).join("");
196253
196371
  const tcBorders = borders ? `<w:tcBorders>${borders}</w:tcBorders>` : "";
196372
+ const vMerge = cell.vMerge === "restart" ? '<w:vMerge w:val="restart"/>' : cell.vMerge === "continue" ? "<w:vMerge/>" : "";
196254
196373
  const verticalAlign = cell.verticalAlign ? `<w:vAlign w:val="${cell.verticalAlign}"/>` : "";
196255
- const tcPr = `<w:tcPr><w:tcW w:w="0" w:type="auto"/>` + (gridSpan > 1 ? `<w:gridSpan w:val="${gridSpan}"/>` : "") + tcBorders + shading + tcMar + verticalAlign + "</w:tcPr>";
196374
+ const tcPr = `<w:tcPr><w:tcW w:w="0" w:type="auto"/>` + (gridSpan > 1 ? `<w:gridSpan w:val="${gridSpan}"/>` : "") + vMerge + tcBorders + shading + tcMar + verticalAlign + "</w:tcPr>";
196256
196375
  return `<w:tc>${tcPr}${cell.paragraphs.map((block) => ("rows" in block) ? renderTable(block) : renderParagraph(block)).join("")}</w:tc>`;
196257
196376
  }
196258
196377
  function renderPasteRunProperties(run, options) {
@@ -196524,13 +196643,14 @@ function collidesWithExistingParaId(state, candidate2) {
196524
196643
  return true;
196525
196644
  return false;
196526
196645
  }
196527
- var WORDPROCESSINGML_NAMESPACE3 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", PASTE_TABLE_GRID_TWIPS = 9360, VML_NAMESPACE = "urn:schemas-microsoft-com:vml", OFFICE_NAMESPACE = "urn:schemas-microsoft-com:office:office";
196646
+ var WORDPROCESSINGML_NAMESPACE3 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", PASTE_TABLE_DEFAULT_CONTENT_WIDTH_TWIPS = 9360, PASTE_TABLE_GRID_TWIPS, DEFAULT_PAGE_MARGIN_TWIPS = 1440, VML_NAMESPACE = "urn:schemas-microsoft-com:vml", OFFICE_NAMESPACE = "urn:schemas-microsoft-com:office:office";
196528
196647
  var init_paragraph_contribution = __esm(() => {
196529
196648
  init_xml_sax();
196530
196649
  init_xml_text();
196531
196650
  init_paragraph_para_id_attrs();
196532
196651
  init_highlight_ooxml();
196533
196652
  init_paste_run_validation();
196653
+ PASTE_TABLE_GRID_TWIPS = PASTE_TABLE_DEFAULT_CONTENT_WIDTH_TWIPS;
196534
196654
  });
196535
196655
 
196536
196656
  // ../../../v2/editor-core/dist/document/transactions/compile-comment-helpers.js
@@ -228297,19 +228417,22 @@ function mapPasteTableParagraphs(block, paragraph, table = (block2) => block2) {
228297
228417
  }))
228298
228418
  });
228299
228419
  }
228300
- function pasteTableSpec(block, mintNextParaId, bindW14NamespaceInline, runs = (block2) => block2.runs.map(toPasteTextRunSpec)) {
228420
+ function pasteTableSpec(block, mintNextParaId, bindW14NamespaceInline, runs = (block2) => block2.runs.map(toPasteTextRunSpec), gridWidthTwips) {
228301
228421
  return {
228302
228422
  ...block.styleRef !== undefined ? { styleRef: block.styleRef } : {},
228303
228423
  ...block.cellSpacingPt !== undefined ? { cellSpacingPt: block.cellSpacingPt } : {},
228424
+ ...block.columnWidthShares !== undefined ? { columnWidthShares: block.columnWidthShares } : {},
228425
+ ...gridWidthTwips !== undefined ? { gridWidthTwips } : {},
228304
228426
  rows: block.rows.map((row) => ({
228305
228427
  ...row.header !== undefined ? { header: row.header } : {},
228306
228428
  cells: row.cells.map((cell) => ({
228307
228429
  ...cell.gridSpan !== undefined ? { gridSpan: cell.gridSpan } : {},
228430
+ ...cell.vMerge !== undefined ? { vMerge: cell.vMerge } : {},
228308
228431
  ...cell.shadingColor !== undefined ? { shadingColor: cell.shadingColor } : {},
228309
228432
  ...cell.padding !== undefined ? { padding: cell.padding } : {},
228310
228433
  ...cell.verticalAlign !== undefined ? { verticalAlign: cell.verticalAlign } : {},
228311
228434
  ...cell.borders !== undefined ? { borders: cell.borders } : {},
228312
- paragraphs: cell.blocks.map((child) => child.kind === "table" ? pasteTableSpec(child, mintNextParaId, bindW14NamespaceInline, runs) : {
228435
+ paragraphs: cell.blocks.map((child) => child.kind === "table" ? pasteTableSpec(child, mintNextParaId, bindW14NamespaceInline, runs, gridWidthTwips) : {
228313
228436
  paraId: mintNextParaId(),
228314
228437
  bindW14NamespaceInline,
228315
228438
  styleId: child.styleRef ?? null,
@@ -241091,10 +241214,19 @@ function planParagraphSplice(input) {
241091
241214
  const bindW14NamespaceInline = !positionBindsW14Namespace(input.partBytes, input.paragraphStartByte, {
241092
241215
  scopeHintOpenTag: envelope.open
241093
241216
  });
241217
+ const sectionProperties = splitPasteParagraphSectionProperties(envelope.pPr, namespaceBindingsAtPosition(input.partBytes, input.paragraphStartByte, envelope.open));
241218
+ if (!sectionProperties)
241219
+ return { ok: false, reason: "paste-target-unsupported" };
241220
+ let destinationGridWidthTwips;
241094
241221
  const standalone = (block, blockIndex, inheritedPPrXml) => {
241095
241222
  if (block.kind === "table") {
241223
+ if (destinationGridWidthTwips === undefined) {
241224
+ const prefixXml = new TextDecoder().decode(input.partBytes.subarray(0, input.paragraphStartByte));
241225
+ const destinationXml = input.paragraphReplacementEndByte === undefined ? new TextDecoder().decode(input.partBytes) : prefixXml + input.anchorXml + new TextDecoder().decode(input.partBytes.subarray(input.paragraphReplacementEndByte));
241226
+ destinationGridWidthTwips = pasteDestinationContentWidthTwipsFromPartXml(destinationXml, prefixXml.length);
241227
+ }
241096
241228
  const before = createdParaIds.length;
241097
- const tableSpec = pasteTableSpec(block, mintId, bindW14NamespaceInline, (paragraph) => (input.inlineSpecs?.get(paragraph) ?? paragraph.runs.map(toPasteTextRunSpec)).map((run) => applyPasteCommentIdMap(run, input.commentIdMap)));
241229
+ const tableSpec = pasteTableSpec(block, mintId, bindW14NamespaceInline, (paragraph) => (input.inlineSpecs?.get(paragraph) ?? paragraph.runs.map(toPasteTextRunSpec)).map((run) => applyPasteCommentIdMap(run, input.commentIdMap)), destinationGridWidthTwips);
241098
241230
  const xml = input.trackedStamp ? renderTrackedPasteTableBlock(tableSpec, input.trackedStamp) : renderPasteTableBlock(tableSpec);
241099
241231
  destinationParaIdsByBlock[blockIndex].push(...createdParaIds.slice(before));
241100
241232
  return xml;
@@ -241138,7 +241270,7 @@ function planParagraphSplice(input) {
241138
241270
  if (!relocateEmptyAnchor) {
241139
241271
  if (mergeFirst && anchorParaId)
241140
241272
  destinationParaIdsByBlock[0].push(anchorParaId);
241141
- const headPPr = input.trackedStamp ? renderTrackedParagraphMarkProperties(envelope.pPr, input.trackedStamp) : envelope.pPr;
241273
+ const headPPr = input.trackedStamp ? renderTrackedParagraphMarkProperties(sectionProperties.ordinaryPropertiesXml, input.trackedStamp) : sectionProperties.ordinaryPropertiesXml;
241142
241274
  const headOpen = input.trackedStamp ? withTrackedRsid(envelope.open, input.trackedStamp.rsid) : envelope.open;
241143
241275
  paragraphs.push(headOpen + headPPr + split.headXml + (mergeFirst ? runsOf(blocks[0]) : "") + envelope.close);
241144
241276
  }
@@ -241146,7 +241278,7 @@ function planParagraphSplice(input) {
241146
241278
  const middleXml = [];
241147
241279
  for (let middleIndex = 0;middleIndex < middleBlocks.length; middleIndex += 1) {
241148
241280
  const block = middleBlocks[middleIndex];
241149
- middleXml.push(standalone(block, middleStart + middleIndex, mergeable(block) ? envelope.pPr : undefined));
241281
+ middleXml.push(standalone(block, middleStart + middleIndex, mergeable(block) ? sectionProperties.ordinaryPropertiesXml : undefined));
241150
241282
  }
241151
241283
  if (middleXml.length)
241152
241284
  paragraphs.push(renderBlockSdtSequence(middleBlocks, middleXml, input.blockSdtIds ?? new Map));
@@ -241161,8 +241293,8 @@ function planParagraphSplice(input) {
241161
241293
  paragraphs.push(tailOpen + envelope.pPr + tailRunsXml + envelope.close);
241162
241294
  } else if (relocateEmptyAnchor) {
241163
241295
  paragraphs.push(envelope.open + envelope.pPr + envelope.close);
241164
- } else if (blocks[blocks.length - 1]?.kind === "table") {
241165
- paragraphs.push(withParaId(envelope.open, mintId(), input.partBytes, input.paragraphStartByte) + envelope.close);
241296
+ } else if (blocks[blocks.length - 1]?.kind === "table" || sectionProperties.hasSection) {
241297
+ paragraphs.push(withParaId(envelope.open, mintId(), input.partBytes, input.paragraphStartByte) + (sectionProperties.hasSection ? envelope.pPr : "") + envelope.close);
241166
241298
  }
241167
241299
  }
241168
241300
  const insertedVisibleChars = blocks.reduce((sum, block) => sum + blockVisibleChars(block), 0);
@@ -241333,11 +241465,11 @@ function parseParagraphEnvelope(anchorXml) {
241333
241465
  if (innerEnd < 0)
241334
241466
  return null;
241335
241467
  const afterOpen = anchorXml.slice(openMatch[0].length);
241336
- const pPrMatch = /^\s*<([\w.-]+:)?pPr\b(?:[^>]*\/>|[^>]*>[\s\S]*?<\/(?:[\w.-]+:)?pPr\s*>)/.exec(afterOpen);
241337
- const innerStart = openMatch[0].length + (pPrMatch?.[0]?.length ?? 0);
241468
+ const { pPr } = splitLeadingParagraphPropertyBlock(afterOpen);
241469
+ const innerStart = openMatch[0].length + pPr.length;
241338
241470
  return {
241339
241471
  open: openMatch[0],
241340
- pPr: pPrMatch?.[0] ?? "",
241472
+ pPr,
241341
241473
  close,
241342
241474
  innerStart,
241343
241475
  innerEnd
@@ -241373,6 +241505,7 @@ var init_compile_paste_splice = __esm(() => {
241373
241505
  init_paragraph_contribution();
241374
241506
  init_paragraph_para_id_attrs();
241375
241507
  init_paste_blocks();
241508
+ init_paragraph_property_block();
241376
241509
  });
241377
241510
 
241378
241511
  // ../../../v2/editor-core/dist/document/transactions/compile-paste-lists.js
@@ -243598,7 +243731,10 @@ function resolveFragmentApplyTarget(state, op) {
243598
243731
  }
243599
243732
  const bodyXml = TD70.decode(bytes.subarray(bodyContentStart, bodyContentEnd));
243600
243733
  const sections = scanBodySections(`${bodyXml}</w:body>`);
243601
- if (!sections.reachedBodyEnd || sections.paragraphSectionCount > 0) {
243734
+ if (!sections.reachedBodyEnd) {
243735
+ return { ok: false, reason: "paste-whole-story-sections-unsupported" };
243736
+ }
243737
+ if (sections.paragraphSectionCount > 0 && (op.changeMode ?? "direct") === "tracked") {
243602
243738
  return { ok: false, reason: "paste-whole-story-sections-unsupported" };
243603
243739
  }
243604
243740
  const children = scan.bootstrapSlice?.children ?? [];
@@ -243748,7 +243884,12 @@ function resolveFragmentApplyTarget(state, op) {
243748
243884
  const crossParagraph = startAnchor.ordinal !== endAnchor.ordinal;
243749
243885
  const replacesContent = crossParagraph || target.charOffset !== explicitEnd.charOffset;
243750
243886
  if (crossParagraph) {
243751
- const structuralFailure = validateRangeCollapseStructure(residentBytes, index.entries, startAnchor.entry, endAnchor.entry, op.changeMode ?? "direct", target.collapsedObjectBoundary, explicitEnd.objectBoundary, { allowTrackedSdtContent: true, inlineRange: { startOffset: target.charOffset, endOffset: explicitEnd.charOffset } });
243887
+ const changeMode = op.changeMode ?? "direct";
243888
+ const structuralFailure = validateRangeCollapseStructure(residentBytes, index.entries, startAnchor.entry, endAnchor.entry, changeMode, target.collapsedObjectBoundary, explicitEnd.objectBoundary, {
243889
+ allowTrackedSdtContent: true,
243890
+ inlineRange: { startOffset: target.charOffset, endOffset: explicitEnd.charOffset },
243891
+ ...changeMode === "direct" ? { allowSectionBoundary: true } : {}
243892
+ });
243752
243893
  if (structuralFailure)
243753
243894
  return { ok: false, reason: structuralFailure };
243754
243895
  } else if (replacesContent && residentBytes) {
@@ -244423,6 +244564,7 @@ function runWholeStoryReplaceCommit(input, target, blocks, extras, inlineExtras)
244423
244564
  blockSdtIds: inlineExtras.blockSdtIds,
244424
244565
  partBytes: bytes,
244425
244566
  insertionByte: target.byteStart,
244567
+ wholeStoryReplace: true,
244426
244568
  ordinalSeed: 0,
244427
244569
  scopeHintOpenTag: target.bodyStartTagXml,
244428
244570
  ...extras.commentIdMap ? { commentIdMap: extras.commentIdMap } : {},
@@ -244631,13 +244773,14 @@ function renderCompletePasteFragment(input) {
244631
244773
  return paraId;
244632
244774
  }
244633
244775
  };
244776
+ const destinationGridWidthTwips = pasteDestinationContentWidthTwipsFromPartXml(TD70.decode(input.partBytes), input.wholeStoryReplace ? undefined : TD70.decode(input.partBytes.subarray(0, input.insertionByte)).length);
244634
244777
  const renderedBlocks = [];
244635
244778
  for (let blockIndex = 0;blockIndex < input.blocks.length; blockIndex += 1) {
244636
244779
  const block = input.blocks[blockIndex];
244637
244780
  const before = createdParaIds.length;
244638
244781
  let xml;
244639
244782
  if (block.kind === "table") {
244640
- const spec = pasteTableSpec(block, mintNextParaId, bindW14NamespaceInline, (paragraph) => (input.inlineSpecs.get(paragraph) ?? paragraph.runs.map(toPasteTextRunSpec)).map((run) => applyPasteCommentIdMap(run, input.commentIdMap)));
244783
+ const spec = pasteTableSpec(block, mintNextParaId, bindW14NamespaceInline, (paragraph) => (input.inlineSpecs.get(paragraph) ?? paragraph.runs.map(toPasteTextRunSpec)).map((run) => applyPasteCommentIdMap(run, input.commentIdMap)), destinationGridWidthTwips);
244641
244784
  xml = input.trackedStamp ? renderTrackedPasteTableBlock(spec, input.trackedStamp) : renderPasteTableBlock(spec);
244642
244785
  } else if (block.kind === "horizontalRule") {
244643
244786
  const spec = {
@@ -245153,6 +245296,7 @@ function runCrossParagraphPasteCommit(input, target, blocks, extras, inlineExtra
245153
245296
  endObjectBoundary: target.end.objectBoundary,
245154
245297
  removedBookmarkNames: rangeIntegrity.removedBookmarkNames,
245155
245298
  allocateWId: () => plannedWIds[usedWIds++],
245299
+ collapseSectionBoundaries: true,
245156
245300
  transformCollapsedParagraph: (collapsedParagraphXml) => {
245157
245301
  const planned = planParagraphSplice({
245158
245302
  anchorXml: collapsedParagraphXml,
@@ -245161,6 +245305,7 @@ function runCrossParagraphPasteCommit(input, target, blocks, extras, inlineExtra
245161
245305
  charOffset: target.start.charOffset,
245162
245306
  partBytes: bytes,
245163
245307
  paragraphStartByte: start.byteStart,
245308
+ paragraphReplacementEndByte: end.byteEnd,
245164
245309
  mintParaId: () => mintParaId(state, state.packageRevision, start.ordinal + 1 + (mintSalt += 1)),
245165
245310
  inlineSpecs: inlineExtras.inlineSpecs,
245166
245311
  blockSdtIds: inlineExtras.blockSdtIds,
@@ -246084,18 +246229,10 @@ function validateImageFragment(fragment3) {
246084
246229
  byId.set(asset.id, asset);
246085
246230
  }
246086
246231
  let references = 0;
246087
- for (const block of fragment3.blocks) {
246088
- if (block.kind === "table") {
246089
- for (const row of block.rows) {
246090
- for (const cell of row.cells) {
246091
- if (Array.from(walkPasteBlocks(cell.blocks)).some((paragraph) => paragraph.kind === "paragraph" && paragraph.inlines?.some((inline) => inline.kind === "image"))) {
246092
- return { ok: false, reason: "paste-structure-unsupported" };
246093
- }
246094
- }
246095
- }
246232
+ for (const block of walkPasteBlocks(fragment3.blocks)) {
246233
+ if (block.kind === "table" || block.kind === "horizontalRule")
246096
246234
  continue;
246097
- }
246098
- if (block.kind === "horizontalRule")
246235
+ if (block.kind !== "paragraph" && block.kind !== "heading")
246099
246236
  continue;
246100
246237
  for (const inline of block.inlines ?? []) {
246101
246238
  if (inline.kind === "text") {
@@ -246116,6 +246253,8 @@ function validateImageFragment(fragment3) {
246116
246253
  }
246117
246254
  continue;
246118
246255
  }
246256
+ if (inline.kind !== "image")
246257
+ continue;
246119
246258
  references += 1;
246120
246259
  if (references > MAX_IMAGE_REF_COUNT || !byId.has(inline.assetId) || !Number.isInteger(inline.widthPx) || inline.widthPx < 1 || inline.widthPx > 1e4 || !Number.isInteger(inline.heightPx) || inline.heightPx < 1 || inline.heightPx > 1e4 || !isValidOptionalXmlAttributeText(inline.name, 1024) || !isValidOptionalXmlAttributeText(inline.alt, 1024) || !isValidOptionalXmlAttributeText(inline.title, 1024)) {
246121
246260
  return { ok: false, reason: "paste-structure-unsupported" };
@@ -246367,9 +246506,15 @@ function validateBlocks(blocks) {
246367
246506
  if (block.cellSpacingPt !== undefined && !isSafePaddingPoints(block.cellSpacingPt)) {
246368
246507
  return { ok: false, reason: "paste-structure-unsupported" };
246369
246508
  }
246509
+ if (block.columnWidthShares !== undefined) {
246510
+ if (!Array.isArray(block.columnWidthShares) || block.columnWidthShares.length === 0 || block.columnWidthShares.length > MAX_WORD_TABLE_COLUMNS || block.columnWidthShares.some((share) => typeof share !== "number" || !Number.isFinite(share) || share <= 0)) {
246511
+ return { ok: false, reason: "paste-structure-unsupported" };
246512
+ }
246513
+ }
246370
246514
  if (!Array.isArray(block.rows) || block.rows.length === 0) {
246371
246515
  return { ok: false, reason: "paste-structure-unsupported" };
246372
246516
  }
246517
+ let tableColumnCount2 = 0;
246373
246518
  for (const [rowIndex, row] of block.rows.entries()) {
246374
246519
  if (!row || typeof row !== "object")
246375
246520
  return { ok: false, reason: "paste-structure-unsupported" };
@@ -246401,6 +246546,12 @@ function validateBlocks(blocks) {
246401
246546
  if (cell.gridSpan !== undefined && (!Number.isSafeInteger(cell.gridSpan) || cell.gridSpan < 1)) {
246402
246547
  return { ok: false, reason: "paste-structure-unsupported" };
246403
246548
  }
246549
+ if (cell.vMerge !== undefined && cell.vMerge !== "restart" && cell.vMerge !== "continue") {
246550
+ return { ok: false, reason: "paste-structure-unsupported" };
246551
+ }
246552
+ if (cell.verticalAlign !== undefined && cell.verticalAlign !== "top" && cell.verticalAlign !== "center" && cell.verticalAlign !== "bottom") {
246553
+ return { ok: false, reason: "paste-structure-unsupported" };
246554
+ }
246404
246555
  rowColumnCount += cell.gridSpan ?? 1;
246405
246556
  if (rowColumnCount > MAX_WORD_TABLE_COLUMNS) {
246406
246557
  return { ok: false, reason: "paste-structure-unsupported" };
@@ -246446,6 +246597,10 @@ function validateBlocks(blocks) {
246446
246597
  if (!validation2.ok)
246447
246598
  return validation2;
246448
246599
  }
246600
+ tableColumnCount2 = Math.max(tableColumnCount2, rowColumnCount);
246601
+ }
246602
+ if (block.columnWidthShares !== undefined && block.columnWidthShares.length !== Math.max(1, tableColumnCount2)) {
246603
+ return { ok: false, reason: "paste-structure-unsupported" };
246449
246604
  }
246450
246605
  ancestors.delete(block);
246451
246606
  continue;
@@ -283847,7 +284002,9 @@ var init_xml = __esm(() => {
283847
284002
  function preparePaintedOffsets(paraXml, namespaceBindings = {}) {
283848
284003
  const runs = paintedRuns(paraXml, namespaceBindings);
283849
284004
  const objects = runs.filter((run) => run.objectOrdinal !== null);
284005
+ const last = runs.at(-1);
283850
284006
  return {
284007
+ totalLength: last ? last.paintedStart + last.paintedLength : 0,
283851
284008
  containedObjectOrdinals(start, end) {
283852
284009
  const contained = [];
283853
284010
  for (let i2 = lowerBound(objects, start, "start");i2 < objects.length; i2++) {
@@ -283867,8 +284024,8 @@ function preparePaintedOffsets(paraXml, namespaceBindings = {}) {
283867
284024
  return offset;
283868
284025
  const run = runs[lowerBound(runs, offset, "end")];
283869
284026
  if (!run) {
283870
- const last = runs.at(-1);
283871
- return last ? last.kernelStart + last.kernelLength : 0;
284027
+ const last2 = runs.at(-1);
284028
+ return last2 ? last2.kernelStart + last2.kernelLength : 0;
283872
284029
  }
283873
284030
  return run.objectOrdinal === null ? run.kernelStart + Math.max(0, offset - run.paintedStart) : run.kernelStart;
283874
284031
  },
@@ -284056,7 +284213,9 @@ function prepareSelectionTargetResolution(input) {
284056
284213
  const painted = objectRuns > 0 ? preparePaintedOffsets(paraXml, fullBytes ? partRootNamespaceBindings(fullBytes) : input.namespaceBindings ?? {}) : null;
284057
284214
  const originalStart = target.start.offset;
284058
284215
  const originalEnd = target.end.offset;
284216
+ const offsetLength = painted?.totalLength ?? kernelTextLength;
284059
284217
  return {
284218
+ offsetLength,
284060
284219
  resolveOffsets(paintedStartOffset = originalStart, paintedEndOffset = originalEnd) {
284061
284220
  if (paintedStartOffset > paintedEndOffset) {
284062
284221
  return { error: "INVALID_TARGET", message: "selection end precedes selection start." };
@@ -284066,7 +284225,7 @@ function prepareSelectionTargetResolution(input) {
284066
284225
  let paintedObjectContained = false;
284067
284226
  let collapsedObjectBoundary;
284068
284227
  if (painted) {
284069
- if (startOffset < 0 || endOffset > entry.textLength + objectRuns) {
284228
+ if (startOffset < 0 || endOffset > offsetLength) {
284070
284229
  return { error: "INVALID_TARGET", message: "selection offsets exceed paragraph text." };
284071
284230
  }
284072
284231
  paintedObjectContained = painted.containsObject(startOffset, endOffset);
@@ -312086,6 +312245,9 @@ function paragraphPropsForElement(element, sheet, context) {
312086
312245
  }
312087
312246
  function cellPropsForElement(element, sheet, context) {
312088
312247
  const props = {};
312248
+ const valign = normalizeCellVerticalAlign(attributeValue2(element, "valign") ?? "");
312249
+ if (valign)
312250
+ props.verticalAlign = valign;
312089
312251
  for (const declaration of resolvedDeclarations(element, sheet)) {
312090
312252
  if (!CELL_PROPERTIES.has(declaration.property))
312091
312253
  continue;
@@ -312205,9 +312367,8 @@ function applyRunDeclaration(props, declaration) {
312205
312367
  return true;
312206
312368
  }
312207
312369
  if (declaration.property === "font-size") {
312208
- const points = cssLengthToPoints(value2);
312209
- const halfPoints = points === null ? 0 : points * 2;
312210
- if (points === null || points <= 0 || points > MAX_WORD_FONT_SIZE_POINTS2 || !Number.isSafeInteger(halfPoints) || halfPoints < 1)
312370
+ const points = parseFontSizePoints(value2);
312371
+ if (points === null)
312211
312372
  return false;
312212
312373
  props.fontSize = points;
312213
312374
  return true;
@@ -312297,6 +312458,13 @@ function applyCellDeclaration(props, declaration) {
312297
312458
  props.shading = color;
312298
312459
  return true;
312299
312460
  }
312461
+ if (declaration.property === "vertical-align") {
312462
+ const align = normalizeCellVerticalAlign(declaration.value);
312463
+ if (!align)
312464
+ return false;
312465
+ props.verticalAlign = align;
312466
+ return true;
312467
+ }
312300
312468
  if (declaration.property === "padding") {
312301
312469
  const values = expandBoxLengths(declaration.value);
312302
312470
  if (!values)
@@ -312342,6 +312510,16 @@ function applyCellDeclaration(props, declaration) {
312342
312510
  }
312343
312511
  return false;
312344
312512
  }
312513
+ function normalizeCellVerticalAlign(value2) {
312514
+ const normalized = value2.trim().toLowerCase();
312515
+ if (normalized === "top")
312516
+ return "top";
312517
+ if (normalized === "middle" || normalized === "center")
312518
+ return "center";
312519
+ if (normalized === "bottom")
312520
+ return "bottom";
312521
+ return;
312522
+ }
312345
312523
  function normalizeAlignment(value2) {
312346
312524
  const normalized = value2?.trim().toLowerCase();
312347
312525
  if (normalized === "left" || normalized === "center" || normalized === "right")
@@ -312376,6 +312554,14 @@ function expandBoxLengths(value2) {
312376
312554
  const left = values[3] ?? right;
312377
312555
  return { top, right, bottom, left };
312378
312556
  }
312557
+ function parseFontSizePoints(value2) {
312558
+ const points = cssLengthToPoints(value2);
312559
+ const halfPoints = points === null ? 0 : points * 2;
312560
+ if (points === null || points <= 0 || points > MAX_WORD_FONT_SIZE_POINTS2 || !Number.isSafeInteger(halfPoints) || halfPoints < 1) {
312561
+ return null;
312562
+ }
312563
+ return points;
312564
+ }
312379
312565
  function cssLengthToPoints(value2, allowNegative = false) {
312380
312566
  const points = cssAbsoluteLengthToPoints(value2, allowNegative);
312381
312567
  if (points === null)
@@ -312440,6 +312626,21 @@ function normalizeCellBorder(value2) {
312440
312626
  return null;
312441
312627
  return lineWeightPt !== undefined ? `${lineStyle} ${lineWeightPt}pt #${color}` : null;
312442
312628
  }
312629
+ function parseHtmlTableWidth(value2) {
312630
+ const trimmed = value2.trim();
312631
+ const percent = /^((?:\d+(?:\.\d+)?|\.\d+))\s*%$/i.exec(trimmed);
312632
+ if (percent) {
312633
+ const amount = Number.parseFloat(percent[1]);
312634
+ return Number.isFinite(amount) && amount > 0 ? { unit: "percent", value: amount } : null;
312635
+ }
312636
+ const unitless = /^((?:\d+(?:\.\d+)?|\.\d+))$/.exec(trimmed);
312637
+ if (unitless) {
312638
+ const amount = Number.parseFloat(unitless[1]);
312639
+ return Number.isFinite(amount) && amount > 0 ? { unit: "pt", value: amount * 0.75 } : null;
312640
+ }
312641
+ const points = cssLengthToPoints(trimmed);
312642
+ return points !== null && points > 0 ? { unit: "pt", value: points } : null;
312643
+ }
312443
312644
  function cssColor(value2) {
312444
312645
  const trimmed = value2.trim();
312445
312646
  const named = NAMED_COLORS2[trimmed.toLowerCase()];
@@ -312543,6 +312744,204 @@ var init_css = __esm(() => {
312543
312744
  };
312544
312745
  });
312545
312746
 
312747
+ // ../../../v2/document-api-v2-adapter/dist/clipboard/base64.js
312748
+ function decodedLength(value2) {
312749
+ if (value2.length === 0 || value2.length % 4 !== 0 || /[^A-Za-z0-9+/=]/.test(value2)) {
312750
+ return null;
312751
+ }
312752
+ const paddingStart = value2.indexOf("=");
312753
+ if (paddingStart !== -1 && paddingStart !== value2.length - 1 && !(paddingStart === value2.length - 2 && value2.endsWith("=="))) {
312754
+ return null;
312755
+ }
312756
+ return value2.length / 4 * 3 - (value2.endsWith("==") ? 2 : value2.endsWith("=") ? 1 : 0);
312757
+ }
312758
+ function base64DecodedLength(value2) {
312759
+ return decodedLength(value2);
312760
+ }
312761
+ function bytesToBase64(bytes) {
312762
+ if (typeof globalThis.btoa === "function") {
312763
+ let binary = "";
312764
+ for (let offset = 0;offset < bytes.length; offset += 32768) {
312765
+ binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
312766
+ }
312767
+ return globalThis.btoa(binary);
312768
+ }
312769
+ return Buffer.from(bytes).toString("base64");
312770
+ }
312771
+ function base64ToBytes(value2, maxDecodedBytes) {
312772
+ const length = decodedLength(value2);
312773
+ if (length === null || length > maxDecodedBytes)
312774
+ return null;
312775
+ try {
312776
+ if (typeof globalThis.atob === "function") {
312777
+ const binary = globalThis.atob(value2);
312778
+ const bytes = new Uint8Array(binary.length);
312779
+ for (let index = 0;index < binary.length; index += 1)
312780
+ bytes[index] = binary.charCodeAt(index);
312781
+ return bytes;
312782
+ }
312783
+ return Uint8Array.from(Buffer.from(value2, "base64"));
312784
+ } catch {
312785
+ return null;
312786
+ }
312787
+ }
312788
+
312789
+ // ../../../v2/document-api-v2-adapter/dist/images/raster-dimensions.js
312790
+ function readPngDimensions(bytes) {
312791
+ if (bytes.length < 33 || bytes[0] !== 137 || bytes[1] !== 80 || bytes[2] !== 78 || bytes[3] !== 71 || bytes[4] !== 13 || bytes[5] !== 10 || bytes[6] !== 26 || bytes[7] !== 10) {
312792
+ return null;
312793
+ }
312794
+ let offset = 8;
312795
+ let dimensions = null;
312796
+ while (offset + 12 <= bytes.length) {
312797
+ const length = readUint32be(bytes, offset);
312798
+ const dataEnd = offset + 8 + length;
312799
+ const chunkEnd = dataEnd + 4;
312800
+ if (chunkEnd > bytes.length)
312801
+ return null;
312802
+ const type = String.fromCharCode(bytes[offset + 4], bytes[offset + 5], bytes[offset + 6], bytes[offset + 7]);
312803
+ if (offset === 8) {
312804
+ if (type !== "IHDR" || length !== 13)
312805
+ return null;
312806
+ const widthPx = readUint32be(bytes, offset + 8);
312807
+ const heightPx = readUint32be(bytes, offset + 12);
312808
+ if (widthPx <= 0 || heightPx <= 0)
312809
+ return null;
312810
+ dimensions = { widthPx, heightPx };
312811
+ } else if (type === "IDAT") {
312812
+ return dimensions;
312813
+ } else if (type === "IEND") {
312814
+ return null;
312815
+ }
312816
+ offset = chunkEnd;
312817
+ }
312818
+ return null;
312819
+ }
312820
+ function readJpegDimensions(bytes) {
312821
+ if (bytes.length < 4 || bytes[0] !== 255 || bytes[1] !== 216)
312822
+ return null;
312823
+ let offset = 2;
312824
+ while (offset + 9 < bytes.length) {
312825
+ if (bytes[offset] !== 255)
312826
+ return null;
312827
+ const marker = bytes[offset + 1];
312828
+ offset += 2;
312829
+ while (bytes[offset] === 255)
312830
+ offset += 1;
312831
+ if (marker === 217 || marker === 218)
312832
+ return null;
312833
+ const segmentLength = (bytes[offset] << 8) + bytes[offset + 1];
312834
+ if (segmentLength < 2 || offset + segmentLength > bytes.length)
312835
+ return null;
312836
+ if (marker >= 192 && marker <= 195 || marker >= 197 && marker <= 199 || marker >= 201 && marker <= 203 || marker >= 205 && marker <= 207) {
312837
+ return {
312838
+ heightPx: (bytes[offset + 3] << 8) + bytes[offset + 4],
312839
+ widthPx: (bytes[offset + 5] << 8) + bytes[offset + 6]
312840
+ };
312841
+ }
312842
+ offset += segmentLength;
312843
+ }
312844
+ return null;
312845
+ }
312846
+ function readUint32be(bytes, offset) {
312847
+ return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
312848
+ }
312849
+
312850
+ // ../../../v2/document-api-v2-adapter/dist/conversion/html/trusted-image.js
312851
+ function isTrustedHtmlImageDataUri(value2) {
312852
+ return TRUSTED_DATA_IMAGE.test(value2.trim());
312853
+ }
312854
+ function convertTrustedHtmlImage(element, sheet) {
312855
+ if (element.tagName !== "img")
312856
+ return null;
312857
+ const src = attributeValue2(element, "src")?.trim();
312858
+ if (!src)
312859
+ return null;
312860
+ const match = src.trim().match(TRUSTED_DATA_IMAGE);
312861
+ if (!match)
312862
+ return null;
312863
+ const payload = match[2].replace(/\s+/g, "");
312864
+ const bytes = base64ToBytes(payload, MAX_V22_ASSET_DECODED_BYTES2);
312865
+ if (!bytes)
312866
+ return null;
312867
+ const sniffed = sniffRasterMime(bytes);
312868
+ if (!sniffed)
312869
+ return null;
312870
+ const normalizedSrc = `data:${sniffed};base64,${payload}`;
312871
+ const intrinsic = sniffed === "image/png" ? readPngDimensions(bytes) : readJpegDimensions(bytes);
312872
+ if (!intrinsic)
312873
+ return null;
312874
+ const widthAttr = parsePositiveNumber(attributeValue2(element, "width"));
312875
+ const heightAttr = parsePositiveNumber(attributeValue2(element, "height"));
312876
+ const declarations = resolvedDeclarations(element, sheet);
312877
+ const widthStyle = declarations.find((declaration) => declaration.property === "width")?.value.trim().toLowerCase();
312878
+ const heightStyle = declarations.find((declaration) => declaration.property === "height")?.value.trim().toLowerCase();
312879
+ const widthFromStyle = cssLengthPoints(widthStyle);
312880
+ const heightFromStyle = cssLengthPoints(heightStyle);
312881
+ const authoredWidthPt = widthFromStyle ?? (widthStyle === "auto" || widthAttr === null ? null : widthAttr * 0.75);
312882
+ const authoredHeightPt = heightFromStyle ?? (heightStyle === "auto" || heightAttr === null ? null : heightAttr * 0.75);
312883
+ const widthPt = authoredWidthPt ?? (authoredHeightPt === null ? null : authoredHeightPt * intrinsic.widthPx / intrinsic.heightPx);
312884
+ const heightPt = authoredHeightPt ?? (authoredWidthPt === null ? null : authoredWidthPt * intrinsic.heightPx / intrinsic.widthPx);
312885
+ const geometry = widthPt !== null && heightPt !== null && Number.isFinite(widthPt) && Number.isFinite(heightPt) && widthPt > 0 && heightPt > 0 ? { width: widthPt, height: heightPt } : undefined;
312886
+ const alt = xmlSafeImageText(attributeValue2(element, "alt"));
312887
+ const title = xmlSafeImageText(attributeValue2(element, "title"));
312888
+ return {
312889
+ kind: "image",
312890
+ image: {
312891
+ src: normalizedSrc,
312892
+ ...geometry ? { geometry } : {},
312893
+ ...alt || title ? {
312894
+ accessibility: {
312895
+ ...alt ? { alt } : {},
312896
+ ...title ? { title } : {}
312897
+ },
312898
+ ...alt ? { alt } : {}
312899
+ } : {}
312900
+ }
312901
+ };
312902
+ }
312903
+ function xmlSafeImageText(value2) {
312904
+ if (value2 === undefined)
312905
+ return;
312906
+ const normalized = value2.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g, " ").replace(/\s+/g, " ").trim();
312907
+ if (!normalized || normalized.length > 1024 || !isXml10SafeAttributeValue(normalized))
312908
+ return;
312909
+ return normalized;
312910
+ }
312911
+ function sniffRasterMime(bytes) {
312912
+ if (bytes.length >= 8 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
312913
+ return "image/png";
312914
+ }
312915
+ if (bytes.length >= 2 && bytes[0] === 255 && bytes[1] === 216)
312916
+ return "image/jpeg";
312917
+ return null;
312918
+ }
312919
+ function parsePositiveNumber(value2) {
312920
+ if (value2 === undefined)
312921
+ return null;
312922
+ const parsed = Number.parseFloat(value2.trim());
312923
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
312924
+ }
312925
+ function cssLengthPoints(token) {
312926
+ if (token === undefined)
312927
+ return null;
312928
+ const length = token.match(/^(-?(?:\d+(?:\.\d+)?|\.\d+))(px|pt|in|cm|mm)$/i);
312929
+ if (!length)
312930
+ return null;
312931
+ const amount = Number.parseFloat(length[1]);
312932
+ if (!Number.isFinite(amount) || amount <= 0)
312933
+ return null;
312934
+ const unit = length[2].toLowerCase();
312935
+ const factor = { px: 0.75, pt: 1, in: 72, cm: 72 / 2.54, mm: 72 / 25.4 }[unit];
312936
+ return factor === undefined ? null : amount * factor;
312937
+ }
312938
+ var TRUSTED_DATA_IMAGE;
312939
+ var init_trusted_image = __esm(() => {
312940
+ init_src3();
312941
+ init_css();
312942
+ TRUSTED_DATA_IMAGE = /^data:(image\/(?:png|jpeg|jpg));base64,([\s\S]*)$/i;
312943
+ });
312944
+
312546
312945
  // ../../../v2/document-api-v2-adapter/dist/conversion/html/limits.js
312547
312946
  function resolveHtmlConversionLimits(overrides) {
312548
312947
  const limits = { ...DEFAULT_HTML_CONVERSION_LIMITS, ...overrides };
@@ -312977,6 +313376,18 @@ function convertFlowChildren(children2, context, inlineContext, path6, indexOffs
312977
313376
  flushPending();
312978
313377
  inspectUnsafeAttributes(node3, context, nodePath);
312979
313378
  const nextInlineContext = inlineContextForElement(node3, context, inlineContext, nodePath);
313379
+ if (node3.tagName === "a") {
313380
+ addDiagnostic(context, {
313381
+ code: "conversion-unsupported-construct",
313382
+ severity: "warning",
313383
+ message: "A hyperlink around block content was removed while preserving its content.",
313384
+ construct: "hyperlink",
313385
+ disposition: "downgraded",
313386
+ lossy: true,
313387
+ path: nodePath,
313388
+ range: sourceRangeForNode(node3)
313389
+ });
313390
+ }
312980
313391
  if (!FLOW_WRAPPERS.has(node3.tagName) && !INLINE_ELEMENTS.has(node3.tagName)) {
312981
313392
  reportUnknownWrapper(node3, context, nodePath);
312982
313393
  }
@@ -313003,6 +313414,15 @@ function convertBlock(element, context, inherited, path6) {
313003
313414
  reportDroppedElement(element, context, path6, "script", "conversion-unsafe-content");
313004
313415
  return [];
313005
313416
  }
313417
+ if (element.tagName === "img") {
313418
+ const image = convertTrustedHtmlImage(element, context.sheet);
313419
+ if (image) {
313420
+ claimContentNode(context, path6);
313421
+ return [paragraph2(context, [image], undefined, path6)];
313422
+ }
313423
+ reportDroppedElement(element, context, path6, "image", "conversion-unsafe-content");
313424
+ return [];
313425
+ }
313006
313426
  if (MEDIA_ELEMENTS.has(element.tagName)) {
313007
313427
  reportDroppedElement(element, context, path6, "image", "conversion-unsafe-content");
313008
313428
  return [];
@@ -313451,21 +313871,6 @@ function convertTable(table, context, inherited, path6) {
313451
313871
  });
313452
313872
  structurallyRejected = true;
313453
313873
  }
313454
- const rowSpanRaw = attributeValue2(cell, "rowspan");
313455
- const rowSpan = rowSpanRaw === undefined ? 1 : Number.parseInt(rowSpanRaw, 10);
313456
- if (rowSpanRaw !== undefined && (!Number.isSafeInteger(rowSpan) || rowSpan !== 1)) {
313457
- addDiagnostic(context, {
313458
- code: "conversion-unsupported-construct",
313459
- severity: "error",
313460
- message: "Row-spanning table cells cannot be represented by this conversion.",
313461
- construct: "rowSpan",
313462
- disposition: "rejected",
313463
- lossy: true,
313464
- path: [...rowPath, cellIndex, "@rowspan"],
313465
- range: sourceRangeForAttribute(cell, "rowspan") ?? sourceRangeForNode(cell)
313466
- });
313467
- structurallyRejected = true;
313468
- }
313469
313874
  const colSpanRaw = attributeValue2(cell, "colspan");
313470
313875
  const colSpan = colSpanRaw === undefined ? 1 : Number.parseInt(colSpanRaw, 10);
313471
313876
  if (Number.isFinite(colSpan) && colSpan > MAX_WORD_TABLE_GRID_COLUMNS) {
@@ -313507,8 +313912,11 @@ function convertTable(table, context, inherited, path6) {
313507
313912
  const tableCellProps = cellPropsForElement(table, context.sheet, cssContext(context, path6));
313508
313913
  const tableBorderSuppression = tableCellProps?.borders && ["top", "right", "bottom", "left"].every((side) => tableCellProps.borders?.[side] === "none");
313509
313914
  const convertedRows = [];
313510
- for (const { row, path: rowPath } of rows) {
313915
+ const convertedHtmlRows = [];
313916
+ let remainingCoveredRows = 0;
313917
+ for (const { row, path: rowPath, remainingGroupRows } of rows) {
313511
313918
  const cells = [];
313919
+ let maxNewCover = 0;
313512
313920
  for (let cellIndex = 0;cellIndex < row.childNodes.length; cellIndex += 1) {
313513
313921
  const cell = row.childNodes[cellIndex];
313514
313922
  if (!isElement(cell) || cell.tagName !== "td" && cell.tagName !== "th")
@@ -313516,6 +313924,23 @@ function convertTable(table, context, inherited, path6) {
313516
313924
  const cellPath = [...rowPath, cellIndex];
313517
313925
  inspectUnsafeAttributes(cell, context, cellPath);
313518
313926
  const colSpan = positiveIntegerAttribute(cell, "colspan", context, cellPath, "colSpan");
313927
+ const authoredRowSpan = htmlRowSpanAttribute(cell, context, cellPath);
313928
+ const rowSpan = authoredRowSpan === undefined ? undefined : authoredRowSpan === 0 ? remainingGroupRows : Math.min(authoredRowSpan, remainingGroupRows);
313929
+ if (authoredRowSpan !== undefined && authoredRowSpan > 0 && rowSpan !== authoredRowSpan) {
313930
+ addDiagnostic(context, {
313931
+ code: "conversion-normalized-construct",
313932
+ severity: "warning",
313933
+ message: "Table cell rowspan was limited to the remaining explicit rows in its HTML row group.",
313934
+ construct: "rowSpan",
313935
+ disposition: "normalized",
313936
+ lossy: true,
313937
+ path: [...cellPath, "@rowspan"],
313938
+ range: sourceRangeForAttribute(cell, "rowspan") ?? sourceRangeForNode(cell)
313939
+ });
313940
+ }
313941
+ if (rowSpan !== undefined && rowSpan > 1) {
313942
+ maxNewCover = Math.max(maxNewCover, rowSpan - 1);
313943
+ }
313519
313944
  const cellContext = inlineContextForElement(cell, context, tableContext, cellPath, undefined, CELL_NON_RUN_CSS);
313520
313945
  const droppedContentStart = context.droppedContentCount;
313521
313946
  const content = convertFlowChildren(cell.childNodes, context, cellContext, cellPath);
@@ -313530,14 +313955,18 @@ function convertTable(table, context, inherited, path6) {
313530
313955
  cells.push({
313531
313956
  ...props ? { props } : {},
313532
313957
  ...colSpan !== undefined && colSpan > 1 ? { colSpan } : {},
313958
+ ...rowSpan !== undefined && rowSpan > 1 ? { rowSpan } : {},
313533
313959
  ...cell.tagName === "th" ? { header: true } : {},
313534
313960
  content: content.length > 0 ? content : [
313535
313961
  paragraph2(context, [], undefined, cellPath, context.droppedContentCount === droppedContentStart)
313536
313962
  ]
313537
313963
  });
313538
313964
  }
313539
- if (cells.length > 0)
313965
+ if (cells.length > 0 || remainingCoveredRows > 0) {
313540
313966
  convertedRows.push({ cells });
313967
+ convertedHtmlRows.push(row);
313968
+ }
313969
+ remainingCoveredRows = Math.max(remainingCoveredRows - 1, maxNewCover, 0);
313541
313970
  }
313542
313971
  context.tableStyleAggregationDepth -= 1;
313543
313972
  if (context.suppressedTableStyleDiagnosticCount > suppressedStyleStart) {
@@ -313554,8 +313983,15 @@ function convertTable(table, context, inherited, path6) {
313554
313983
  }
313555
313984
  if (convertedRows.length === 0)
313556
313985
  return null;
313986
+ const columns = tableColumnSharesFromHtml(table, convertedHtmlRows, convertedRows, context, path6);
313557
313987
  claimContentNode(context, path6);
313558
- return { kind: "table", table: { rows: convertedRows } };
313988
+ return {
313989
+ kind: "table",
313990
+ table: {
313991
+ rows: convertedRows,
313992
+ ...columns ? { columns } : {}
313993
+ }
313994
+ };
313559
313995
  }
313560
313996
  function appendInlineNode(element, builder, context, inherited, path6) {
313561
313997
  if (isWordListMarkerContainer(element))
@@ -313573,6 +314009,15 @@ function appendInlineNode(element, builder, context, inherited, path6) {
313573
314009
  reportDroppedElement(element, context, path6, "script", "conversion-unsafe-content");
313574
314010
  return;
313575
314011
  }
314012
+ if (element.tagName === "img") {
314013
+ const image = convertTrustedHtmlImage(element, context.sheet);
314014
+ if (image) {
314015
+ builder.appendInline(image);
314016
+ return;
314017
+ }
314018
+ reportDroppedElement(element, context, path6, "image", "conversion-unsafe-content");
314019
+ return;
314020
+ }
313576
314021
  if (MEDIA_ELEMENTS.has(element.tagName)) {
313577
314022
  reportDroppedElement(element, context, path6, "image", "conversion-unsafe-content");
313578
314023
  return;
@@ -313675,6 +314120,20 @@ function appendHyperlink(element, builder, context, inherited, path6) {
313675
314120
  builder.appendInlines(children2);
313676
314121
  return;
313677
314122
  }
314123
+ if (children2.some((inline) => inline.kind === "image")) {
314124
+ addDiagnostic(context, {
314125
+ code: "conversion-unsupported-construct",
314126
+ severity: "warning",
314127
+ message: "A hyperlink containing an image was removed while preserving its image and text.",
314128
+ construct: "hyperlink",
314129
+ disposition: "downgraded",
314130
+ lossy: true,
314131
+ path: path6,
314132
+ range: sourceRangeForNode(element)
314133
+ });
314134
+ builder.appendInlines(children2);
314135
+ return;
314136
+ }
313678
314137
  const targetFrame = attributeValue2(element, "target");
313679
314138
  const tooltip = attributeValue2(element, "title");
313680
314139
  if (targetFrame) {
@@ -313735,7 +314194,8 @@ function inspectUnsafeAttributes(element, context, path6) {
313735
314194
  }
313736
314195
  if (URL_ATTRIBUTES.has(name) && !(element.tagName === "a" && name === "href")) {
313737
314196
  const targets = name === "srcset" ? attribute.value.split(",").map((entry) => entry.trim().split(/\s+/)[0] ?? "") : [attribute.value.trim()];
313738
- if (targets.some((target) => target !== "" && !isValidExternalHyperlinkHref(target))) {
314197
+ const trustedImageSrc = element.tagName === "img" && name === "src" && targets.every((target) => target === "" || isTrustedHtmlImageDataUri(target));
314198
+ if (!trustedImageSrc && targets.some((target) => target !== "" && !isValidExternalHyperlinkHref(target))) {
313739
314199
  addDiagnostic(context, {
313740
314200
  code: "conversion-unsafe-url",
313741
314201
  severity: "warning",
@@ -313826,7 +314286,7 @@ function cssContext(context, path6, ignoredDroppedProperties, ignoredRunProperti
313826
314286
  };
313827
314287
  }
313828
314288
  function isBlockElement(element) {
313829
- return BLOCK_ELEMENTS.has(element.tagName) || ACTIVE_ELEMENTS.has(element.tagName) || MEDIA_ELEMENTS.has(element.tagName) || isSuspiciousRecoveredElement(element);
314289
+ return BLOCK_ELEMENTS.has(element.tagName) || ACTIVE_ELEMENTS.has(element.tagName) || element.tagName !== "img" && MEDIA_ELEMENTS.has(element.tagName) || isSuspiciousRecoveredElement(element);
313830
314290
  }
313831
314291
  function isSuspiciousRecoveredElement(element) {
313832
314292
  return /[^a-z0-9:-]/i.test(element.tagName);
@@ -313924,21 +314384,151 @@ function positiveIntegerAttribute(element, attribute, context, path6, construct)
313924
314384
  });
313925
314385
  return 1;
313926
314386
  }
314387
+ function htmlRowSpanAttribute(element, context, path6) {
314388
+ const raw = attributeValue2(element, "rowspan");
314389
+ if (raw === undefined)
314390
+ return;
314391
+ const digits = /^[\t\n\f\r ]*([+-]?\d+)/.exec(raw)?.[1];
314392
+ const value2 = digits === undefined ? Number.NaN : Number.parseInt(digits, 10);
314393
+ if (value2 >= 0)
314394
+ return Math.min(value2, 65534);
314395
+ addDiagnostic(context, {
314396
+ code: "conversion-malformed-input",
314397
+ severity: "info",
314398
+ message: "Invalid rowspan value was normalized to 1.",
314399
+ construct: "rowSpan",
314400
+ disposition: "normalized",
314401
+ lossy: false,
314402
+ path: [...path6, "@rowspan"],
314403
+ range: sourceRangeForAttribute(element, "rowspan") ?? sourceRangeForNode(element)
314404
+ });
314405
+ return 1;
314406
+ }
314407
+ function tableColumnSharesFromHtml(table, htmlRows, convertedRows, context, path6) {
314408
+ let activeSpans = [];
314409
+ let gridColumnCount = 1;
314410
+ const candidates = [];
314411
+ for (let rowIndex = 0;rowIndex < convertedRows.length; rowIndex += 1) {
314412
+ const row = convertedRows[rowIndex];
314413
+ const htmlCells = htmlRows[rowIndex].childNodes.filter((cell) => isElement(cell) && (cell.tagName === "td" || cell.tagName === "th"));
314414
+ const shares = [];
314415
+ let cellCount = 0;
314416
+ let col = 0;
314417
+ let sourceIndex = 0;
314418
+ while (sourceIndex < row.cells.length || activeSpans.some((span) => span.remaining > 0 && span.col >= col)) {
314419
+ const continuation = activeSpans.find((span) => span.col === col && span.remaining > 0);
314420
+ if (continuation) {
314421
+ for (let index = 0;index < continuation.colSpan; index += 1)
314422
+ shares.push(continuation.share);
314423
+ continuation.remaining -= 1;
314424
+ col += continuation.colSpan;
314425
+ cellCount += 1;
314426
+ continue;
314427
+ }
314428
+ if (sourceIndex >= row.cells.length) {
314429
+ const next = activeSpans.filter((span) => span.remaining > 0 && span.col > col).sort((left, right) => left.col - right.col)[0];
314430
+ if (!next)
314431
+ break;
314432
+ while (col < next.col) {
314433
+ shares.push(null);
314434
+ col += 1;
314435
+ }
314436
+ continue;
314437
+ }
314438
+ const cell = row.cells[sourceIndex];
314439
+ const htmlCell = htmlCells[sourceIndex];
314440
+ sourceIndex += 1;
314441
+ const colSpan = cell.colSpan ?? 1;
314442
+ if (col + colSpan > MAX_WORD_TABLE_GRID_COLUMNS)
314443
+ return;
314444
+ const width = htmlElementTableWidth(htmlCell, context.sheet);
314445
+ const share = width === null ? null : { unit: width.unit, value: width.value / colSpan };
314446
+ for (let index = 0;index < colSpan; index += 1)
314447
+ shares.push(share);
314448
+ if ((cell.rowSpan ?? 1) > 1) {
314449
+ activeSpans.push({ col, colSpan, remaining: cell.rowSpan - 1, share });
314450
+ }
314451
+ col += colSpan;
314452
+ cellCount += 1;
314453
+ }
314454
+ activeSpans = activeSpans.filter((span) => span.remaining > 0);
314455
+ gridColumnCount = Math.max(gridColumnCount, col);
314456
+ candidates.push({ shares, cellCount });
314457
+ }
314458
+ let bestShares;
314459
+ let bestCellCount = 0;
314460
+ const sourceWidth = htmlElementTableWidth(table, context.sheet);
314461
+ const sourceWidthPt = sourceWidth?.unit === "pt" ? sourceWidth.value : null;
314462
+ let incomparableWidths = false;
314463
+ for (const { shares, cellCount } of candidates) {
314464
+ if (shares.length !== gridColumnCount)
314465
+ continue;
314466
+ if (!shares.every((width) => width !== null && Number.isFinite(width.value) && width.value > 0))
314467
+ continue;
314468
+ if (sourceWidthPt === null && shares.some((width) => width.unit !== shares[0].unit)) {
314469
+ incomparableWidths = true;
314470
+ continue;
314471
+ }
314472
+ const normalized = shares.map((width) => width.unit === "percent" && sourceWidthPt !== null ? width.value / 100 * sourceWidthPt : width.value);
314473
+ if (normalized.some((value2) => !Number.isFinite(value2) || value2 <= 0))
314474
+ continue;
314475
+ if (cellCount <= bestCellCount)
314476
+ continue;
314477
+ bestShares = normalized;
314478
+ bestCellCount = cellCount;
314479
+ }
314480
+ if (incomparableWidths) {
314481
+ addDiagnostic(context, {
314482
+ code: "conversion-normalized-construct",
314483
+ severity: "warning",
314484
+ message: "Mixed percentage and absolute table cell widths could not be compared without a source table width; a comparable row or equal-width fallback was used.",
314485
+ construct: "table",
314486
+ disposition: "normalized",
314487
+ lossy: true,
314488
+ path: path6,
314489
+ range: sourceRangeForNode(table)
314490
+ });
314491
+ }
314492
+ return bestShares?.map((width) => ({ width }));
314493
+ }
314494
+ function htmlElementTableWidth(element, sheet) {
314495
+ const styleWidth = resolvedDeclarations(element, sheet).find((declaration) => declaration.property === "width")?.value;
314496
+ if (styleWidth) {
314497
+ const fromStyle = parseHtmlTableWidth(styleWidth);
314498
+ if (fromStyle !== null)
314499
+ return fromStyle;
314500
+ }
314501
+ const widthAttr = attributeValue2(element, "width");
314502
+ return widthAttr === undefined ? null : parseHtmlTableWidth(widthAttr);
314503
+ }
313927
314504
  function collectTableRows(table, tablePath) {
313928
314505
  const rows = [];
313929
- const visit = (parent, path6) => {
313930
- for (let index = 0;index < parent.childNodes.length; index += 1) {
313931
- const child = parent.childNodes[index];
313932
- if (!isElement(child))
313933
- continue;
313934
- const childPath = [...path6, index];
313935
- if (child.tagName === "tr")
313936
- rows.push({ row: child, path: childPath });
313937
- else if (child.tagName === "thead" || child.tagName === "tbody" || child.tagName === "tfoot")
313938
- visit(child, childPath);
314506
+ const appendGroup = (group) => {
314507
+ for (let index = 0;index < group.length; index += 1) {
314508
+ rows.push({ ...group[index], remainingGroupRows: group.length - index });
313939
314509
  }
313940
314510
  };
313941
- visit(table, tablePath);
314511
+ let directRows = [];
314512
+ for (let index = 0;index < table.childNodes.length; index += 1) {
314513
+ const child = table.childNodes[index];
314514
+ if (!isElement(child))
314515
+ continue;
314516
+ const childPath = [...tablePath, index];
314517
+ if (child.tagName === "tr") {
314518
+ directRows.push({ row: child, path: childPath });
314519
+ } else if (child.tagName === "thead" || child.tagName === "tbody" || child.tagName === "tfoot") {
314520
+ appendGroup(directRows);
314521
+ directRows = [];
314522
+ const group = [];
314523
+ for (let rowIndex = 0;rowIndex < child.childNodes.length; rowIndex += 1) {
314524
+ const row = child.childNodes[rowIndex];
314525
+ if (isElement(row) && row.tagName === "tr")
314526
+ group.push({ row, path: [...childPath, rowIndex] });
314527
+ }
314528
+ appendGroup(group);
314529
+ }
314530
+ }
314531
+ appendGroup(directRows);
313942
314532
  return rows;
313943
314533
  }
313944
314534
  function findDescendantElement(element, tagName) {
@@ -314035,6 +314625,8 @@ function hasSubstantiveInline(inline) {
314035
314625
  return inline.run.text.length > 0;
314036
314626
  if (inline.kind === "lineBreak")
314037
314627
  return true;
314628
+ if (inline.kind === "image")
314629
+ return true;
314038
314630
  if (inline.kind === "hyperlink")
314039
314631
  return inline.hyperlink.inlines.some(hasSubstantiveInline);
314040
314632
  return false;
@@ -314148,6 +314740,7 @@ var init_converter = __esm(() => {
314148
314740
  init_fragment_output_budget();
314149
314741
  init_hyperlink_values();
314150
314742
  init_css();
314743
+ init_trusted_image();
314151
314744
  init_limits();
314152
314745
  init_word_lists();
314153
314746
  BLOCK_ELEMENTS = new Set([
@@ -325506,105 +326099,6 @@ var init_convert_to_fragment = __esm(() => {
325506
326099
  init_markdown();
325507
326100
  });
325508
326101
 
325509
- // ../../../v2/document-api-v2-adapter/dist/clipboard/base64.js
325510
- function decodedLength(value2) {
325511
- if (value2.length === 0 || value2.length % 4 !== 0 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value2)) {
325512
- return null;
325513
- }
325514
- return value2.length / 4 * 3 - (value2.endsWith("==") ? 2 : value2.endsWith("=") ? 1 : 0);
325515
- }
325516
- function base64DecodedLength(value2) {
325517
- return decodedLength(value2);
325518
- }
325519
- function bytesToBase64(bytes) {
325520
- if (typeof globalThis.btoa === "function") {
325521
- let binary = "";
325522
- for (let offset = 0;offset < bytes.length; offset += 32768) {
325523
- binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
325524
- }
325525
- return globalThis.btoa(binary);
325526
- }
325527
- return Buffer.from(bytes).toString("base64");
325528
- }
325529
- function base64ToBytes(value2, maxDecodedBytes) {
325530
- const length = decodedLength(value2);
325531
- if (length === null || length > maxDecodedBytes)
325532
- return null;
325533
- try {
325534
- if (typeof globalThis.atob === "function") {
325535
- const binary = globalThis.atob(value2);
325536
- const bytes = new Uint8Array(binary.length);
325537
- for (let index2 = 0;index2 < binary.length; index2 += 1)
325538
- bytes[index2] = binary.charCodeAt(index2);
325539
- return bytes;
325540
- }
325541
- return Uint8Array.from(Buffer.from(value2, "base64"));
325542
- } catch {
325543
- return null;
325544
- }
325545
- }
325546
-
325547
- // ../../../v2/document-api-v2-adapter/dist/images/raster-dimensions.js
325548
- function readPngDimensions(bytes) {
325549
- if (bytes.length < 33 || bytes[0] !== 137 || bytes[1] !== 80 || bytes[2] !== 78 || bytes[3] !== 71 || bytes[4] !== 13 || bytes[5] !== 10 || bytes[6] !== 26 || bytes[7] !== 10) {
325550
- return null;
325551
- }
325552
- let offset = 8;
325553
- let dimensions = null;
325554
- while (offset + 12 <= bytes.length) {
325555
- const length = readUint32be(bytes, offset);
325556
- const dataEnd = offset + 8 + length;
325557
- const chunkEnd = dataEnd + 4;
325558
- if (chunkEnd > bytes.length)
325559
- return null;
325560
- const type = String.fromCharCode(bytes[offset + 4], bytes[offset + 5], bytes[offset + 6], bytes[offset + 7]);
325561
- if (offset === 8) {
325562
- if (type !== "IHDR" || length !== 13)
325563
- return null;
325564
- const widthPx = readUint32be(bytes, offset + 8);
325565
- const heightPx = readUint32be(bytes, offset + 12);
325566
- if (widthPx <= 0 || heightPx <= 0)
325567
- return null;
325568
- dimensions = { widthPx, heightPx };
325569
- } else if (type === "IDAT") {
325570
- return dimensions;
325571
- } else if (type === "IEND") {
325572
- return null;
325573
- }
325574
- offset = chunkEnd;
325575
- }
325576
- return null;
325577
- }
325578
- function readJpegDimensions(bytes) {
325579
- if (bytes.length < 4 || bytes[0] !== 255 || bytes[1] !== 216)
325580
- return null;
325581
- let offset = 2;
325582
- while (offset + 9 < bytes.length) {
325583
- if (bytes[offset] !== 255)
325584
- return null;
325585
- const marker = bytes[offset + 1];
325586
- offset += 2;
325587
- while (bytes[offset] === 255)
325588
- offset += 1;
325589
- if (marker === 217 || marker === 218)
325590
- return null;
325591
- const segmentLength = (bytes[offset] << 8) + bytes[offset + 1];
325592
- if (segmentLength < 2 || offset + segmentLength > bytes.length)
325593
- return null;
325594
- if (marker >= 192 && marker <= 195 || marker >= 197 && marker <= 199 || marker >= 201 && marker <= 203 || marker >= 205 && marker <= 207) {
325595
- return {
325596
- heightPx: (bytes[offset + 3] << 8) + bytes[offset + 4],
325597
- widthPx: (bytes[offset + 5] << 8) + bytes[offset + 6]
325598
- };
325599
- }
325600
- offset += segmentLength;
325601
- }
325602
- return null;
325603
- }
325604
- function readUint32be(bytes, offset) {
325605
- return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
325606
- }
325607
-
325608
326102
  // ../../../v2/document-api-v2-adapter/dist/conversion/fragment-images.js
325609
326103
  function createFragmentImageLowering(invalid3, unsupported4) {
325610
326104
  const assets = [];
@@ -325640,17 +326134,20 @@ function createFragmentImageLowering(invalid3, unsupported4) {
325640
326134
  }
325641
326135
  if (++references > MAX_V22_IMAGE_REF_COUNT)
325642
326136
  invalid3(path7, "Fragment contains too many image references.");
325643
- const match = /^data:(image\/(?:png|jpeg|jpg));base64,([\s\S]*)$/i.exec(image.src);
326137
+ const match = image.src.trim().match(/^data:(image\/(?:png|jpeg|jpg));base64,([\s\S]*)$/i);
325644
326138
  if (!match)
325645
326139
  unsupported4([...payloadPath, "src"], "Rich inbound images require a PNG or JPEG base64 data URI.");
325646
- const mimeType = match[1].toLowerCase() === "image/png" ? "image/png" : "image/jpeg";
326140
+ const payload = match[2].replace(/\s+/g, "");
325647
326141
  let asset = bySource.get(image.src);
325648
326142
  if (!asset) {
325649
326143
  if (assets.length >= MAX_V22_ASSET_COUNT)
325650
326144
  invalid3(path7, "Fragment contains too many image assets.");
325651
- const bytes = base64ToBytes(match[2], MAX_V22_ASSET_DECODED_BYTES2);
326145
+ const bytes = base64ToBytes(payload, MAX_V22_ASSET_DECODED_BYTES2);
325652
326146
  if (!bytes)
325653
326147
  invalid3([...payloadPath, "src"], "Image base64 is invalid or exceeds the decoded asset limit.");
326148
+ const mimeType = sniffRasterMime2(bytes);
326149
+ if (!mimeType)
326150
+ invalid3([...payloadPath, "src"], "Image bytes are not a PNG or JPEG raster.");
325654
326151
  totalBytes += bytes.length;
325655
326152
  if (totalBytes > MAX_V22_TOTAL_DECODED_BYTES2)
325656
326153
  invalid3(path7, "Fragment image bytes exceed the decoded asset limit.");
@@ -325658,7 +326155,7 @@ function createFragmentImageLowering(invalid3, unsupported4) {
325658
326155
  assets.push(asset);
325659
326156
  bySource.set(image.src, asset);
325660
326157
  }
325661
- const intrinsic = mimeType === "image/png" ? readPngDimensions(asset.bytes) : readJpegDimensions(asset.bytes);
326158
+ const intrinsic = asset.mimeType === "image/png" ? readPngDimensions(asset.bytes) : readJpegDimensions(asset.bytes);
325662
326159
  if (!intrinsic)
325663
326160
  invalid3([...payloadPath, "src"], "Image dimensions could not be determined.");
325664
326161
  const width = image.geometry?.width;
@@ -325666,8 +326163,8 @@ function createFragmentImageLowering(invalid3, unsupported4) {
325666
326163
  if (width === undefined !== (height === undefined)) {
325667
326164
  unsupported4([...payloadPath, "geometry"], "Rich inbound image geometry requires both width and height.");
325668
326165
  }
325669
- const widthPx = width === undefined ? intrinsic.widthPx : width * 4 / 3;
325670
- const heightPx = height === undefined ? intrinsic.heightPx : height * 4 / 3;
326166
+ const widthPx = width === undefined ? intrinsic.widthPx : Math.round(width * 4 / 3);
326167
+ const heightPx = height === undefined ? intrinsic.heightPx : Math.round(height * 4 / 3);
325671
326168
  if (![widthPx, heightPx].every((value2) => Number.isInteger(value2) && value2 >= 1 && value2 <= 1e4)) {
325672
326169
  invalid3([...payloadPath, "geometry"], "Image dimensions must map to integer pixels between 1 and 10000.");
325673
326170
  }
@@ -325675,14 +326172,26 @@ function createFragmentImageLowering(invalid3, unsupported4) {
325675
326172
  }
325676
326173
  };
325677
326174
  }
326175
+ function sniffRasterMime2(bytes) {
326176
+ if (bytes.length >= 8 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
326177
+ return "image/png";
326178
+ }
326179
+ if (bytes.length >= 2 && bytes[0] === 255 && bytes[1] === 216)
326180
+ return "image/jpeg";
326181
+ return null;
326182
+ }
325678
326183
  var init_fragment_images = __esm(() => {
325679
326184
  init_src3();
325680
326185
  });
325681
326186
 
325682
326187
  // ../../../v2/document-api-v2-adapter/dist/conversion/lower-fragment.js
325683
- function lowerFragmentToApplyPlan(fragment4) {
326188
+ function lowerFragmentToApplyPlan(fragment4, options = {}) {
326189
+ const maxOutputCodeUnits = options.maxOutputCodeUnits ?? DEFAULT_MAX_FRAGMENT_STRING_CODE_UNITS;
326190
+ if (!Number.isSafeInteger(maxOutputCodeUnits) || maxOutputCodeUnits < 1) {
326191
+ throw new TypeError("maxOutputCodeUnits must be a positive safe integer.");
326192
+ }
325684
326193
  try {
325685
- const stringViolation = inspectFragmentStringOutput(fragment4, DEFAULT_MAX_FRAGMENT_STRING_CODE_UNITS);
326194
+ const stringViolation = inspectFragmentStringOutput(fragment4, maxOutputCodeUnits);
325686
326195
  if (stringViolation?.kind === "xml") {
325687
326196
  invalid3(stringViolation.path, "Fragment strings must contain only XML 1.0-safe characters.");
325688
326197
  }
@@ -326089,51 +326598,100 @@ function romanOrdinal(core2, path7) {
326089
326598
  return positiveInteger(total, path7);
326090
326599
  }
326091
326600
  function lowerTable(node4, path7, images) {
326092
- if (node4.table.props || node4.table.columns) {
326093
- unsupported4([...path7, "table"], "Table properties and explicit columns are not materializable.");
326601
+ if (node4.table.props) {
326602
+ unsupported4([...path7, "table"], "Table properties are not materializable.");
326094
326603
  }
326604
+ let activeSpans = [];
326605
+ const rows = node4.table.rows.map((row, rowIndex) => {
326606
+ const rowPath = [...path7, "table", "rows", rowIndex];
326607
+ if (row.props && Object.keys(row.props).length > 0) {
326608
+ unsupported4([...rowPath, "props"], "Direct table-row properties are not materializable.");
326609
+ }
326610
+ const header = rowIndex === 0 && row.cells.length > 0 && row.cells.every((cell) => cell.header === true);
326611
+ const cells = [];
326612
+ let col = 0;
326613
+ let sourceIndex = 0;
326614
+ while (sourceIndex < row.cells.length || activeSpans.some((span) => span.remaining > 0 && span.col >= col)) {
326615
+ const continuation = activeSpans.find((span) => span.col === col && span.remaining > 0);
326616
+ if (continuation) {
326617
+ cells.push({
326618
+ blocks: [{ kind: "paragraph", runs: [] }],
326619
+ ...continuation.gridSpan > 1 ? { gridSpan: continuation.gridSpan } : {},
326620
+ vMerge: "continue"
326621
+ });
326622
+ continuation.remaining -= 1;
326623
+ col += continuation.gridSpan;
326624
+ continue;
326625
+ }
326626
+ if (sourceIndex >= row.cells.length) {
326627
+ const next = activeSpans.filter((span) => span.remaining > 0 && span.col > col).sort((a, b) => a.col - b.col)[0];
326628
+ if (!next)
326629
+ break;
326630
+ while (col < next.col) {
326631
+ cells.push({ blocks: [{ kind: "paragraph", runs: [] }] });
326632
+ col += 1;
326633
+ }
326634
+ continue;
326635
+ }
326636
+ const cell = row.cells[sourceIndex];
326637
+ const cellPath = [...rowPath, "cells", sourceIndex];
326638
+ sourceIndex += 1;
326639
+ const gridSpan = cell.colSpan === undefined ? 1 : tableGridSpan(cell.colSpan, [...cellPath, "colSpan"]);
326640
+ const rowSpan = cell.rowSpan === undefined ? 1 : positiveInteger(cell.rowSpan, [...cellPath, "rowSpan"]);
326641
+ if (col + gridSpan > MAX_WORD_TABLE_GRID_COLUMNS3) {
326642
+ invalid3([...rowPath, "cells"], `Table rows cannot exceed ${MAX_WORD_TABLE_GRID_COLUMNS3} grid columns.`);
326643
+ }
326644
+ if (cell.content.length === 0)
326645
+ invalid3([...cellPath, "content"], "Table cells must contain a paragraph.");
326646
+ const blocks = cell.content.flatMap((content3, contentIndex) => {
326647
+ const contentPath = [...cellPath, "content", contentIndex];
326648
+ const lowered = lowerTableCellContent(content3, contentPath, images);
326649
+ return cell.header ? lowered.map(emphasizeHeaderCellBlock) : lowered;
326650
+ });
326651
+ cells.push({
326652
+ blocks,
326653
+ sourcePath: cellPath,
326654
+ ...gridSpan > 1 ? { gridSpan } : {},
326655
+ ...rowSpan > 1 ? { vMerge: "restart" } : {},
326656
+ ...lowerCellProperties(cell.props, [...cellPath, "props"])
326657
+ });
326658
+ if (rowSpan > 1) {
326659
+ activeSpans.push({ col, gridSpan, remaining: rowSpan - 1 });
326660
+ }
326661
+ col += gridSpan;
326662
+ }
326663
+ activeSpans = activeSpans.filter((span) => span.remaining > 0);
326664
+ return {
326665
+ sourcePath: rowPath,
326666
+ ...header ? { header: true } : {},
326667
+ cells
326668
+ };
326669
+ });
326670
+ const columnCount = Math.max(1, ...rows.map((row) => row.cells.reduce((sum, cell) => sum + Math.max(1, cell.gridSpan ?? 1), 0)));
326671
+ const columnWidthShares = lowerPasteColumnWidthShares(node4.table.columns, columnCount, [...path7, "table", "columns"]);
326095
326672
  return {
326096
326673
  kind: "table",
326097
326674
  sourcePath: path7,
326098
326675
  ...node4.table.styleRef ? { styleRef: node4.table.styleRef } : {},
326099
- rows: node4.table.rows.map((row, rowIndex) => {
326100
- const rowPath = [...path7, "table", "rows", rowIndex];
326101
- if (row.props && Object.keys(row.props).length > 0) {
326102
- unsupported4([...rowPath, "props"], "Direct table-row properties are not materializable.");
326103
- }
326104
- const header = rowIndex === 0 && row.cells.length > 0 && row.cells.every((cell) => cell.header === true);
326105
- let rowGridColumns = 0;
326106
- return {
326107
- sourcePath: rowPath,
326108
- ...header ? { header: true } : {},
326109
- cells: row.cells.map((cell, cellIndex) => {
326110
- const cellPath = [...rowPath, "cells", cellIndex];
326111
- if (cell.rowSpan !== undefined && cell.rowSpan !== 1) {
326112
- unsupported4([...cellPath, "rowSpan"], "Vertically spanned table cells are not materializable.");
326113
- }
326114
- const gridSpan = cell.colSpan === undefined ? 1 : tableGridSpan(cell.colSpan, [...cellPath, "colSpan"]);
326115
- rowGridColumns += gridSpan;
326116
- if (rowGridColumns > MAX_WORD_TABLE_GRID_COLUMNS3) {
326117
- invalid3([...rowPath, "cells"], `Table rows cannot exceed ${MAX_WORD_TABLE_GRID_COLUMNS3} grid columns.`);
326118
- }
326119
- if (cell.content.length === 0)
326120
- invalid3([...cellPath, "content"], "Table cells must contain a paragraph.");
326121
- const blocks = cell.content.flatMap((content3, contentIndex) => {
326122
- const contentPath = [...cellPath, "content", contentIndex];
326123
- const lowered = lowerTableCellContent(content3, contentPath, images);
326124
- return cell.header ? lowered.map(emphasizeHeaderCellBlock) : lowered;
326125
- });
326126
- return {
326127
- blocks,
326128
- sourcePath: cellPath,
326129
- ...cell.colSpan !== undefined ? { gridSpan } : {},
326130
- ...lowerCellProperties(cell.props, [...cellPath, "props"])
326131
- };
326132
- })
326133
- };
326134
- })
326676
+ ...columnWidthShares ? { columnWidthShares } : {},
326677
+ rows
326135
326678
  };
326136
326679
  }
326680
+ function lowerPasteColumnWidthShares(columns, columnCount, path7) {
326681
+ if (!columns)
326682
+ return;
326683
+ if (columns.length !== columnCount) {
326684
+ unsupported4(path7, `Table columns must match the ${columnCount}-column paste grid.`);
326685
+ }
326686
+ const shares = columns.map((column, index2) => {
326687
+ const width = column.width;
326688
+ if (width === undefined || !Number.isFinite(width) || width <= 0) {
326689
+ unsupported4([...path7, index2, "width"], "Paste table column widths must be positive finite shares.");
326690
+ }
326691
+ return width;
326692
+ });
326693
+ return shares;
326694
+ }
326137
326695
  function lowerTableCellContent(content3, path7, images) {
326138
326696
  if (content3.kind === "paragraph") {
326139
326697
  return [lowerParagraph(content3.paragraph, path7, [...path7, "paragraph"], images)];
@@ -326191,6 +326749,10 @@ function lowerCellProperties(props, path7) {
326191
326749
  }
326192
326750
  shadingColor = props.shading.value.toUpperCase();
326193
326751
  }
326752
+ const verticalAlign = props.verticalAlign;
326753
+ if (verticalAlign !== undefined && verticalAlign !== "top" && verticalAlign !== "center" && verticalAlign !== "bottom") {
326754
+ unsupported4([...path7, "verticalAlign"], "Table-cell verticalAlign must be top, center, or bottom.");
326755
+ }
326194
326756
  const padding = props.padding ? {
326195
326757
  ...props.padding.top !== undefined ? { topPt: safeScaledNonnegative(props.padding.top, 20, [...path7, "padding", "top"]) } : {},
326196
326758
  ...props.padding.right !== undefined ? { rightPt: safeScaledNonnegative(props.padding.right, 20, [...path7, "padding", "right"]) } : {},
@@ -326203,8 +326765,8 @@ function lowerCellProperties(props, path7) {
326203
326765
  })) : undefined;
326204
326766
  return {
326205
326767
  ...shadingColor ? { shadingColor } : {},
326768
+ ...verticalAlign ? { verticalAlign } : {},
326206
326769
  ...padding && Object.keys(padding).length > 0 ? { padding } : {},
326207
- ...props.verticalAlign ? { verticalAlign: props.verticalAlign } : {},
326208
326770
  ...borders && Object.keys(borders).length > 0 ? { borders } : {}
326209
326771
  };
326210
326772
  }
@@ -327495,9 +328057,17 @@ function normalizeTableBlock(block, index2, version2) {
327495
328057
  if (block.cellSpacingPt !== undefined && !isSafePaddingPoints2(block.cellSpacingPt)) {
327496
328058
  return fail4("Paste table cellSpacingPt must be a non-negative finite point value within the safe twip range.");
327497
328059
  }
328060
+ let columnWidthShares;
328061
+ if (block.columnWidthShares !== undefined) {
328062
+ if (!Array.isArray(block.columnWidthShares) || block.columnWidthShares.length === 0 || block.columnWidthShares.length > MAX_WORD_TABLE_COLUMNS2 || block.columnWidthShares.some((share) => typeof share !== "number" || !Number.isFinite(share) || share <= 0)) {
328063
+ return fail4("Paste table columnWidthShares must contain positive finite shares within the column limit.");
328064
+ }
328065
+ columnWidthShares = [...block.columnWidthShares];
328066
+ }
327498
328067
  if (!Array.isArray(block.rows) || block.rows.length === 0)
327499
328068
  return fail4("Paste table blocks require rows.");
327500
328069
  const rows = [];
328070
+ let tableColumnCount2 = 0;
327501
328071
  for (const [rowIndex, row] of block.rows.entries()) {
327502
328072
  if (!isRecord14(row) || !Array.isArray(row.cells) || row.cells.length === 0) {
327503
328073
  return fail4("Paste table rows require cells.");
@@ -327535,6 +328105,9 @@ function normalizeTableBlock(block, index2, version2) {
327535
328105
  if (gridColumnCount > MAX_WORD_TABLE_COLUMNS2) {
327536
328106
  return fail4(`Paste table rows cannot span more than ${MAX_WORD_TABLE_COLUMNS2} grid columns.`);
327537
328107
  }
328108
+ if (cell.vMerge !== undefined && cell.vMerge !== "restart" && cell.vMerge !== "continue") {
328109
+ return fail4("Paste table cell vMerge must be restart or continue.");
328110
+ }
327538
328111
  let shadingColor;
327539
328112
  if (cell.shadingColor !== undefined) {
327540
328113
  if (typeof cell.shadingColor !== "string" || !/^#?[0-9a-f]{6}$/i.test(cell.shadingColor)) {
@@ -327612,6 +328185,7 @@ function normalizeTableBlock(block, index2, version2) {
327612
328185
  cells.push({
327613
328186
  blocks: cellBlocks,
327614
328187
  ...cell.gridSpan !== undefined ? { gridSpan: cell.gridSpan } : {},
328188
+ ...cell.vMerge !== undefined ? { vMerge: cell.vMerge } : {},
327615
328189
  ...shadingColor ? { shadingColor } : {},
327616
328190
  ...padding ? { padding } : {},
327617
328191
  ...verticalAlign ? { verticalAlign } : {},
@@ -327624,6 +328198,10 @@ function normalizeTableBlock(block, index2, version2) {
327624
328198
  ...row.header === true ? { header: true } : {},
327625
328199
  ...rowSourcePath ? { sourcePath: rowSourcePath } : {}
327626
328200
  });
328201
+ tableColumnCount2 = Math.max(tableColumnCount2, gridColumnCount);
328202
+ }
328203
+ if (columnWidthShares && columnWidthShares.length !== tableColumnCount2) {
328204
+ return fail4("Paste table columnWidthShares must contain one share per grid column.");
327627
328205
  }
327628
328206
  const sourcePath = normalizeSourcePath(block.sourcePath, ["blocks", index2, "sourcePath"]);
327629
328207
  if (isPlanFailure(sourcePath))
@@ -327632,6 +328210,7 @@ function normalizeTableBlock(block, index2, version2) {
327632
328210
  kind: "table",
327633
328211
  ...blockSdts ? { blockSdts } : {},
327634
328212
  rows,
328213
+ ...columnWidthShares ? { columnWidthShares } : {},
327635
328214
  ...block.cellSpacingPt !== undefined ? { cellSpacingPt: block.cellSpacingPt } : {},
327636
328215
  ...sourcePath ? { sourcePath } : {}
327637
328216
  };
@@ -328005,6 +328584,534 @@ var init_word_notes = __esm(() => {
328005
328584
  WORD_NOTE_SEPARATOR_BLOCK = /<(div|p)\b[^>]*\bmso-element\s*:\s*(?:footnote|endnote)(?:-continuation)?-separator\b[^>]*>[\s\S]*?<\/\1>/gi;
328006
328585
  });
328007
328586
 
328587
+ // ../../../v2/document-api-v2-adapter/dist/clipboard/word-vml-images.js
328588
+ function recoverWordVmlClipboardHtml(html, rtf, rasters = []) {
328589
+ const unchanged = { html, recoveredBase64CodeUnits: 0 };
328590
+ if (!html || !/<v:imagedata\b/i.test(html))
328591
+ return unchanged;
328592
+ const scanned = wordVmlShapeRanges(html);
328593
+ if (scanned === null)
328594
+ return { ...unchanged, sourceStructureExceeded: true };
328595
+ const shapes = scanned.shapes;
328596
+ if (shapes.length === 0)
328597
+ return unchanged;
328598
+ let recoveryBudget = MAX_WORD_IMAGE_RECOVERY_BYTES;
328599
+ const images = [
328600
+ ...extractRtfRasterImages(rtf ?? "", () => recoveryBudget, (spent) => {
328601
+ recoveryBudget -= spent;
328602
+ }),
328603
+ ...rasters.flatMap((raster) => {
328604
+ if (recoveryBudget <= 0)
328605
+ return [];
328606
+ if (raster.mime === "image/png" ? !isPng(raster.bytes) : !isJpeg(raster.bytes))
328607
+ return [];
328608
+ if (raster.bytes.byteLength > recoveryBudget)
328609
+ return [];
328610
+ recoveryBudget -= raster.bytes.byteLength;
328611
+ const dims = raster.mime === "image/png" ? readPngDimensions(raster.bytes) : readJpegDimensions(raster.bytes);
328612
+ return [
328613
+ {
328614
+ mime: raster.mime,
328615
+ bytes: raster.bytes,
328616
+ aspect: dims && dims.heightPx > 0 ? dims.widthPx / dims.heightPx : null,
328617
+ fromRtf: false
328618
+ }
328619
+ ];
328620
+ })
328621
+ ];
328622
+ if (images.length === 0)
328623
+ return unchanged;
328624
+ const used = new Set;
328625
+ reserveExplicitRasterImages(images, scanned.explicitImageSources, used);
328626
+ const parts = [];
328627
+ let copiedThrough = 0;
328628
+ let recoveredBase64CodeUnits = 0;
328629
+ for (const shape of shapes) {
328630
+ if (!isWordClipImageSrc(shape.src))
328631
+ continue;
328632
+ const { widthPt, heightPt } = readShapePointSize(shape.openTag);
328633
+ const shapeAspect = widthPt !== null && heightPt !== null && heightPt > 0 ? widthPt / heightPt : null;
328634
+ const imageIndex = pickRasterIndex(images, used, shapeAspect);
328635
+ if (imageIndex === null)
328636
+ continue;
328637
+ used.add(imageIndex);
328638
+ const image = images[imageIndex];
328639
+ const sizeAttr = widthPt !== null && heightPt !== null ? ` style="width:${formatPointAttr(widthPt)}pt;height:${formatPointAttr(heightPt)}pt"` : widthPt !== null ? ` style="width:${formatPointAttr(widthPt)}pt"` : heightPt !== null ? ` style="height:${formatPointAttr(heightPt)}pt"` : "";
328640
+ const base643 = bytesToBase642(image.bytes);
328641
+ recoveredBase64CodeUnits += base643.length;
328642
+ const img = `<img${sizeAttr} src="data:${image.mime};base64,${base643}">`;
328643
+ parts.push(html.slice(copiedThrough, shape.start), shape.hiddenByComment ? `-->${img}<!--` : img);
328644
+ copiedThrough = shape.end;
328645
+ }
328646
+ if (copiedThrough === 0)
328647
+ return unchanged;
328648
+ parts.push(html.slice(copiedThrough));
328649
+ return { html: parts.join(""), recoveredBase64CodeUnits };
328650
+ }
328651
+ function reserveExplicitRasterImages(images, sources, used) {
328652
+ if (sources.length === 0)
328653
+ return;
328654
+ const occurrences = new Map;
328655
+ for (const [index2, image] of images.entries()) {
328656
+ const key2 = bytesToBase642(image.bytes);
328657
+ const matching = occurrences.get(key2);
328658
+ if (matching)
328659
+ matching.indices.push(index2);
328660
+ else
328661
+ occurrences.set(key2, { indices: [index2], next: 0 });
328662
+ }
328663
+ for (const source of sources) {
328664
+ const match = /^data:image\/(?:png|jpeg|jpg);base64,([\s\S]*)$/i.exec(source.trim());
328665
+ if (!match)
328666
+ continue;
328667
+ const bytes = base64ToBytes(match[1].replace(/\s+/g, ""), MAX_WORD_IMAGE_RECOVERY_BYTES);
328668
+ if (!bytes)
328669
+ continue;
328670
+ const matching = occurrences.get(bytesToBase642(bytes));
328671
+ const index2 = matching?.indices[matching.next];
328672
+ if (index2 === undefined)
328673
+ continue;
328674
+ matching.next++;
328675
+ used.add(index2);
328676
+ }
328677
+ }
328678
+ function wordVmlShapeRanges(html) {
328679
+ if (html.length > DEFAULT_HTML_CONVERSION_LIMITS.maxSourceCodeUnits)
328680
+ return null;
328681
+ const ranges = [];
328682
+ const stack = [];
328683
+ const parseBudget = { nodes: 0, sourceCodeUnits: 0 };
328684
+ const parsed = ignoredHtmlImageRegions(html, parseBudget);
328685
+ if (parsed === null)
328686
+ return null;
328687
+ const { ignoredRegions, explicitImageSources } = parsed;
328688
+ const commentEnds = /--!?>/g;
328689
+ let conditionalCommentEnd = null;
328690
+ let cursor = 0;
328691
+ while (cursor < html.length) {
328692
+ const start = html.indexOf("<", cursor);
328693
+ if (start < 0)
328694
+ break;
328695
+ if (conditionalCommentEnd !== null && start >= conditionalCommentEnd)
328696
+ conditionalCommentEnd = null;
328697
+ const ignoredEnd = ignoredRegions.get(start);
328698
+ if (ignoredEnd !== undefined) {
328699
+ cursor = ignoredEnd;
328700
+ continue;
328701
+ }
328702
+ if (html.startsWith("<!--", start)) {
328703
+ if (html.startsWith("<!-->", start)) {
328704
+ cursor = start + 5;
328705
+ continue;
328706
+ }
328707
+ commentEnds.lastIndex = start + 4;
328708
+ const close = commentEnds.exec(html);
328709
+ if (!close)
328710
+ break;
328711
+ if (conditionalCommentEnd === null && close[0] === "-->" && /^<!--\[if\b/i.test(html.slice(start, start + 12))) {
328712
+ let headerEnd = start + 7;
328713
+ while (headerEnd < close.index && !(html[headerEnd] === "]" && html[headerEnd + 1] === ">"))
328714
+ headerEnd++;
328715
+ if (headerEnd < close.index && !html.startsWith("<!-->", headerEnd + 2)) {
328716
+ const bodyStart = headerEnd + 2;
328717
+ const bodyRegions = ignoredHtmlImageRegions(html.slice(bodyStart, close.index), parseBudget);
328718
+ if (bodyRegions === null)
328719
+ return null;
328720
+ for (const [regionStart, regionEnd] of bodyRegions.ignoredRegions) {
328721
+ ignoredRegions.set(bodyStart + regionStart, bodyStart + regionEnd);
328722
+ }
328723
+ conditionalCommentEnd = commentEnds.lastIndex;
328724
+ cursor = bodyStart;
328725
+ continue;
328726
+ }
328727
+ }
328728
+ cursor = commentEnds.lastIndex;
328729
+ continue;
328730
+ }
328731
+ const closing = html[start + 1] === "/";
328732
+ const nameStart = start + (closing ? 2 : 1);
328733
+ if (!/[a-z]/i.test(html[nameStart] ?? "")) {
328734
+ cursor = nameStart;
328735
+ continue;
328736
+ }
328737
+ let nameEnd = nameStart;
328738
+ while (nameEnd < html.length && !/[\t\n\f\r />]/.test(html[nameEnd]))
328739
+ nameEnd++;
328740
+ const name = html.slice(nameStart, nameEnd).toLowerCase();
328741
+ const tag = readHtmlTagEnd(html, nameEnd);
328742
+ if (tag === null)
328743
+ break;
328744
+ cursor = tag.end;
328745
+ if (name === "v:shape") {
328746
+ if (closing) {
328747
+ const shape = stack.pop();
328748
+ if (shape && !shape.nested && shape.src !== null && shape.commentEnd === conditionalCommentEnd) {
328749
+ ranges.push({
328750
+ start: shape.start,
328751
+ end: cursor,
328752
+ openTag: shape.openTag,
328753
+ src: shape.src,
328754
+ hiddenByComment: shape.commentEnd !== null
328755
+ });
328756
+ }
328757
+ } else if (!tag.selfClosing) {
328758
+ const parent = stack.at(-1);
328759
+ if (parent)
328760
+ parent.nested = true;
328761
+ stack.push({ start, openTag: html.slice(start, cursor), src: null, nested: false, commentEnd: conditionalCommentEnd });
328762
+ }
328763
+ } else if (name === "v:imagedata" && !closing) {
328764
+ const shape = stack.at(-1);
328765
+ if (shape && shape.src === null)
328766
+ shape.src = readTagAttribute(html.slice(start, cursor), "src");
328767
+ }
328768
+ }
328769
+ return { shapes: ranges, explicitImageSources };
328770
+ }
328771
+ function ignoredHtmlImageRegions(html, budget) {
328772
+ budget.sourceCodeUnits += html.length;
328773
+ if (budget.sourceCodeUnits > 2 * DEFAULT_HTML_CONVERSION_LIMITS.maxSourceCodeUnits)
328774
+ return null;
328775
+ const overflow = new Error("Word image recovery source exceeds HTML structure limits.");
328776
+ let depth = -1;
328777
+ const reserveNode = () => {
328778
+ if (++budget.nodes > DEFAULT_HTML_CONVERSION_LIMITS.maxNodes + 2)
328779
+ throw overflow;
328780
+ };
328781
+ const detachedFront = new WeakMap;
328782
+ const queuedParents = new Set;
328783
+ const compactChildren = (parent) => {
328784
+ const count = detachedFront.get(parent);
328785
+ if (count === undefined)
328786
+ return;
328787
+ parent.childNodes.splice(0, count);
328788
+ detachedFront.delete(parent);
328789
+ queuedParents.delete(parent);
328790
+ };
328791
+ const treeAdapter = {
328792
+ ...defaultTreeAdapter,
328793
+ createElement(...args) {
328794
+ reserveNode();
328795
+ return defaultTreeAdapter.createElement(...args);
328796
+ },
328797
+ createCommentNode(data) {
328798
+ reserveNode();
328799
+ return defaultTreeAdapter.createCommentNode(data);
328800
+ },
328801
+ detachNode(node4) {
328802
+ const parent = node4.parentNode;
328803
+ if (parent === null)
328804
+ return;
328805
+ const first = detachedFront.get(parent) ?? 0;
328806
+ if (parent.childNodes[first] === node4) {
328807
+ detachedFront.set(parent, first + 1);
328808
+ queuedParents.add(parent);
328809
+ node4.parentNode = null;
328810
+ } else {
328811
+ compactChildren(parent);
328812
+ defaultTreeAdapter.detachNode(node4);
328813
+ }
328814
+ },
328815
+ getFirstChild(parent) {
328816
+ return parent.childNodes[detachedFront.get(parent) ?? 0] ?? null;
328817
+ },
328818
+ getChildNodes(parent) {
328819
+ compactChildren(parent);
328820
+ return defaultTreeAdapter.getChildNodes(parent);
328821
+ },
328822
+ insertBefore(parent, node4, reference) {
328823
+ compactChildren(parent);
328824
+ defaultTreeAdapter.insertBefore(parent, node4, reference);
328825
+ },
328826
+ insertText(parent, text4) {
328827
+ compactChildren(parent);
328828
+ if (parent.childNodes.at(-1)?.nodeName !== "#text")
328829
+ reserveNode();
328830
+ defaultTreeAdapter.insertText(parent, text4);
328831
+ },
328832
+ insertTextBefore(parent, text4, reference) {
328833
+ compactChildren(parent);
328834
+ if (parent.childNodes[parent.childNodes.indexOf(reference) - 1]?.nodeName !== "#text")
328835
+ reserveNode();
328836
+ defaultTreeAdapter.insertTextBefore(parent, text4, reference);
328837
+ },
328838
+ onItemPush() {
328839
+ if (++depth > DEFAULT_HTML_CONVERSION_LIMITS.maxNestingDepth)
328840
+ throw overflow;
328841
+ },
328842
+ onItemPop() {
328843
+ depth--;
328844
+ }
328845
+ };
328846
+ let fragment4;
328847
+ try {
328848
+ fragment4 = parseFragment(html, { sourceCodeLocationInfo: true, treeAdapter });
328849
+ } catch (error48) {
328850
+ if (error48 === overflow)
328851
+ return null;
328852
+ throw error48;
328853
+ }
328854
+ for (const parent of queuedParents)
328855
+ compactChildren(parent);
328856
+ const pending = [...fragment4.childNodes];
328857
+ const ignored = new Map;
328858
+ const explicitImageSources = [];
328859
+ while (pending.length > 0) {
328860
+ const node4 = pending.pop();
328861
+ if (!("tagName" in node4))
328862
+ continue;
328863
+ const textOnly = node4.namespaceURI === "http://www.w3.org/1999/xhtml" && (TEXT_ONLY_ELEMENTS.has(node4.tagName) || node4.tagName === "script" || node4.tagName === "plaintext");
328864
+ if (textOnly || DISCARDED_IMAGE_SUBTREES.has(node4.tagName)) {
328865
+ const location2 = node4.sourceCodeLocation;
328866
+ if (location2) {
328867
+ const end = textOnly && !location2.endTag ? html.length : location2.endOffset;
328868
+ if (end > location2.startOffset)
328869
+ ignored.set(location2.startOffset, end);
328870
+ }
328871
+ continue;
328872
+ }
328873
+ if (node4.tagName === "img" && node4.namespaceURI === "http://www.w3.org/1999/xhtml") {
328874
+ const source = node4.attrs.find((attribute) => attribute.name === "src")?.value;
328875
+ if (source)
328876
+ explicitImageSources.push(source);
328877
+ }
328878
+ for (const child of node4.childNodes)
328879
+ pending.push(child);
328880
+ }
328881
+ return { ignoredRegions: ignored, explicitImageSources };
328882
+ }
328883
+ function readHtmlTagEnd(html, start) {
328884
+ let state = "before-name";
328885
+ let quote = "";
328886
+ for (let cursor = start;cursor < html.length; cursor++) {
328887
+ const char = html[cursor];
328888
+ if (state === "quoted") {
328889
+ if (char === quote)
328890
+ state = "after-quoted";
328891
+ continue;
328892
+ }
328893
+ if (char === ">")
328894
+ return { end: cursor + 1, selfClosing: state !== "unquoted" && html[cursor - 1] === "/" };
328895
+ const space = /[\t\n\f\r ]/.test(char);
328896
+ if (state === "unquoted") {
328897
+ if (space)
328898
+ state = "before-name";
328899
+ } else if (state === "before-value") {
328900
+ if (space)
328901
+ continue;
328902
+ if (char === '"' || char === "'") {
328903
+ quote = char;
328904
+ state = "quoted";
328905
+ } else
328906
+ state = "unquoted";
328907
+ } else if (state === "name") {
328908
+ if (space)
328909
+ state = "after-name";
328910
+ else if (char === "=")
328911
+ state = "before-value";
328912
+ else if (char === "/")
328913
+ state = "before-name";
328914
+ } else if (state === "after-name" && char === "=") {
328915
+ state = "before-value";
328916
+ } else if (!space && char !== "/") {
328917
+ state = "name";
328918
+ } else if (char === "/") {
328919
+ state = "before-name";
328920
+ }
328921
+ }
328922
+ return null;
328923
+ }
328924
+ function readTagAttribute(tag, name) {
328925
+ const attributes = /([^\s=<>/]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+)))?/g;
328926
+ for (const match of tag.matchAll(attributes)) {
328927
+ if (match[1].toLowerCase() === name)
328928
+ return match[2] ?? match[3] ?? match[4] ?? "";
328929
+ }
328930
+ return null;
328931
+ }
328932
+ function pickRasterIndex(images, used, shapeAspect) {
328933
+ const unusedRtf = images.findIndex((image, index2) => image.fromRtf && !used.has(index2));
328934
+ if (unusedRtf >= 0)
328935
+ return unusedRtf;
328936
+ let bestClipboard = null;
328937
+ let bestClipboardError = Number.POSITIVE_INFINITY;
328938
+ for (let index2 = 0;index2 < images.length; index2 += 1) {
328939
+ if (used.has(index2))
328940
+ continue;
328941
+ const image = images[index2];
328942
+ if (image.fromRtf)
328943
+ continue;
328944
+ if (shapeAspect === null || image.aspect === null || shapeAspect <= 0 || image.aspect <= 0) {
328945
+ continue;
328946
+ }
328947
+ const error48 = Math.abs(image.aspect - shapeAspect) / Math.max(image.aspect, shapeAspect);
328948
+ if (error48 <= CLIPBOARD_ASPECT_TOLERANCE && error48 < bestClipboardError) {
328949
+ bestClipboard = index2;
328950
+ bestClipboardError = error48;
328951
+ }
328952
+ }
328953
+ return bestClipboard;
328954
+ }
328955
+ function isWordClipImageSrc(src) {
328956
+ const value2 = src.trim().toLowerCase();
328957
+ if (!value2.startsWith("file:"))
328958
+ return false;
328959
+ return /clip_image\d+\.(?:png|jpe?g|gif)/i.test(value2) || value2.includes("msohtmlclip");
328960
+ }
328961
+ function extractRtfRasterImages(rtf, remaining, spend) {
328962
+ if (!rtf || rtf.length > MAX_WORD_RTF_RECOVERY_CHARACTERS)
328963
+ return [];
328964
+ const out = [];
328965
+ const controls = new RegExp(RTF_RASTER_CONTROL_RE);
328966
+ let match;
328967
+ while (match = controls.exec(rtf)) {
328968
+ if (remaining() <= 0)
328969
+ break;
328970
+ const picture = readRtfPictureData(rtf, controls.lastIndex);
328971
+ controls.lastIndex = picture.end;
328972
+ if (!picture.data)
328973
+ continue;
328974
+ const kind = match[1] === "jpegblip" ? "image/jpeg" : "image/png";
328975
+ const byteLength = picture.data.hexDigits / 2;
328976
+ if (byteLength > remaining())
328977
+ continue;
328978
+ const bytes = new Uint8Array(byteLength);
328979
+ let highNibble = -1;
328980
+ let byteIndex = 0;
328981
+ for (let index2 = picture.data.start;index2 < picture.data.end; index2++) {
328982
+ const nibble = hexNibble(rtf.charCodeAt(index2));
328983
+ if (nibble < 0)
328984
+ continue;
328985
+ if (highNibble < 0)
328986
+ highNibble = nibble;
328987
+ else {
328988
+ bytes[byteIndex++] = highNibble << 4 | nibble;
328989
+ highNibble = -1;
328990
+ }
328991
+ }
328992
+ if (kind === "image/png" && !isPng(bytes))
328993
+ continue;
328994
+ if (kind === "image/jpeg" && !isJpeg(bytes))
328995
+ continue;
328996
+ spend(bytes.byteLength);
328997
+ const dims = kind === "image/png" ? readPngDimensions(bytes) : readJpegDimensions(bytes);
328998
+ out.push({
328999
+ mime: kind,
329000
+ bytes,
329001
+ aspect: dims && dims.heightPx > 0 ? dims.widthPx / dims.heightPx : null,
329002
+ fromRtf: true
329003
+ });
329004
+ }
329005
+ return out;
329006
+ }
329007
+ function readRtfPictureData(rtf, start) {
329008
+ let cursor = start;
329009
+ const skipWhitespace2 = () => {
329010
+ while (cursor < rtf.length && isRtfWhitespace(rtf.charCodeAt(cursor)))
329011
+ cursor++;
329012
+ };
329013
+ while (cursor < rtf.length) {
329014
+ skipWhitespace2();
329015
+ if (rtf[cursor] === "\\") {
329016
+ cursor++;
329017
+ const controlStart = cursor;
329018
+ while (cursor < rtf.length && /[a-z]/.test(rtf[cursor]))
329019
+ cursor++;
329020
+ if (cursor === controlStart)
329021
+ return { end: cursor, data: null };
329022
+ if (rtf[cursor] === "-")
329023
+ cursor++;
329024
+ while (cursor < rtf.length && /\d/.test(rtf[cursor]))
329025
+ cursor++;
329026
+ } else if (rtf.startsWith("{\\*\\blipuid", cursor)) {
329027
+ cursor += "{\\*\\blipuid".length;
329028
+ skipWhitespace2();
329029
+ const uidStart = cursor;
329030
+ while (cursor < rtf.length && (hexNibble(rtf.charCodeAt(cursor)) >= 0 || isRtfWhitespace(rtf.charCodeAt(cursor))))
329031
+ cursor++;
329032
+ if (cursor === uidStart || rtf[cursor] !== "}")
329033
+ return { end: cursor, data: null };
329034
+ cursor++;
329035
+ } else
329036
+ break;
329037
+ }
329038
+ const dataStart = cursor;
329039
+ let hexDigits = 0;
329040
+ while (cursor < rtf.length) {
329041
+ const code2 = rtf.charCodeAt(cursor);
329042
+ if (hexNibble(code2) >= 0)
329043
+ hexDigits++;
329044
+ else if (!isRtfWhitespace(code2))
329045
+ break;
329046
+ cursor++;
329047
+ }
329048
+ if (rtf[cursor] !== "}" || hexDigits < 16 || hexDigits % 2 !== 0)
329049
+ return { end: cursor, data: null };
329050
+ return { end: cursor + 1, data: { start: dataStart, end: cursor, hexDigits } };
329051
+ }
329052
+ function isRtfWhitespace(code2) {
329053
+ return code2 === 32 || code2 === 9 || code2 === 10 || code2 === 13;
329054
+ }
329055
+ function hexNibble(code2) {
329056
+ if (code2 >= 48 && code2 <= 57)
329057
+ return code2 - 48;
329058
+ if (code2 >= 65 && code2 <= 70)
329059
+ return code2 - 65 + 10;
329060
+ if (code2 >= 97 && code2 <= 102)
329061
+ return code2 - 97 + 10;
329062
+ return -1;
329063
+ }
329064
+ function readShapePointSize(shape) {
329065
+ const style = readTagAttribute(shape, "style") ?? "";
329066
+ return {
329067
+ widthPt: cssLengthPoints2(style, "width"),
329068
+ heightPt: cssLengthPoints2(style, "height")
329069
+ };
329070
+ }
329071
+ function formatPointAttr(points) {
329072
+ return String(Math.round(points * 100) / 100);
329073
+ }
329074
+ function cssLengthPoints2(style, property2) {
329075
+ const match = style.match(new RegExp(`(?:^|;)\\s*${property2}\\s*:\\s*([^;]+)`, "i"));
329076
+ if (!match)
329077
+ return null;
329078
+ const token = match[1].trim().toLowerCase();
329079
+ const length = token.match(/^(-?(?:\d+(?:\.\d+)?|\.\d+))(px|pt|in|cm|mm)$/i);
329080
+ if (!length)
329081
+ return null;
329082
+ const amount = Number.parseFloat(length[1]);
329083
+ if (!Number.isFinite(amount) || amount <= 0)
329084
+ return null;
329085
+ const unit = length[2].toLowerCase();
329086
+ const factor = { px: 0.75, pt: 1, in: 72, cm: 72 / 2.54, mm: 72 / 25.4 }[unit];
329087
+ return factor === undefined ? null : amount * factor;
329088
+ }
329089
+ function bytesToBase642(bytes) {
329090
+ let binary = "";
329091
+ const chunk = 32768;
329092
+ for (let i2 = 0;i2 < bytes.length; i2 += chunk) {
329093
+ binary += String.fromCharCode(...bytes.subarray(i2, i2 + chunk));
329094
+ }
329095
+ return btoa(binary);
329096
+ }
329097
+ function isPng(bytes) {
329098
+ return bytes.length >= 8 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71;
329099
+ }
329100
+ function isJpeg(bytes) {
329101
+ return bytes.length >= 2 && bytes[0] === 255 && bytes[1] === 216;
329102
+ }
329103
+ var RTF_RASTER_CONTROL_RE, CLIPBOARD_ASPECT_TOLERANCE = 0.2, MAX_WORD_IMAGE_RECOVERY_BYTES, MAX_WORD_RECOVERED_BASE64_CODE_UNITS, MAX_WORD_RTF_RECOVERY_CHARACTERS, TEXT_ONLY_ELEMENTS, DISCARDED_IMAGE_SUBTREES;
329104
+ var init_word_vml_images = __esm(() => {
329105
+ init_dist3();
329106
+ init_limits();
329107
+ RTF_RASTER_CONTROL_RE = /\\(pngblip|jpegblip)\b/g;
329108
+ MAX_WORD_IMAGE_RECOVERY_BYTES = 16 * 1024 * 1024;
329109
+ MAX_WORD_RECOVERED_BASE64_CODE_UNITS = 2 * MAX_WORD_IMAGE_RECOVERY_BYTES;
329110
+ MAX_WORD_RTF_RECOVERY_CHARACTERS = 40 * 1024 * 1024;
329111
+ TEXT_ONLY_ELEMENTS = new Set(["title", "textarea", "style", "xmp", "iframe", "noembed", "noframes", "noscript"]);
329112
+ DISCARDED_IMAGE_SUBTREES = new Set(["template", "object", "applet", "canvas", "video", "audio", "svg", "math", "picture"]);
329113
+ });
329114
+
328008
329115
  // ../../../v2/document-api-v2-adapter/dist/clipboard/plan.js
328009
329116
  function createClipboardInsertPlan(payload, options = {}) {
328010
329117
  const richItem = payload.items.find((item) => item.type === SUPERDOC_V22_CLIPBOARD_MIME);
@@ -328022,7 +329129,7 @@ function createClipboardInsertPlan(payload, options = {}) {
328022
329129
  ];
328023
329130
  }
328024
329131
  }
328025
- const byteCount = estimatePayloadBytes(payload.items.filter((item) => item.type !== SUPERDOC_V22_CLIPBOARD_MIME));
329132
+ const byteCount = estimatePastePlanBytes(payload.items);
328026
329133
  if (byteCount > (options.maxBytes ?? DEFAULT_MAX_CLIPBOARD_BYTES))
328027
329134
  return failPlan("paste-payload-too-large", "Clipboard payload exceeds the configured size cap.", "unknown");
328028
329135
  const v2 = parseV2FragmentPayload(payload);
@@ -328090,7 +329197,7 @@ function planFromPlainText(text4, plainFallback) {
328090
329197
  }
328091
329198
  function createPortableHtmlInsertPlan(payload, options = {}) {
328092
329199
  const portable = { ...payload, items: payload.items.filter((item) => item.type === "text/html" || item.type === "text/plain") };
328093
- if (estimatePayloadBytes(portable.items) > (options.maxBytes ?? DEFAULT_MAX_CLIPBOARD_BYTES)) {
329200
+ if (estimatePastePlanBytes(portable.items) > (options.maxBytes ?? DEFAULT_MAX_CLIPBOARD_BYTES)) {
328094
329201
  return failPlan("paste-payload-too-large", "Clipboard payload exceeds the configured size cap.", "html");
328095
329202
  }
328096
329203
  const html = readStringItem(portable, "text/html");
@@ -328099,8 +329206,30 @@ function createPortableHtmlInsertPlan(payload, options = {}) {
328099
329206
  return planFromHtml(portable, html, options, true);
328100
329207
  }
328101
329208
  function planFromHtml(payload, html, options, rejectUnsafeContent = false) {
328102
- const rewritten = rewriteWordNoteClipboardHtml(html);
328103
- const converted = convertContentToFragment({ format: "html", source: rewritten });
329209
+ if (html.length > DEFAULT_HTML_CONVERSION_LIMITS.maxSourceCodeUnits) {
329210
+ return failPlan("paste-payload-too-large", "HTML clipboard source exceeds its size cap.", "html");
329211
+ }
329212
+ const rtf = readStringItem(payload, "text/rtf");
329213
+ if (rtf && rtf.length > MAX_WORD_RTF_RECOVERY_CHARACTERS && /<v:imagedata\b/i.test(html)) {
329214
+ return failPlan("paste-payload-too-large", "Word RTF image recovery payload exceeds its size cap.", "html");
329215
+ }
329216
+ const recovered = recoverWordVmlClipboardHtml(rewriteWordNoteClipboardHtml(html), rtf, clipboardRasterImages(payload));
329217
+ if (recovered.sourceStructureExceeded) {
329218
+ return failPlan("paste-structure-unsupported", "Word image recovery source exceeds HTML structure limits.", "html");
329219
+ }
329220
+ const allowance = recovered.recoveredBase64CodeUnits;
329221
+ if (!Number.isSafeInteger(allowance) || allowance < 0 || allowance > MAX_WORD_RECOVERED_BASE64_CODE_UNITS) {
329222
+ return failPlan("paste-payload-too-large", "Recovered image data exceeds its size cap.", "html");
329223
+ }
329224
+ const rewritten = recovered.html;
329225
+ const converted = convertContentToFragment({
329226
+ format: "html",
329227
+ source: rewritten,
329228
+ options: { limits: {
329229
+ maxSourceCodeUnits: DEFAULT_HTML_CONVERSION_LIMITS.maxSourceCodeUnits + allowance,
329230
+ maxOutputCodeUnits: DEFAULT_HTML_CONVERSION_LIMITS.maxOutputCodeUnits + allowance
329231
+ } }
329232
+ });
328104
329233
  const diagnostics = converted.diagnostics.map(toClipboardHtmlDiagnostic);
328105
329234
  if (rejectUnsafeContent && diagnostics.some((entry) => entry.reason === "paste-security-rejected")) {
328106
329235
  return failPlan("paste-security-rejected", "The portable HTML flavor contains unsafe content.", "html");
@@ -328109,7 +329238,9 @@ function planFromHtml(payload, html, options, rejectUnsafeContent = false) {
328109
329238
  if (fatal) {
328110
329239
  return fallbackFromFatalHtml(payload, options, fatal, diagnostics);
328111
329240
  }
328112
- const lowered = lowerFragmentToApplyPlan(converted.fragment);
329241
+ const lowered = lowerFragmentToApplyPlan(converted.fragment, {
329242
+ maxOutputCodeUnits: DEFAULT_MAX_FRAGMENT_STRING_CODE_UNITS + allowance
329243
+ });
328113
329244
  if (!lowered.ok) {
328114
329245
  const reason = lowered.code === "INVALID_PAYLOAD" ? "paste-structure-unsupported" : "paste-no-faithful-representation";
328115
329246
  return fallbackOrFail(payload, options, reason, lowered.message);
@@ -328233,6 +329364,19 @@ function sourceKindForPayload(payload) {
328233
329364
  return "plain-text";
328234
329365
  return "unknown";
328235
329366
  }
329367
+ function clipboardRasterImages(payload) {
329368
+ const out = [];
329369
+ for (const item of payload.items) {
329370
+ if (item.kind !== "bytes" || !(item.data instanceof Uint8Array) || item.data.length === 0)
329371
+ continue;
329372
+ const type = item.type.toLowerCase();
329373
+ if (type === "image/png")
329374
+ out.push({ mime: "image/png", bytes: item.data });
329375
+ else if (type === "image/jpeg" || type === "image/jpg")
329376
+ out.push({ mime: "image/jpeg", bytes: item.data });
329377
+ }
329378
+ return out;
329379
+ }
328236
329380
  function readStringItem(payload, type) {
328237
329381
  const item = payload.items.find((candidate2) => candidate2.type === type);
328238
329382
  return item?.kind === "string" && typeof item.data === "string" ? item.data : null;
@@ -328270,8 +329414,15 @@ function readHtmlAttribute(tag, name) {
328270
329414
  const match = new RegExp(`\\b${escaped}\\s*=\\s*(["'])([\\s\\S]*?)\\1`, "i").exec(tag);
328271
329415
  return match?.[2] ?? null;
328272
329416
  }
328273
- function estimatePayloadBytes(items) {
328274
- return items.reduce((sum, item) => sum + estimateClipboardItemBytes(item), 0);
329417
+ function estimatePastePlanBytes(items) {
329418
+ const hasHtml = items.some((item) => item.type === "text/html" && item.kind === "string" && item.data.length > 0);
329419
+ return items.reduce((sum, item) => {
329420
+ if (item.type === SUPERDOC_V22_CLIPBOARD_MIME)
329421
+ return sum;
329422
+ if (hasHtml && (item.type.startsWith("image/") || item.type === "text/rtf"))
329423
+ return sum;
329424
+ return sum + estimateClipboardItemBytes(item);
329425
+ }, 0);
328275
329426
  }
328276
329427
  function estimateClipboardItemBytes(item) {
328277
329428
  if (item.kind === "bytes" && item.data instanceof Uint8Array)
@@ -328282,6 +329433,8 @@ var UTF8_ENCODER2;
328282
329433
  var init_plan3 = __esm(() => {
328283
329434
  init_src3();
328284
329435
  init_convert_to_fragment();
329436
+ init_limits();
329437
+ init_fragment_output_budget();
328285
329438
  init_lower_fragment();
328286
329439
  init_contracts();
328287
329440
  init_media();
@@ -328289,6 +329442,7 @@ var init_plan3 = __esm(() => {
328289
329442
  init_parse_v1_slice();
328290
329443
  init_parse_v2_fragment();
328291
329444
  init_word_notes();
329445
+ init_word_vml_images();
328292
329446
  UTF8_ENCODER2 = new TextEncoder;
328293
329447
  });
328294
329448
 
@@ -342010,10 +343164,10 @@ function resolveCreateTableContentWidthTwips(context, at, insertionByte) {
342010
343164
  const section = location2.kind === "documentStart" ? sections[0] : location2.kind === "documentEnd" ? sections[sections.length - 1] : sections.find((candidate2) => candidate2.sourceAnchor.stability === "byte-span" && candidate2.sourceAnchor.byteSpan[1] >= insertionByte) ?? sections[sections.length - 1];
342011
343165
  const pageSetup = section?.pageSetup;
342012
343166
  const pageWidth = pageSetup?.pageSize?.widthTwips ?? DEFAULT_PAGE_WIDTH_TWIPS;
342013
- const leftMargin = pageSetup?.margins?.leftTwips ?? DEFAULT_PAGE_MARGIN_TWIPS;
342014
- const rightMargin = pageSetup?.margins?.rightTwips ?? DEFAULT_PAGE_MARGIN_TWIPS;
343167
+ const leftMargin = pageSetup?.margins?.leftTwips ?? DEFAULT_PAGE_MARGIN_TWIPS2;
343168
+ const rightMargin = pageSetup?.margins?.rightTwips ?? DEFAULT_PAGE_MARGIN_TWIPS2;
342015
343169
  const contentWidth = pageWidth - leftMargin - rightMargin;
342016
- return Number.isFinite(contentWidth) && contentWidth > 0 ? Math.round(contentWidth) : DEFAULT_PAGE_WIDTH_TWIPS - 2 * DEFAULT_PAGE_MARGIN_TWIPS;
343170
+ return Number.isFinite(contentWidth) && contentWidth > 0 ? Math.round(contentWidth) : DEFAULT_PAGE_WIDTH_TWIPS - 2 * DEFAULT_PAGE_MARGIN_TWIPS2;
342017
343171
  }
342018
343172
  function hasDirectTableStyle(model) {
342019
343173
  const tblPr = parsePropertiesChildren(model.tblPrXml, "tblPr", model.prefix);
@@ -342795,7 +343949,7 @@ function writeAfterPropertyXml(model, spec, wrappedXml) {
342795
343949
  }
342796
343950
  }
342797
343951
  }
342798
- var COLLABORATIVE_TABLE_REWRITE_PREFIXES, TD95, EMPTY_TABLE_CONTEXT_AT_SELECTION, TRACKED_TABLE_COLUMN_RESTORE_NS2 = "urn:superdoc:tracked-table-column", DEFAULT_PAGE_WIDTH_TWIPS = 12240, DEFAULT_PAGE_MARGIN_TWIPS = 1440;
343952
+ var COLLABORATIVE_TABLE_REWRITE_PREFIXES, TD95, EMPTY_TABLE_CONTEXT_AT_SELECTION, TRACKED_TABLE_COLUMN_RESTORE_NS2 = "urn:superdoc:tracked-table-column", DEFAULT_PAGE_WIDTH_TWIPS = 12240, DEFAULT_PAGE_MARGIN_TWIPS2 = 1440;
342799
343953
  var init_adapter8 = __esm(() => {
342800
343954
  init_src3();
342801
343955
  init_sd_document_session_internal();
@@ -381301,8 +382455,8 @@ function readTargetContentWidthPx(context, input) {
381301
382455
  try {
381302
382456
  const pageSetup = pickClampSection(context, input)?.pageSetup;
381303
382457
  const widthTwips = pageSetup?.pageSize?.widthTwips ?? DEFAULT_PAGE_WIDTH_TWIPS2;
381304
- const leftTwips = pageSetup?.margins?.leftTwips ?? DEFAULT_PAGE_MARGIN_TWIPS2;
381305
- const rightTwips = pageSetup?.margins?.rightTwips ?? DEFAULT_PAGE_MARGIN_TWIPS2;
382458
+ const leftTwips = pageSetup?.margins?.leftTwips ?? DEFAULT_PAGE_MARGIN_TWIPS3;
382459
+ const rightTwips = pageSetup?.margins?.rightTwips ?? DEFAULT_PAGE_MARGIN_TWIPS3;
381306
382460
  const contentTwips = widthTwips - leftTwips - rightTwips;
381307
382461
  if (!Number.isFinite(contentTwips) || contentTwips <= 0)
381308
382462
  return null;
@@ -382990,7 +384144,7 @@ function findAdjacentCaptionParagraph(context, blockId) {
382990
384144
  function escapeRegExp17(value2) {
382991
384145
  return value2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
382992
384146
  }
382993
- var IMAGE_HYPERLINK_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", EMU_PER_PX6 = 9525, CROP_SCALE2 = 1000, DEFAULT_FLOATING_RELATIVE_HEIGHT = 251659264, DECORATIVE_EXT_URI = "{C183D7F6-B498-43B3-948B-1728B52AA6E4}", DECORATIVE_NAMESPACE = "http://schemas.microsoft.com/office/drawing/2017/decorative", DRAWING_NAMESPACE = "http://schemas.openxmlformats.org/drawingml/2006/main", RELATIONSHIP_NAMESPACE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships", CONVERTED_INLINE_ANCHORS, DEFAULT_PAGE_WIDTH_TWIPS2 = 12240, DEFAULT_PAGE_MARGIN_TWIPS2 = 1440, TWIPS_PER_PX = 15;
384147
+ var IMAGE_HYPERLINK_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", EMU_PER_PX6 = 9525, CROP_SCALE2 = 1000, DEFAULT_FLOATING_RELATIVE_HEIGHT = 251659264, DECORATIVE_EXT_URI = "{C183D7F6-B498-43B3-948B-1728B52AA6E4}", DECORATIVE_NAMESPACE = "http://schemas.microsoft.com/office/drawing/2017/decorative", DRAWING_NAMESPACE = "http://schemas.openxmlformats.org/drawingml/2006/main", RELATIONSHIP_NAMESPACE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships", CONVERTED_INLINE_ANCHORS, DEFAULT_PAGE_WIDTH_TWIPS2 = 12240, DEFAULT_PAGE_MARGIN_TWIPS3 = 1440, TWIPS_PER_PX = 15;
382994
384148
  var init_adapter21 = __esm(() => {
382995
384149
  init_mutation_guard();
382996
384150
  init_adapter4();
@@ -403878,6 +405032,57 @@ function resolveClipboardPasteTarget(context, target, options, applyPlan2) {
403878
405032
  storyLocator: locator
403879
405033
  };
403880
405034
  }
405035
+ function isExactWholeBodyTextSelection(context, target, index2, offsetSpace) {
405036
+ if (target.start.kind !== "text" || target.end.kind !== "text" || index2.entries.length === 0) {
405037
+ return false;
405038
+ }
405039
+ const first = index2.entries[0];
405040
+ const last = index2.entries[index2.entries.length - 1];
405041
+ let start = target.start;
405042
+ let end = target.end;
405043
+ if (first.blockId !== last.blockId && start.blockId === last.blockId && end.blockId === first.blockId) {
405044
+ [start, end] = [end, start];
405045
+ }
405046
+ if (start.blockId === end.blockId && start.offset === end.offset) {
405047
+ return false;
405048
+ }
405049
+ if (start.blockId !== first.blockId || end.blockId !== last.blockId || start.offset !== 0) {
405050
+ return false;
405051
+ }
405052
+ const preparePaintedParagraph = (point3) => prepareSelectionTargetResolution({
405053
+ target: {
405054
+ kind: "selection",
405055
+ start: point3,
405056
+ end: point3,
405057
+ ...target.story ? { story: target.story } : {}
405058
+ },
405059
+ index: index2,
405060
+ readPartBytes: (partUri) => getSDDocumentSessionInternalPartBytes(context.session, partUri),
405061
+ readPartRange: (partUri, startByte, endByte) => getSDDocumentSessionInternalPartRange(context.session, partUri, startByte, endByte),
405062
+ buildOffsetMap: buildOffsetMapForCoordinateSpace5,
405063
+ offsetSpace: "selection"
405064
+ });
405065
+ if (offsetSpace !== "selection") {
405066
+ if (end.offset !== last.textLength)
405067
+ return false;
405068
+ return index2.entries.every((entry) => {
405069
+ const bytes = getSDDocumentSessionInternalPartBytes(context.session, entry.partUri);
405070
+ const paragraphBytes = bytes?.subarray(entry.byteStart, entry.byteEnd) ?? getSDDocumentSessionInternalPartRange(context.session, entry.partUri, entry.byteStart, entry.byteEnd);
405071
+ if (!paragraphBytes)
405072
+ return false;
405073
+ const inlineMap = parseParagraphInlineMap(CLIPBOARD_TD.decode(paragraphBytes));
405074
+ if (inlineMap.leaves().some((piece) => piece.kind === "unknown" || piece.kind === "container" && (piece.policy === "atomic" || piece.policy === "fail-closed")))
405075
+ return false;
405076
+ const prepared2 = preparePaintedParagraph({ kind: "text", blockId: entry.blockId, offset: 0 });
405077
+ return !("error" in prepared2) && prepared2.offsetLength === entry.textLength;
405078
+ });
405079
+ }
405080
+ const prepared = preparePaintedParagraph(end);
405081
+ if ("error" in prepared || end.offset !== prepared.offsetLength)
405082
+ return false;
405083
+ const resolved = prepared.resolveOffsets();
405084
+ return !("error" in resolved) && resolved.startOffset === last.textLength;
405085
+ }
403881
405086
  function resolveSelectionPasteTarget(context, target, options, applyPlan2) {
403882
405087
  if (target.start.kind !== "text" || target.end.kind !== "text") {
403883
405088
  return {
@@ -403913,13 +405118,41 @@ function resolveSelectionPasteTarget(context, target, options, applyPlan2) {
403913
405118
  if (!index2)
403914
405119
  return { ok: false, code: "PRECONDITION_FAILED", message: "paragraph index is not available." };
403915
405120
  const offsetSpace = selectionOffsetSpaceOption(options);
405121
+ const changeMode = options?.changeMode ?? "direct";
405122
+ if (changeMode === "direct" && story.storyKind === "main" && isExactWholeBodyTextSelection(context, target, index2, offsetSpace)) {
405123
+ const partBytes = getSDDocumentSessionInternalPartBytes(context.session, story.partUri);
405124
+ if (partBytes) {
405125
+ const partXml = CLIPBOARD_TD.decode(partBytes);
405126
+ const lockFailure = guardContentControlDeletion({
405127
+ xml: partXml,
405128
+ start: 0,
405129
+ end: partXml.length,
405130
+ operation: "clipboard-whole-body-paste"
405131
+ });
405132
+ if (lockFailure) {
405133
+ return { ok: false, code: lockFailure.code, message: lockFailure.message };
405134
+ }
405135
+ }
405136
+ return {
405137
+ ok: true,
405138
+ kernelTarget: { kind: "story", storyId: story.storyId, placement: "replace" },
405139
+ storyLocator,
405140
+ effectAnchor: {
405141
+ blockId: index2.entries[0].blockId,
405142
+ startOffset: 0,
405143
+ paintedStartOffset: 0,
405144
+ relocatedEmptyAnchor: false
405145
+ }
405146
+ };
405147
+ }
403916
405148
  if (target.start.blockId !== target.end.blockId) {
403917
405149
  const resolved2 = resolveCrossParagraphSelectionPlan({
403918
405150
  target,
403919
405151
  index: index2,
403920
405152
  readPartBytes: (partUri) => getSDDocumentSessionInternalPartBytes(context.session, partUri),
403921
405153
  buildOffsetMap: buildOffsetMapForCoordinateSpace5,
403922
- ...offsetSpace ? { offsetSpace } : {}
405154
+ ...offsetSpace ? { offsetSpace } : {},
405155
+ ...changeMode === "direct" ? { allowSectionBoundary: true } : {}
403923
405156
  });
403924
405157
  if ("error" in resolved2)
403925
405158
  return { ok: false, code: resolved2.error, message: resolved2.message };
@@ -404074,6 +405307,7 @@ var init_adapter37 = __esm(() => {
404074
405307
  init_text_range_shifts();
404075
405308
  init_adapter5();
404076
405309
  init_adapter7();
405310
+ init_deletion_locks();
404077
405311
  init_contracts();
404078
405312
  init_parse5();
404079
405313
  init_plan3();