@superdoc/mcp 1.7.0-next.15 → 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 +1803 -262
  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.15";
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";
@@ -121556,6 +121556,12 @@ function validateClipboardPlan(plan, operationName) {
121556
121556
  if (!Array.isArray(plan.diagnostics)) {
121557
121557
  throw new DocumentApiValidationError("INVALID_INPUT", `${operationName} plan.diagnostics must be an array.`);
121558
121558
  }
121559
+ if (plan.sourceStyleContext !== undefined && plan.sourceStyleContext !== null) {
121560
+ const source = plan.sourceStyleContext;
121561
+ if (typeof source !== "object" || Array.isArray(source) || typeof source.documentEpoch !== "string" || source.documentEpoch.length === 0 || source.documentEpoch.length > 255 || typeof source.digest !== "string" || !/^[a-f0-9]{64}$/.test(source.digest)) {
121562
+ throw new DocumentApiValidationError("INVALID_INPUT", `${operationName} plan.sourceStyleContext is invalid.`);
121563
+ }
121564
+ }
121559
121565
  }
121560
121566
  function validatePasteFragment(fragment2, operationName) {
121561
121567
  if (!fragment2 || typeof fragment2 !== "object") {
@@ -195904,7 +195910,7 @@ function isValidPasteRunMarks(value) {
195904
195910
  if (marks[key2] !== undefined && typeof marks[key2] !== "boolean")
195905
195911
  return false;
195906
195912
  }
195907
- if (marks.color !== undefined && (typeof marks.color !== "string" || !/^[0-9A-F]{6}$/i.test(marks.color))) {
195913
+ if (marks.color !== undefined && (typeof marks.color !== "string" || marks.color !== "auto" && !/^[0-9A-F]{6}$/i.test(marks.color))) {
195908
195914
  return false;
195909
195915
  }
195910
195916
  if (marks.highlight !== undefined) {
@@ -195990,7 +195996,8 @@ function renderParagraphProperties2(styleId, numberingProperties, paragraphPrope
195990
195996
  if (indent)
195991
195997
  parts.push(indent);
195992
195998
  if (paragraphProperties?.alignment) {
195993
- 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)}"/>`);
195994
196001
  }
195995
196002
  const markRunProps = renderRunPropertiesXml(paragraphProperties?.markRunProps);
195996
196003
  if (markRunProps)
@@ -196138,9 +196145,11 @@ function hasOnlyKeys(value, keys) {
196138
196145
  return Object.keys(value).every((key2) => allowed.has(key2));
196139
196146
  }
196140
196147
  function toPasteTextRunSpec(run) {
196148
+ const characterStyleId = run.characterStyleId ?? run.styleRef;
196141
196149
  return {
196142
196150
  text: run.text,
196143
196151
  ...run.marks ? { marks: run.marks } : {},
196152
+ ...characterStyleId ? { characterStyleId } : {},
196144
196153
  ...run.commentIds && run.commentIds.length > 0 ? { commentIds: run.commentIds } : {},
196145
196154
  ...run.trackedInsertion ? { trackedInsertion: true } : {}
196146
196155
  };
@@ -196198,18 +196207,135 @@ function renderTrackedPasteRuns(runs, stamp) {
196198
196207
  return out.join("");
196199
196208
  }
196200
196209
  function renderPasteTableBlock(spec) {
196201
- const columnCount = Math.max(1, ...spec.rows.map((row) => row.cells.reduce((sum, cell) => sum + Math.max(1, cell.gridSpan ?? 1), 0)));
196202
- const columnWidth = Math.max(1, Math.floor(PASTE_TABLE_GRID_TWIPS / columnCount));
196203
- const grid = `<w:tblGrid>${`<w:gridCol w:w="${columnWidth}"/>`.repeat(columnCount)}</w:tblGrid>`;
196210
+ const grid = renderPasteTableGrid(spec);
196204
196211
  const rows = renderPasteTableRows(spec);
196205
196212
  return `<w:tbl>${renderPasteTableProperties(spec)}${grid}${rows}</w:tbl>`;
196206
196213
  }
196207
196214
  function renderTrackedPasteTableBlock(spec, stamp) {
196208
- const columnCount = tableColumnCount(spec);
196209
- const columnWidth = Math.max(1, Math.floor(PASTE_TABLE_GRID_TWIPS / columnCount));
196210
- const grid = `<w:tblGrid>${`<w:gridCol w:w="${columnWidth}"/>`.repeat(columnCount)}</w:tblGrid>`;
196215
+ const grid = renderPasteTableGrid(spec);
196211
196216
  return `<w:tbl>${renderPasteTableProperties(spec)}${grid}${renderTrackedPasteTableRows(spec, stamp)}</w:tbl>`;
196212
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
+ }
196213
196339
  function renderPasteTableRows(tableSpec) {
196214
196340
  return tableSpec.rows.map((row) => {
196215
196341
  const rowProperties = row.header ? "<w:trPr><w:tblHeader/></w:trPr>" : "";
@@ -196243,8 +196369,9 @@ function renderPasteTableCell(cell, renderParagraph = renderPasteParagraphBlock,
196243
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())}"/>`] : [];
196244
196370
  }).join("");
196245
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/>" : "";
196246
196373
  const verticalAlign = cell.verticalAlign ? `<w:vAlign w:val="${cell.verticalAlign}"/>` : "";
196247
- 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>";
196248
196375
  return `<w:tc>${tcPr}${cell.paragraphs.map((block) => ("rows" in block) ? renderTable(block) : renderParagraph(block)).join("")}</w:tc>`;
196249
196376
  }
196250
196377
  function renderPasteRunProperties(run, options) {
@@ -196284,12 +196411,14 @@ function renderPasteRun(run, options = {}) {
196284
196411
  const local = run.kind === "footnoteRef" ? "footnoteReference" : "endnoteReference";
196285
196412
  return `<w:r><w:rPr><w:rStyle w:val="${style}"/></w:rPr><w:${local} w:id="${escapeXmlAttribute(run.noteId)}"/></w:r>`;
196286
196413
  }
196414
+ const characterStyleId = (run.kind === undefined || run.kind === "text" ? run.characterStyleId : undefined) ?? options.characterStyleId;
196415
+ const runOptions = characterStyleId ? { characterStyleId } : options;
196287
196416
  if (run.kind === "lineBreak") {
196288
- return `<w:r>${renderPasteRunProperties(run, options)}<w:br/></w:r>`;
196417
+ return `<w:r>${renderPasteRunProperties(run, runOptions)}<w:br/></w:r>`;
196289
196418
  }
196290
196419
  if (!("text" in run))
196291
196420
  return "";
196292
- const rPr = renderPasteRunProperties(run, options);
196421
+ const rPr = renderPasteRunProperties(run, runOptions);
196293
196422
  if (run.text.length === 0)
196294
196423
  return "";
196295
196424
  const segments = run.text.split("\t");
@@ -196361,7 +196490,11 @@ function renderRunPropertiesXml(marks, options = {}) {
196361
196490
  }
196362
196491
  if (marks.strike !== undefined)
196363
196492
  parts.push(marks.strike ? "<w:strike/>" : '<w:strike w:val="0"/>');
196364
- if (marks.color && isHexColor(marks.color)) {
196493
+ if (marks.strike === false && options.characterStyleId)
196494
+ parts.push('<w:dstrike w:val="0"/>');
196495
+ if (marks.color === "auto") {
196496
+ parts.push('<w:color w:val="auto"/>');
196497
+ } else if (marks.color && isHexColor(marks.color)) {
196365
196498
  parts.push(`<w:color w:val="${escapeXmlAttribute(marks.color.toUpperCase())}"/>`);
196366
196499
  }
196367
196500
  if (typeof marks.fontSizePt === "number" && Number.isFinite(marks.fontSizePt) && marks.fontSizePt > 0) {
@@ -196372,7 +196505,7 @@ function renderRunPropertiesXml(marks, options = {}) {
196372
196505
  parts.push(`<w:szCs w:val="${Math.round(marks.fontSizeCsPt * 2)}"/>`);
196373
196506
  if (marks.underline !== undefined)
196374
196507
  parts.push(`<w:u w:val="${marks.underline ? "single" : "none"}"/>`);
196375
- const highlightXml = renderHighlightOrShadingXml(marks.highlight);
196508
+ const highlightXml = marks.highlight?.trim().toLowerCase() === "none" ? '<w:highlight w:val="none"/>' : renderHighlightOrShadingXml(marks.highlight);
196376
196509
  if (highlightXml)
196377
196510
  parts.push(highlightXml);
196378
196511
  if (isPasteVerticalAlign(marks.verticalAlign)) {
@@ -196510,13 +196643,14 @@ function collidesWithExistingParaId(state, candidate2) {
196510
196643
  return true;
196511
196644
  return false;
196512
196645
  }
196513
- 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";
196514
196647
  var init_paragraph_contribution = __esm(() => {
196515
196648
  init_xml_sax();
196516
196649
  init_xml_text();
196517
196650
  init_paragraph_para_id_attrs();
196518
196651
  init_highlight_ooxml();
196519
196652
  init_paste_run_validation();
196653
+ PASTE_TABLE_GRID_TWIPS = PASTE_TABLE_DEFAULT_CONTENT_WIDTH_TWIPS;
196520
196654
  });
196521
196655
 
196522
196656
  // ../../../v2/editor-core/dist/document/transactions/compile-comment-helpers.js
@@ -228283,19 +228417,22 @@ function mapPasteTableParagraphs(block, paragraph, table = (block2) => block2) {
228283
228417
  }))
228284
228418
  });
228285
228419
  }
228286
- function pasteTableSpec(block, mintNextParaId, bindW14NamespaceInline, runs = (block2) => block2.runs.map(toPasteTextRunSpec)) {
228420
+ function pasteTableSpec(block, mintNextParaId, bindW14NamespaceInline, runs = (block2) => block2.runs.map(toPasteTextRunSpec), gridWidthTwips) {
228287
228421
  return {
228288
228422
  ...block.styleRef !== undefined ? { styleRef: block.styleRef } : {},
228289
228423
  ...block.cellSpacingPt !== undefined ? { cellSpacingPt: block.cellSpacingPt } : {},
228424
+ ...block.columnWidthShares !== undefined ? { columnWidthShares: block.columnWidthShares } : {},
228425
+ ...gridWidthTwips !== undefined ? { gridWidthTwips } : {},
228290
228426
  rows: block.rows.map((row) => ({
228291
228427
  ...row.header !== undefined ? { header: row.header } : {},
228292
228428
  cells: row.cells.map((cell) => ({
228293
228429
  ...cell.gridSpan !== undefined ? { gridSpan: cell.gridSpan } : {},
228430
+ ...cell.vMerge !== undefined ? { vMerge: cell.vMerge } : {},
228294
228431
  ...cell.shadingColor !== undefined ? { shadingColor: cell.shadingColor } : {},
228295
228432
  ...cell.padding !== undefined ? { padding: cell.padding } : {},
228296
228433
  ...cell.verticalAlign !== undefined ? { verticalAlign: cell.verticalAlign } : {},
228297
228434
  ...cell.borders !== undefined ? { borders: cell.borders } : {},
228298
- 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) : {
228299
228436
  paraId: mintNextParaId(),
228300
228437
  bindW14NamespaceInline,
228301
228438
  styleId: child.styleRef ?? null,
@@ -241077,10 +241214,19 @@ function planParagraphSplice(input) {
241077
241214
  const bindW14NamespaceInline = !positionBindsW14Namespace(input.partBytes, input.paragraphStartByte, {
241078
241215
  scopeHintOpenTag: envelope.open
241079
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;
241080
241221
  const standalone = (block, blockIndex, inheritedPPrXml) => {
241081
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
+ }
241082
241228
  const before = createdParaIds.length;
241083
- 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);
241084
241230
  const xml = input.trackedStamp ? renderTrackedPasteTableBlock(tableSpec, input.trackedStamp) : renderPasteTableBlock(tableSpec);
241085
241231
  destinationParaIdsByBlock[blockIndex].push(...createdParaIds.slice(before));
241086
241232
  return xml;
@@ -241124,7 +241270,7 @@ function planParagraphSplice(input) {
241124
241270
  if (!relocateEmptyAnchor) {
241125
241271
  if (mergeFirst && anchorParaId)
241126
241272
  destinationParaIdsByBlock[0].push(anchorParaId);
241127
- const headPPr = input.trackedStamp ? renderTrackedParagraphMarkProperties(envelope.pPr, input.trackedStamp) : envelope.pPr;
241273
+ const headPPr = input.trackedStamp ? renderTrackedParagraphMarkProperties(sectionProperties.ordinaryPropertiesXml, input.trackedStamp) : sectionProperties.ordinaryPropertiesXml;
241128
241274
  const headOpen = input.trackedStamp ? withTrackedRsid(envelope.open, input.trackedStamp.rsid) : envelope.open;
241129
241275
  paragraphs.push(headOpen + headPPr + split.headXml + (mergeFirst ? runsOf(blocks[0]) : "") + envelope.close);
241130
241276
  }
@@ -241132,7 +241278,7 @@ function planParagraphSplice(input) {
241132
241278
  const middleXml = [];
241133
241279
  for (let middleIndex = 0;middleIndex < middleBlocks.length; middleIndex += 1) {
241134
241280
  const block = middleBlocks[middleIndex];
241135
- middleXml.push(standalone(block, middleStart + middleIndex, mergeable(block) ? envelope.pPr : undefined));
241281
+ middleXml.push(standalone(block, middleStart + middleIndex, mergeable(block) ? sectionProperties.ordinaryPropertiesXml : undefined));
241136
241282
  }
241137
241283
  if (middleXml.length)
241138
241284
  paragraphs.push(renderBlockSdtSequence(middleBlocks, middleXml, input.blockSdtIds ?? new Map));
@@ -241147,8 +241293,8 @@ function planParagraphSplice(input) {
241147
241293
  paragraphs.push(tailOpen + envelope.pPr + tailRunsXml + envelope.close);
241148
241294
  } else if (relocateEmptyAnchor) {
241149
241295
  paragraphs.push(envelope.open + envelope.pPr + envelope.close);
241150
- } else if (blocks[blocks.length - 1]?.kind === "table") {
241151
- 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);
241152
241298
  }
241153
241299
  }
241154
241300
  const insertedVisibleChars = blocks.reduce((sum, block) => sum + blockVisibleChars(block), 0);
@@ -241319,11 +241465,11 @@ function parseParagraphEnvelope(anchorXml) {
241319
241465
  if (innerEnd < 0)
241320
241466
  return null;
241321
241467
  const afterOpen = anchorXml.slice(openMatch[0].length);
241322
- const pPrMatch = /^\s*<([\w.-]+:)?pPr\b(?:[^>]*\/>|[^>]*>[\s\S]*?<\/(?:[\w.-]+:)?pPr\s*>)/.exec(afterOpen);
241323
- const innerStart = openMatch[0].length + (pPrMatch?.[0]?.length ?? 0);
241468
+ const { pPr } = splitLeadingParagraphPropertyBlock(afterOpen);
241469
+ const innerStart = openMatch[0].length + pPr.length;
241324
241470
  return {
241325
241471
  open: openMatch[0],
241326
- pPr: pPrMatch?.[0] ?? "",
241472
+ pPr,
241327
241473
  close,
241328
241474
  innerStart,
241329
241475
  innerEnd
@@ -241359,6 +241505,7 @@ var init_compile_paste_splice = __esm(() => {
241359
241505
  init_paragraph_contribution();
241360
241506
  init_paragraph_para_id_attrs();
241361
241507
  init_paste_blocks();
241508
+ init_paragraph_property_block();
241362
241509
  });
241363
241510
 
241364
241511
  // ../../../v2/editor-core/dist/document/transactions/compile-paste-lists.js
@@ -241698,15 +241845,26 @@ function normalizeMatchDestinationParagraph(block) {
241698
241845
  runs: block.runs.map(withoutSourceMarks),
241699
241846
  ...block.sourcePath ? { sourcePath: block.sourcePath } : {},
241700
241847
  ...block.inlines ? {
241701
- inlines: block.inlines.map((inline) => inline.kind === "text" ? withoutSourceMarks(inline) : inline.kind === "hyperlink" ? {
241702
- ...inline,
241703
- inlines: inline.inlines.map((child) => child.kind === "text" ? withoutSourceMarks(child) : child)
241704
- } : inline)
241848
+ inlines: block.inlines.map(withoutSourceInlineFormatting)
241705
241849
  } : {}
241706
241850
  };
241707
241851
  }
241852
+ function withoutSourceInlineFormatting(inline) {
241853
+ if (inline.kind === "text")
241854
+ return withoutSourceMarks(inline);
241855
+ if (inline.kind === "sdt") {
241856
+ return withoutSourceSdtFormatting(inline);
241857
+ }
241858
+ if (inline.kind === "hyperlink") {
241859
+ return { ...inline, inlines: inline.inlines.map((child) => child.kind === "text" ? withoutSourceMarks(child) : child) };
241860
+ }
241861
+ return inline;
241862
+ }
241863
+ function withoutSourceSdtFormatting(inline) {
241864
+ return { ...inline, inlines: inline.inlines.map((child) => child.kind === "text" ? withoutSourceMarks(child) : child.kind === "sdt" ? withoutSourceSdtFormatting(child) : child) };
241865
+ }
241708
241866
  function withoutSourceMarks(run) {
241709
- const { marks: _sourceMarks, ...retained } = run;
241867
+ const { marks: _sourceMarks, styleRef: _sourceStyle, ...retained } = run;
241710
241868
  return retained;
241711
241869
  }
241712
241870
  var init_match_destination_paste = __esm(() => {
@@ -243573,7 +243731,10 @@ function resolveFragmentApplyTarget(state, op) {
243573
243731
  }
243574
243732
  const bodyXml = TD70.decode(bytes.subarray(bodyContentStart, bodyContentEnd));
243575
243733
  const sections = scanBodySections(`${bodyXml}</w:body>`);
243576
- 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") {
243577
243738
  return { ok: false, reason: "paste-whole-story-sections-unsupported" };
243578
243739
  }
243579
243740
  const children = scan.bootstrapSlice?.children ?? [];
@@ -243723,7 +243884,12 @@ function resolveFragmentApplyTarget(state, op) {
243723
243884
  const crossParagraph = startAnchor.ordinal !== endAnchor.ordinal;
243724
243885
  const replacesContent = crossParagraph || target.charOffset !== explicitEnd.charOffset;
243725
243886
  if (crossParagraph) {
243726
- 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
+ });
243727
243893
  if (structuralFailure)
243728
243894
  return { ok: false, reason: structuralFailure };
243729
243895
  } else if (replacesContent && residentBytes) {
@@ -244398,6 +244564,7 @@ function runWholeStoryReplaceCommit(input, target, blocks, extras, inlineExtras)
244398
244564
  blockSdtIds: inlineExtras.blockSdtIds,
244399
244565
  partBytes: bytes,
244400
244566
  insertionByte: target.byteStart,
244567
+ wholeStoryReplace: true,
244401
244568
  ordinalSeed: 0,
244402
244569
  scopeHintOpenTag: target.bodyStartTagXml,
244403
244570
  ...extras.commentIdMap ? { commentIdMap: extras.commentIdMap } : {},
@@ -244606,13 +244773,14 @@ function renderCompletePasteFragment(input) {
244606
244773
  return paraId;
244607
244774
  }
244608
244775
  };
244776
+ const destinationGridWidthTwips = pasteDestinationContentWidthTwipsFromPartXml(TD70.decode(input.partBytes), input.wholeStoryReplace ? undefined : TD70.decode(input.partBytes.subarray(0, input.insertionByte)).length);
244609
244777
  const renderedBlocks = [];
244610
244778
  for (let blockIndex = 0;blockIndex < input.blocks.length; blockIndex += 1) {
244611
244779
  const block = input.blocks[blockIndex];
244612
244780
  const before = createdParaIds.length;
244613
244781
  let xml;
244614
244782
  if (block.kind === "table") {
244615
- 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);
244616
244784
  xml = input.trackedStamp ? renderTrackedPasteTableBlock(spec, input.trackedStamp) : renderPasteTableBlock(spec);
244617
244785
  } else if (block.kind === "horizontalRule") {
244618
244786
  const spec = {
@@ -245128,6 +245296,7 @@ function runCrossParagraphPasteCommit(input, target, blocks, extras, inlineExtra
245128
245296
  endObjectBoundary: target.end.objectBoundary,
245129
245297
  removedBookmarkNames: rangeIntegrity.removedBookmarkNames,
245130
245298
  allocateWId: () => plannedWIds[usedWIds++],
245299
+ collapseSectionBoundaries: true,
245131
245300
  transformCollapsedParagraph: (collapsedParagraphXml) => {
245132
245301
  const planned = planParagraphSplice({
245133
245302
  anchorXml: collapsedParagraphXml,
@@ -245136,6 +245305,7 @@ function runCrossParagraphPasteCommit(input, target, blocks, extras, inlineExtra
245136
245305
  charOffset: target.start.charOffset,
245137
245306
  partBytes: bytes,
245138
245307
  paragraphStartByte: start.byteStart,
245308
+ paragraphReplacementEndByte: end.byteEnd,
245139
245309
  mintParaId: () => mintParaId(state, state.packageRevision, start.ordinal + 1 + (mintSalt += 1)),
245140
245310
  inlineSpecs: inlineExtras.inlineSpecs,
245141
245311
  blockSdtIds: inlineExtras.blockSdtIds,
@@ -245978,6 +246148,9 @@ function explicitPasteStyleRefsExist(state, blocks) {
245978
246148
  const inspectParagraph = (block) => {
245979
246149
  if (block.styleRef && !block.pPrXml)
245980
246150
  references.push({ styleId: block.styleRef, type: "paragraph" });
246151
+ for (const styleId of characterStyleRefsInParagraph(block)) {
246152
+ references.push({ styleId, type: "character" });
246153
+ }
245981
246154
  };
245982
246155
  for (const block of walkPasteBlocks(blocks)) {
245983
246156
  if (block.kind === "paragraph")
@@ -245987,6 +246160,28 @@ function explicitPasteStyleRefsExist(state, blocks) {
245987
246160
  }
245988
246161
  return explicitStyleReferencesExist(state, references);
245989
246162
  }
246163
+ function characterStyleRefsInParagraph(block) {
246164
+ const refs = [];
246165
+ for (const run of block.runs) {
246166
+ if (typeof run.styleRef === "string" && run.styleRef.length > 0)
246167
+ refs.push(run.styleRef);
246168
+ }
246169
+ const walkInlines = (inlines) => {
246170
+ if (!inlines)
246171
+ return;
246172
+ for (const inline of inlines) {
246173
+ if (inline.kind === "text") {
246174
+ if (typeof inline.styleRef === "string" && inline.styleRef.length > 0)
246175
+ refs.push(inline.styleRef);
246176
+ continue;
246177
+ }
246178
+ if (inline.kind === "hyperlink" || inline.kind === "sdt")
246179
+ walkInlines(inline.inlines);
246180
+ }
246181
+ };
246182
+ walkInlines(block.inlines);
246183
+ return refs;
246184
+ }
245990
246185
  function resolveSemanticStyleBlocks(blocks, styleIdByRole) {
245991
246186
  const paragraph = (block) => {
245992
246187
  if (!block.semanticStyleRole)
@@ -246034,18 +246229,10 @@ function validateImageFragment(fragment3) {
246034
246229
  byId.set(asset.id, asset);
246035
246230
  }
246036
246231
  let references = 0;
246037
- for (const block of fragment3.blocks) {
246038
- if (block.kind === "table") {
246039
- for (const row of block.rows) {
246040
- for (const cell of row.cells) {
246041
- if (Array.from(walkPasteBlocks(cell.blocks)).some((paragraph) => paragraph.kind === "paragraph" && paragraph.inlines?.some((inline) => inline.kind === "image"))) {
246042
- return { ok: false, reason: "paste-structure-unsupported" };
246043
- }
246044
- }
246045
- }
246232
+ for (const block of walkPasteBlocks(fragment3.blocks)) {
246233
+ if (block.kind === "table" || block.kind === "horizontalRule")
246046
246234
  continue;
246047
- }
246048
- if (block.kind === "horizontalRule")
246235
+ if (block.kind !== "paragraph" && block.kind !== "heading")
246049
246236
  continue;
246050
246237
  for (const inline of block.inlines ?? []) {
246051
246238
  if (inline.kind === "text") {
@@ -246066,6 +246253,8 @@ function validateImageFragment(fragment3) {
246066
246253
  }
246067
246254
  continue;
246068
246255
  }
246256
+ if (inline.kind !== "image")
246257
+ continue;
246069
246258
  references += 1;
246070
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)) {
246071
246260
  return { ok: false, reason: "paste-structure-unsupported" };
@@ -246317,9 +246506,15 @@ function validateBlocks(blocks) {
246317
246506
  if (block.cellSpacingPt !== undefined && !isSafePaddingPoints(block.cellSpacingPt)) {
246318
246507
  return { ok: false, reason: "paste-structure-unsupported" };
246319
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
+ }
246320
246514
  if (!Array.isArray(block.rows) || block.rows.length === 0) {
246321
246515
  return { ok: false, reason: "paste-structure-unsupported" };
246322
246516
  }
246517
+ let tableColumnCount2 = 0;
246323
246518
  for (const [rowIndex, row] of block.rows.entries()) {
246324
246519
  if (!row || typeof row !== "object")
246325
246520
  return { ok: false, reason: "paste-structure-unsupported" };
@@ -246351,6 +246546,12 @@ function validateBlocks(blocks) {
246351
246546
  if (cell.gridSpan !== undefined && (!Number.isSafeInteger(cell.gridSpan) || cell.gridSpan < 1)) {
246352
246547
  return { ok: false, reason: "paste-structure-unsupported" };
246353
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
+ }
246354
246555
  rowColumnCount += cell.gridSpan ?? 1;
246355
246556
  if (rowColumnCount > MAX_WORD_TABLE_COLUMNS) {
246356
246557
  return { ok: false, reason: "paste-structure-unsupported" };
@@ -246396,6 +246597,10 @@ function validateBlocks(blocks) {
246396
246597
  if (!validation2.ok)
246397
246598
  return validation2;
246398
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" };
246399
246604
  }
246400
246605
  ancestors.delete(block);
246401
246606
  continue;
@@ -246505,6 +246710,8 @@ function validateParagraphBlock(block, budget) {
246505
246710
  for (const run of block.runs) {
246506
246711
  if (typeof run.text !== "string")
246507
246712
  return { ok: false, reason: "paste-structure-unsupported" };
246713
+ if (!isValidPasteCharacterStyleRef(run.styleRef))
246714
+ return { ok: false, reason: "paste-structure-unsupported" };
246508
246715
  if (!isValidPasteRunMarks(run.marks))
246509
246716
  return { ok: false, reason: "paste-structure-unsupported" };
246510
246717
  if (block.inlines === undefined && !recordSourcePath(run.sourcePath, budget.sourcePaths)) {
@@ -246527,7 +246734,7 @@ function validatePasteInline(inline, budget, depth = 0) {
246527
246734
  return (inline.controlType === "text" || inline.controlType === "richText") && isValidOptionalXmlAttributeText(inline.tag, 255) && isValidOptionalXmlAttributeText(inline.alias, 255) && Array.isArray(inline.inlines) && inline.inlines.length > 0 && inline.inlines.every((child) => child.kind === "text" || child.kind === "lineBreak" || child.kind === "sdt") && inline.inlines.every((child) => validatePasteInline(child, budget, depth + 1));
246528
246735
  }
246529
246736
  if (inline.kind === "text") {
246530
- return typeof inline.text === "string" && !hasUnsupportedControlChar(inline.text) && isValidPasteRunMarks(inline.marks);
246737
+ return typeof inline.text === "string" && isValidPasteCharacterStyleRef(inline.styleRef) && !hasUnsupportedControlChar(inline.text) && isValidPasteRunMarks(inline.marks);
246531
246738
  }
246532
246739
  if (inline.kind === "lineBreak")
246533
246740
  return true;
@@ -246572,12 +246779,15 @@ function hasMatchingInlineTextProjection(block) {
246572
246779
  });
246573
246780
  return textInlines.length === block.runs.length && textInlines.every((inline, index) => {
246574
246781
  const run = block.runs[index];
246575
- return inline.text === run.text && haveEqualRunMarks(inline.marks, run.marks);
246782
+ return inline.text === run.text && inline.styleRef === run.styleRef && haveEqualRunMarks(inline.marks, run.marks);
246576
246783
  });
246577
246784
  }
246578
246785
  function haveEqualRunMarks(left, right) {
246579
246786
  return left?.boldCs === right?.boldCs && left?.italicCs === right?.italicCs && left?.caps === right?.caps && left?.smallCaps === right?.smallCaps && left?.fontSizeCsPt === right?.fontSizeCsPt && left?.bold === right?.bold && left?.italic === right?.italic && left?.underline === right?.underline && left?.strike === right?.strike && left?.color === right?.color && left?.highlight === right?.highlight && left?.fontSizePt === right?.fontSizePt && left?.fontFamily === right?.fontFamily && left?.verticalAlign === right?.verticalAlign;
246580
246787
  }
246788
+ function isValidPasteCharacterStyleRef(value) {
246789
+ return value === undefined || typeof value === "string" && value.length > 0 && isValidOptionalXmlAttributeText(value, 255);
246790
+ }
246581
246791
  function isValidOptionalXmlAttributeText(value, maxLength) {
246582
246792
  return value === undefined || typeof value === "string" && value.length <= maxLength && !hasUnsupportedXmlAttributeChar(value);
246583
246793
  }
@@ -283792,7 +284002,9 @@ var init_xml = __esm(() => {
283792
284002
  function preparePaintedOffsets(paraXml, namespaceBindings = {}) {
283793
284003
  const runs = paintedRuns(paraXml, namespaceBindings);
283794
284004
  const objects = runs.filter((run) => run.objectOrdinal !== null);
284005
+ const last = runs.at(-1);
283795
284006
  return {
284007
+ totalLength: last ? last.paintedStart + last.paintedLength : 0,
283796
284008
  containedObjectOrdinals(start, end) {
283797
284009
  const contained = [];
283798
284010
  for (let i2 = lowerBound(objects, start, "start");i2 < objects.length; i2++) {
@@ -283812,8 +284024,8 @@ function preparePaintedOffsets(paraXml, namespaceBindings = {}) {
283812
284024
  return offset;
283813
284025
  const run = runs[lowerBound(runs, offset, "end")];
283814
284026
  if (!run) {
283815
- const last = runs.at(-1);
283816
- return last ? last.kernelStart + last.kernelLength : 0;
284027
+ const last2 = runs.at(-1);
284028
+ return last2 ? last2.kernelStart + last2.kernelLength : 0;
283817
284029
  }
283818
284030
  return run.objectOrdinal === null ? run.kernelStart + Math.max(0, offset - run.paintedStart) : run.kernelStart;
283819
284031
  },
@@ -284001,7 +284213,9 @@ function prepareSelectionTargetResolution(input) {
284001
284213
  const painted = objectRuns > 0 ? preparePaintedOffsets(paraXml, fullBytes ? partRootNamespaceBindings(fullBytes) : input.namespaceBindings ?? {}) : null;
284002
284214
  const originalStart = target.start.offset;
284003
284215
  const originalEnd = target.end.offset;
284216
+ const offsetLength = painted?.totalLength ?? kernelTextLength;
284004
284217
  return {
284218
+ offsetLength,
284005
284219
  resolveOffsets(paintedStartOffset = originalStart, paintedEndOffset = originalEnd) {
284006
284220
  if (paintedStartOffset > paintedEndOffset) {
284007
284221
  return { error: "INVALID_TARGET", message: "selection end precedes selection start." };
@@ -284011,7 +284225,7 @@ function prepareSelectionTargetResolution(input) {
284011
284225
  let paintedObjectContained = false;
284012
284226
  let collapsedObjectBoundary;
284013
284227
  if (painted) {
284014
- if (startOffset < 0 || endOffset > entry.textLength + objectRuns) {
284228
+ if (startOffset < 0 || endOffset > offsetLength) {
284015
284229
  return { error: "INVALID_TARGET", message: "selection offsets exceed paragraph text." };
284016
284230
  }
284017
284231
  paintedObjectContained = painted.containsObject(startOffset, endOffset);
@@ -312031,6 +312245,9 @@ function paragraphPropsForElement(element, sheet, context) {
312031
312245
  }
312032
312246
  function cellPropsForElement(element, sheet, context) {
312033
312247
  const props = {};
312248
+ const valign = normalizeCellVerticalAlign(attributeValue2(element, "valign") ?? "");
312249
+ if (valign)
312250
+ props.verticalAlign = valign;
312034
312251
  for (const declaration of resolvedDeclarations(element, sheet)) {
312035
312252
  if (!CELL_PROPERTIES.has(declaration.property))
312036
312253
  continue;
@@ -312150,9 +312367,8 @@ function applyRunDeclaration(props, declaration) {
312150
312367
  return true;
312151
312368
  }
312152
312369
  if (declaration.property === "font-size") {
312153
- const points = cssLengthToPoints(value2);
312154
- const halfPoints = points === null ? 0 : points * 2;
312155
- 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)
312156
312372
  return false;
312157
312373
  props.fontSize = points;
312158
312374
  return true;
@@ -312242,6 +312458,13 @@ function applyCellDeclaration(props, declaration) {
312242
312458
  props.shading = color;
312243
312459
  return true;
312244
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
+ }
312245
312468
  if (declaration.property === "padding") {
312246
312469
  const values = expandBoxLengths(declaration.value);
312247
312470
  if (!values)
@@ -312287,6 +312510,16 @@ function applyCellDeclaration(props, declaration) {
312287
312510
  }
312288
312511
  return false;
312289
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
+ }
312290
312523
  function normalizeAlignment(value2) {
312291
312524
  const normalized = value2?.trim().toLowerCase();
312292
312525
  if (normalized === "left" || normalized === "center" || normalized === "right")
@@ -312321,6 +312554,14 @@ function expandBoxLengths(value2) {
312321
312554
  const left = values[3] ?? right;
312322
312555
  return { top, right, bottom, left };
312323
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
+ }
312324
312565
  function cssLengthToPoints(value2, allowNegative = false) {
312325
312566
  const points = cssAbsoluteLengthToPoints(value2, allowNegative);
312326
312567
  if (points === null)
@@ -312385,6 +312626,21 @@ function normalizeCellBorder(value2) {
312385
312626
  return null;
312386
312627
  return lineWeightPt !== undefined ? `${lineStyle} ${lineWeightPt}pt #${color}` : null;
312387
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
+ }
312388
312644
  function cssColor(value2) {
312389
312645
  const trimmed = value2.trim();
312390
312646
  const named = NAMED_COLORS2[trimmed.toLowerCase()];
@@ -312488,6 +312744,204 @@ var init_css = __esm(() => {
312488
312744
  };
312489
312745
  });
312490
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
+
312491
312945
  // ../../../v2/document-api-v2-adapter/dist/conversion/html/limits.js
312492
312946
  function resolveHtmlConversionLimits(overrides) {
312493
312947
  const limits = { ...DEFAULT_HTML_CONVERSION_LIMITS, ...overrides };
@@ -312922,6 +313376,18 @@ function convertFlowChildren(children2, context, inlineContext, path6, indexOffs
312922
313376
  flushPending();
312923
313377
  inspectUnsafeAttributes(node3, context, nodePath);
312924
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
+ }
312925
313391
  if (!FLOW_WRAPPERS.has(node3.tagName) && !INLINE_ELEMENTS.has(node3.tagName)) {
312926
313392
  reportUnknownWrapper(node3, context, nodePath);
312927
313393
  }
@@ -312948,6 +313414,15 @@ function convertBlock(element, context, inherited, path6) {
312948
313414
  reportDroppedElement(element, context, path6, "script", "conversion-unsafe-content");
312949
313415
  return [];
312950
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
+ }
312951
313426
  if (MEDIA_ELEMENTS.has(element.tagName)) {
312952
313427
  reportDroppedElement(element, context, path6, "image", "conversion-unsafe-content");
312953
313428
  return [];
@@ -313396,21 +313871,6 @@ function convertTable(table, context, inherited, path6) {
313396
313871
  });
313397
313872
  structurallyRejected = true;
313398
313873
  }
313399
- const rowSpanRaw = attributeValue2(cell, "rowspan");
313400
- const rowSpan = rowSpanRaw === undefined ? 1 : Number.parseInt(rowSpanRaw, 10);
313401
- if (rowSpanRaw !== undefined && (!Number.isSafeInteger(rowSpan) || rowSpan !== 1)) {
313402
- addDiagnostic(context, {
313403
- code: "conversion-unsupported-construct",
313404
- severity: "error",
313405
- message: "Row-spanning table cells cannot be represented by this conversion.",
313406
- construct: "rowSpan",
313407
- disposition: "rejected",
313408
- lossy: true,
313409
- path: [...rowPath, cellIndex, "@rowspan"],
313410
- range: sourceRangeForAttribute(cell, "rowspan") ?? sourceRangeForNode(cell)
313411
- });
313412
- structurallyRejected = true;
313413
- }
313414
313874
  const colSpanRaw = attributeValue2(cell, "colspan");
313415
313875
  const colSpan = colSpanRaw === undefined ? 1 : Number.parseInt(colSpanRaw, 10);
313416
313876
  if (Number.isFinite(colSpan) && colSpan > MAX_WORD_TABLE_GRID_COLUMNS) {
@@ -313452,8 +313912,11 @@ function convertTable(table, context, inherited, path6) {
313452
313912
  const tableCellProps = cellPropsForElement(table, context.sheet, cssContext(context, path6));
313453
313913
  const tableBorderSuppression = tableCellProps?.borders && ["top", "right", "bottom", "left"].every((side) => tableCellProps.borders?.[side] === "none");
313454
313914
  const convertedRows = [];
313455
- for (const { row, path: rowPath } of rows) {
313915
+ const convertedHtmlRows = [];
313916
+ let remainingCoveredRows = 0;
313917
+ for (const { row, path: rowPath, remainingGroupRows } of rows) {
313456
313918
  const cells = [];
313919
+ let maxNewCover = 0;
313457
313920
  for (let cellIndex = 0;cellIndex < row.childNodes.length; cellIndex += 1) {
313458
313921
  const cell = row.childNodes[cellIndex];
313459
313922
  if (!isElement(cell) || cell.tagName !== "td" && cell.tagName !== "th")
@@ -313461,6 +313924,23 @@ function convertTable(table, context, inherited, path6) {
313461
313924
  const cellPath = [...rowPath, cellIndex];
313462
313925
  inspectUnsafeAttributes(cell, context, cellPath);
313463
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
+ }
313464
313944
  const cellContext = inlineContextForElement(cell, context, tableContext, cellPath, undefined, CELL_NON_RUN_CSS);
313465
313945
  const droppedContentStart = context.droppedContentCount;
313466
313946
  const content = convertFlowChildren(cell.childNodes, context, cellContext, cellPath);
@@ -313475,14 +313955,18 @@ function convertTable(table, context, inherited, path6) {
313475
313955
  cells.push({
313476
313956
  ...props ? { props } : {},
313477
313957
  ...colSpan !== undefined && colSpan > 1 ? { colSpan } : {},
313958
+ ...rowSpan !== undefined && rowSpan > 1 ? { rowSpan } : {},
313478
313959
  ...cell.tagName === "th" ? { header: true } : {},
313479
313960
  content: content.length > 0 ? content : [
313480
313961
  paragraph2(context, [], undefined, cellPath, context.droppedContentCount === droppedContentStart)
313481
313962
  ]
313482
313963
  });
313483
313964
  }
313484
- if (cells.length > 0)
313965
+ if (cells.length > 0 || remainingCoveredRows > 0) {
313485
313966
  convertedRows.push({ cells });
313967
+ convertedHtmlRows.push(row);
313968
+ }
313969
+ remainingCoveredRows = Math.max(remainingCoveredRows - 1, maxNewCover, 0);
313486
313970
  }
313487
313971
  context.tableStyleAggregationDepth -= 1;
313488
313972
  if (context.suppressedTableStyleDiagnosticCount > suppressedStyleStart) {
@@ -313499,8 +313983,15 @@ function convertTable(table, context, inherited, path6) {
313499
313983
  }
313500
313984
  if (convertedRows.length === 0)
313501
313985
  return null;
313986
+ const columns = tableColumnSharesFromHtml(table, convertedHtmlRows, convertedRows, context, path6);
313502
313987
  claimContentNode(context, path6);
313503
- return { kind: "table", table: { rows: convertedRows } };
313988
+ return {
313989
+ kind: "table",
313990
+ table: {
313991
+ rows: convertedRows,
313992
+ ...columns ? { columns } : {}
313993
+ }
313994
+ };
313504
313995
  }
313505
313996
  function appendInlineNode(element, builder, context, inherited, path6) {
313506
313997
  if (isWordListMarkerContainer(element))
@@ -313518,6 +314009,15 @@ function appendInlineNode(element, builder, context, inherited, path6) {
313518
314009
  reportDroppedElement(element, context, path6, "script", "conversion-unsafe-content");
313519
314010
  return;
313520
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
+ }
313521
314021
  if (MEDIA_ELEMENTS.has(element.tagName)) {
313522
314022
  reportDroppedElement(element, context, path6, "image", "conversion-unsafe-content");
313523
314023
  return;
@@ -313620,6 +314120,20 @@ function appendHyperlink(element, builder, context, inherited, path6) {
313620
314120
  builder.appendInlines(children2);
313621
314121
  return;
313622
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
+ }
313623
314137
  const targetFrame = attributeValue2(element, "target");
313624
314138
  const tooltip = attributeValue2(element, "title");
313625
314139
  if (targetFrame) {
@@ -313680,7 +314194,8 @@ function inspectUnsafeAttributes(element, context, path6) {
313680
314194
  }
313681
314195
  if (URL_ATTRIBUTES.has(name) && !(element.tagName === "a" && name === "href")) {
313682
314196
  const targets = name === "srcset" ? attribute.value.split(",").map((entry) => entry.trim().split(/\s+/)[0] ?? "") : [attribute.value.trim()];
313683
- 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))) {
313684
314199
  addDiagnostic(context, {
313685
314200
  code: "conversion-unsafe-url",
313686
314201
  severity: "warning",
@@ -313771,7 +314286,7 @@ function cssContext(context, path6, ignoredDroppedProperties, ignoredRunProperti
313771
314286
  };
313772
314287
  }
313773
314288
  function isBlockElement(element) {
313774
- 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);
313775
314290
  }
313776
314291
  function isSuspiciousRecoveredElement(element) {
313777
314292
  return /[^a-z0-9:-]/i.test(element.tagName);
@@ -313869,21 +314384,151 @@ function positiveIntegerAttribute(element, attribute, context, path6, construct)
313869
314384
  });
313870
314385
  return 1;
313871
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
+ }
313872
314504
  function collectTableRows(table, tablePath) {
313873
314505
  const rows = [];
313874
- const visit = (parent, path6) => {
313875
- for (let index = 0;index < parent.childNodes.length; index += 1) {
313876
- const child = parent.childNodes[index];
313877
- if (!isElement(child))
313878
- continue;
313879
- const childPath = [...path6, index];
313880
- if (child.tagName === "tr")
313881
- rows.push({ row: child, path: childPath });
313882
- else if (child.tagName === "thead" || child.tagName === "tbody" || child.tagName === "tfoot")
313883
- 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 });
313884
314509
  }
313885
314510
  };
313886
- 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);
313887
314532
  return rows;
313888
314533
  }
313889
314534
  function findDescendantElement(element, tagName) {
@@ -313980,6 +314625,8 @@ function hasSubstantiveInline(inline) {
313980
314625
  return inline.run.text.length > 0;
313981
314626
  if (inline.kind === "lineBreak")
313982
314627
  return true;
314628
+ if (inline.kind === "image")
314629
+ return true;
313983
314630
  if (inline.kind === "hyperlink")
313984
314631
  return inline.hyperlink.inlines.some(hasSubstantiveInline);
313985
314632
  return false;
@@ -314093,6 +314740,7 @@ var init_converter = __esm(() => {
314093
314740
  init_fragment_output_budget();
314094
314741
  init_hyperlink_values();
314095
314742
  init_css();
314743
+ init_trusted_image();
314096
314744
  init_limits();
314097
314745
  init_word_lists();
314098
314746
  BLOCK_ELEMENTS = new Set([
@@ -325451,105 +326099,6 @@ var init_convert_to_fragment = __esm(() => {
325451
326099
  init_markdown();
325452
326100
  });
325453
326101
 
325454
- // ../../../v2/document-api-v2-adapter/dist/clipboard/base64.js
325455
- function decodedLength(value2) {
325456
- 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)) {
325457
- return null;
325458
- }
325459
- return value2.length / 4 * 3 - (value2.endsWith("==") ? 2 : value2.endsWith("=") ? 1 : 0);
325460
- }
325461
- function base64DecodedLength(value2) {
325462
- return decodedLength(value2);
325463
- }
325464
- function bytesToBase64(bytes) {
325465
- if (typeof globalThis.btoa === "function") {
325466
- let binary = "";
325467
- for (let offset = 0;offset < bytes.length; offset += 32768) {
325468
- binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
325469
- }
325470
- return globalThis.btoa(binary);
325471
- }
325472
- return Buffer.from(bytes).toString("base64");
325473
- }
325474
- function base64ToBytes(value2, maxDecodedBytes) {
325475
- const length = decodedLength(value2);
325476
- if (length === null || length > maxDecodedBytes)
325477
- return null;
325478
- try {
325479
- if (typeof globalThis.atob === "function") {
325480
- const binary = globalThis.atob(value2);
325481
- const bytes = new Uint8Array(binary.length);
325482
- for (let index2 = 0;index2 < binary.length; index2 += 1)
325483
- bytes[index2] = binary.charCodeAt(index2);
325484
- return bytes;
325485
- }
325486
- return Uint8Array.from(Buffer.from(value2, "base64"));
325487
- } catch {
325488
- return null;
325489
- }
325490
- }
325491
-
325492
- // ../../../v2/document-api-v2-adapter/dist/images/raster-dimensions.js
325493
- function readPngDimensions(bytes) {
325494
- 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) {
325495
- return null;
325496
- }
325497
- let offset = 8;
325498
- let dimensions = null;
325499
- while (offset + 12 <= bytes.length) {
325500
- const length = readUint32be(bytes, offset);
325501
- const dataEnd = offset + 8 + length;
325502
- const chunkEnd = dataEnd + 4;
325503
- if (chunkEnd > bytes.length)
325504
- return null;
325505
- const type = String.fromCharCode(bytes[offset + 4], bytes[offset + 5], bytes[offset + 6], bytes[offset + 7]);
325506
- if (offset === 8) {
325507
- if (type !== "IHDR" || length !== 13)
325508
- return null;
325509
- const widthPx = readUint32be(bytes, offset + 8);
325510
- const heightPx = readUint32be(bytes, offset + 12);
325511
- if (widthPx <= 0 || heightPx <= 0)
325512
- return null;
325513
- dimensions = { widthPx, heightPx };
325514
- } else if (type === "IDAT") {
325515
- return dimensions;
325516
- } else if (type === "IEND") {
325517
- return null;
325518
- }
325519
- offset = chunkEnd;
325520
- }
325521
- return null;
325522
- }
325523
- function readJpegDimensions(bytes) {
325524
- if (bytes.length < 4 || bytes[0] !== 255 || bytes[1] !== 216)
325525
- return null;
325526
- let offset = 2;
325527
- while (offset + 9 < bytes.length) {
325528
- if (bytes[offset] !== 255)
325529
- return null;
325530
- const marker = bytes[offset + 1];
325531
- offset += 2;
325532
- while (bytes[offset] === 255)
325533
- offset += 1;
325534
- if (marker === 217 || marker === 218)
325535
- return null;
325536
- const segmentLength = (bytes[offset] << 8) + bytes[offset + 1];
325537
- if (segmentLength < 2 || offset + segmentLength > bytes.length)
325538
- return null;
325539
- if (marker >= 192 && marker <= 195 || marker >= 197 && marker <= 199 || marker >= 201 && marker <= 203 || marker >= 205 && marker <= 207) {
325540
- return {
325541
- heightPx: (bytes[offset + 3] << 8) + bytes[offset + 4],
325542
- widthPx: (bytes[offset + 5] << 8) + bytes[offset + 6]
325543
- };
325544
- }
325545
- offset += segmentLength;
325546
- }
325547
- return null;
325548
- }
325549
- function readUint32be(bytes, offset) {
325550
- return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
325551
- }
325552
-
325553
326102
  // ../../../v2/document-api-v2-adapter/dist/conversion/fragment-images.js
325554
326103
  function createFragmentImageLowering(invalid3, unsupported4) {
325555
326104
  const assets = [];
@@ -325585,17 +326134,20 @@ function createFragmentImageLowering(invalid3, unsupported4) {
325585
326134
  }
325586
326135
  if (++references > MAX_V22_IMAGE_REF_COUNT)
325587
326136
  invalid3(path7, "Fragment contains too many image references.");
325588
- 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);
325589
326138
  if (!match)
325590
326139
  unsupported4([...payloadPath, "src"], "Rich inbound images require a PNG or JPEG base64 data URI.");
325591
- const mimeType = match[1].toLowerCase() === "image/png" ? "image/png" : "image/jpeg";
326140
+ const payload = match[2].replace(/\s+/g, "");
325592
326141
  let asset = bySource.get(image.src);
325593
326142
  if (!asset) {
325594
326143
  if (assets.length >= MAX_V22_ASSET_COUNT)
325595
326144
  invalid3(path7, "Fragment contains too many image assets.");
325596
- const bytes = base64ToBytes(match[2], MAX_V22_ASSET_DECODED_BYTES2);
326145
+ const bytes = base64ToBytes(payload, MAX_V22_ASSET_DECODED_BYTES2);
325597
326146
  if (!bytes)
325598
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.");
325599
326151
  totalBytes += bytes.length;
325600
326152
  if (totalBytes > MAX_V22_TOTAL_DECODED_BYTES2)
325601
326153
  invalid3(path7, "Fragment image bytes exceed the decoded asset limit.");
@@ -325603,7 +326155,7 @@ function createFragmentImageLowering(invalid3, unsupported4) {
325603
326155
  assets.push(asset);
325604
326156
  bySource.set(image.src, asset);
325605
326157
  }
325606
- const intrinsic = mimeType === "image/png" ? readPngDimensions(asset.bytes) : readJpegDimensions(asset.bytes);
326158
+ const intrinsic = asset.mimeType === "image/png" ? readPngDimensions(asset.bytes) : readJpegDimensions(asset.bytes);
325607
326159
  if (!intrinsic)
325608
326160
  invalid3([...payloadPath, "src"], "Image dimensions could not be determined.");
325609
326161
  const width = image.geometry?.width;
@@ -325611,8 +326163,8 @@ function createFragmentImageLowering(invalid3, unsupported4) {
325611
326163
  if (width === undefined !== (height === undefined)) {
325612
326164
  unsupported4([...payloadPath, "geometry"], "Rich inbound image geometry requires both width and height.");
325613
326165
  }
325614
- const widthPx = width === undefined ? intrinsic.widthPx : width * 4 / 3;
325615
- 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);
325616
326168
  if (![widthPx, heightPx].every((value2) => Number.isInteger(value2) && value2 >= 1 && value2 <= 1e4)) {
325617
326169
  invalid3([...payloadPath, "geometry"], "Image dimensions must map to integer pixels between 1 and 10000.");
325618
326170
  }
@@ -325620,14 +326172,26 @@ function createFragmentImageLowering(invalid3, unsupported4) {
325620
326172
  }
325621
326173
  };
325622
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
+ }
325623
326183
  var init_fragment_images = __esm(() => {
325624
326184
  init_src3();
325625
326185
  });
325626
326186
 
325627
326187
  // ../../../v2/document-api-v2-adapter/dist/conversion/lower-fragment.js
325628
- 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
+ }
325629
326193
  try {
325630
- const stringViolation = inspectFragmentStringOutput(fragment4, DEFAULT_MAX_FRAGMENT_STRING_CODE_UNITS);
326194
+ const stringViolation = inspectFragmentStringOutput(fragment4, maxOutputCodeUnits);
325631
326195
  if (stringViolation?.kind === "xml") {
325632
326196
  invalid3(stringViolation.path, "Fragment strings must contain only XML 1.0-safe characters.");
325633
326197
  }
@@ -326034,51 +326598,100 @@ function romanOrdinal(core2, path7) {
326034
326598
  return positiveInteger(total, path7);
326035
326599
  }
326036
326600
  function lowerTable(node4, path7, images) {
326037
- if (node4.table.props || node4.table.columns) {
326038
- 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.");
326039
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"]);
326040
326672
  return {
326041
326673
  kind: "table",
326042
326674
  sourcePath: path7,
326043
326675
  ...node4.table.styleRef ? { styleRef: node4.table.styleRef } : {},
326044
- rows: node4.table.rows.map((row, rowIndex) => {
326045
- const rowPath = [...path7, "table", "rows", rowIndex];
326046
- if (row.props && Object.keys(row.props).length > 0) {
326047
- unsupported4([...rowPath, "props"], "Direct table-row properties are not materializable.");
326048
- }
326049
- const header = rowIndex === 0 && row.cells.length > 0 && row.cells.every((cell) => cell.header === true);
326050
- let rowGridColumns = 0;
326051
- return {
326052
- sourcePath: rowPath,
326053
- ...header ? { header: true } : {},
326054
- cells: row.cells.map((cell, cellIndex) => {
326055
- const cellPath = [...rowPath, "cells", cellIndex];
326056
- if (cell.rowSpan !== undefined && cell.rowSpan !== 1) {
326057
- unsupported4([...cellPath, "rowSpan"], "Vertically spanned table cells are not materializable.");
326058
- }
326059
- const gridSpan = cell.colSpan === undefined ? 1 : tableGridSpan(cell.colSpan, [...cellPath, "colSpan"]);
326060
- rowGridColumns += gridSpan;
326061
- if (rowGridColumns > MAX_WORD_TABLE_GRID_COLUMNS3) {
326062
- invalid3([...rowPath, "cells"], `Table rows cannot exceed ${MAX_WORD_TABLE_GRID_COLUMNS3} grid columns.`);
326063
- }
326064
- if (cell.content.length === 0)
326065
- invalid3([...cellPath, "content"], "Table cells must contain a paragraph.");
326066
- const blocks = cell.content.flatMap((content3, contentIndex) => {
326067
- const contentPath = [...cellPath, "content", contentIndex];
326068
- const lowered = lowerTableCellContent(content3, contentPath, images);
326069
- return cell.header ? lowered.map(emphasizeHeaderCellBlock) : lowered;
326070
- });
326071
- return {
326072
- blocks,
326073
- sourcePath: cellPath,
326074
- ...cell.colSpan !== undefined ? { gridSpan } : {},
326075
- ...lowerCellProperties(cell.props, [...cellPath, "props"])
326076
- };
326077
- })
326078
- };
326079
- })
326676
+ ...columnWidthShares ? { columnWidthShares } : {},
326677
+ rows
326080
326678
  };
326081
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
+ }
326082
326695
  function lowerTableCellContent(content3, path7, images) {
326083
326696
  if (content3.kind === "paragraph") {
326084
326697
  return [lowerParagraph(content3.paragraph, path7, [...path7, "paragraph"], images)];
@@ -326136,6 +326749,10 @@ function lowerCellProperties(props, path7) {
326136
326749
  }
326137
326750
  shadingColor = props.shading.value.toUpperCase();
326138
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
+ }
326139
326756
  const padding = props.padding ? {
326140
326757
  ...props.padding.top !== undefined ? { topPt: safeScaledNonnegative(props.padding.top, 20, [...path7, "padding", "top"]) } : {},
326141
326758
  ...props.padding.right !== undefined ? { rightPt: safeScaledNonnegative(props.padding.right, 20, [...path7, "padding", "right"]) } : {},
@@ -326148,8 +326765,8 @@ function lowerCellProperties(props, path7) {
326148
326765
  })) : undefined;
326149
326766
  return {
326150
326767
  ...shadingColor ? { shadingColor } : {},
326768
+ ...verticalAlign ? { verticalAlign } : {},
326151
326769
  ...padding && Object.keys(padding).length > 0 ? { padding } : {},
326152
- ...props.verticalAlign ? { verticalAlign: props.verticalAlign } : {},
326153
326770
  ...borders && Object.keys(borders).length > 0 ? { borders } : {}
326154
326771
  };
326155
326772
  }
@@ -326648,6 +327265,38 @@ var init_parse_v1_slice = __esm(() => {
326648
327265
  init_src3();
326649
327266
  });
326650
327267
 
327268
+ // ../../../v2/document-api-v2-adapter/dist/clipboard/style-context.js
327269
+ function clipboardStyleContext(context) {
327270
+ const parts = [
327271
+ readStyleDefinitionsPartBytes(context),
327272
+ ...["/word/numbering.xml", "/word/theme/theme1.xml", "/word/settings.xml", "/word/fontTable.xml"].map((uri) => getSDDocumentSessionInternalPartBytes(context.session, uri) ?? null)
327273
+ ];
327274
+ return {
327275
+ documentEpoch: getSDDocumentSessionInternalSourceCommit(context.session).documentEpoch,
327276
+ digest: sha256HexSync(new TextEncoder().encode(JSON.stringify(parts.map((bytes) => bytes ? sha256HexSync(bytes) : null))))
327277
+ };
327278
+ }
327279
+ function clipboardStyleContextMatches(context, value2) {
327280
+ const source = normalizeClipboardStyleContext(value2);
327281
+ if (!source)
327282
+ return false;
327283
+ if (source.documentEpoch === getSDDocumentSessionInternalSourceCommit(context.session).documentEpoch)
327284
+ return true;
327285
+ return source.digest === clipboardStyleContext(context).digest;
327286
+ }
327287
+ function normalizeClipboardStyleContext(value2) {
327288
+ if (!value2 || typeof value2 !== "object" || Array.isArray(value2))
327289
+ return null;
327290
+ const source = value2;
327291
+ if (typeof source.documentEpoch !== "string" || source.documentEpoch.length === 0 || source.documentEpoch.length > 255 || typeof source.digest !== "string" || !/^[a-f0-9]{64}$/.test(source.digest))
327292
+ return null;
327293
+ return { documentEpoch: source.documentEpoch, digest: source.digest };
327294
+ }
327295
+ var init_style_context = __esm(() => {
327296
+ init_sd_document_session_internal();
327297
+ init_part();
327298
+ });
327299
+
326651
327300
  // ../../../v2/document-api-v2-adapter/dist/clipboard/parse-v2-fragment.js
326652
327301
  function parseV2FragmentPayload(payload, mime = SUPERDOC_V2_CLIPBOARD_MIME) {
326653
327302
  const item = payload.items.find((candidate2) => candidate2.type === mime);
@@ -326683,9 +327332,11 @@ function parseV2FragmentPayload(payload, mime = SUPERDOC_V2_CLIPBOARD_MIME) {
326683
327332
  ]
326684
327333
  };
326685
327334
  }
327335
+ const prepared = prepareClipboardPlan(fragment4.fragment, "superdoc-v2-fragment", fragment4.fragment.diagnostics ?? []);
326686
327336
  return {
326687
327337
  ok: true,
326688
- ...prepareClipboardPlan(fragment4.fragment, "superdoc-v2-fragment", fragment4.fragment.diagnostics ?? [])
327338
+ ...prepared,
327339
+ plan: { ...prepared.plan, sourceStyleContext: normalizeClipboardStyleContext(parsed.sourceStyleContext) }
326689
327340
  };
326690
327341
  }
326691
327342
  function normalizeV2WireFragment(value2) {
@@ -326809,9 +327460,13 @@ function normalizeParagraphBlock(value2, path7, version2, allowHeading) {
326809
327460
  const review = normalizeRunReviewFields(run, [...path7, "runs", runIndex]);
326810
327461
  if (isPlanFailure(review))
326811
327462
  return review;
327463
+ const styleRef = normalizeCharacterStyleRef(run.styleRef, [...path7, "runs", runIndex, "styleRef"]);
327464
+ if (isPlanFailure(styleRef))
327465
+ return styleRef;
326812
327466
  runs.push({
326813
327467
  text: run.text,
326814
327468
  ...marks ? { marks } : {},
327469
+ ...styleRef ? { styleRef } : {},
326815
327470
  ...sourcePath2 ? { sourcePath: sourcePath2 } : {},
326816
327471
  ...review
326817
327472
  });
@@ -326829,7 +327484,7 @@ function normalizeParagraphBlock(value2, path7, version2, allowHeading) {
326829
327484
  inlines.push(normalized);
326830
327485
  }
326831
327486
  const projected = inlines.flatMap(projectInlineText);
326832
- if (projected.length !== runs.length || projected.some((inline, runIndex) => inline.text !== runs[runIndex]?.text || JSON.stringify(inline.marks ?? {}) !== JSON.stringify(runs[runIndex]?.marks ?? {}))) {
327487
+ if (projected.length !== runs.length || projected.some((inline, runIndex) => inline.text !== runs[runIndex]?.text || JSON.stringify(inline.marks ?? {}) !== JSON.stringify(runs[runIndex]?.marks ?? {}) || (inline.styleRef ?? undefined) !== (runs[runIndex]?.styleRef ?? undefined))) {
326833
327488
  return structureFailure("Paragraph runs must equal the text projection of inlines.", path7);
326834
327489
  }
326835
327490
  }
@@ -326905,6 +327560,14 @@ function normalizeBlockSdts(value2, path7) {
326905
327560
  function validSdtMetadata(value2) {
326906
327561
  return (value2.lockMode === undefined || value2.lockMode === "unlocked" || value2.lockMode === "sdtLocked" || value2.lockMode === "contentLocked" || value2.lockMode === "sdtContentLocked") && (value2.multiline === undefined || value2.controlType === "text" && typeof value2.multiline === "boolean");
326907
327562
  }
327563
+ function normalizeCharacterStyleRef(value2, path7) {
327564
+ if (value2 === undefined)
327565
+ return;
327566
+ if (typeof value2 !== "string" || value2.length === 0 || !isXml10SafeAttributeValue(value2) || value2.length > 255) {
327567
+ return structureFailure("Paste run styleRef must be a non-empty XML-safe style id of at most 255 characters.", path7);
327568
+ }
327569
+ return value2;
327570
+ }
326908
327571
  function projectInlineText(inline) {
326909
327572
  if (inline.kind === "text")
326910
327573
  return [inline];
@@ -326960,10 +327623,14 @@ function normalizeInline(value2, path7, allowHyperlink, depth = 0) {
326960
327623
  const review = normalizeRunReviewFields(value2, path7);
326961
327624
  if (isPlanFailure(review))
326962
327625
  return review;
327626
+ const styleRef = normalizeCharacterStyleRef(value2.styleRef, [...path7, "styleRef"]);
327627
+ if (isPlanFailure(styleRef))
327628
+ return styleRef;
326963
327629
  return {
326964
327630
  kind: "text",
326965
327631
  text: value2.text,
326966
327632
  ...marks ? { marks } : {},
327633
+ ...styleRef ? { styleRef } : {},
326967
327634
  ...sourcePath ? { sourcePath } : {},
326968
327635
  ...review
326969
327636
  };
@@ -327390,9 +328057,17 @@ function normalizeTableBlock(block, index2, version2) {
327390
328057
  if (block.cellSpacingPt !== undefined && !isSafePaddingPoints2(block.cellSpacingPt)) {
327391
328058
  return fail4("Paste table cellSpacingPt must be a non-negative finite point value within the safe twip range.");
327392
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
+ }
327393
328067
  if (!Array.isArray(block.rows) || block.rows.length === 0)
327394
328068
  return fail4("Paste table blocks require rows.");
327395
328069
  const rows = [];
328070
+ let tableColumnCount2 = 0;
327396
328071
  for (const [rowIndex, row] of block.rows.entries()) {
327397
328072
  if (!isRecord14(row) || !Array.isArray(row.cells) || row.cells.length === 0) {
327398
328073
  return fail4("Paste table rows require cells.");
@@ -327430,6 +328105,9 @@ function normalizeTableBlock(block, index2, version2) {
327430
328105
  if (gridColumnCount > MAX_WORD_TABLE_COLUMNS2) {
327431
328106
  return fail4(`Paste table rows cannot span more than ${MAX_WORD_TABLE_COLUMNS2} grid columns.`);
327432
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
+ }
327433
328111
  let shadingColor;
327434
328112
  if (cell.shadingColor !== undefined) {
327435
328113
  if (typeof cell.shadingColor !== "string" || !/^#?[0-9a-f]{6}$/i.test(cell.shadingColor)) {
@@ -327507,6 +328185,7 @@ function normalizeTableBlock(block, index2, version2) {
327507
328185
  cells.push({
327508
328186
  blocks: cellBlocks,
327509
328187
  ...cell.gridSpan !== undefined ? { gridSpan: cell.gridSpan } : {},
328188
+ ...cell.vMerge !== undefined ? { vMerge: cell.vMerge } : {},
327510
328189
  ...shadingColor ? { shadingColor } : {},
327511
328190
  ...padding ? { padding } : {},
327512
328191
  ...verticalAlign ? { verticalAlign } : {},
@@ -327519,6 +328198,10 @@ function normalizeTableBlock(block, index2, version2) {
327519
328198
  ...row.header === true ? { header: true } : {},
327520
328199
  ...rowSourcePath ? { sourcePath: rowSourcePath } : {}
327521
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.");
327522
328205
  }
327523
328206
  const sourcePath = normalizeSourcePath(block.sourcePath, ["blocks", index2, "sourcePath"]);
327524
328207
  if (isPlanFailure(sourcePath))
@@ -327527,6 +328210,7 @@ function normalizeTableBlock(block, index2, version2) {
327527
328210
  kind: "table",
327528
328211
  ...blockSdts ? { blockSdts } : {},
327529
328212
  rows,
328213
+ ...columnWidthShares ? { columnWidthShares } : {},
327530
328214
  ...block.cellSpacingPt !== undefined ? { cellSpacingPt: block.cellSpacingPt } : {},
327531
328215
  ...sourcePath ? { sourcePath } : {}
327532
328216
  };
@@ -327545,8 +328229,8 @@ function normalizeMarks2(value2, path7) {
327545
328229
  out[key2] = value2[key2];
327546
328230
  }
327547
328231
  if (value2.color !== undefined) {
327548
- if (typeof value2.color !== "string" || !/^#?[0-9A-Fa-f]{6}$/.test(value2.color)) {
327549
- return structureFailure("Paste run color must be a six-digit RGB value.", [...path7, "color"]);
328232
+ if (typeof value2.color !== "string" || value2.color !== "auto" && !/^#?[0-9A-Fa-f]{6}$/.test(value2.color)) {
328233
+ return structureFailure("Paste run color must be a six-digit RGB value or auto.", [...path7, "color"]);
327550
328234
  }
327551
328235
  out.color = value2.color.replace(/^#/, "");
327552
328236
  }
@@ -327606,6 +328290,7 @@ var init_parse_v2_fragment = __esm(() => {
327606
328290
  init_contracts();
327607
328291
  init_fragment_output_budget();
327608
328292
  init_hyperlink_values();
328293
+ init_style_context();
327609
328294
  RUN_MARK_KEYS = new Set([
327610
328295
  "boldCs",
327611
328296
  "italicCs",
@@ -327899,6 +328584,534 @@ var init_word_notes = __esm(() => {
327899
328584
  WORD_NOTE_SEPARATOR_BLOCK = /<(div|p)\b[^>]*\bmso-element\s*:\s*(?:footnote|endnote)(?:-continuation)?-separator\b[^>]*>[\s\S]*?<\/\1>/gi;
327900
328585
  });
327901
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
+
327902
329115
  // ../../../v2/document-api-v2-adapter/dist/clipboard/plan.js
327903
329116
  function createClipboardInsertPlan(payload, options = {}) {
327904
329117
  const richItem = payload.items.find((item) => item.type === SUPERDOC_V22_CLIPBOARD_MIME);
@@ -327916,7 +329129,7 @@ function createClipboardInsertPlan(payload, options = {}) {
327916
329129
  ];
327917
329130
  }
327918
329131
  }
327919
- const byteCount = estimatePayloadBytes(payload.items.filter((item) => item.type !== SUPERDOC_V22_CLIPBOARD_MIME));
329132
+ const byteCount = estimatePastePlanBytes(payload.items);
327920
329133
  if (byteCount > (options.maxBytes ?? DEFAULT_MAX_CLIPBOARD_BYTES))
327921
329134
  return failPlan("paste-payload-too-large", "Clipboard payload exceeds the configured size cap.", "unknown");
327922
329135
  const v2 = parseV2FragmentPayload(payload);
@@ -327982,15 +329195,52 @@ function planFromPlainText(text4, plainFallback) {
327982
329195
  ...prepareClipboardPlan(fragment4, "plain-text", [], plainFallback)
327983
329196
  };
327984
329197
  }
327985
- function planFromHtml(payload, html, options) {
327986
- const rewritten = rewriteWordNoteClipboardHtml(html);
327987
- const converted = convertContentToFragment({ format: "html", source: rewritten });
329198
+ function createPortableHtmlInsertPlan(payload, options = {}) {
329199
+ const portable = { ...payload, items: payload.items.filter((item) => item.type === "text/html" || item.type === "text/plain") };
329200
+ if (estimatePastePlanBytes(portable.items) > (options.maxBytes ?? DEFAULT_MAX_CLIPBOARD_BYTES)) {
329201
+ return failPlan("paste-payload-too-large", "Clipboard payload exceeds the configured size cap.", "html");
329202
+ }
329203
+ const html = readStringItem(portable, "text/html");
329204
+ if (html === null)
329205
+ return failPlan("paste-no-faithful-representation", "No portable HTML flavor is available.", "html");
329206
+ return planFromHtml(portable, html, options, true);
329207
+ }
329208
+ function planFromHtml(payload, html, options, rejectUnsafeContent = false) {
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
+ });
327988
329233
  const diagnostics = converted.diagnostics.map(toClipboardHtmlDiagnostic);
329234
+ if (rejectUnsafeContent && diagnostics.some((entry) => entry.reason === "paste-security-rejected")) {
329235
+ return failPlan("paste-security-rejected", "The portable HTML flavor contains unsafe content.", "html");
329236
+ }
327989
329237
  const fatal = converted.diagnostics.find((entry) => entry.severity === "error");
327990
329238
  if (fatal) {
327991
329239
  return fallbackFromFatalHtml(payload, options, fatal, diagnostics);
327992
329240
  }
327993
- const lowered = lowerFragmentToApplyPlan(converted.fragment);
329241
+ const lowered = lowerFragmentToApplyPlan(converted.fragment, {
329242
+ maxOutputCodeUnits: DEFAULT_MAX_FRAGMENT_STRING_CODE_UNITS + allowance
329243
+ });
327994
329244
  if (!lowered.ok) {
327995
329245
  const reason = lowered.code === "INVALID_PAYLOAD" ? "paste-structure-unsupported" : "paste-no-faithful-representation";
327996
329246
  return fallbackOrFail(payload, options, reason, lowered.message);
@@ -328114,6 +329364,19 @@ function sourceKindForPayload(payload) {
328114
329364
  return "plain-text";
328115
329365
  return "unknown";
328116
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
+ }
328117
329380
  function readStringItem(payload, type) {
328118
329381
  const item = payload.items.find((candidate2) => candidate2.type === type);
328119
329382
  return item?.kind === "string" && typeof item.data === "string" ? item.data : null;
@@ -328151,8 +329414,15 @@ function readHtmlAttribute(tag, name) {
328151
329414
  const match = new RegExp(`\\b${escaped}\\s*=\\s*(["'])([\\s\\S]*?)\\1`, "i").exec(tag);
328152
329415
  return match?.[2] ?? null;
328153
329416
  }
328154
- function estimatePayloadBytes(items) {
328155
- 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);
328156
329426
  }
328157
329427
  function estimateClipboardItemBytes(item) {
328158
329428
  if (item.kind === "bytes" && item.data instanceof Uint8Array)
@@ -328163,6 +329433,8 @@ var UTF8_ENCODER2;
328163
329433
  var init_plan3 = __esm(() => {
328164
329434
  init_src3();
328165
329435
  init_convert_to_fragment();
329436
+ init_limits();
329437
+ init_fragment_output_budget();
328166
329438
  init_lower_fragment();
328167
329439
  init_contracts();
328168
329440
  init_media();
@@ -328170,6 +329442,7 @@ var init_plan3 = __esm(() => {
328170
329442
  init_parse_v1_slice();
328171
329443
  init_parse_v2_fragment();
328172
329444
  init_word_notes();
329445
+ init_word_vml_images();
328173
329446
  UTF8_ENCODER2 = new TextEncoder;
328174
329447
  });
328175
329448
 
@@ -328689,7 +329962,11 @@ function* serializeSelectionRangeSteps(context, target, includeHtml, options) {
328689
329962
  const selectedInlineControl = options?.wholeParagraphs !== true && startEntry.ordinal === endEntry.ordinal && map3.pieces.some((piece) => piece.kind === "container" && piece.containerKind === "sdt" && piece.visibleStart === from && piece.visibleEnd === to);
328690
329963
  const fullyCovered = !selectedInlineControl && from === 0 && to === map3.visibleLength && (options?.wholeParagraphs === true || startEntry.ordinal !== endEntry.ordinal || properties.styleRef !== undefined || properties.numbering !== undefined || hasParagraphProperties(paragraphXml));
328691
329964
  const styleModel = copyStyleModel ?? (copyStyleModel = compileCopyStyleModel(context));
328692
- const styleContext = copyStyleContext(styleModel, properties.styleRef);
329965
+ const styleContext = {
329966
+ ...copyStyleContext(styleModel, properties.styleRef),
329967
+ materializeParagraphFormatting: !fullyCovered,
329968
+ effectiveTypingMarks: options?.effectiveTypingMarks
329969
+ };
328693
329970
  const semanticStyleRole = portableSemanticStyleRole(styleModel, properties.styleRef);
328694
329971
  const semanticHeadingLevel = semanticStyleRole?.startsWith("heading-") ? Number(semanticStyleRole.slice("heading-".length)) : null;
328695
329972
  const parts = [];
@@ -328866,13 +330143,14 @@ function* serializeSelectionRangeSteps(context, target, includeHtml, options) {
328866
330143
  })), notes.diagnostics());
328867
330144
  plan = buildPlan(fallbackFragment, "plain-text", notes.diagnostics(), true);
328868
330145
  } else {
330146
+ const sourceStyleContext = clipboardStyleContext(context);
328869
330147
  const hasPreservedControls = blocks.some((block) => !!block.blockSdts?.length || block.parts.some((part) => part.kind === "sdt"));
328870
330148
  const legacyDiagnostics = hasPreservedControls ? [...notes.diagnostics(), diagnostic("paste-no-faithful-representation", "The v2.1 clipboard flavor retains visible text but not content-control structure; use the v2.2 flavor to preserve controls.", "superdoc-v2-fragment", "warning")] : notes.diagnostics();
328871
330149
  const fragment4 = withPasteComments(buildFragment(grouped.map(fragmentBlockFor), legacyDiagnostics), commentsById);
328872
330150
  items.push({
328873
330151
  type: SUPERDOC_V2_CLIPBOARD_MIME,
328874
330152
  kind: "string",
328875
- data: JSON.stringify(fragment4)
330153
+ data: JSON.stringify({ ...fragment4, sourceStyleContext })
328876
330154
  });
328877
330155
  const assets = [...rich.assetsByPartUri.values()];
328878
330156
  const hasRichInlineStructure = blocks.some((block) => !!block.blockSdts?.length || block.parts.some((part) => part.kind === "hyperlink" || part.kind === "image" || part.kind === "sdt"));
@@ -328885,11 +330163,12 @@ function* serializeSelectionRangeSteps(context, target, includeHtml, options) {
328885
330163
  assets: assets.map((asset) => asset.wire),
328886
330164
  diagnostics: notes.diagnostics()
328887
330165
  }, commentsById);
328888
- items.push({ type: SUPERDOC_V22_CLIPBOARD_MIME, kind: "string", data: JSON.stringify(wireFragment) });
330166
+ items.push({ type: SUPERDOC_V22_CLIPBOARD_MIME, kind: "string", data: JSON.stringify({ ...wireFragment, sourceStyleContext }) });
328889
330167
  plan = buildPlan({ ...wireFragment, assets: assets.map((asset) => asset.decoded) }, "superdoc-v2-fragment", notes.diagnostics());
328890
330168
  } else {
328891
330169
  plan = buildPlan(fragment4, "superdoc-v2-fragment", notes.diagnostics());
328892
330170
  }
330171
+ plan = { ...plan, sourceStyleContext };
328893
330172
  }
328894
330173
  return {
328895
330174
  ok: true,
@@ -329259,22 +330538,26 @@ function walkPieces(pieces, from, to, out, notes, styleContext, review) {
329259
330538
  const sliceEnd = Math.min(to, piece.visibleEnd) - piece.visibleStart;
329260
330539
  const text4 = decoded.slice(sliceStart, sliceEnd);
329261
330540
  if (text4.length > 0) {
329262
- const marks = resolveRunMarks(piece.runProperties, styleContext);
330541
+ const characterStyleRef = styleContext?.effectiveTypingMarks ? undefined : parseCharacterStyleRef(piece.runProperties);
330542
+ const marks = characterStyleRef ? parseNamedStyleRunMarks(piece.runProperties, styleContext) : resolveRunMarks(piece.runProperties, styleContext);
329263
330543
  const spanStart = piece.visibleStart + sliceStart;
329264
330544
  const spanEnd = piece.visibleStart + sliceEnd;
329265
330545
  out.push({
329266
330546
  kind: "run",
329267
- run: serializePasteRun(text4, marks, piece, spanStart, spanEnd, review)
330547
+ run: serializePasteRun(text4, marks, piece, spanStart, spanEnd, review, characterStyleRef),
330548
+ ...characterStyleRef ? { htmlMarks: resolveNamedStyleHtmlMarks(piece.runProperties, styleContext) } : {}
329268
330549
  });
329269
330550
  }
329270
330551
  break;
329271
330552
  }
329272
330553
  case "control": {
329273
330554
  if (piece.control === "tab" || piece.control === "symbol") {
329274
- const marks = resolveRunMarks(piece.runProperties, styleContext);
330555
+ const characterStyleRef = styleContext?.effectiveTypingMarks ? undefined : parseCharacterStyleRef(piece.runProperties);
330556
+ const marks = characterStyleRef ? parseNamedStyleRunMarks(piece.runProperties, styleContext) : resolveRunMarks(piece.runProperties, styleContext);
329275
330557
  out.push({
329276
330558
  kind: "run",
329277
- run: serializePasteRun(piece.symbolText ?? "\t", marks, piece, piece.visibleStart, piece.visibleEnd, review)
330559
+ ...characterStyleRef ? { htmlMarks: resolveNamedStyleHtmlMarks(piece.runProperties, styleContext) } : {},
330560
+ run: serializePasteRun(piece.symbolText ?? "\t", marks, piece, piece.visibleStart, piece.visibleEnd, review, characterStyleRef)
329278
330561
  });
329279
330562
  } else {
329280
330563
  out.push({ kind: "break" });
@@ -329335,16 +330618,21 @@ function selectionPreservesComment(markerId, from, to, review) {
329335
330618
  return false;
329336
330619
  return review.commentRanges.some((range) => range.id === markerId && range.start < to && range.end > from);
329337
330620
  }
329338
- function serializePasteRun(text4, marks, piece, spanStart, spanEnd, review) {
330621
+ function serializePasteRun(text4, marks, piece, spanStart, spanEnd, review, styleRef) {
329339
330622
  const commentIds = resolveCommentIdsForSpan(spanStart, spanEnd, review);
329340
330623
  const trackedInsertion = piece.containerStack.some((scope) => scope.kind === "ins");
329341
330624
  return {
329342
330625
  text: text4,
329343
330626
  ...marks ? { marks } : {},
330627
+ ...styleRef ? { styleRef } : {},
329344
330628
  ...commentIds.length > 0 ? { commentIds } : {},
329345
330629
  ...trackedInsertion ? { trackedInsertion: true } : {}
329346
330630
  };
329347
330631
  }
330632
+ function parseCharacterStyleRef(rPrXml) {
330633
+ const value2 = parseWordRunPropertiesXml(rPrXml).styleId;
330634
+ return value2 && value2.length > 0 ? value2 : undefined;
330635
+ }
329348
330636
  function resolveCommentIdsForSpan(spanStart, spanEnd, review) {
329349
330637
  if (!review)
329350
330638
  return [];
@@ -329681,6 +330969,115 @@ function parseRunPropertiesMarks(rPrXml) {
329681
330969
  marks.verticalAlign = verticalAlign;
329682
330970
  return Object.keys(marks).length > 0 ? marks : undefined;
329683
330971
  }
330972
+ function resolveNamedStyleHtmlMarks(rPrXml, styleContext) {
330973
+ const marks = resolveRunMarks(rPrXml, styleContext);
330974
+ if (!marks?.color && parseWordRunPropertiesXml(rPrXml).color?.val?.toLowerCase() === "auto") {
330975
+ return { ...marks, color: "auto" };
330976
+ }
330977
+ return marks;
330978
+ }
330979
+ function parseNamedStyleRunMarks(rPrXml, styleContext) {
330980
+ const direct = parseWordRunPropertiesXml(rPrXml);
330981
+ const marks = {};
330982
+ if (direct.bold !== undefined)
330983
+ marks.bold = direct.bold === true;
330984
+ if (direct.boldCs !== undefined)
330985
+ marks.boldCs = direct.boldCs === true;
330986
+ if (direct.italic !== undefined)
330987
+ marks.italic = direct.italic === true;
330988
+ if (direct.iCs !== undefined)
330989
+ marks.italicCs = direct.iCs === true;
330990
+ if (direct.textTransform !== undefined)
330991
+ marks.caps = direct.textTransform === "uppercase";
330992
+ if (direct.smallCaps !== undefined)
330993
+ marks.smallCaps = direct.smallCaps === true;
330994
+ if (direct.underline !== undefined)
330995
+ marks.underline = direct.underline["w:val"] !== "none";
330996
+ if (typeof direct.fontSize === "number" && direct.fontSize > 0)
330997
+ marks.fontSizePt = direct.fontSize / 2;
330998
+ if (typeof direct.fontSizeCs === "number" && direct.fontSizeCs > 0)
330999
+ marks.fontSizeCsPt = direct.fontSizeCs / 2;
331000
+ if (isPortableVerticalAlign(direct.vertAlign))
331001
+ marks.verticalAlign = direct.vertAlign;
331002
+ const highlight = normalizePasteHighlight(direct.highlight?.["w:val"], readHighlightFallbackShdFill(rPrXml));
331003
+ if (highlight)
331004
+ marks.highlight = highlight;
331005
+ if (direct.highlight?.["w:val"]?.toLowerCase() === "none")
331006
+ marks.highlight = "none";
331007
+ if (direct.strike !== undefined || direct.dstrike !== undefined) {
331008
+ const resolved = styleContext?.model.resolveRun({
331009
+ inlineRpr: direct,
331010
+ resolvedParagraphProperties: styleContext.paragraphProperties
331011
+ }) ?? direct;
331012
+ marks.strike = resolved.strike === true || resolved.dstrike === true;
331013
+ }
331014
+ if (rPrXml) {
331015
+ const normalized = normalizeRunAttrsFromOoxml(direct, {
331016
+ themeColors: styleContext?.model.themeColors,
331017
+ themeFontScheme: styleContext?.model.themeFontScheme
331018
+ });
331019
+ if (!marks.color && normalized.color && /^#[0-9a-f]{6}$/i.test(normalized.color)) {
331020
+ marks.color = normalized.color.slice(1).toUpperCase();
331021
+ }
331022
+ if (!marks.color && direct.color?.val?.toLowerCase() === "auto")
331023
+ marks.color = "auto";
331024
+ const fontProperties = direct.fontFamily && styleContext ? styleContext.model.resolveRun({ inlineRpr: direct, resolvedParagraphProperties: styleContext.paragraphProperties }) : direct;
331025
+ const fontNormalized = normalizeRunAttrsFromOoxml(fontProperties, {
331026
+ themeColors: styleContext?.model.themeColors,
331027
+ themeFontScheme: styleContext?.model.themeFontScheme
331028
+ });
331029
+ const fontFamily = direct.fontFamily ? fontNormalized.fontFamily?.split(",")[0]?.trim().replace(/^['"]|['"]$/g, "") : undefined;
331030
+ if (fontFamily)
331031
+ marks.fontFamily = fontFamily;
331032
+ }
331033
+ if (styleContext?.materializeParagraphFormatting) {
331034
+ const source = resolveRunMarks(rPrXml, styleContext);
331035
+ const defaults = resolveRunMarks(rPrXml, {
331036
+ ...styleContext,
331037
+ paragraphProperties: styleContext.model.resolveParagraph({ inlineProps: null }),
331038
+ styleRunProperties: {}
331039
+ });
331040
+ const owned = namedStyleMarkKeys(rPrXml, styleContext.model);
331041
+ for (const key2 of Object.keys(source ?? {})) {
331042
+ if (!owned.has(key2) || source[key2] !== defaults?.[key2])
331043
+ Object.assign(marks, { [key2]: source[key2] });
331044
+ }
331045
+ }
331046
+ return Object.keys(marks).length > 0 ? marks : undefined;
331047
+ }
331048
+ function namedStyleMarkKeys(rPrXml, model) {
331049
+ const keys = new Set;
331050
+ const propertiesByMark = {
331051
+ bold: ["bold"],
331052
+ boldCs: ["boldCs"],
331053
+ italic: ["italic"],
331054
+ italicCs: ["iCs"],
331055
+ caps: ["textTransform"],
331056
+ smallCaps: ["smallCaps"],
331057
+ strike: ["strike", "dstrike"],
331058
+ underline: ["underline"],
331059
+ color: ["color"],
331060
+ fontFamily: ["fontFamily"],
331061
+ fontSizePt: ["fontSize"],
331062
+ fontSizeCsPt: ["fontSizeCs"],
331063
+ highlight: ["highlight", "shading"],
331064
+ verticalAlign: ["vertAlign"]
331065
+ };
331066
+ const seen = new Set;
331067
+ let id = parseCharacterStyleRef(rPrXml);
331068
+ while (id && !seen.has(id)) {
331069
+ seen.add(id);
331070
+ const style = model.translatedLinkedStyles.styles[id];
331071
+ if (!style)
331072
+ break;
331073
+ for (const mark of Object.keys(propertiesByMark)) {
331074
+ if (propertiesByMark[mark].some((property2) => style.runProperties?.[property2] !== undefined))
331075
+ keys.add(mark);
331076
+ }
331077
+ id = style.basedOn;
331078
+ }
331079
+ return keys;
331080
+ }
329684
331081
  function normalizePasteHighlight(rawHighlight, fallbackHighlight) {
329685
331082
  if (rawHighlight) {
329686
331083
  const wordHighlight = normalizeWordHighlightValue(rawHighlight);
@@ -329971,7 +331368,14 @@ function serializedLeafPartInline(part) {
329971
331368
  return part.image;
329972
331369
  if (part.kind === "break")
329973
331370
  return { kind: "lineBreak" };
329974
- return { kind: "text", text: part.run.text, ...part.run.marks ? { marks: part.run.marks } : {}, ...part.run.commentIds ? { commentIds: part.run.commentIds } : {}, ...part.run.trackedInsertion ? { trackedInsertion: true } : {} };
331371
+ return {
331372
+ kind: "text",
331373
+ text: part.run.text,
331374
+ ...part.run.marks ? { marks: part.run.marks } : {},
331375
+ ...part.run.styleRef ? { styleRef: part.run.styleRef } : {},
331376
+ ...part.run.commentIds ? { commentIds: part.run.commentIds } : {},
331377
+ ...part.run.trackedInsertion ? { trackedInsertion: true } : {}
331378
+ };
329975
331379
  }
329976
331380
  function fragmentBlockFor(grouped) {
329977
331381
  if (grouped.kind === "paragraph")
@@ -330043,8 +331447,9 @@ function blockInlineHtml(block, assets, defaultTextColor) {
330043
331447
  function renderHtmlPart(part, assets, defaultTextColor) {
330044
331448
  if (part.kind === "break")
330045
331449
  return "<br/>";
330046
- if (part.kind === "run")
330047
- return renderHtmlRun(part.run, defaultTextColor);
331450
+ if (part.kind === "run") {
331451
+ return renderHtmlRun(part.htmlMarks ? { ...part.run, marks: part.htmlMarks } : part.run, defaultTextColor);
331452
+ }
330048
331453
  if (part.kind === "image") {
330049
331454
  const asset = assets.get(part.image.assetId);
330050
331455
  if (!asset)
@@ -330214,7 +331619,7 @@ function renderHtmlRun(run, defaultTextColor) {
330214
331619
  const styles = [];
330215
331620
  const color2 = marks.color ?? defaultTextColor;
330216
331621
  if (color2)
330217
- styles.push(`color: #${color2}`);
331622
+ styles.push(color2 === "auto" ? "color: initial" : `color: #${color2}`);
330218
331623
  if (marks.fontSizePt)
330219
331624
  styles.push(`font-size: ${marks.fontSizePt}pt`);
330220
331625
  if (marks.fontFamily)
@@ -330257,6 +331662,7 @@ var init_serialize = __esm(() => {
330257
331662
  init_common();
330258
331663
  init_paragraph_property_order();
330259
331664
  init_contracts();
331665
+ init_style_context();
330260
331666
  init_public_model();
330261
331667
  init_hyperlink_values();
330262
331668
  init_footnote_range();
@@ -334407,7 +335813,7 @@ class V2SelectionMutationAdapter {
334407
335813
  start: { kind: "text", blockId: plan.startBlockId, offset: from },
334408
335814
  end: { kind: "text", blockId: plan.startBlockId, offset: from + 1 },
334409
335815
  ...storyLocator ? { story: storyLocator } : {}
334410
- }, false, { offsetSpace: "kernel" });
335816
+ }, false, { offsetSpace: "kernel", effectiveTypingMarks: true });
334411
335817
  if (!source.ok)
334412
335818
  return failureWithoutResolution(source.code, source.message);
334413
335819
  const block = source.result.plan?.fragment.blocks[0];
@@ -341758,10 +343164,10 @@ function resolveCreateTableContentWidthTwips(context, at, insertionByte) {
341758
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];
341759
343165
  const pageSetup = section?.pageSetup;
341760
343166
  const pageWidth = pageSetup?.pageSize?.widthTwips ?? DEFAULT_PAGE_WIDTH_TWIPS;
341761
- const leftMargin = pageSetup?.margins?.leftTwips ?? DEFAULT_PAGE_MARGIN_TWIPS;
341762
- 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;
341763
343169
  const contentWidth = pageWidth - leftMargin - rightMargin;
341764
- 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;
341765
343171
  }
341766
343172
  function hasDirectTableStyle(model) {
341767
343173
  const tblPr = parsePropertiesChildren(model.tblPrXml, "tblPr", model.prefix);
@@ -342543,7 +343949,7 @@ function writeAfterPropertyXml(model, spec, wrappedXml) {
342543
343949
  }
342544
343950
  }
342545
343951
  }
342546
- 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;
342547
343953
  var init_adapter8 = __esm(() => {
342548
343954
  init_src3();
342549
343955
  init_sd_document_session_internal();
@@ -381049,8 +382455,8 @@ function readTargetContentWidthPx(context, input) {
381049
382455
  try {
381050
382456
  const pageSetup = pickClampSection(context, input)?.pageSetup;
381051
382457
  const widthTwips = pageSetup?.pageSize?.widthTwips ?? DEFAULT_PAGE_WIDTH_TWIPS2;
381052
- const leftTwips = pageSetup?.margins?.leftTwips ?? DEFAULT_PAGE_MARGIN_TWIPS2;
381053
- 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;
381054
382460
  const contentTwips = widthTwips - leftTwips - rightTwips;
381055
382461
  if (!Number.isFinite(contentTwips) || contentTwips <= 0)
381056
382462
  return null;
@@ -382738,7 +384144,7 @@ function findAdjacentCaptionParagraph(context, blockId) {
382738
384144
  function escapeRegExp17(value2) {
382739
384145
  return value2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
382740
384146
  }
382741
- 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;
382742
384148
  var init_adapter21 = __esm(() => {
382743
384149
  init_mutation_guard();
382744
384150
  init_adapter4();
@@ -403160,6 +404566,9 @@ class V2ClipboardAdapter {
403160
404566
  }
403161
404567
  insert(input, options) {
403162
404568
  const planned = resolveInsertPlan(input);
404569
+ return this.insertPrepared(input, options, planned);
404570
+ }
404571
+ insertPrepared(input, options, planned) {
403163
404572
  if (!planned.ok) {
403164
404573
  if (input.payload)
403165
404574
  return failureFromParse(this.parse(input.payload, { fallback: input.fallback }));
@@ -403191,6 +404600,27 @@ class V2ClipboardAdapter {
403191
404600
  formattingMode: planned.plan.summary.sourceKind === "plain-text" ? "match-destination" : input.formattingMode ?? "preserve-source",
403192
404601
  fragment: planned.applyPlan
403193
404602
  };
404603
+ if (input.plan && planned.plan.sourceStyleContext !== undefined && operation.formattingMode === "preserve-source" && hasNamedCharacterStyles(planned.plan.fragment.blocks) && !clipboardStyleContextMatches(this.context, planned.plan.sourceStyleContext)) {
404604
+ return failure25(publicFailureCodeForPasteReason("paste-no-faithful-representation"), "The generated native plan has incompatible source styles; insert the original payload for portable recovery.", "paste-no-faithful-representation");
404605
+ }
404606
+ if (input.payload && !input.plan && operation.formattingMode === "preserve-source" && planned.plan.summary.sourceKind === "superdoc-v2-fragment" && hasNamedCharacterStyles(planned.plan.fragment.blocks)) {
404607
+ const preflight = preflightSDDocumentSessionInternalFragmentApply(this.context.session, operation);
404608
+ const missingStyles = !preflight.ok && preflight.reason === "style-reference-not-found";
404609
+ const conflictingContext = preflight.ok && !clipboardStyleContextMatches(this.context, planned.plan.sourceStyleContext);
404610
+ if (missingStyles || conflictingContext) {
404611
+ if (planned.plan.fragment.comments?.length || hasNativeReviewOrControls(planned.plan.fragment.blocks)) {
404612
+ return failure25(publicFailureCodeForPasteReason("paste-no-faithful-representation"), "Portable style recovery would discard comments, tracked insertions, or content controls.", "paste-no-faithful-representation", planned.plan.diagnostics);
404613
+ }
404614
+ const portable = createPortableHtmlInsertPlan(input.payload, { fallback: input.fallback });
404615
+ if (portable.ok) {
404616
+ const warning = diagnostic("paste-no-faithful-representation", "Source style definitions are unavailable or differ; the portable HTML appearance was used.", "html", "warning");
404617
+ return this.insertPrepared({ ...input, payload: undefined, fragment: undefined, plan: undefined }, options, { ...portable, plan: { ...portable.plan, diagnostics: [...planned.plan.diagnostics, ...portable.plan.diagnostics, warning] } });
404618
+ }
404619
+ if (conflictingContext) {
404620
+ return failure25(publicFailureCodeForPasteReason(portable.reason), portable.diagnostics[0]?.message ?? portable.reason, portable.reason, portable.diagnostics);
404621
+ }
404622
+ }
404623
+ }
403194
404624
  if (options?.dryRun) {
403195
404625
  const preflight = preflightSDDocumentSessionInternalFragmentApply(this.context.session, operation);
403196
404626
  if (!preflight.ok) {
@@ -403321,6 +404751,34 @@ class V2ClipboardAdapter {
403321
404751
  return attachMutationPublicRevision(serialized.result, this.context.currentPublicRevision());
403322
404752
  }
403323
404753
  }
404754
+ function hasNamedCharacterStyles(blocks) {
404755
+ return blocks.some((block) => {
404756
+ if (block.kind === "table") {
404757
+ return block.rows.some((row) => row.cells.some((cell) => hasNamedCharacterStyles(cell.blocks)));
404758
+ }
404759
+ if (block.kind !== "paragraph" && block.kind !== "heading")
404760
+ return false;
404761
+ return block.runs.some((run) => !!run.styleRef) || inlinesHaveNamedCharacterStyles(block.inlines ?? []);
404762
+ });
404763
+ }
404764
+ function hasNativeReviewOrControls(blocks) {
404765
+ return blocks.some((block) => {
404766
+ if ("blockSdts" in block && block.blockSdts?.length)
404767
+ return true;
404768
+ if (block.kind === "table") {
404769
+ return block.rows.some((row) => row.cells.some((cell) => hasNativeReviewOrControls(cell.blocks)));
404770
+ }
404771
+ if (block.kind !== "paragraph" && block.kind !== "heading")
404772
+ return false;
404773
+ return block.runs.some((run) => run.commentIds?.length || run.trackedInsertion) || inlinesHaveNativeReviewOrControls(block.inlines ?? []);
404774
+ });
404775
+ }
404776
+ function inlinesHaveNativeReviewOrControls(inlines) {
404777
+ return inlines.some((inline) => inline.kind === "sdt" || (inline.kind === "text" ? !!inline.commentIds?.length || inline.trackedInsertion === true : inline.kind === "hyperlink" && inlinesHaveNativeReviewOrControls(inline.inlines)));
404778
+ }
404779
+ function inlinesHaveNamedCharacterStyles(inlines) {
404780
+ return inlines.some((inline) => inline.kind === "text" ? !!inline.styleRef : (inline.kind === "hyperlink" || inline.kind === "sdt") && inlinesHaveNamedCharacterStyles(inline.inlines));
404781
+ }
403324
404782
  function captureClipboardReadState(context) {
403325
404783
  return {
403326
404784
  source: getSDDocumentSessionInternalSourceCommit(context.session),
@@ -403491,7 +404949,8 @@ function resolveInsertPlan(input) {
403491
404949
  const prepared = prepareClipboardPlan(normalized.fragment, input.plan.summary.sourceKind, input.plan.diagnostics, input.plan.summary.plainFallback);
403492
404950
  return {
403493
404951
  ok: true,
403494
- ...prepared
404952
+ ...prepared,
404953
+ plan: { ...prepared.plan, ...input.plan.sourceStyleContext !== undefined ? { sourceStyleContext: input.plan.sourceStyleContext } : {} }
403495
404954
  };
403496
404955
  }
403497
404956
  if (input.payload) {
@@ -403573,6 +405032,57 @@ function resolveClipboardPasteTarget(context, target, options, applyPlan2) {
403573
405032
  storyLocator: locator
403574
405033
  };
403575
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
+ }
403576
405086
  function resolveSelectionPasteTarget(context, target, options, applyPlan2) {
403577
405087
  if (target.start.kind !== "text" || target.end.kind !== "text") {
403578
405088
  return {
@@ -403608,13 +405118,41 @@ function resolveSelectionPasteTarget(context, target, options, applyPlan2) {
403608
405118
  if (!index2)
403609
405119
  return { ok: false, code: "PRECONDITION_FAILED", message: "paragraph index is not available." };
403610
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
+ }
403611
405148
  if (target.start.blockId !== target.end.blockId) {
403612
405149
  const resolved2 = resolveCrossParagraphSelectionPlan({
403613
405150
  target,
403614
405151
  index: index2,
403615
405152
  readPartBytes: (partUri) => getSDDocumentSessionInternalPartBytes(context.session, partUri),
403616
405153
  buildOffsetMap: buildOffsetMapForCoordinateSpace5,
403617
- ...offsetSpace ? { offsetSpace } : {}
405154
+ ...offsetSpace ? { offsetSpace } : {},
405155
+ ...changeMode === "direct" ? { allowSectionBoundary: true } : {}
403618
405156
  });
403619
405157
  if ("error" in resolved2)
403620
405158
  return { ok: false, code: resolved2.error, message: resolved2.message };
@@ -403769,8 +405307,11 @@ var init_adapter37 = __esm(() => {
403769
405307
  init_text_range_shifts();
403770
405308
  init_adapter5();
403771
405309
  init_adapter7();
405310
+ init_deletion_locks();
403772
405311
  init_contracts();
403773
405312
  init_parse5();
405313
+ init_plan3();
405314
+ init_style_context();
403774
405315
  init_parse_v2_fragment();
403775
405316
  init_serialize();
403776
405317
  CLIPBOARD_TD = new TextDecoder;