superdoc 1.0.0-beta.14 → 1.0.0-beta.15

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 (30) hide show
  1. package/dist/chunks/{PdfViewer-DrsLL5TV.es.js → PdfViewer-CjlHzt9e.es.js} +1 -1
  2. package/dist/chunks/{PdfViewer-Cdc_EOZ9.cjs → PdfViewer-DltPlBWC.cjs} +1 -1
  3. package/dist/chunks/{index-9ZvcPlCg.cjs → index-BZnlco_f.cjs} +3 -3
  4. package/dist/chunks/{index-I4Ew0HDV-EPhjcu7T.cjs → index-Bds7gW4r-JPDW6c39.cjs} +1 -1
  5. package/dist/chunks/{index-I4Ew0HDV-Bht7-IGi.es.js → index-Bds7gW4r-Pk_xAuWe.es.js} +1 -1
  6. package/dist/chunks/{index-DB1DyDmZ.es.js → index-qg0AxQJC.es.js} +3 -3
  7. package/dist/chunks/{super-editor.es-DxAG4BVh.es.js → super-editor.es-CQTkj_nb.es.js} +2031 -472
  8. package/dist/chunks/{super-editor.es-DuS77THX.cjs → super-editor.es-CuAhqbzW.cjs} +2031 -472
  9. package/dist/packages/superdoc/src/core/SuperDoc.d.ts.map +1 -1
  10. package/dist/style.css +6 -6
  11. package/dist/super-editor/ai-writer.es.js +2 -2
  12. package/dist/super-editor/chunks/{converter-CfmIU--8.js → converter-qMoZOGGn.js} +412 -252
  13. package/dist/super-editor/chunks/{docx-zipper-B-CXiNSb.js → docx-zipper-QKiyORxV.js} +1 -1
  14. package/dist/super-editor/chunks/{editor-wC_gs8Bl.js → editor-D8ZdjC2V.js} +1633 -215
  15. package/dist/super-editor/chunks/{index-I4Ew0HDV.js → index-Bds7gW4r.js} +1 -1
  16. package/dist/super-editor/chunks/{toolbar-BR1GYvwW.js → toolbar-Spi7vpev.js} +2 -2
  17. package/dist/super-editor/converter.es.js +1 -1
  18. package/dist/super-editor/docx-zipper.es.js +2 -2
  19. package/dist/super-editor/editor.es.js +3 -3
  20. package/dist/super-editor/file-zipper.es.js +1 -1
  21. package/dist/super-editor/style.css +6 -6
  22. package/dist/super-editor/super-editor.es.js +8 -100
  23. package/dist/super-editor/toolbar.es.js +2 -2
  24. package/dist/super-editor.cjs +1 -1
  25. package/dist/super-editor.es.js +1 -1
  26. package/dist/superdoc.cjs +2 -2
  27. package/dist/superdoc.es.js +2 -2
  28. package/dist/superdoc.umd.js +2033 -474
  29. package/dist/superdoc.umd.js.map +1 -1
  30. package/package.json +1 -1
@@ -18983,7 +18983,6 @@ const encode$B = (params2, encodedAttrs = {}) => {
18983
18983
  }
18984
18984
  }
18985
18985
  });
18986
- console.log("subs:", subs);
18987
18986
  return subs;
18988
18987
  };
18989
18988
  function decode$D(params2) {
@@ -20142,6 +20141,51 @@ function getStrikeValue(attributes) {
20142
20141
  if (value === "0" || value === "false" || value === "off") return "0";
20143
20142
  return "1";
20144
20143
  }
20144
+ function parseProperties(node) {
20145
+ const marks = [];
20146
+ const unknownMarks = [];
20147
+ const { attributes = {}, elements = [] } = node;
20148
+ const { nodes, paragraphProperties = {}, runProperties = {} } = splitElementsAndProperties(elements);
20149
+ const hasRun = elements.find((element) => element.name === "w:r");
20150
+ if (hasRun) paragraphProperties.elements = paragraphProperties?.elements?.filter((el) => el.name !== "w:rPr");
20151
+ if (runProperties && runProperties?.elements?.length) {
20152
+ marks.push(...parseMarks(runProperties, unknownMarks));
20153
+ }
20154
+ if (paragraphProperties && paragraphProperties.elements?.length) {
20155
+ const disallowedParagraphProperties = ["w:u"];
20156
+ const filteredParagraphProperties = {
20157
+ ...paragraphProperties,
20158
+ elements: paragraphProperties.elements?.filter((el) => !disallowedParagraphProperties.includes(el.name))
20159
+ };
20160
+ marks.push(...parseMarks(filteredParagraphProperties, unknownMarks));
20161
+ }
20162
+ marks.push(...handleStyleChangeMarks(runProperties, marks));
20163
+ if (paragraphProperties && paragraphProperties.elements?.length) {
20164
+ attributes["paragraphProperties"] = paragraphProperties;
20165
+ }
20166
+ if (marks && node.name === "w:p") {
20167
+ marks.forEach((mark) => {
20168
+ const attrValue = Object.keys(mark.attrs ?? {})[0];
20169
+ if (attrValue) {
20170
+ const value = mark.attrs[attrValue];
20171
+ attributes[attrValue] = value;
20172
+ }
20173
+ });
20174
+ }
20175
+ return { elements: nodes, attributes, marks, unknownMarks };
20176
+ }
20177
+ function splitElementsAndProperties(elements) {
20178
+ const pPr = elements.find((el) => el.name === "w:pPr");
20179
+ const rPr = elements.find((el) => el.name === "w:rPr");
20180
+ const sectPr = elements.find((el) => el.name === "w:sectPr");
20181
+ const els = elements.filter((el) => el.name !== "w:pPr" && el.name !== "w:rPr" && el.name !== "w:sectPr");
20182
+ return {
20183
+ nodes: els,
20184
+ paragraphProperties: pPr,
20185
+ runProperties: rPr,
20186
+ sectionProperties: sectPr
20187
+ };
20188
+ }
20145
20189
  function getTableStyleId(path) {
20146
20190
  const tbl = path.find((ancestor) => ancestor.name === "w:tbl");
20147
20191
  if (!tbl) {
@@ -20166,13 +20210,6 @@ const handleParagraphNode$1 = (params2) => {
20166
20210
  if (pPr) {
20167
20211
  inlineParagraphProperties = translator$12.encode({ ...params2, nodes: [pPr] }) || {};
20168
20212
  }
20169
- const handleStandardNode2 = nodeListHandler.handlerEntities.find(
20170
- (e) => e.handlerName === "standardNodeHandler"
20171
- )?.handler;
20172
- if (!handleStandardNode2) {
20173
- console.error("Standard node handler not found");
20174
- return null;
20175
- }
20176
20213
  const insideTable = (params2.path || []).some((ancestor) => ancestor.name === "w:tc");
20177
20214
  const tableStyleId = getTableStyleId(params2.path || []);
20178
20215
  const resolvedParagraphProperties = resolveParagraphProperties(
@@ -20181,15 +20218,29 @@ const handleParagraphNode$1 = (params2) => {
20181
20218
  insideTable,
20182
20219
  tableStyleId
20183
20220
  );
20184
- const updatedParams = {
20185
- ...params2,
20186
- nodes: [node],
20187
- extraParams: { ...params2.extraParams, paragraphProperties: resolvedParagraphProperties }
20188
- };
20189
- const result = handleStandardNode2(updatedParams);
20190
- if (result.nodes.length === 1) {
20191
- schemaNode = result.nodes[0];
20221
+ const { elements = [], attributes = {}, marks = [] } = parseProperties(node, params2.docx);
20222
+ const childContent = [];
20223
+ if (elements.length) {
20224
+ const updatedElements = elements.map((el) => {
20225
+ if (!el.marks) el.marks = [];
20226
+ el.marks.push(...marks);
20227
+ return el;
20228
+ });
20229
+ const childParams = {
20230
+ ...params2,
20231
+ nodes: updatedElements,
20232
+ extraParams: { ...params2.extraParams, paragraphProperties: resolvedParagraphProperties },
20233
+ path: [...params2.path || [], node]
20234
+ };
20235
+ const translatedChildren = nodeListHandler.handler(childParams);
20236
+ childContent.push(...translatedChildren);
20192
20237
  }
20238
+ schemaNode = {
20239
+ type: "paragraph",
20240
+ content: childContent,
20241
+ attrs: { ...attributes },
20242
+ marks: []
20243
+ };
20193
20244
  schemaNode.type = "paragraph";
20194
20245
  schemaNode.attrs.paragraphProperties = inlineParagraphProperties;
20195
20246
  schemaNode.attrs.rsidRDefault = node.attributes?.["w:rsidRDefault"];
@@ -21837,13 +21888,14 @@ const tableOfContentsHandler = (params2) => {
21837
21888
  nodes: node.elements,
21838
21889
  path: [...params2.path || [], node]
21839
21890
  });
21891
+ const normalizedContent = normalizeDocPartContent(translatedContent);
21840
21892
  const sdtPr = params2.extraParams.sdtPr;
21841
21893
  const id = sdtPr.elements?.find((el) => el.name === "w:id")?.attributes["w:val"] || "";
21842
21894
  const docPartObj = sdtPr?.elements.find((el) => el.name === "w:docPartObj");
21843
21895
  const docPartUnique = docPartObj?.elements.some((el) => el.name === "w:docPartUnique") ?? false;
21844
21896
  const result = {
21845
21897
  type: "documentPartObject",
21846
- content: translatedContent,
21898
+ content: normalizedContent,
21847
21899
  attrs: {
21848
21900
  id,
21849
21901
  docPartGallery: "Table of Contents",
@@ -21883,6 +21935,22 @@ const genericDocPartHandler = (params2) => {
21883
21935
  const validGalleryTypeMap = {
21884
21936
  "Table of Contents": tableOfContentsHandler
21885
21937
  };
21938
+ const inlineNodeTypes = /* @__PURE__ */ new Set(["bookmarkStart", "bookmarkEnd"]);
21939
+ const wrapInlineNode = (node) => ({
21940
+ type: "paragraph",
21941
+ content: [node]
21942
+ });
21943
+ const normalizeDocPartContent = (nodes = []) => {
21944
+ const normalized = [];
21945
+ nodes.forEach((node) => {
21946
+ if (inlineNodeTypes.has(node?.type)) {
21947
+ normalized.push(wrapInlineNode(node));
21948
+ } else {
21949
+ normalized.push(node);
21950
+ }
21951
+ });
21952
+ return normalized;
21953
+ };
21886
21954
  function handleDocumentSectionNode$1(params2) {
21887
21955
  const { nodes, nodeListHandler } = params2;
21888
21956
  if (nodes.length === 0 || nodes[0].name !== "w:sdt") {
@@ -24961,7 +25029,8 @@ function handleImageNode$1(node, params2, isAnchor) {
24961
25029
  horizontal: positionHValue,
24962
25030
  top: positionVValue
24963
25031
  };
24964
- const simplePos = node.elements.find((el) => el.name === "wp:simplePos");
25032
+ const useSimplePos = attributes["simplePos"] === "1" || attributes["simplePos"] === 1;
25033
+ const simplePos = useSimplePos ? node.elements.find((el) => el.name === "wp:simplePos") : null;
24965
25034
  const wrapNode = isAnchor ? node.elements.find(
24966
25035
  (el) => ["wp:wrapNone", "wp:wrapSquare", "wp:wrapThrough", "wp:wrapTight", "wp:wrapTopAndBottom"].includes(el.name)
24967
25036
  ) : null;
@@ -32729,15 +32798,26 @@ const getCommentSchema = (type2, commentIndex) => {
32729
32798
  }
32730
32799
  };
32731
32800
  };
32732
- const getConfig = (type2) => ({
32733
- xmlName: `${XML_NODE_NAME$7}${type2}`,
32734
- sdNodeOrKeyName: `${SD_NODE_NAME$6}${type2}`,
32735
- type: NodeTranslator.translatorTypes.NODE,
32736
- encode: () => {
32737
- },
32738
- decode: decode$7,
32739
- attributes: [attrConfig]
32740
- });
32801
+ const getConfig = (type2) => {
32802
+ const sdName = `${SD_NODE_NAME$6}${type2}`;
32803
+ const isStart = type2 === "Start";
32804
+ return {
32805
+ xmlName: `${XML_NODE_NAME$7}${type2}`,
32806
+ sdNodeOrKeyName: sdName,
32807
+ type: NodeTranslator.translatorTypes.NODE,
32808
+ encode: ({ nodes }) => {
32809
+ const node = nodes?.[0];
32810
+ if (!node) return void 0;
32811
+ const attrs = node.attributes ? { ...node.attributes } : {};
32812
+ return {
32813
+ type: isStart ? "commentRangeStart" : "commentRangeEnd",
32814
+ attrs
32815
+ };
32816
+ },
32817
+ decode: decode$7,
32818
+ attributes: [attrConfig]
32819
+ };
32820
+ };
32741
32821
  const commentRangeStartTranslator = NodeTranslator.from(getConfig("Start"));
32742
32822
  const commentRangeEndTranslator = NodeTranslator.from(getConfig("End"));
32743
32823
  const XML_NODE_NAME$6 = "sd:pageReference";
@@ -33461,127 +33541,224 @@ const sdtNodeHandlerEntity = {
33461
33541
  handlerName: "sdtNodeHandler",
33462
33542
  handler: handleSdtNode
33463
33543
  };
33464
- function parseProperties(node) {
33465
- const marks = [];
33466
- const unknownMarks = [];
33467
- const { attributes = {}, elements = [] } = node;
33468
- const { nodes, paragraphProperties = {}, runProperties = {} } = splitElementsAndProperties(elements);
33469
- const hasRun = elements.find((element) => element.name === "w:r");
33470
- if (hasRun) paragraphProperties.elements = paragraphProperties?.elements?.filter((el) => el.name !== "w:rPr");
33471
- if (runProperties && runProperties?.elements?.length) {
33472
- marks.push(...parseMarks(runProperties, unknownMarks));
33473
- }
33474
- if (paragraphProperties && paragraphProperties.elements?.length) {
33475
- const disallowedParagraphProperties = ["w:u"];
33476
- const filteredParagraphProperties = {
33477
- ...paragraphProperties,
33478
- elements: paragraphProperties.elements?.filter((el) => !disallowedParagraphProperties.includes(el.name))
33479
- };
33480
- marks.push(...parseMarks(filteredParagraphProperties, unknownMarks));
33481
- }
33482
- marks.push(...handleStyleChangeMarks(runProperties, marks));
33483
- if (paragraphProperties && paragraphProperties.elements?.length) {
33484
- attributes["paragraphProperties"] = paragraphProperties;
33544
+ const translatorList = Array.from(
33545
+ /* @__PURE__ */ new Set([
33546
+ translator$1M,
33547
+ translator$6,
33548
+ translator$5,
33549
+ translator$4,
33550
+ translator$3,
33551
+ translator$1L,
33552
+ translator$1K,
33553
+ translator$1J,
33554
+ translator$20,
33555
+ translator$1r,
33556
+ translator$1$,
33557
+ translator$q,
33558
+ translator$7,
33559
+ translator$8,
33560
+ translator$1p,
33561
+ translator$23,
33562
+ translator$F,
33563
+ translator$1R,
33564
+ translator$1H,
33565
+ translator$1W,
33566
+ translator$1G,
33567
+ translator$2,
33568
+ translator$1F,
33569
+ translator$s,
33570
+ translator$1X,
33571
+ translator$X,
33572
+ translator$1E,
33573
+ translator$E,
33574
+ translator$D,
33575
+ translator$b,
33576
+ translator$Z,
33577
+ translator$J,
33578
+ translator$I,
33579
+ translator$C,
33580
+ translator$K,
33581
+ translator$22,
33582
+ translator$10,
33583
+ translator$1_,
33584
+ translator$1x,
33585
+ translator$1D,
33586
+ translator$1w,
33587
+ translator$V,
33588
+ translator$U,
33589
+ translator$1C,
33590
+ translator$1B,
33591
+ translator$1A,
33592
+ translator$1z,
33593
+ translator$1P,
33594
+ translator$1n,
33595
+ translator$1y,
33596
+ translator$O,
33597
+ translator$1v,
33598
+ translator$1u,
33599
+ translator$1t,
33600
+ translator$1s,
33601
+ translator$11,
33602
+ translator$1f,
33603
+ translator$1h,
33604
+ translator$12,
33605
+ translator$1g,
33606
+ translator$$,
33607
+ translator$1V,
33608
+ translator$1N,
33609
+ translator$1U,
33610
+ translator$1l,
33611
+ translator$r,
33612
+ translator$1Q,
33613
+ translator$1e,
33614
+ translator$1d,
33615
+ translator$1c,
33616
+ translator$1b,
33617
+ translator$1a,
33618
+ translator$T,
33619
+ translator$1Y,
33620
+ translator$1T,
33621
+ translator$1S,
33622
+ translator$1,
33623
+ translator$21,
33624
+ translator$19,
33625
+ translator$9,
33626
+ translator$e,
33627
+ translator$p,
33628
+ translator$d,
33629
+ translator$B,
33630
+ translator$o,
33631
+ translator$a,
33632
+ translator$A,
33633
+ translator$n,
33634
+ translator$m,
33635
+ translator$l,
33636
+ translator$k,
33637
+ translator$c,
33638
+ translator$j,
33639
+ translator$i,
33640
+ translator$h,
33641
+ translator$g,
33642
+ translator$f,
33643
+ translator$G,
33644
+ translator$P,
33645
+ translator$M,
33646
+ translator$N,
33647
+ translator$H,
33648
+ translator$_,
33649
+ translator$17,
33650
+ translator$R,
33651
+ translator$v,
33652
+ translator$Q,
33653
+ translator$z,
33654
+ translator$w,
33655
+ translator$18,
33656
+ translator$16,
33657
+ translator$15,
33658
+ translator$1j,
33659
+ translator$1Z,
33660
+ translator$L,
33661
+ translator$Y,
33662
+ translator$y,
33663
+ translator$x,
33664
+ translator$14,
33665
+ translator$13,
33666
+ translator$u,
33667
+ translator$t,
33668
+ commentRangeStartTranslator,
33669
+ commentRangeEndTranslator
33670
+ ])
33671
+ );
33672
+ const additionalHandlers = Object.freeze(
33673
+ translatorList.reduce((acc, translator2) => {
33674
+ const key2 = translator2?.xmlName;
33675
+ if (!key2) return acc;
33676
+ acc[key2] = translator2;
33677
+ return acc;
33678
+ }, {})
33679
+ );
33680
+ const baseHandlers = {
33681
+ ...additionalHandlers
33682
+ };
33683
+ const registeredHandlers = Object.freeze(baseHandlers);
33684
+ const INLINE_PARENT_NAMES = /* @__PURE__ */ new Set([
33685
+ "w:r",
33686
+ "w:hyperlink",
33687
+ "w:smartTag",
33688
+ "w:fldSimple",
33689
+ "w:proofErr",
33690
+ "w:del",
33691
+ "w:ins"
33692
+ ]);
33693
+ const INLINE_NODE_NAMES = /* @__PURE__ */ new Set([
33694
+ "m:oMathPara",
33695
+ "m:oMath",
33696
+ "m:t",
33697
+ "m:r",
33698
+ "m:ctrlPr",
33699
+ "m:sSupPr",
33700
+ "m:e",
33701
+ "m:sup",
33702
+ "m:sSup"
33703
+ ]);
33704
+ const BLOCK_BOUNDARY_NAMES = /* @__PURE__ */ new Set(["w:p", "w:body", "w:tbl", "w:tc", "w:tr"]);
33705
+ const isInlineContext = (path = [], currentNodeName) => {
33706
+ if (currentNodeName && INLINE_NODE_NAMES.has(currentNodeName)) {
33707
+ return true;
33485
33708
  }
33486
- if (marks && node.name === "w:p") {
33487
- marks.forEach((mark) => {
33488
- const attrValue = Object.keys(mark.attrs ?? {})[0];
33489
- if (attrValue) {
33490
- const value = mark.attrs[attrValue];
33491
- attributes[attrValue] = value;
33492
- }
33493
- });
33709
+ if (!Array.isArray(path) || path.length === 0) return false;
33710
+ for (let i = path.length - 1; i >= 0; i--) {
33711
+ const ancestorName = path[i]?.name;
33712
+ if (!ancestorName) continue;
33713
+ if (INLINE_NODE_NAMES.has(ancestorName) || INLINE_PARENT_NAMES.has(ancestorName)) {
33714
+ return true;
33715
+ }
33716
+ if (BLOCK_BOUNDARY_NAMES.has(ancestorName)) {
33717
+ return false;
33718
+ }
33494
33719
  }
33495
- return { elements: nodes, attributes, marks, unknownMarks };
33496
- }
33497
- function splitElementsAndProperties(elements) {
33498
- const pPr = elements.find((el) => el.name === "w:pPr");
33499
- const rPr = elements.find((el) => el.name === "w:rPr");
33500
- const sectPr = elements.find((el) => el.name === "w:sectPr");
33501
- const els = elements.filter((el) => el.name !== "w:pPr" && el.name !== "w:rPr" && el.name !== "w:sectPr");
33502
- return {
33503
- nodes: els,
33504
- paragraphProperties: pPr,
33505
- runProperties: rPr,
33506
- sectionProperties: sectPr
33507
- };
33508
- }
33509
- function getElementName(element) {
33510
- return SuperConverter.allowedElements[element.name || element.type];
33511
- }
33512
- const isPropertiesElement = (element) => {
33513
- return !!SuperConverter.propertyTypes[element.name || element.type];
33720
+ return false;
33514
33721
  };
33515
- const handleStandardNode = (params2) => {
33516
- const { nodes, docx, nodeListHandler } = params2;
33517
- if (!nodes || nodes.length === 0) {
33518
- return { nodes: [], consumed: 0 };
33519
- }
33722
+ const handlePassthroughNode = (params2) => {
33723
+ const { nodes = [] } = params2;
33520
33724
  const node = nodes[0];
33521
- const { name } = node;
33522
- const { attributes, elements, marks = [] } = parseProperties(node);
33523
- if (name === "w:sdt") {
33725
+ if (!node) return { nodes: [], consumed: 0 };
33726
+ if (registeredHandlers[node.name]) {
33524
33727
  return { nodes: [], consumed: 0 };
33525
33728
  }
33526
- if (isPropertiesElement(node)) {
33527
- return {
33528
- nodes: [
33529
- {
33530
- type: getElementName(node),
33531
- attrs: { ...attributes },
33532
- marks: []
33533
- }
33534
- ],
33535
- consumed: 0
33536
- };
33537
- }
33538
- if (!getElementName(node)) {
33539
- return {
33540
- nodes: [
33541
- {
33542
- type: name,
33543
- content: elements,
33544
- attrs: { ...attributes },
33545
- marks
33546
- }
33547
- ],
33548
- consumed: 0,
33549
- unhandled: true
33550
- };
33551
- }
33552
- const content = [];
33553
- const parentStyleId = getParentStyleId(node);
33554
- if (elements && elements.length) {
33555
- const updatedElements = elements.map((el) => {
33556
- if (!el.marks) el.marks = [];
33557
- el.marks.push(...marks);
33558
- return el;
33559
- });
33729
+ const originalXml = carbonCopy(node) || {};
33730
+ const originalElementsSource = originalXml.elements;
33731
+ const originalElements = originalElementsSource ? carbonCopy(originalElementsSource) : [];
33732
+ const childElements = Array.isArray(node.elements) ? node.elements : [];
33733
+ let childContent = [];
33734
+ if (childElements.length && params2.nodeListHandler?.handler) {
33560
33735
  const childParams = {
33561
33736
  ...params2,
33562
- nodes: updatedElements,
33563
- parentStyleId,
33737
+ nodes: childElements,
33564
33738
  path: [...params2.path || [], node]
33565
33739
  };
33566
- const childContent = nodeListHandler.handler(childParams);
33567
- content.push(...childContent);
33740
+ childContent = params2.nodeListHandler.handler(childParams) || [];
33568
33741
  }
33569
- const resultNode = {
33570
- type: getElementName(node),
33571
- content,
33572
- attrs: { ...attributes },
33573
- marks: []
33742
+ if (originalElements?.length) {
33743
+ originalXml.elements = originalElements;
33744
+ }
33745
+ const passthroughNode = {
33746
+ type: isInlineContext(params2.path, node.name) ? "passthroughInline" : "passthroughBlock",
33747
+ attrs: {
33748
+ originalName: node.name,
33749
+ originalXml
33750
+ },
33751
+ marks: [],
33752
+ content: childContent
33753
+ };
33754
+ return {
33755
+ nodes: [passthroughNode],
33756
+ consumed: 1
33574
33757
  };
33575
- return { nodes: [resultNode], consumed: 1 };
33576
- };
33577
- const getParentStyleId = (node) => {
33578
- const pPr = node.elements?.find((el) => el.name === "w:pPr");
33579
- const styleTag = pPr?.elements?.find((el) => el.name === "w:pStyle");
33580
- return styleTag ? styleTag.attributes["w:val"] : null;
33581
33758
  };
33582
- const standardNodeHandlerEntity = {
33583
- handlerName: "standardNodeHandler",
33584
- handler: handleStandardNode
33759
+ const passthroughNodeHandlerEntity = {
33760
+ handlerName: "passthroughNodeHandler",
33761
+ handler: handlePassthroughNode
33585
33762
  };
33586
33763
  const handler = (params2) => {
33587
33764
  const { nodes } = params2;
@@ -33605,13 +33782,6 @@ const handleBookmarkNode = (params2) => {
33605
33782
  return { nodes: [], consumed: 0 };
33606
33783
  }
33607
33784
  const node = nodes[0];
33608
- const handleStandardNode2 = nodeListHandler.handlerEntities.find(
33609
- (e) => e.handlerName === "standardNodeHandler"
33610
- )?.handler;
33611
- if (!handleStandardNode2) {
33612
- console.error("Standard node handler not found");
33613
- return { nodes: [], consumed: 0 };
33614
- }
33615
33785
  const customMarks = editor?.extensionService?.extensions?.filter((e) => e.isExternal === true) || [];
33616
33786
  const bookmarkName = node.attributes["w:name"]?.split(";")[0];
33617
33787
  const customMark = customMarks.find((mark) => mark.name === bookmarkName);
@@ -33620,7 +33790,6 @@ const handleBookmarkNode = (params2) => {
33620
33790
  (n) => n.name === "w:bookmarkEnd" && n.attributes["w:id"] === node.attributes["w:id"]
33621
33791
  );
33622
33792
  const textNodes = nodes.slice(1, bookmarkEndIndex);
33623
- const nodeListHandler2 = params2.nodeListHandler;
33624
33793
  const attrs = {};
33625
33794
  node.attributes["w:name"].split(";").forEach((name) => {
33626
33795
  const [key2, value] = name.split("=");
@@ -33628,7 +33797,7 @@ const handleBookmarkNode = (params2) => {
33628
33797
  attrs[key2] = value;
33629
33798
  }
33630
33799
  });
33631
- const translatedText = nodeListHandler2.handler({
33800
+ const translatedText = nodeListHandler.handler({
33632
33801
  ...params2,
33633
33802
  nodes: textNodes,
33634
33803
  path: [...params2.path || [], node]
@@ -33644,13 +33813,11 @@ const handleBookmarkNode = (params2) => {
33644
33813
  consumed: translatedText.length + 2
33645
33814
  };
33646
33815
  }
33647
- const updatedParams = { ...params2, nodes: [node] };
33648
- const result = handleStandardNode2(updatedParams);
33649
- if (result.nodes.length === 1) {
33650
- result.nodes[0].attrs.name = node.attributes["w:name"];
33651
- result.nodes[0].attrs.id = node.attributes["w:id"];
33816
+ const encoded = translator$8.encode({ ...params2, nodes: [node] });
33817
+ if (!encoded) {
33818
+ return { nodes: [], consumed: 0 };
33652
33819
  }
33653
- return result;
33820
+ return { nodes: [encoded], consumed: 1 };
33654
33821
  };
33655
33822
  const handleBookmarkStartNode = (params2) => {
33656
33823
  const { nodes } = params2;
@@ -34297,18 +34464,22 @@ const getInstructionPreProcessor = (instruction) => {
34297
34464
  const preProcessNodesForFldChar = (nodes = [], docx) => {
34298
34465
  const processedNodes = [];
34299
34466
  let collectedNodesStack = [];
34467
+ let rawCollectedNodesStack = [];
34300
34468
  let currentFieldStack = [];
34301
34469
  let unpairedEnd = null;
34302
34470
  let collecting = false;
34303
34471
  const finalizeField = () => {
34304
34472
  if (collecting) {
34305
34473
  const collectedNodes = collectedNodesStack.pop().filter((n) => n !== null);
34474
+ const rawCollectedNodes = rawCollectedNodesStack.pop().filter((n) => n !== null);
34306
34475
  const currentField = currentFieldStack.pop();
34307
- const combined = _processCombinedNodesForFldChar(collectedNodes, currentField.instrText.trim(), docx);
34476
+ const combinedResult = _processCombinedNodesForFldChar(collectedNodes, currentField.instrText.trim(), docx);
34477
+ const outputNodes = combinedResult.handled ? combinedResult.nodes : rawCollectedNodes;
34308
34478
  if (collectedNodesStack.length === 0) {
34309
- processedNodes.push(...combined);
34479
+ processedNodes.push(...outputNodes);
34310
34480
  } else {
34311
- collectedNodesStack[collectedNodesStack.length - 1].push(...combined);
34481
+ collectedNodesStack[collectedNodesStack.length - 1].push(...outputNodes);
34482
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(...outputNodes);
34312
34483
  }
34313
34484
  } else {
34314
34485
  unpairedEnd = true;
@@ -34320,18 +34491,26 @@ const preProcessNodesForFldChar = (nodes = [], docx) => {
34320
34491
  const instrTextEl = node.elements?.find((el) => el.name === "w:instrText");
34321
34492
  collecting = collectedNodesStack.length > 0;
34322
34493
  if (fldType === "begin") {
34323
- collectedNodesStack.push([null]);
34494
+ collectedNodesStack.push([]);
34495
+ rawCollectedNodesStack.push([node]);
34324
34496
  currentFieldStack.push({ instrText: "" });
34325
34497
  continue;
34326
34498
  }
34327
34499
  if (instrTextEl && collecting && currentFieldStack.length > 0) {
34500
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node);
34328
34501
  currentFieldStack[currentFieldStack.length - 1].instrText += (instrTextEl.elements?.[0]?.text || "") + " ";
34329
34502
  continue;
34330
34503
  }
34331
34504
  if (fldType === "end") {
34505
+ if (collecting) {
34506
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node);
34507
+ }
34332
34508
  finalizeField();
34333
34509
  continue;
34334
34510
  } else if (fldType === "separate") {
34511
+ if (collecting) {
34512
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node);
34513
+ }
34335
34514
  continue;
34336
34515
  }
34337
34516
  if (Array.isArray(node.elements)) {
@@ -34341,17 +34520,21 @@ const preProcessNodesForFldChar = (nodes = [], docx) => {
34341
34520
  childResult.unpairedBegin.forEach((pendingField) => {
34342
34521
  currentFieldStack.push(pendingField.fieldInfo);
34343
34522
  collectedNodesStack.push([node]);
34523
+ rawCollectedNodesStack.push([node]);
34344
34524
  });
34345
34525
  } else if (childResult.unpairedEnd) {
34346
34526
  collectedNodesStack[collectedNodesStack.length - 1].push(node);
34527
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node);
34347
34528
  finalizeField();
34348
34529
  } else if (collecting) {
34349
34530
  collectedNodesStack[collectedNodesStack.length - 1].push(node);
34531
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node);
34350
34532
  } else {
34351
34533
  processedNodes.push(node);
34352
34534
  }
34353
34535
  } else if (collecting) {
34354
34536
  collectedNodesStack[collectedNodesStack.length - 1].push(node);
34537
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node);
34355
34538
  } else {
34356
34539
  processedNodes.push(node);
34357
34540
  }
@@ -34373,10 +34556,9 @@ const _processCombinedNodesForFldChar = (nodesToCombine = [], instrText, docx) =
34373
34556
  const instructionType = instrText.trim().split(" ")[0];
34374
34557
  const instructionPreProcessor = getInstructionPreProcessor(instructionType);
34375
34558
  if (instructionPreProcessor) {
34376
- return instructionPreProcessor(nodesToCombine, instrText, docx);
34377
- } else {
34378
- return nodesToCombine;
34559
+ return { nodes: instructionPreProcessor(nodesToCombine, instrText, docx), handled: true };
34379
34560
  }
34561
+ return { nodes: nodesToCombine, handled: false };
34380
34562
  };
34381
34563
  const preProcessPageFieldsOnly = (nodes = []) => {
34382
34564
  const processedNodes = [];
@@ -34451,6 +34633,14 @@ function scanFieldSequence(nodes, beginIndex) {
34451
34633
  endIndex
34452
34634
  };
34453
34635
  }
34636
+ const commentRangeStartHandlerEntity = generateV2HandlerEntity(
34637
+ "commentRangeStartHandler",
34638
+ commentRangeStartTranslator
34639
+ );
34640
+ const commentRangeEndHandlerEntity = generateV2HandlerEntity(
34641
+ "commentRangeEndHandler",
34642
+ commentRangeEndTranslator
34643
+ );
34454
34644
  const createDocumentJson = (docx, converter, editor) => {
34455
34645
  const json = carbonCopy(getInitialJSON(docx));
34456
34646
  if (!json) return null;
@@ -34512,6 +34702,7 @@ const createDocumentJson = (docx, converter, editor) => {
34512
34702
  path: []
34513
34703
  });
34514
34704
  parsedContent = filterOutRootInlineNodes(parsedContent);
34705
+ collapseWhitespaceNextToInlinePassthrough(parsedContent);
34515
34706
  const result = {
34516
34707
  type: "doc",
34517
34708
  content: parsedContent,
@@ -34552,6 +34743,8 @@ const defaultNodeListHandler = () => {
34552
34743
  bookmarkStartNodeHandlerEntity,
34553
34744
  bookmarkEndNodeHandlerEntity,
34554
34745
  hyperlinkNodeHandlerEntity,
34746
+ commentRangeStartHandlerEntity,
34747
+ commentRangeEndHandlerEntity,
34555
34748
  drawingNodeHandlerEntity,
34556
34749
  trackChangeNodeHandlerEntity,
34557
34750
  tableNodeHandlerEntity,
@@ -34560,7 +34753,7 @@ const defaultNodeListHandler = () => {
34560
34753
  autoPageHandlerEntity,
34561
34754
  autoTotalPageCountEntity,
34562
34755
  pageReferenceEntity,
34563
- standardNodeHandlerEntity
34756
+ passthroughNodeHandlerEntity
34564
34757
  ];
34565
34758
  const handler2 = createNodeListHandler(entities);
34566
34759
  return {
@@ -34847,8 +35040,8 @@ const importHeadersFooters = (docx, converter, mainEditor) => {
34847
35040
  editor.options.annotations = true;
34848
35041
  headers.forEach((header) => {
34849
35042
  const { rId, referenceFile, currentFileName } = getHeaderFooterSectionData(header, docx);
34850
- const { processedNodes: headerProcessedNodes } = preProcessPageFieldsOnly(referenceFile.elements[0].elements ?? []);
34851
- referenceFile.elements[0].elements = headerProcessedNodes;
35043
+ const headerNodes = carbonCopy(referenceFile.elements[0].elements ?? []);
35044
+ const { processedNodes: headerProcessedNodes } = preProcessPageFieldsOnly(headerNodes);
34852
35045
  const sectPrHeader = allSectPrElements.find(
34853
35046
  (el) => el.name === "w:headerReference" && el.attributes["r:id"] === rId
34854
35047
  );
@@ -34856,7 +35049,7 @@ const importHeadersFooters = (docx, converter, mainEditor) => {
34856
35049
  if (converter.headerIds[sectionType]) sectionType = null;
34857
35050
  const nodeListHandler = defaultNodeListHandler();
34858
35051
  let schema = nodeListHandler.handler({
34859
- nodes: referenceFile.elements[0].elements,
35052
+ nodes: headerProcessedNodes,
34860
35053
  nodeListHandler,
34861
35054
  docx,
34862
35055
  converter,
@@ -34877,15 +35070,15 @@ const importHeadersFooters = (docx, converter, mainEditor) => {
34877
35070
  if (titlePg) converter.headerIds.titlePg = true;
34878
35071
  footers.forEach((footer) => {
34879
35072
  const { rId, referenceFile, currentFileName } = getHeaderFooterSectionData(footer, docx);
34880
- const { processedNodes: footerProcessedNodes } = preProcessPageFieldsOnly(referenceFile.elements[0].elements ?? []);
34881
- referenceFile.elements[0].elements = footerProcessedNodes;
35073
+ const footerNodes = carbonCopy(referenceFile.elements[0].elements ?? []);
35074
+ const { processedNodes: footerProcessedNodes } = preProcessPageFieldsOnly(footerNodes);
34882
35075
  const sectPrFooter = allSectPrElements.find(
34883
35076
  (el) => el.name === "w:footerReference" && el.attributes["r:id"] === rId
34884
35077
  );
34885
35078
  const sectionType = sectPrFooter?.attributes["w:type"];
34886
35079
  const nodeListHandler = defaultNodeListHandler();
34887
35080
  let schema = nodeListHandler.handler({
34888
- nodes: referenceFile.elements[0].elements,
35081
+ nodes: footerProcessedNodes,
34889
35082
  nodeListHandler,
34890
35083
  docx,
34891
35084
  converter,
@@ -34948,6 +35141,51 @@ function filterOutRootInlineNodes(content = []) {
34948
35141
  ]);
34949
35142
  return content.filter((node) => node && typeof node.type === "string" && !INLINE_TYPES.has(node.type));
34950
35143
  }
35144
+ function collapseWhitespaceNextToInlinePassthrough(content = []) {
35145
+ if (!Array.isArray(content) || content.length === 0) return;
35146
+ const sequence = collectInlineSequence(content);
35147
+ sequence.forEach((entry, index2) => {
35148
+ if (entry.kind !== "passthrough") return;
35149
+ const prev = findNeighborText(sequence, index2, -1);
35150
+ const next = findNeighborText(sequence, index2, 1);
35151
+ if (!prev || !next) return;
35152
+ if (!prev.node.text.endsWith(" ") || !next.node.text.startsWith(" ")) return;
35153
+ prev.node.text = prev.node.text.replace(/ +$/, " ");
35154
+ next.node.text = next.node.text.replace(/^ +/, "");
35155
+ if (next.node.text.length === 0) {
35156
+ next.parent.splice(next.index, 1);
35157
+ }
35158
+ });
35159
+ }
35160
+ function collectInlineSequence(nodes, result = [], insidePassthrough = false) {
35161
+ if (!Array.isArray(nodes) || nodes.length === 0) return result;
35162
+ nodes.forEach((node, index2) => {
35163
+ if (!node) return;
35164
+ const isPassthrough = node.type === "passthroughInline";
35165
+ if (isPassthrough && !insidePassthrough) {
35166
+ result.push({ kind: "passthrough", parent: nodes, index: index2 });
35167
+ }
35168
+ if (node.type === "text" && typeof node.text === "string" && !insidePassthrough) {
35169
+ result.push({ kind: "text", node, parent: nodes, index: index2 });
35170
+ }
35171
+ if (Array.isArray(node.content) && node.content.length) {
35172
+ const nextInside = insidePassthrough || isPassthrough;
35173
+ collectInlineSequence(node.content, result, nextInside);
35174
+ }
35175
+ });
35176
+ return result;
35177
+ }
35178
+ function findNeighborText(sequence, startIndex, direction) {
35179
+ let cursor = startIndex + direction;
35180
+ while (cursor >= 0 && cursor < sequence.length) {
35181
+ const entry = sequence[cursor];
35182
+ if (entry.kind === "text") {
35183
+ return entry;
35184
+ }
35185
+ cursor += direction;
35186
+ }
35187
+ return null;
35188
+ }
34951
35189
  function getThemeColorPalette(docx) {
34952
35190
  const themePart = docx?.["word/theme/theme1.xml"];
34953
35191
  if (!themePart || !Array.isArray(themePart.elements)) return void 0;
@@ -35310,7 +35548,9 @@ function exportSchemaToJson(params2) {
35310
35548
  "page-number": translator$4,
35311
35549
  "total-page-number": translator$3,
35312
35550
  pageReference: translator$6,
35313
- tableOfContents: translator$5
35551
+ tableOfContents: translator$5,
35552
+ passthroughBlock: translatePassthroughNode,
35553
+ passthroughInline: translatePassthroughNode
35314
35554
  };
35315
35555
  let handler2 = router[type2];
35316
35556
  if (handler2 && "decode" in handler2 && typeof handler2.decode === "function") {
@@ -35322,6 +35562,11 @@ function exportSchemaToJson(params2) {
35322
35562
  }
35323
35563
  return handler2(params2);
35324
35564
  }
35565
+ function translatePassthroughNode(params2) {
35566
+ const original = params2?.node?.attrs?.originalXml;
35567
+ if (!original) return null;
35568
+ return carbonCopy(original);
35569
+ }
35325
35570
  function translateBodyNode(params2) {
35326
35571
  let sectPr = params2.bodyNode?.elements?.find((n) => n.name === "w:sectPr");
35327
35572
  if (!sectPr) {
@@ -36021,7 +36266,7 @@ const _SuperConverter = class _SuperConverter2 {
36021
36266
  static getStoredSuperdocVersion(docx) {
36022
36267
  return _SuperConverter2.getStoredCustomProperty(docx, "SuperdocVersion");
36023
36268
  }
36024
- static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.14") {
36269
+ static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.15") {
36025
36270
  return _SuperConverter2.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
36026
36271
  }
36027
36272
  /**
@@ -39221,7 +39466,7 @@ var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "rea
39221
39466
  var __privateAdd$1 = (obj, member, value) => member.has(obj) ? __typeError$1("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
39222
39467
  var __privateSet = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
39223
39468
  var __privateMethod$1 = (obj, member, method) => (__accessCheck$1(obj, member, "access private method"), method);
39224
- var _Attribute_static, getGlobalAttributes_fn, getNodeAndMarksAttributes_fn, _Schema_static, createNodesSchema_fn, createMarksSchema_fn, _events, _ExtensionService_instances, setupExtensions_fn, attachEditorEvents_fn, _editor, _stateValidators, _xmlValidators, _requiredNodeTypes, _requiredMarkTypes, _SuperValidator_instances, initializeValidators_fn, collectValidatorRequirements_fn, analyzeDocument_fn, dispatchWithFallback_fn, _commandService, _Editor_instances, initContainerElement_fn, init_fn, initRichText_fn, onFocus_fn, checkHeadless_fn, registerCopyHandler_fn, insertNewFileData_fn, getPluginKeyName_fn, createExtensionService_fn, createCommandService_fn, createConverter_fn, initMedia_fn, initFonts_fn, checkFonts_fn, determineUnsupportedFonts_fn, createSchema_fn, generatePmData_fn, createView_fn, onCollaborationReady_fn, initComments_fn, dispatchTransaction_fn, handleNodeSelection_fn, prepareDocumentForImport_fn, prepareDocumentForExport_fn, endCollaboration_fn, validateDocumentInit_fn, validateDocumentExport_fn, initDevTools_fn, _map, _editor2, _descriptors, _collections, _editorEntries, _maxCachedEditors, _editorAccessOrder, _pendingCreations, _cacheHits, _cacheMisses, _evictions, _HeaderFooterEditorManager_instances, hasConverter_fn, extractCollections_fn, collectDescriptors_fn, teardownMissingEditors_fn, teardownEditors_fn, createEditor_fn, createEditorContainer_fn, registerConverterEditor_fn, unregisterConverterEditor_fn, updateAccessOrder_fn, enforceCacheSizeLimit_fn, _manager, _mediaFiles, _blockCache, _HeaderFooterLayoutAdapter_instances, getBlocks_fn, getConverterContext_fn, _instances, _options, _editor3, _visibleHost, _viewportHost, _painterHost, _selectionOverlay, _hiddenHost, _layoutOptions, _layoutState, _domPainter, _layoutError, _layoutErrorState, _errorBanner, _errorBannerMessage, _telemetryEmitter, _renderScheduled, _pendingDocChange, _isRerendering, _selectionUpdateScheduled, _remoteCursorUpdateScheduled, _rafHandle, _editorListeners, _sectionMetadata, _documentMode, _inputBridge, _trackedChangesMode, _trackedChangesEnabled, _trackedChangesOverrides, _headerFooterManager, _headerFooterAdapter, _headerFooterIdentifier, _headerLayoutResults, _footerLayoutResults, _headerDecorationProvider, _footerDecorationProvider, _headerFooterManagerCleanups, _headerRegions, _footerRegions, _session, _activeHeaderFooterEditor, _hoverOverlay, _hoverTooltip, _modeBanner, _ariaLiveRegion, _hoverRegion, _clickCount, _lastClickTime, _lastClickPosition, _lastSelectedImageBlockId, _remoteCursorState, _remoteCursorDirty, _remoteCursorOverlay, _localSelectionLayer, _awarenessCleanup, _scrollCleanup, _remoteCursorRafHandle, _scrollTimeout, _PresentationEditor_instances, aggregateLayoutBounds_fn, safeCleanup_fn, setupEditorListeners_fn, setupCollaborationCursors_fn, normalizeAwarenessStates_fn, getFallbackColor_fn, getValidatedColor_fn, scheduleRemoteCursorUpdate_fn, scheduleRemoteCursorReRender_fn, updateRemoteCursors_fn, renderRemoteCursors_fn, renderRemoteCaret_fn, renderRemoteCursorLabel_fn, renderRemoteSelection_fn, setupPointerHandlers_fn, setupInputBridge_fn, initHeaderFooterRegistry_fn, _handlePointerDown, getFirstTextPosition_fn, registerPointerClick_fn, selectWordAt_fn, selectParagraphAt_fn, isWordCharacter_fn, _handlePointerMove, _handlePointerLeave, _handleDoubleClick, _handleKeyDown, focusHeaderFooterShortcut_fn, scheduleRerender_fn, flushRerenderQueue_fn, rerender_fn, ensurePainter_fn, scheduleSelectionUpdate_fn, updateSelection_fn, resolveLayoutOptions_fn, buildHeaderFooterInput_fn, computeHeaderFooterConstraints_fn, updateDecorationProviders_fn, createDecorationProvider_fn, findHeaderFooterPageForPageNumber_fn, computeDecorationBox_fn, rebuildHeaderFooterRegions_fn, hitTestHeaderFooterRegion_fn, pointInRegion_fn, activateHeaderFooterRegion_fn, enterHeaderFooterMode_fn, exitHeaderFooterMode_fn, getActiveDomTarget_fn, emitHeaderFooterModeChanged_fn, emitHeaderFooterEditingContext_fn, updateAwarenessSession_fn, updateModeBanner_fn, announce_fn, validateHeaderFooterEditPermission_fn, emitHeaderFooterEditBlocked_fn, resolveDescriptorForRegion_fn, getBodyPageHeight_fn, getHeaderFooterPageHeight_fn, renderSelectionRects_fn, renderHoverRegion_fn, clearHoverRegion_fn, renderCaretOverlay_fn, getHeaderFooterContext_fn, computeHeaderFooterSelectionRects_fn, computeHeaderFooterCaretRect_fn, syncTrackedChangesPreferences_fn, deriveTrackedChangesMode_fn, deriveTrackedChangesEnabled_fn, getTrackChangesPluginState_fn, computeDefaultLayoutDefaults_fn, parseColumns_fn, inchesToPx_fn, applyZoom_fn, createLayoutMetrics_fn, convertPageLocalToOverlayCoords_fn, normalizeClientPoint_fn, computeCaretLayoutRect_fn, findLineContainingPos_fn, lineHeightBeforeIndex_fn, getCurrentPageIndex_fn, findRegionForPage_fn, handleLayoutError_fn, decorateError_fn, showLayoutErrorBanner_fn, dismissErrorBanner_fn, createHiddenHost_fn, _windowRoot, _layoutSurfaces, _getTargetDom, _onTargetChanged, _listeners, _currentTarget, _destroyed, _useWindowFallback, _PresentationInputBridge_instances, addListener_fn, dispatchToTarget_fn, forwardKeyboardEvent_fn, forwardTextEvent_fn, forwardCompositionEvent_fn, forwardContextMenu_fn, isEventOnActiveTarget_fn, shouldSkipSurface_fn, isInLayoutSurface_fn, getListenerTargets_fn, isPlainCharacterKey_fn, _DocumentSectionView_instances, init_fn2, addToolTip_fn, _ParagraphNodeView_instances, checkShouldUpdate_fn, updateHTMLAttributes_fn, updateDOMStyles_fn, resolveNeighborParagraphProperties_fn, updateListStyles_fn, initList_fn, checkIsList_fn, createMarker_fn, createSeparator_fn, calculateTabSeparatorStyle_fn, calculateMarkerStyle_fn, removeList_fn, getParagraphContext_fn, scheduleAnimation_fn, cancelScheduledAnimation_fn, _FieldAnnotationView_instances, createAnnotation_fn, _AutoPageNumberNodeView_instances, renderDom_fn, scheduleUpdateNodeStyle_fn, _VectorShapeView_instances, ensureParentPositioned_fn, _ShapeGroupView_instances, ensureParentPositioned_fn2;
39469
+ var _Attribute_static, getGlobalAttributes_fn, getNodeAndMarksAttributes_fn, _Schema_static, createNodesSchema_fn, createMarksSchema_fn, _events, _ExtensionService_instances, setupExtensions_fn, attachEditorEvents_fn, _editor, _stateValidators, _xmlValidators, _requiredNodeTypes, _requiredMarkTypes, _SuperValidator_instances, initializeValidators_fn, collectValidatorRequirements_fn, analyzeDocument_fn, dispatchWithFallback_fn, _commandService, _Editor_instances, initContainerElement_fn, init_fn, initRichText_fn, onFocus_fn, checkHeadless_fn, registerCopyHandler_fn, insertNewFileData_fn, getPluginKeyName_fn, createExtensionService_fn, createCommandService_fn, createConverter_fn, initMedia_fn, initFonts_fn, checkFonts_fn, determineUnsupportedFonts_fn, createSchema_fn, generatePmData_fn, createView_fn, onCollaborationReady_fn, initComments_fn, dispatchTransaction_fn, handleNodeSelection_fn, prepareDocumentForImport_fn, prepareDocumentForExport_fn, endCollaboration_fn, validateDocumentInit_fn, validateDocumentExport_fn, initDevTools_fn, _map, _editor2, _descriptors, _collections, _editorEntries, _maxCachedEditors, _editorAccessOrder, _pendingCreations, _cacheHits, _cacheMisses, _evictions, _HeaderFooterEditorManager_instances, hasConverter_fn, extractCollections_fn, collectDescriptors_fn, teardownMissingEditors_fn, teardownEditors_fn, createEditor_fn, createEditorContainer_fn, registerConverterEditor_fn, unregisterConverterEditor_fn, updateAccessOrder_fn, enforceCacheSizeLimit_fn, _manager, _mediaFiles, _blockCache, _HeaderFooterLayoutAdapter_instances, getBlocks_fn, getConverterContext_fn, _instances, _options, _editor3, _visibleHost, _viewportHost, _painterHost, _selectionOverlay, _hiddenHost, _layoutOptions, _layoutState, _domPainter, _layoutError, _layoutErrorState, _errorBanner, _errorBannerMessage, _telemetryEmitter, _renderScheduled, _pendingDocChange, _isRerendering, _selectionUpdateScheduled, _remoteCursorUpdateScheduled, _rafHandle, _editorListeners, _sectionMetadata, _documentMode, _inputBridge, _trackedChangesMode, _trackedChangesEnabled, _trackedChangesOverrides, _headerFooterManager, _headerFooterAdapter, _headerFooterIdentifier, _headerLayoutResults, _footerLayoutResults, _headerDecorationProvider, _footerDecorationProvider, _headerFooterManagerCleanups, _headerRegions, _footerRegions, _session, _activeHeaderFooterEditor, _hoverOverlay, _hoverTooltip, _modeBanner, _ariaLiveRegion, _hoverRegion, _clickCount, _lastClickTime, _lastClickPosition, _lastSelectedImageBlockId, _remoteCursorState, _remoteCursorDirty, _remoteCursorOverlay, _localSelectionLayer, _awarenessCleanup, _scrollCleanup, _remoteCursorRafHandle, _scrollTimeout, _PresentationEditor_instances, aggregateLayoutBounds_fn, safeCleanup_fn, setupEditorListeners_fn, setupCollaborationCursors_fn, normalizeAwarenessStates_fn, getFallbackColor_fn, getValidatedColor_fn, scheduleRemoteCursorUpdate_fn, scheduleRemoteCursorReRender_fn, updateRemoteCursors_fn, renderRemoteCursors_fn, renderRemoteCaret_fn, renderRemoteCursorLabel_fn, renderRemoteSelection_fn, setupPointerHandlers_fn, setupInputBridge_fn, initHeaderFooterRegistry_fn, _handlePointerDown, getFirstTextPosition_fn, registerPointerClick_fn, selectWordAt_fn, selectParagraphAt_fn, isWordCharacter_fn, _handlePointerMove, _handlePointerLeave, _handleDoubleClick, _handleKeyDown, focusHeaderFooterShortcut_fn, scheduleRerender_fn, flushRerenderQueue_fn, rerender_fn, ensurePainter_fn, scheduleSelectionUpdate_fn, updateSelection_fn, resolveLayoutOptions_fn, buildHeaderFooterInput_fn, computeHeaderFooterConstraints_fn, updateDecorationProviders_fn, createDecorationProvider_fn, findHeaderFooterPageForPageNumber_fn, computeDecorationBox_fn, rebuildHeaderFooterRegions_fn, hitTestHeaderFooterRegion_fn, pointInRegion_fn, activateHeaderFooterRegion_fn, enterHeaderFooterMode_fn, exitHeaderFooterMode_fn, getActiveDomTarget_fn, emitHeaderFooterModeChanged_fn, emitHeaderFooterEditingContext_fn, updateAwarenessSession_fn, updateModeBanner_fn, announce_fn, validateHeaderFooterEditPermission_fn, emitHeaderFooterEditBlocked_fn, resolveDescriptorForRegion_fn, getBodyPageHeight_fn, getHeaderFooterPageHeight_fn, renderSelectionRects_fn, renderHoverRegion_fn, clearHoverRegion_fn, renderCaretOverlay_fn, getHeaderFooterContext_fn, computeHeaderFooterSelectionRects_fn, computeHeaderFooterCaretRect_fn, syncTrackedChangesPreferences_fn, deriveTrackedChangesMode_fn, deriveTrackedChangesEnabled_fn, getTrackChangesPluginState_fn, computeDefaultLayoutDefaults_fn, parseColumns_fn, inchesToPx_fn, applyZoom_fn, createLayoutMetrics_fn, convertPageLocalToOverlayCoords_fn, normalizeClientPoint_fn, computeCaretLayoutRect_fn, computeCaretLayoutRectFromDOM_fn, computeTableCaretLayoutRect_fn, findLineContainingPos_fn, lineHeightBeforeIndex_fn, getCurrentPageIndex_fn, findRegionForPage_fn, handleLayoutError_fn, decorateError_fn, showLayoutErrorBanner_fn, dismissErrorBanner_fn, createHiddenHost_fn, _windowRoot, _layoutSurfaces, _getTargetDom, _onTargetChanged, _listeners, _currentTarget, _destroyed, _useWindowFallback, _PresentationInputBridge_instances, addListener_fn, dispatchToTarget_fn, forwardKeyboardEvent_fn, forwardTextEvent_fn, forwardCompositionEvent_fn, forwardContextMenu_fn, isEventOnActiveTarget_fn, shouldSkipSurface_fn, isInLayoutSurface_fn, getListenerTargets_fn, isPlainCharacterKey_fn, _DocumentSectionView_instances, init_fn2, addToolTip_fn, _ParagraphNodeView_instances, checkShouldUpdate_fn, updateHTMLAttributes_fn, updateDOMStyles_fn, resolveNeighborParagraphProperties_fn, updateListStyles_fn, initList_fn, checkIsList_fn, createMarker_fn, createSeparator_fn, calculateTabSeparatorStyle_fn, calculateMarkerStyle_fn, removeList_fn, getParagraphContext_fn, scheduleAnimation_fn, cancelScheduledAnimation_fn, _FieldAnnotationView_instances, createAnnotation_fn, _AutoPageNumberNodeView_instances, renderDom_fn, scheduleUpdateNodeStyle_fn, _VectorShapeView_instances, ensureParentPositioned_fn, _ShapeGroupView_instances, ensureParentPositioned_fn2;
39225
39470
  var GOOD_LEAF_SIZE = 200;
39226
39471
  var RopeSequence = function RopeSequence2() {
39227
39472
  };
@@ -40094,17 +40339,20 @@ function findOffsetInNode(node, coords) {
40094
40339
  }
40095
40340
  function findOffsetInText(node, coords) {
40096
40341
  let len = node.nodeValue.length;
40097
- let range2 = document.createRange();
40342
+ let range2 = document.createRange(), result;
40098
40343
  for (let i = 0; i < len; i++) {
40099
40344
  range2.setEnd(node, i + 1);
40100
40345
  range2.setStart(node, i);
40101
40346
  let rect = singleRect(range2, 1);
40102
40347
  if (rect.top == rect.bottom)
40103
40348
  continue;
40104
- if (inRect(coords, rect))
40105
- return { node, offset: i + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0) };
40349
+ if (inRect(coords, rect)) {
40350
+ result = { node, offset: i + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0) };
40351
+ break;
40352
+ }
40106
40353
  }
40107
- return { node, offset: 0 };
40354
+ range2.detach();
40355
+ return result || { node, offset: 0 };
40108
40356
  }
40109
40357
  function inRect(coords, rect) {
40110
40358
  return coords.left >= rect.left - 1 && coords.left <= rect.right + 1 && coords.top >= rect.top - 1 && coords.top <= rect.bottom + 1;
@@ -42851,7 +43099,7 @@ editHandlers.compositionstart = editHandlers.compositionupdate = (view) => {
42851
43099
  if (!view.composing) {
42852
43100
  view.domObserver.flush();
42853
43101
  let { state: state2 } = view, $pos = state2.selection.$to;
42854
- if (state2.selection instanceof TextSelection$1 && (state2.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some((m2) => m2.type.spec.inclusive === false))) {
43102
+ if (state2.selection instanceof TextSelection$1 && (state2.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some((m2) => m2.type.spec.inclusive === false) || chrome && windows$1 && selectionBeforeUneditable(view))) {
42855
43103
  view.markCursor = view.state.storedMarks || $pos.marks();
42856
43104
  endComposition(view, true);
42857
43105
  view.markCursor = null;
@@ -42879,6 +43127,13 @@ editHandlers.compositionstart = editHandlers.compositionupdate = (view) => {
42879
43127
  }
42880
43128
  scheduleComposeEnd(view, timeoutComposition);
42881
43129
  };
43130
+ function selectionBeforeUneditable(view) {
43131
+ let { focusNode, focusOffset } = view.domSelectionRange();
43132
+ if (!focusNode || focusNode.nodeType != 1 || focusOffset >= focusNode.childNodes.length)
43133
+ return false;
43134
+ let next = focusNode.childNodes[focusOffset];
43135
+ return next.nodeType == 1 && next.contentEditable == "false";
43136
+ }
42882
43137
  editHandlers.compositionend = (view, event) => {
42883
43138
  if (view.composing) {
42884
43139
  view.input.composing = false;
@@ -43082,10 +43337,14 @@ handlers.dragend = (view) => {
43082
43337
  }, 50);
43083
43338
  };
43084
43339
  editHandlers.dragover = editHandlers.dragenter = (_2, e) => e.preventDefault();
43085
- editHandlers.drop = (view, _event) => {
43086
- let event = _event;
43087
- let dragging = view.dragging;
43088
- view.dragging = null;
43340
+ editHandlers.drop = (view, event) => {
43341
+ try {
43342
+ handleDrop(view, event, view.dragging);
43343
+ } finally {
43344
+ view.dragging = null;
43345
+ }
43346
+ };
43347
+ function handleDrop(view, event, dragging) {
43089
43348
  if (!event.dataTransfer)
43090
43349
  return;
43091
43350
  let eventPos = view.posAtCoords(eventCoords(event));
@@ -43138,7 +43397,7 @@ editHandlers.drop = (view, _event) => {
43138
43397
  }
43139
43398
  view.focus();
43140
43399
  view.dispatch(tr.setMeta("uiEvent", "drop"));
43141
- };
43400
+ }
43142
43401
  handlers.focus = (view) => {
43143
43402
  view.input.lastFocus = Date.now();
43144
43403
  if (!view.focused) {
@@ -43988,6 +44247,13 @@ class DOMObserver {
43988
44247
  br.remove();
43989
44248
  }
43990
44249
  }
44250
+ } else if ((chrome || safari) && added.some((n) => n.nodeName == "BR") && (view.input.lastKeyCode == 8 || view.input.lastKeyCode == 46)) {
44251
+ for (let node of added)
44252
+ if (node.nodeName == "BR" && node.parentNode) {
44253
+ let after = node.nextSibling;
44254
+ if (after && after.nodeType == 1 && after.contentEditable == "false")
44255
+ node.parentNode.removeChild(node);
44256
+ }
43991
44257
  }
43992
44258
  let readSel = null;
43993
44259
  if (from2 < 0 && newSel && view.input.lastFocus > Date.now() - 200 && Math.max(view.input.lastTouch, view.input.lastClick.time) < Date.now() - 300 && selectionCollapsed(sel) && (readSel = selectionFromDOM(view)) && readSel.eq(Selection.near(view.state.doc.resolve(0), 1))) {
@@ -49171,7 +49437,7 @@ const Keymap = Extension.create({
49171
49437
  const baseKeymap = {
49172
49438
  Enter: () => handleEnter(this.editor),
49173
49439
  "Shift-Enter": () => this.editor.commands.insertLineBreak(),
49174
- "Mod-Enter": () => this.editor.commands.exitCode(),
49440
+ "Mod-Enter": () => this.editor.commands.insertPageBreak(),
49175
49441
  Backspace: () => handleBackspace(this.editor),
49176
49442
  "Mod-Backspace": () => handleBackspace(this.editor),
49177
49443
  "Shift-Backspace": () => handleBackspace(this.editor),
@@ -52728,7 +52994,7 @@ const isHeadless = (editor) => {
52728
52994
  const shouldSkipNodeView = (editor) => {
52729
52995
  return isHeadless(editor);
52730
52996
  };
52731
- const summaryVersion = "1.0.0-beta.14";
52997
+ const summaryVersion = "1.0.0-beta.15";
52732
52998
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
52733
52999
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
52734
53000
  function mapAttributes(attrs) {
@@ -53507,7 +53773,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
53507
53773
  { default: remarkStringify },
53508
53774
  { default: remarkGfm }
53509
53775
  ] = await Promise.all([
53510
- Promise.resolve().then(() => require("./index-I4Ew0HDV-EPhjcu7T.cjs")),
53776
+ Promise.resolve().then(() => require("./index-Bds7gW4r-JPDW6c39.cjs")),
53511
53777
  Promise.resolve().then(() => require("./index-DRCvimau-H4Ck3S9a.cjs")),
53512
53778
  Promise.resolve().then(() => require("./index-C_x_N6Uh-Db3CUJMX.cjs")),
53513
53779
  Promise.resolve().then(() => require("./index-D_sWOSiG-BtDZzJ6I.cjs")),
@@ -53712,7 +53978,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
53712
53978
  * Process collaboration migrations
53713
53979
  */
53714
53980
  processCollaborationMigrations() {
53715
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.14");
53981
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.15");
53716
53982
  if (!this.options.ydoc) return;
53717
53983
  const metaMap = this.options.ydoc.getMap("meta");
53718
53984
  let docVersion = metaMap.get("version");
@@ -55441,6 +55707,23 @@ const resolveColorFromAttributes = (attrs, themeColors) => {
55441
55707
  const MAX_DATA_ATTR_COUNT = 50;
55442
55708
  const MAX_DATA_ATTR_VALUE_LENGTH = 1e3;
55443
55709
  const MAX_DATA_ATTR_NAME_LENGTH = 100;
55710
+ const pushCommentAnnotation = (run2, attrs) => {
55711
+ const commentId = typeof attrs?.commentId === "string" ? attrs.commentId : void 0;
55712
+ const importedId = typeof attrs?.importedId === "string" ? attrs.importedId : void 0;
55713
+ const internal = attrs?.internal === true;
55714
+ if (!commentId && !importedId) return;
55715
+ const annotations = run2.comments ? [...run2.comments] : [];
55716
+ const key2 = `${commentId ?? ""}::${importedId ?? ""}`;
55717
+ const exists2 = annotations.some((c2) => `${c2.commentId ?? ""}::${c2.importedId ?? ""}` === key2);
55718
+ if (!exists2) {
55719
+ annotations.push({
55720
+ commentId: commentId ?? importedId,
55721
+ importedId,
55722
+ internal
55723
+ });
55724
+ }
55725
+ run2.comments = annotations;
55726
+ };
55444
55727
  const extractDataAttributes = (attrs) => {
55445
55728
  if (!attrs) return void 0;
55446
55729
  const result = {};
@@ -55723,6 +56006,11 @@ const applyMarksToRun = (run2, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG
55723
56006
  case "textStyle":
55724
56007
  applyTextStyleMark(run2, mark.attrs ?? {}, themeColors);
55725
56008
  break;
56009
+ case "commentMark":
56010
+ case "comment": {
56011
+ pushCommentAnnotation(run2, mark.attrs ?? {});
56012
+ break;
56013
+ }
55726
56014
  case "underline": {
55727
56015
  const style2 = normalizeUnderlineStyle(mark.attrs?.underlineType);
55728
56016
  if (style2) {
@@ -57639,10 +57927,17 @@ const hydrateParagraphStyleAttrs = (para, context, preResolved) => {
57639
57927
  }
57640
57928
  const resolvedExtended = resolved;
57641
57929
  const resolvedAsRecord = resolved;
57930
+ let resolvedIndent = cloneIfObject(resolvedAsRecord.indent);
57931
+ const styleIdLower = typeof styleId === "string" ? styleId.toLowerCase() : "";
57932
+ const isHeadingStyle = typeof resolvedExtended.outlineLvl === "number" || styleIdLower.startsWith("heading ") || styleIdLower.startsWith("heading");
57933
+ const onlyFirstLineIndent = resolvedIndent && resolvedIndent.firstLine != null && resolvedIndent.hanging == null && resolvedIndent.left == null && resolvedIndent.right == null;
57934
+ if (isHeadingStyle && (!resolvedIndent || Object.keys(resolvedIndent).length === 0 || onlyFirstLineIndent)) {
57935
+ resolvedIndent = { firstLine: 0, hanging: 0, left: resolvedIndent?.left, right: resolvedIndent?.right };
57936
+ }
57642
57937
  const hydrated = {
57643
57938
  resolved,
57644
57939
  spacing: cloneIfObject(resolvedAsRecord.spacing),
57645
- indent: cloneIfObject(resolvedAsRecord.indent),
57940
+ indent: resolvedIndent,
57646
57941
  borders: cloneIfObject(resolvedExtended.borders),
57647
57942
  shading: cloneIfObject(resolvedExtended.shading),
57648
57943
  alignment: resolvedExtended.justification,
@@ -57750,6 +58045,12 @@ const cloneParagraphAttrs = (attrs) => {
57750
58045
  }
57751
58046
  if (attrs.shading) clone.shading = { ...attrs.shading };
57752
58047
  if (attrs.tabs) clone.tabs = attrs.tabs.map((tab) => ({ ...tab }));
58048
+ if (attrs.dropCapDescriptor) {
58049
+ clone.dropCapDescriptor = {
58050
+ ...attrs.dropCapDescriptor,
58051
+ run: { ...attrs.dropCapDescriptor.run }
58052
+ };
58053
+ }
57753
58054
  return clone;
57754
58055
  };
57755
58056
  const buildStyleNodeFromAttrs = (attrs, spacing, indent) => {
@@ -57861,6 +58162,119 @@ const normalizeResolvedTabAlignment = (value) => {
57861
58162
  return void 0;
57862
58163
  }
57863
58164
  };
58165
+ const DEFAULT_DROP_CAP_FONT_SIZE_PX = 64;
58166
+ const DEFAULT_DROP_CAP_FONT_FAMILY = "Times New Roman";
58167
+ const extractDropCapRunFromParagraph = (para) => {
58168
+ const content = para.content;
58169
+ if (!Array.isArray(content) || content.length === 0) {
58170
+ return null;
58171
+ }
58172
+ let text = "";
58173
+ let runProperties = {};
58174
+ let textStyleMarks = {};
58175
+ const MAX_RECURSION_DEPTH = 50;
58176
+ const extractTextAndStyle = (nodes, depth = 0) => {
58177
+ if (depth > MAX_RECURSION_DEPTH) {
58178
+ console.warn(`extractTextAndStyle exceeded max recursion depth (${MAX_RECURSION_DEPTH})`);
58179
+ return false;
58180
+ }
58181
+ for (const node of nodes) {
58182
+ if (!node) continue;
58183
+ if (node.type === "text" && typeof node.text === "string" && node.text.length > 0) {
58184
+ text = node.text;
58185
+ if (Array.isArray(node.marks)) {
58186
+ for (const mark of node.marks) {
58187
+ if (mark?.type === "textStyle" && mark.attrs) {
58188
+ textStyleMarks = { ...textStyleMarks, ...mark.attrs };
58189
+ }
58190
+ }
58191
+ }
58192
+ return true;
58193
+ }
58194
+ if (node.type === "run") {
58195
+ if (node.attrs?.runProperties && typeof node.attrs.runProperties === "object") {
58196
+ runProperties = { ...runProperties, ...node.attrs.runProperties };
58197
+ }
58198
+ if (Array.isArray(node.marks)) {
58199
+ for (const mark of node.marks) {
58200
+ if (mark?.type === "textStyle" && mark.attrs) {
58201
+ textStyleMarks = { ...textStyleMarks, ...mark.attrs };
58202
+ }
58203
+ }
58204
+ }
58205
+ if (Array.isArray(node.content) && extractTextAndStyle(node.content, depth + 1)) {
58206
+ return true;
58207
+ }
58208
+ }
58209
+ if (Array.isArray(node.content) && extractTextAndStyle(node.content, depth + 1)) {
58210
+ return true;
58211
+ }
58212
+ }
58213
+ return false;
58214
+ };
58215
+ extractTextAndStyle(content);
58216
+ if (!text) {
58217
+ return null;
58218
+ }
58219
+ const mergedStyle = { ...runProperties, ...textStyleMarks };
58220
+ let fontSizePx = DEFAULT_DROP_CAP_FONT_SIZE_PX;
58221
+ const rawFontSize = mergedStyle.fontSize ?? mergedStyle["w:sz"] ?? mergedStyle.sz;
58222
+ if (rawFontSize != null) {
58223
+ if (typeof rawFontSize === "number") {
58224
+ const converted = rawFontSize > 100 ? ptToPx(rawFontSize / 2) : rawFontSize;
58225
+ fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
58226
+ } else if (typeof rawFontSize === "string") {
58227
+ const numericPart = parseFloat(rawFontSize);
58228
+ if (Number.isFinite(numericPart)) {
58229
+ if (rawFontSize.endsWith("pt")) {
58230
+ const converted = ptToPx(numericPart);
58231
+ fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
58232
+ } else if (rawFontSize.endsWith("px")) {
58233
+ fontSizePx = numericPart;
58234
+ } else {
58235
+ const converted = numericPart > 100 ? ptToPx(numericPart / 2) : numericPart;
58236
+ fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
58237
+ }
58238
+ }
58239
+ }
58240
+ }
58241
+ let fontFamily2 = DEFAULT_DROP_CAP_FONT_FAMILY;
58242
+ const rawFontFamily = mergedStyle.fontFamily ?? mergedStyle["w:rFonts"] ?? mergedStyle.rFonts;
58243
+ if (typeof rawFontFamily === "string") {
58244
+ fontFamily2 = rawFontFamily;
58245
+ } else if (rawFontFamily && typeof rawFontFamily === "object") {
58246
+ const rFonts = rawFontFamily;
58247
+ const ascii = rFonts["w:ascii"] ?? rFonts.ascii;
58248
+ if (typeof ascii === "string") {
58249
+ fontFamily2 = ascii;
58250
+ }
58251
+ }
58252
+ const dropCapRun = {
58253
+ text,
58254
+ fontFamily: fontFamily2,
58255
+ fontSize: fontSizePx
58256
+ };
58257
+ const bold = mergedStyle.bold ?? mergedStyle["w:b"] ?? mergedStyle.b;
58258
+ if (isTruthy(bold)) {
58259
+ dropCapRun.bold = true;
58260
+ }
58261
+ const italic = mergedStyle.italic ?? mergedStyle["w:i"] ?? mergedStyle.i;
58262
+ if (isTruthy(italic)) {
58263
+ dropCapRun.italic = true;
58264
+ }
58265
+ const color = mergedStyle.color ?? mergedStyle["w:color"] ?? mergedStyle.val;
58266
+ if (typeof color === "string" && color.length > 0 && color.toLowerCase() !== "auto") {
58267
+ dropCapRun.color = color.startsWith("#") ? color : `#${color}`;
58268
+ }
58269
+ const position = mergedStyle.position ?? mergedStyle["w:position"];
58270
+ if (position != null) {
58271
+ const posNum = pickNumber(position);
58272
+ if (posNum != null) {
58273
+ dropCapRun.position = ptToPx(posNum / 2);
58274
+ }
58275
+ }
58276
+ return dropCapRun;
58277
+ };
57864
58278
  const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleContext, _paragraphNode) => {
57865
58279
  if (numberingProps === null) {
57866
58280
  return null;
@@ -58126,6 +58540,24 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
58126
58540
  const dropCap = framePr["w:dropCap"] ?? framePr.dropCap;
58127
58541
  if (dropCap != null && (typeof dropCap === "string" || typeof dropCap === "number" || typeof dropCap === "boolean")) {
58128
58542
  paragraphAttrs.dropCap = dropCap;
58543
+ const dropCapMode = typeof dropCap === "string" ? dropCap.toLowerCase() : "drop";
58544
+ const linesValue = pickNumber(framePr["w:lines"] ?? framePr.lines);
58545
+ const wrapValue = asString(framePr["w:wrap"] ?? framePr.wrap);
58546
+ const dropCapRunInfo = extractDropCapRunFromParagraph(para);
58547
+ if (dropCapRunInfo) {
58548
+ const descriptor = {
58549
+ mode: dropCapMode === "margin" ? "margin" : "drop",
58550
+ lines: linesValue != null && linesValue > 0 ? linesValue : 3,
58551
+ run: dropCapRunInfo
58552
+ };
58553
+ if (wrapValue) {
58554
+ const normalizedWrap = wrapValue.toLowerCase();
58555
+ if (normalizedWrap === "around" || normalizedWrap === "notbeside" || normalizedWrap === "none" || normalizedWrap === "tight") {
58556
+ descriptor.wrap = normalizedWrap === "notbeside" ? "notBeside" : normalizedWrap;
58557
+ }
58558
+ }
58559
+ paragraphAttrs.dropCapDescriptor = descriptor;
58560
+ }
58129
58561
  }
58130
58562
  const frame = {};
58131
58563
  const wrap2 = asString(framePr["w:wrap"] ?? framePr.wrap);
@@ -58899,13 +59331,26 @@ const dataAttrsCompatible = (a, b2) => {
58899
59331
  }
58900
59332
  return true;
58901
59333
  };
59334
+ const commentsCompatible = (a, b2) => {
59335
+ const aComments = a.comments ?? [];
59336
+ const bComments = b2.comments ?? [];
59337
+ if (aComments.length === 0 && bComments.length === 0) return true;
59338
+ if (aComments.length !== bComments.length) return false;
59339
+ const normalize2 = (c2) => `${c2.commentId ?? ""}::${c2.importedId ?? ""}::${c2.internal ? "1" : "0"}`;
59340
+ const aKeys = aComments.map(normalize2).sort();
59341
+ const bKeys = bComments.map(normalize2).sort();
59342
+ for (let i = 0; i < aKeys.length; i++) {
59343
+ if (aKeys[i] !== bKeys[i]) return false;
59344
+ }
59345
+ return true;
59346
+ };
58902
59347
  function mergeAdjacentRuns(runs) {
58903
59348
  if (runs.length <= 1) return runs;
58904
59349
  const merged = [];
58905
59350
  let current = runs[0];
58906
59351
  for (let i = 1; i < runs.length; i++) {
58907
59352
  const next = runs[i];
58908
- const canMerge = isTextRun$1(current) && isTextRun$1(next) && !current.token && !next.token && current.pmStart != null && current.pmEnd != null && next.pmStart != null && next.pmEnd != null && current.pmEnd === next.pmStart && current.fontFamily === next.fontFamily && current.fontSize === next.fontSize && current.bold === next.bold && current.italic === next.italic && current.underline === next.underline && current.strike === next.strike && current.color === next.color && current.highlight === next.highlight && (current.letterSpacing ?? 0) === (next.letterSpacing ?? 0) && trackedChangesCompatible(current, next) && dataAttrsCompatible(current, next);
59353
+ const canMerge = isTextRun$1(current) && isTextRun$1(next) && !current.token && !next.token && current.pmStart != null && current.pmEnd != null && next.pmStart != null && next.pmEnd != null && current.pmEnd === next.pmStart && current.fontFamily === next.fontFamily && current.fontSize === next.fontSize && current.bold === next.bold && current.italic === next.italic && current.underline === next.underline && current.strike === next.strike && current.color === next.color && current.highlight === next.highlight && (current.letterSpacing ?? 0) === (next.letterSpacing ?? 0) && trackedChangesCompatible(current, next) && dataAttrsCompatible(current, next) && commentsCompatible(current, next);
58909
59354
  if (canMerge) {
58910
59355
  const currText = current.text ?? "";
58911
59356
  const nextText = next.text ?? "";
@@ -59387,6 +59832,22 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
59387
59832
  id: nextId(),
59388
59833
  attrs: node.attrs || {}
59389
59834
  });
59835
+ } else {
59836
+ const lineBreakRun = { kind: "lineBreak", attrs: {} };
59837
+ const lbAttrs = {};
59838
+ if (attrs.lineBreakType) lbAttrs.lineBreakType = String(attrs.lineBreakType);
59839
+ if (attrs.clear) lbAttrs.clear = String(attrs.clear);
59840
+ if (Object.keys(lbAttrs).length > 0) {
59841
+ lineBreakRun.attrs = lbAttrs;
59842
+ } else {
59843
+ delete lineBreakRun.attrs;
59844
+ }
59845
+ const pos = positions.get(node);
59846
+ if (pos) {
59847
+ lineBreakRun.pmStart = pos.start;
59848
+ lineBreakRun.pmEnd = pos.end;
59849
+ }
59850
+ currentRuns.push(lineBreakRun);
59390
59851
  }
59391
59852
  return;
59392
59853
  }
@@ -60411,7 +60872,39 @@ function toFlowBlocks(pmDoc, options) {
60411
60872
  }
60412
60873
  instrumentation?.log?.({ totalBlocks: blocks.length, blockCounts, bookmarks: bookmarks.size });
60413
60874
  const hydratedBlocks = hydrateImageBlocks(blocks, options?.mediaFiles);
60414
- return { blocks: hydratedBlocks, bookmarks };
60875
+ const mergedBlocks = mergeDropCapParagraphs(hydratedBlocks);
60876
+ return { blocks: mergedBlocks, bookmarks };
60877
+ }
60878
+ function mergeDropCapParagraphs(blocks) {
60879
+ const result = [];
60880
+ let i = 0;
60881
+ while (i < blocks.length) {
60882
+ const block = blocks[i];
60883
+ if (block.kind === "paragraph" && block.attrs?.dropCapDescriptor && i + 1 < blocks.length) {
60884
+ const dropCapBlock = block;
60885
+ const nextBlock = blocks[i + 1];
60886
+ if (nextBlock.kind === "paragraph") {
60887
+ const textBlock = nextBlock;
60888
+ const mergedBlock = {
60889
+ kind: "paragraph",
60890
+ id: textBlock.id,
60891
+ runs: textBlock.runs,
60892
+ attrs: {
60893
+ ...textBlock.attrs,
60894
+ dropCapDescriptor: dropCapBlock.attrs?.dropCapDescriptor,
60895
+ // Clear the legacy dropCap flag on the merged block
60896
+ dropCap: void 0
60897
+ }
60898
+ };
60899
+ result.push(mergedBlock);
60900
+ i += 2;
60901
+ continue;
60902
+ }
60903
+ }
60904
+ result.push(block);
60905
+ i += 1;
60906
+ }
60907
+ return result;
60415
60908
  }
60416
60909
  function paragraphToFlowBlocks(para, nextBlockId, positions, defaultFont, defaultSize, styleContext, listCounterContext, trackedChanges, bookmarks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors, converterContext) {
60417
60910
  return paragraphToFlowBlocks$1(
@@ -60486,7 +60979,7 @@ function getMeasurementContext() {
60486
60979
  return measurementCtx;
60487
60980
  }
60488
60981
  function getRunFontString(run2) {
60489
- if (run2.kind === "tab" || run2.kind === "image") {
60982
+ if (run2.kind === "tab" || run2.kind === "lineBreak" || "src" in run2) {
60490
60983
  return "normal normal 16px Arial";
60491
60984
  }
60492
60985
  const style2 = run2.italic ? "italic" : "normal";
@@ -60505,7 +60998,11 @@ function sliceRunsForLine$1(block, line) {
60505
60998
  result.push(run2);
60506
60999
  continue;
60507
61000
  }
60508
- if (run2.kind === "image") {
61001
+ if ("src" in run2) {
61002
+ result.push(run2);
61003
+ continue;
61004
+ }
61005
+ if (run2.kind === "lineBreak") {
60509
61006
  result.push(run2);
60510
61007
  continue;
60511
61008
  }
@@ -60532,13 +61029,17 @@ function sliceRunsForLine$1(block, line) {
60532
61029
  }
60533
61030
  function measureCharacterX(block, line, charOffset) {
60534
61031
  const ctx2 = getMeasurementContext();
61032
+ const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
61033
+ if (hasExplicitPositioning && line.segments && ctx2) {
61034
+ return measureCharacterXSegmentBased(block, line, charOffset, ctx2);
61035
+ }
60535
61036
  if (!ctx2) {
60536
61037
  const runs2 = sliceRunsForLine$1(block, line);
60537
61038
  const charsInLine = Math.max(
60538
61039
  1,
60539
61040
  runs2.reduce((sum, run2) => {
60540
61041
  if (isTabRun$1(run2)) return sum + TAB_CHAR_LENGTH;
60541
- if (run2.kind === "image") return sum;
61042
+ if ("src" in run2 || run2.kind === "lineBreak") return sum;
60542
61043
  return sum + (run2.text ?? "").length;
60543
61044
  }, 0)
60544
61045
  );
@@ -60559,7 +61060,7 @@ function measureCharacterX(block, line, charOffset) {
60559
61060
  currentCharOffset += runLength2;
60560
61061
  continue;
60561
61062
  }
60562
- const text = run2.kind === "image" ? "" : run2.text ?? "";
61063
+ const text = "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
60563
61064
  const runLength = text.length;
60564
61065
  if (currentCharOffset + runLength >= charOffset) {
60565
61066
  const offsetInRun = charOffset - currentCharOffset;
@@ -60576,6 +61077,47 @@ function measureCharacterX(block, line, charOffset) {
60576
61077
  }
60577
61078
  return currentX;
60578
61079
  }
61080
+ function measureCharacterXSegmentBased(block, line, charOffset, ctx2) {
61081
+ if (block.kind !== "paragraph" || !line.segments) return 0;
61082
+ let lineCharCount = 0;
61083
+ for (const segment of line.segments) {
61084
+ const run2 = block.runs[segment.runIndex];
61085
+ if (!run2) continue;
61086
+ const segmentChars = segment.toChar - segment.fromChar;
61087
+ if (lineCharCount + segmentChars >= charOffset) {
61088
+ const offsetInSegment = charOffset - lineCharCount;
61089
+ let segmentBaseX = segment.x;
61090
+ if (segmentBaseX === void 0) {
61091
+ segmentBaseX = 0;
61092
+ for (const prevSeg of line.segments) {
61093
+ if (prevSeg === segment) break;
61094
+ const prevRun = block.runs[prevSeg.runIndex];
61095
+ if (!prevRun) continue;
61096
+ if (prevSeg.x !== void 0) {
61097
+ segmentBaseX = prevSeg.x + (prevSeg.width ?? 0);
61098
+ } else {
61099
+ segmentBaseX += prevSeg.width ?? 0;
61100
+ }
61101
+ }
61102
+ }
61103
+ if (isTabRun$1(run2)) {
61104
+ return segmentBaseX + (offsetInSegment > 0 ? segment.width ?? 0 : 0);
61105
+ }
61106
+ if ("src" in run2 || run2.kind === "lineBreak") {
61107
+ return segmentBaseX + (offsetInSegment >= segmentChars ? segment.width ?? 0 : 0);
61108
+ }
61109
+ const text = run2.text ?? "";
61110
+ const segmentText = text.slice(segment.fromChar, segment.toChar);
61111
+ const textUpToTarget = segmentText.slice(0, offsetInSegment);
61112
+ ctx2.font = getRunFontString(run2);
61113
+ const measured = ctx2.measureText(textUpToTarget);
61114
+ const spacingWidth = computeLetterSpacingWidth(run2, offsetInSegment, segmentChars);
61115
+ return segmentBaseX + measured.width + spacingWidth;
61116
+ }
61117
+ lineCharCount += segmentChars;
61118
+ }
61119
+ return line.width;
61120
+ }
60579
61121
  function findCharacterAtX(block, line, x2, pmStart) {
60580
61122
  const ctx2 = getMeasurementContext();
60581
61123
  if (!ctx2) {
@@ -60584,7 +61126,7 @@ function findCharacterAtX(block, line, x2, pmStart) {
60584
61126
  1,
60585
61127
  runs2.reduce((sum, run2) => {
60586
61128
  if (isTabRun$1(run2)) return sum + TAB_CHAR_LENGTH;
60587
- if (run2.kind === "image") return sum;
61129
+ if ("src" in run2 || run2.kind === "lineBreak") return sum;
60588
61130
  return sum + (run2.text ?? "").length;
60589
61131
  }, 0)
60590
61132
  );
@@ -60619,7 +61161,7 @@ function findCharacterAtX(block, line, x2, pmStart) {
60619
61161
  currentCharOffset += TAB_CHAR_LENGTH;
60620
61162
  continue;
60621
61163
  }
60622
- const text = run2.kind === "image" ? "" : run2.text ?? "";
61164
+ const text = "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
60623
61165
  const runLength = text.length;
60624
61166
  if (runLength === 0) continue;
60625
61167
  ctx2.font = getRunFontString(run2);
@@ -60656,7 +61198,7 @@ function findCharacterAtX(block, line, x2, pmStart) {
60656
61198
  };
60657
61199
  }
60658
61200
  const computeLetterSpacingWidth = (run2, precedingChars, runLength) => {
60659
- if (isTabRun$1(run2) || run2.kind === "image" || !run2.letterSpacing) {
61201
+ if (isTabRun$1(run2) || "src" in run2 || !("letterSpacing" in run2) || !run2.letterSpacing) {
60660
61202
  return 0;
60661
61203
  }
60662
61204
  const maxGaps = Math.max(runLength - 1, 0);
@@ -60666,6 +61208,8 @@ const computeLetterSpacingWidth = (run2, precedingChars, runLength) => {
60666
61208
  const clamped = Math.min(Math.max(precedingChars, 0), maxGaps);
60667
61209
  return clamped * run2.letterSpacing;
60668
61210
  };
61211
+ const log = (...args) => {
61212
+ };
60669
61213
  const CLASS_NAMES$1 = {
60670
61214
  page: "superdoc-page",
60671
61215
  fragment: "superdoc-fragment",
@@ -60681,6 +61225,11 @@ function clickToPositionDom(domContainer, clientX, clientY) {
60681
61225
  const pageLocalY = clientY - pageRect.top;
60682
61226
  const viewX = pageRect.left + pageLocalX;
60683
61227
  const viewY = pageRect.top + pageLocalY;
61228
+ log("Page found:", {
61229
+ pageIndex: pageEl.dataset.pageIndex,
61230
+ pageRect: { left: pageRect.left, top: pageRect.top, width: pageRect.width, height: pageRect.height },
61231
+ viewCoords: { viewX, viewY }
61232
+ });
60684
61233
  let hitChain = [];
60685
61234
  const doc2 = document;
60686
61235
  if (typeof doc2.elementsFromPoint === "function") {
@@ -60692,15 +61241,62 @@ function clickToPositionDom(domContainer, clientX, clientY) {
60692
61241
  if (!Array.isArray(hitChain)) {
60693
61242
  return null;
60694
61243
  }
61244
+ const hitChainData = hitChain.map((el) => {
61245
+ const rect = el.getBoundingClientRect();
61246
+ return {
61247
+ tag: el.tagName,
61248
+ classes: el.className,
61249
+ blockId: el.dataset?.blockId,
61250
+ pmStart: el.dataset?.pmStart,
61251
+ pmEnd: el.dataset?.pmEnd,
61252
+ rect: {
61253
+ top: Math.round(rect.top),
61254
+ bottom: Math.round(rect.bottom),
61255
+ left: Math.round(rect.left),
61256
+ right: Math.round(rect.right),
61257
+ height: Math.round(rect.height)
61258
+ }
61259
+ };
61260
+ });
61261
+ log("Hit chain elements:", JSON.stringify(hitChainData, null, 2));
61262
+ const allFragments = Array.from(pageEl.querySelectorAll(`.${CLASS_NAMES$1.fragment}`));
61263
+ const fragmentData = allFragments.map((el) => {
61264
+ const rect = el.getBoundingClientRect();
61265
+ return {
61266
+ blockId: el.dataset.blockId,
61267
+ pmStart: el.dataset.pmStart,
61268
+ pmEnd: el.dataset.pmEnd,
61269
+ rect: {
61270
+ top: Math.round(rect.top),
61271
+ bottom: Math.round(rect.bottom),
61272
+ left: Math.round(rect.left),
61273
+ right: Math.round(rect.right),
61274
+ height: Math.round(rect.height)
61275
+ }
61276
+ };
61277
+ });
61278
+ log("All fragments on page:", JSON.stringify(fragmentData, null, 2));
60695
61279
  const fragmentEl = hitChain.find((el) => el.classList?.contains?.(CLASS_NAMES$1.fragment));
60696
61280
  if (!fragmentEl) {
60697
61281
  const fallbackFragment = pageEl.querySelector(`.${CLASS_NAMES$1.fragment}`);
60698
61282
  if (!fallbackFragment) {
60699
61283
  return null;
60700
61284
  }
60701
- return processFragment(fallbackFragment, viewX, viewY);
61285
+ log("Using fallback fragment:", {
61286
+ blockId: fallbackFragment.dataset.blockId,
61287
+ pmStart: fallbackFragment.dataset.pmStart,
61288
+ pmEnd: fallbackFragment.dataset.pmEnd
61289
+ });
61290
+ const result2 = processFragment(fallbackFragment, viewX, viewY);
61291
+ return result2;
60702
61292
  }
60703
- return processFragment(fragmentEl, viewX, viewY);
61293
+ log("Fragment found:", {
61294
+ blockId: fragmentEl.dataset.blockId,
61295
+ pmStart: fragmentEl.dataset.pmStart,
61296
+ pmEnd: fragmentEl.dataset.pmEnd
61297
+ });
61298
+ const result = processFragment(fragmentEl, viewX, viewY);
61299
+ return result;
60704
61300
  }
60705
61301
  function findPageElement(domContainer, clientX, clientY) {
60706
61302
  if (domContainer.classList?.contains?.(CLASS_NAMES$1.page)) {
@@ -60732,7 +61328,20 @@ function findPageElement(domContainer, clientX, clientY) {
60732
61328
  return null;
60733
61329
  }
60734
61330
  function processFragment(fragmentEl, viewX, viewY) {
61331
+ log("processFragment:", { viewX, viewY, blockId: fragmentEl.dataset.blockId });
60735
61332
  const lineEls = Array.from(fragmentEl.querySelectorAll(`.${CLASS_NAMES$1.line}`));
61333
+ log(
61334
+ "Lines in fragment:",
61335
+ lineEls.map((el, i) => {
61336
+ const rect = el.getBoundingClientRect();
61337
+ return {
61338
+ index: i,
61339
+ pmStart: el.dataset.pmStart,
61340
+ pmEnd: el.dataset.pmEnd,
61341
+ rect: { top: rect.top, bottom: rect.bottom, left: rect.left, right: rect.right }
61342
+ };
61343
+ })
61344
+ );
60736
61345
  if (lineEls.length === 0) {
60737
61346
  return null;
60738
61347
  }
@@ -60742,10 +61351,30 @@ function processFragment(fragmentEl, viewX, viewY) {
60742
61351
  }
60743
61352
  const lineStart = Number(lineEl.dataset.pmStart ?? "NaN");
60744
61353
  const lineEnd = Number(lineEl.dataset.pmEnd ?? "NaN");
61354
+ const lineRect = lineEl.getBoundingClientRect();
61355
+ log("Selected line:", {
61356
+ pmStart: lineStart,
61357
+ pmEnd: lineEnd,
61358
+ rect: { top: lineRect.top, bottom: lineRect.bottom, left: lineRect.left, right: lineRect.right }
61359
+ });
60745
61360
  if (!Number.isFinite(lineStart) || !Number.isFinite(lineEnd)) {
60746
61361
  return null;
60747
61362
  }
60748
61363
  const spanEls = Array.from(lineEl.querySelectorAll("span"));
61364
+ log(
61365
+ "Spans in line:",
61366
+ spanEls.map((el, i) => {
61367
+ const rect = el.getBoundingClientRect();
61368
+ return {
61369
+ index: i,
61370
+ pmStart: el.dataset.pmStart,
61371
+ pmEnd: el.dataset.pmEnd,
61372
+ text: el.textContent?.substring(0, 20) + (el.textContent && el.textContent.length > 20 ? "..." : ""),
61373
+ visibility: el.style.visibility,
61374
+ rect: { left: rect.left, right: rect.right, width: rect.width }
61375
+ };
61376
+ })
61377
+ );
60749
61378
  if (spanEls.length === 0) {
60750
61379
  return lineStart;
60751
61380
  }
@@ -60763,6 +61392,14 @@ function processFragment(fragmentEl, viewX, viewY) {
60763
61392
  }
60764
61393
  const spanStart = Number(targetSpan.dataset.pmStart ?? "NaN");
60765
61394
  const spanEnd = Number(targetSpan.dataset.pmEnd ?? "NaN");
61395
+ const targetRect = targetSpan.getBoundingClientRect();
61396
+ log("Target span:", {
61397
+ pmStart: spanStart,
61398
+ pmEnd: spanEnd,
61399
+ text: targetSpan.textContent?.substring(0, 30),
61400
+ visibility: targetSpan.style.visibility,
61401
+ rect: { left: targetRect.left, right: targetRect.right, width: targetRect.width }
61402
+ });
60766
61403
  if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) {
60767
61404
  return null;
60768
61405
  }
@@ -60782,28 +61419,53 @@ function findLineAtY(lineEls, viewY) {
60782
61419
  if (lineEls.length === 0) {
60783
61420
  return null;
60784
61421
  }
60785
- for (const lineEl of lineEls) {
61422
+ for (let i = 0; i < lineEls.length; i++) {
61423
+ const lineEl = lineEls[i];
60786
61424
  const rect = lineEl.getBoundingClientRect();
60787
61425
  if (viewY >= rect.top && viewY <= rect.bottom) {
61426
+ log("findLineAtY: Found line at index", i, {
61427
+ pmStart: lineEl.dataset.pmStart,
61428
+ pmEnd: lineEl.dataset.pmEnd,
61429
+ rect: { top: rect.top, bottom: rect.bottom },
61430
+ viewY
61431
+ });
60788
61432
  return lineEl;
60789
61433
  }
60790
61434
  }
60791
- return lineEls[lineEls.length - 1];
61435
+ const lastLine = lineEls[lineEls.length - 1];
61436
+ log("findLineAtY: Y beyond all lines, using last line:", {
61437
+ pmStart: lastLine.dataset.pmStart,
61438
+ pmEnd: lastLine.dataset.pmEnd,
61439
+ viewY
61440
+ });
61441
+ return lastLine;
60792
61442
  }
60793
61443
  function findSpanAtX(spanEls, viewX) {
60794
61444
  if (spanEls.length === 0) {
60795
61445
  return null;
60796
61446
  }
60797
61447
  let targetSpan = spanEls[0];
60798
- for (const span of spanEls) {
61448
+ for (let i = 0; i < spanEls.length; i++) {
61449
+ const span = spanEls[i];
60799
61450
  const rect = span.getBoundingClientRect();
60800
61451
  if (viewX >= rect.left && viewX <= rect.right) {
61452
+ log("findSpanAtX: Found containing span at index", i, {
61453
+ pmStart: span.dataset.pmStart,
61454
+ pmEnd: span.dataset.pmEnd,
61455
+ rect: { left: rect.left, right: rect.right },
61456
+ viewX
61457
+ });
60801
61458
  return span;
60802
61459
  }
60803
61460
  if (viewX > rect.right) {
60804
61461
  targetSpan = span;
60805
61462
  }
60806
61463
  }
61464
+ log("findSpanAtX: No containing span, using nearest:", {
61465
+ pmStart: targetSpan.dataset.pmStart,
61466
+ pmEnd: targetSpan.dataset.pmEnd,
61467
+ viewX
61468
+ });
60807
61469
  return targetSpan;
60808
61470
  }
60809
61471
  function findCharIndexAtX(textNode, span, targetX) {
@@ -60933,7 +61595,7 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
60933
61595
  zones.push(zone);
60934
61596
  },
60935
61597
  getExclusionsForLine(lineY, lineHeight2, columnIndex, pageNumber) {
60936
- return zones.filter((zone) => {
61598
+ const result = zones.filter((zone) => {
60937
61599
  if (zone.pageNumber !== pageNumber || zone.columnIndex !== columnIndex) {
60938
61600
  return false;
60939
61601
  }
@@ -60941,8 +61603,10 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
60941
61603
  const lineBottom = lineY + lineHeight2;
60942
61604
  const zoneTop = zone.bounds.y - zone.distances.top;
60943
61605
  const zoneBottom = zone.bounds.y + zone.bounds.height + zone.distances.bottom;
60944
- return lineBottom > zoneTop && lineTop < zoneBottom;
61606
+ const overlaps = lineBottom > zoneTop && lineTop < zoneBottom;
61607
+ return overlaps;
60945
61608
  });
61609
+ return result;
60946
61610
  },
60947
61611
  computeAvailableWidth(lineY, lineHeight2, baseWidth, columnIndex, pageNumber) {
60948
61612
  const exclusions = this.getExclusionsForLine(lineY, lineHeight2, columnIndex, pageNumber);
@@ -60955,6 +61619,8 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
60955
61619
  }
60956
61620
  const leftFloats = [];
60957
61621
  const rightFloats = [];
61622
+ const columnOrigin = marginLeft + columnIndex * (columns.width + columns.gap);
61623
+ const columnCenter = columnOrigin + baseWidth / 2;
60958
61624
  for (const zone of wrappingZones) {
60959
61625
  if (zone.wrapMode === "left") {
60960
61626
  leftFloats.push(zone);
@@ -60962,7 +61628,7 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
60962
61628
  rightFloats.push(zone);
60963
61629
  } else if (zone.wrapMode === "both" || zone.wrapMode === "largest") {
60964
61630
  const zoneCenter = zone.bounds.x + zone.bounds.width / 2;
60965
- if (zoneCenter < baseWidth / 2) {
61631
+ if (zoneCenter < columnCenter) {
60966
61632
  leftFloats.push(zone);
60967
61633
  } else {
60968
61634
  rightFloats.push(zone);
@@ -60974,7 +61640,6 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
60974
61640
  const boundary = zone.bounds.x + zone.bounds.width + zone.distances.left + zone.distances.right;
60975
61641
  leftBoundary = Math.max(leftBoundary, boundary);
60976
61642
  }
60977
- const columnOrigin = marginLeft + columnIndex * (columns.width + columns.gap);
60978
61643
  const columnRightEdge = columnOrigin + baseWidth;
60979
61644
  let rightBoundary = columnRightEdge;
60980
61645
  for (const zone of rightFloats) {
@@ -61297,9 +61962,6 @@ const extractBlockPmRange = (block) => {
61297
61962
  pmEnd: end2 ?? (start2 != null ? start2 + 1 : void 0)
61298
61963
  };
61299
61964
  };
61300
- const anchorDebugLog = (...args) => {
61301
- return;
61302
- };
61303
61965
  function layoutParagraphBlock(ctx2, anchors) {
61304
61966
  const { block, measure, columnWidth, ensurePage, advanceColumn, columnX, floatManager } = ctx2;
61305
61967
  const remeasureParagraph2 = ctx2.remeasureParagraph;
@@ -61308,23 +61970,45 @@ function layoutParagraphBlock(ctx2, anchors) {
61308
61970
  for (const entry of anchors.anchoredDrawings) {
61309
61971
  if (anchors.placedAnchoredIds.has(entry.block.id)) continue;
61310
61972
  const state2 = ensurePage();
61311
- const baseAnchorY = state2.cursorY;
61312
- const firstLineHeight = measure.lines?.[0]?.lineHeight ?? 0;
61313
61973
  const vRelativeFrom = entry.block.anchor?.vRelativeFrom;
61314
- const paragraphAdjustment = vRelativeFrom === "paragraph" ? firstLineHeight / 2 : 0;
61315
- const anchorY = baseAnchorY + paragraphAdjustment;
61316
- anchorDebugLog("Positioning anchored image:", {
61317
- blockId: entry.block.id,
61318
- baseAnchorY,
61319
- paragraphAdjustment,
61320
- anchorY,
61321
- offsetV: entry.block.anchor?.offsetV,
61322
- finalY: anchorY + (entry.block.anchor?.offsetV ?? 0),
61323
- measureHeight: entry.measure.height,
61324
- measureWidth: entry.measure.width,
61325
- pageNumber: state2.page.number,
61326
- vRelativeFrom
61327
- });
61974
+ const alignV = entry.block.anchor?.alignV;
61975
+ const offsetV = entry.block.anchor?.offsetV ?? 0;
61976
+ const imageHeight = entry.measure.height;
61977
+ const contentTop = state2.topMargin;
61978
+ const contentBottom = state2.contentBottom;
61979
+ const contentHeight = Math.max(0, contentBottom - contentTop);
61980
+ let anchorY;
61981
+ if (vRelativeFrom === "margin") {
61982
+ if (alignV === "top") {
61983
+ anchorY = contentTop + offsetV;
61984
+ } else if (alignV === "bottom") {
61985
+ anchorY = contentBottom - imageHeight + offsetV;
61986
+ } else if (alignV === "center") {
61987
+ anchorY = contentTop + (contentHeight - imageHeight) / 2 + offsetV;
61988
+ } else {
61989
+ anchorY = contentTop + offsetV;
61990
+ }
61991
+ } else if (vRelativeFrom === "page") {
61992
+ if (alignV === "top") {
61993
+ anchorY = offsetV;
61994
+ } else if (alignV === "bottom") {
61995
+ const pageHeight = contentBottom + (anchors.pageMargins.bottom ?? 0);
61996
+ anchorY = pageHeight - imageHeight + offsetV;
61997
+ } else if (alignV === "center") {
61998
+ const pageHeight = contentBottom + (anchors.pageMargins.bottom ?? 0);
61999
+ anchorY = (pageHeight - imageHeight) / 2 + offsetV;
62000
+ } else {
62001
+ anchorY = offsetV;
62002
+ }
62003
+ } else if (vRelativeFrom === "paragraph") {
62004
+ const baseAnchorY = state2.cursorY;
62005
+ const firstLineHeight = measure.lines?.[0]?.lineHeight ?? 0;
62006
+ const paragraphAdjustment = firstLineHeight / 2;
62007
+ anchorY = baseAnchorY + paragraphAdjustment + offsetV;
62008
+ } else {
62009
+ const baseAnchorY = state2.cursorY;
62010
+ anchorY = baseAnchorY + offsetV;
62011
+ }
61328
62012
  floatManager.registerDrawing(entry.block, entry.measure, anchorY, state2.columnIndex, state2.page.number);
61329
62013
  const anchorX = entry.block.anchor ? computeAnchorX(
61330
62014
  entry.block.anchor,
@@ -61364,7 +62048,7 @@ function layoutParagraphBlock(ctx2, anchors) {
61364
62048
  kind: "image",
61365
62049
  blockId: entry.block.id,
61366
62050
  x: anchorX,
61367
- y: anchorY + (entry.block.anchor?.offsetV ?? 0),
62051
+ y: anchorY,
61368
62052
  width: entry.measure.width,
61369
62053
  height: entry.measure.height,
61370
62054
  isAnchored: true,
@@ -61380,7 +62064,7 @@ function layoutParagraphBlock(ctx2, anchors) {
61380
62064
  blockId: entry.block.id,
61381
62065
  drawingKind: entry.block.drawingKind,
61382
62066
  x: anchorX,
61383
- y: anchorY + (entry.block.anchor?.offsetV ?? 0),
62067
+ y: anchorY,
61384
62068
  width: entry.measure.width,
61385
62069
  height: entry.measure.height,
61386
62070
  geometry: entry.measure.geometry,
@@ -61441,7 +62125,39 @@ function layoutParagraphBlock(ctx2, anchors) {
61441
62125
  state2.lastParagraphStyleId = styleId;
61442
62126
  return;
61443
62127
  }
62128
+ let narrowestWidth = columnWidth;
62129
+ let narrowestOffsetX = 0;
61444
62130
  let didRemeasureForFloats = false;
62131
+ if (typeof remeasureParagraph2 === "function") {
62132
+ const tempState = ensurePage();
62133
+ let tempY = tempState.cursorY;
62134
+ if (!appliedSpacingBefore && spacingBefore > 0) {
62135
+ const prevTrailing = tempState.trailingSpacing ?? 0;
62136
+ const neededSpacingBefore = Math.max(spacingBefore - prevTrailing, 0);
62137
+ tempY += neededSpacingBefore;
62138
+ }
62139
+ for (let i = 0; i < lines.length; i++) {
62140
+ const lineY = tempY;
62141
+ const lineHeight2 = lines[i]?.lineHeight || 0;
62142
+ const { width: availableWidth, offsetX: computedOffset } = floatManager.computeAvailableWidth(
62143
+ lineY,
62144
+ lineHeight2,
62145
+ columnWidth,
62146
+ tempState.columnIndex,
62147
+ tempState.page.number
62148
+ );
62149
+ if (availableWidth < narrowestWidth) {
62150
+ narrowestWidth = availableWidth;
62151
+ narrowestOffsetX = computedOffset;
62152
+ }
62153
+ tempY += lineHeight2;
62154
+ }
62155
+ if (narrowestWidth < columnWidth) {
62156
+ const newMeasure = remeasureParagraph2(block, narrowestWidth);
62157
+ lines = normalizeLines(newMeasure);
62158
+ didRemeasureForFloats = true;
62159
+ }
62160
+ }
61445
62161
  while (fromLine < lines.length) {
61446
62162
  let state2 = ensurePage();
61447
62163
  if (state2.trailingSpacing == null) state2.trailingSpacing = 0;
@@ -61486,23 +62202,9 @@ function layoutParagraphBlock(ctx2, anchors) {
61486
62202
  }
61487
62203
  let effectiveColumnWidth = columnWidth;
61488
62204
  let offsetX = 0;
61489
- if (!didRemeasureForFloats && typeof remeasureParagraph2 === "function") {
61490
- const firstLineY = state2.cursorY;
61491
- const firstLineHeight = lines[fromLine]?.lineHeight || 0;
61492
- const { width: adjustedWidth, offsetX: computedOffset } = floatManager.computeAvailableWidth(
61493
- firstLineY,
61494
- firstLineHeight,
61495
- columnWidth,
61496
- state2.columnIndex,
61497
- state2.page.number
61498
- );
61499
- if (adjustedWidth < columnWidth) {
61500
- const newMeasure = remeasureParagraph2(block, adjustedWidth);
61501
- lines = normalizeLines(newMeasure);
61502
- didRemeasureForFloats = true;
61503
- effectiveColumnWidth = adjustedWidth;
61504
- offsetX = computedOffset;
61505
- }
62205
+ if (didRemeasureForFloats) {
62206
+ effectiveColumnWidth = narrowestWidth;
62207
+ offsetX = narrowestOffsetX;
61506
62208
  }
61507
62209
  const slice2 = sliceLines(lines, fromLine, state2.contentBottom - state2.cursorY);
61508
62210
  const fragmentHeight = slice2.height;
@@ -61516,15 +62218,6 @@ function layoutParagraphBlock(ctx2, anchors) {
61516
62218
  width: effectiveColumnWidth,
61517
62219
  ...computeFragmentPmRange(block, lines, fromLine, slice2.toLine)
61518
62220
  };
61519
- anchorDebugLog("Positioning paragraph fragment:", {
61520
- blockId: block.id,
61521
- fragmentY: state2.cursorY,
61522
- fragmentHeight,
61523
- firstLineHeight: lines[fromLine]?.lineHeight,
61524
- firstLineAscent: lines[fromLine]?.ascent,
61525
- firstLineDescent: lines[fromLine]?.descent,
61526
- pageNumber: state2.page.number
61527
- });
61528
62221
  if (measure.marker && fromLine === 0) {
61529
62222
  fragment.markerWidth = measure.marker.markerWidth;
61530
62223
  }
@@ -61737,9 +62430,32 @@ function layoutTableBlock({
61737
62430
  state2.page.fragments.push(fragment);
61738
62431
  state2.cursorY += height;
61739
62432
  }
62433
+ function isPageRelativeAnchor(block) {
62434
+ const vRelativeFrom = block.anchor?.vRelativeFrom;
62435
+ return vRelativeFrom === "margin" || vRelativeFrom === "page";
62436
+ }
62437
+ function collectPreRegisteredAnchors(blocks, measures) {
62438
+ const result = [];
62439
+ const len = Math.min(blocks.length, measures.length);
62440
+ for (let i = 0; i < len; i += 1) {
62441
+ const block = blocks[i];
62442
+ const measure = measures[i];
62443
+ const isImage = block.kind === "image" && measure?.kind === "image";
62444
+ const isDrawing = block.kind === "drawing" && measure?.kind === "drawing";
62445
+ if (!isImage && !isDrawing) continue;
62446
+ const drawingBlock = block;
62447
+ const drawingMeasure = measure;
62448
+ if (!drawingBlock.anchor?.isAnchored) continue;
62449
+ if (isPageRelativeAnchor(drawingBlock)) {
62450
+ result.push({ block: drawingBlock, measure: drawingMeasure });
62451
+ }
62452
+ }
62453
+ return result;
62454
+ }
61740
62455
  function collectAnchoredDrawings(blocks, measures) {
61741
62456
  const map22 = /* @__PURE__ */ new Map();
61742
- for (let i = 0; i < blocks.length; i += 1) {
62457
+ const len = Math.min(blocks.length, measures.length);
62458
+ for (let i = 0; i < len; i += 1) {
61743
62459
  if (blocks[i].kind === "paragraph") ;
61744
62460
  }
61745
62461
  const nearestPrevParagraph = (fromIndex) => {
@@ -61749,12 +62465,12 @@ function collectAnchoredDrawings(blocks, measures) {
61749
62465
  return null;
61750
62466
  };
61751
62467
  const nearestNextParagraph = (fromIndex) => {
61752
- for (let i = fromIndex + 1; i < blocks.length; i += 1) {
62468
+ for (let i = fromIndex + 1; i < len; i += 1) {
61753
62469
  if (blocks[i].kind === "paragraph") return i;
61754
62470
  }
61755
62471
  return null;
61756
62472
  };
61757
- for (let i = 0; i < blocks.length; i += 1) {
62473
+ for (let i = 0; i < len; i += 1) {
61758
62474
  const block = blocks[i];
61759
62475
  const measure = measures[i];
61760
62476
  const isImage = block.kind === "image" && measure?.kind === "image";
@@ -61762,7 +62478,12 @@ function collectAnchoredDrawings(blocks, measures) {
61762
62478
  if (!isImage && !isDrawing) continue;
61763
62479
  const drawingBlock = block;
61764
62480
  const drawingMeasure = measure;
61765
- if (!drawingBlock.anchor?.isAnchored) continue;
62481
+ if (!drawingBlock.anchor?.isAnchored) {
62482
+ continue;
62483
+ }
62484
+ if (isPageRelativeAnchor(drawingBlock)) {
62485
+ continue;
62486
+ }
61766
62487
  let anchorParaIndex = nearestPrevParagraph(i);
61767
62488
  if (anchorParaIndex == null) anchorParaIndex = nearestNextParagraph(i);
61768
62489
  if (anchorParaIndex == null) continue;
@@ -62358,6 +63079,54 @@ function layoutDocument(blocks, measures, options = {}) {
62358
63079
  };
62359
63080
  const anchoredByParagraph = collectAnchoredDrawings(blocks, measures);
62360
63081
  const placedAnchoredIds = /* @__PURE__ */ new Set();
63082
+ const preRegisteredAnchors = collectPreRegisteredAnchors(blocks, measures);
63083
+ const preRegisteredPositions = /* @__PURE__ */ new Map();
63084
+ for (const entry of preRegisteredAnchors) {
63085
+ const state2 = paginator.ensurePage();
63086
+ const vRelativeFrom = entry.block.anchor?.vRelativeFrom ?? "paragraph";
63087
+ const alignV = entry.block.anchor?.alignV ?? "top";
63088
+ const offsetV = entry.block.anchor?.offsetV ?? 0;
63089
+ const imageHeight = entry.measure.height ?? 0;
63090
+ const contentTop = state2.topMargin;
63091
+ const contentBottom = state2.contentBottom;
63092
+ const contentHeight = Math.max(0, contentBottom - contentTop);
63093
+ let anchorY;
63094
+ if (vRelativeFrom === "margin") {
63095
+ if (alignV === "top") {
63096
+ anchorY = contentTop + offsetV;
63097
+ } else if (alignV === "bottom") {
63098
+ anchorY = contentBottom - imageHeight + offsetV;
63099
+ } else if (alignV === "center") {
63100
+ anchorY = contentTop + (contentHeight - imageHeight) / 2 + offsetV;
63101
+ } else {
63102
+ anchorY = contentTop + offsetV;
63103
+ }
63104
+ } else if (vRelativeFrom === "page") {
63105
+ if (alignV === "top") {
63106
+ anchorY = offsetV;
63107
+ } else if (alignV === "bottom") {
63108
+ const pageHeight = contentBottom + margins.bottom;
63109
+ anchorY = pageHeight - imageHeight + offsetV;
63110
+ } else if (alignV === "center") {
63111
+ const pageHeight = contentBottom + margins.bottom;
63112
+ anchorY = (pageHeight - imageHeight) / 2 + offsetV;
63113
+ } else {
63114
+ anchorY = offsetV;
63115
+ }
63116
+ } else {
63117
+ anchorY = contentTop + offsetV;
63118
+ }
63119
+ const anchorX = entry.block.anchor ? computeAnchorX(
63120
+ entry.block.anchor,
63121
+ state2.columnIndex,
63122
+ normalizeColumns(activeColumns, contentWidth),
63123
+ entry.measure.width,
63124
+ { left: margins.left, right: margins.right },
63125
+ activePageSize.w
63126
+ ) : margins.left;
63127
+ floatManager.registerDrawing(entry.block, entry.measure, anchorY, state2.columnIndex, state2.page.number);
63128
+ preRegisteredPositions.set(entry.block.id, { anchorX, anchorY, pageNumber: state2.page.number });
63129
+ }
62361
63130
  for (let index2 = 0; index2 < blocks.length; index2 += 1) {
62362
63131
  const block = blocks[index2];
62363
63132
  const measure = measures[index2];
@@ -62517,6 +63286,52 @@ function layoutDocument(blocks, measures, options = {}) {
62517
63286
  if (measure.kind !== "image") {
62518
63287
  throw new Error(`layoutDocument: expected image measure for block ${block.id}`);
62519
63288
  }
63289
+ const preRegPos = preRegisteredPositions.get(block.id);
63290
+ if (preRegPos && Number.isFinite(preRegPos.anchorX) && Number.isFinite(preRegPos.anchorY) && Number.isFinite(preRegPos.pageNumber)) {
63291
+ const state2 = paginator.ensurePage();
63292
+ const imgBlock = block;
63293
+ const imgMeasure = measure;
63294
+ const pageContentHeight = Math.max(0, state2.contentBottom - state2.topMargin);
63295
+ const relativeFrom = imgBlock.anchor?.hRelativeFrom ?? "column";
63296
+ const cols = getCurrentColumns();
63297
+ let maxWidth;
63298
+ if (relativeFrom === "page") {
63299
+ maxWidth = cols.count === 1 ? activePageSize.w - margins.left - margins.right : activePageSize.w;
63300
+ } else if (relativeFrom === "margin") {
63301
+ maxWidth = activePageSize.w - margins.left - margins.right;
63302
+ } else {
63303
+ maxWidth = cols.width;
63304
+ }
63305
+ const aspectRatio = imgMeasure.width > 0 && imgMeasure.height > 0 ? imgMeasure.width / imgMeasure.height : 1;
63306
+ const minWidth = 20;
63307
+ const minHeight = minWidth / aspectRatio;
63308
+ const metadata = {
63309
+ originalWidth: imgMeasure.width,
63310
+ originalHeight: imgMeasure.height,
63311
+ maxWidth,
63312
+ maxHeight: pageContentHeight,
63313
+ aspectRatio,
63314
+ minWidth,
63315
+ minHeight
63316
+ };
63317
+ const fragment = {
63318
+ kind: "image",
63319
+ blockId: imgBlock.id,
63320
+ x: preRegPos.anchorX,
63321
+ y: preRegPos.anchorY,
63322
+ width: imgMeasure.width,
63323
+ height: imgMeasure.height,
63324
+ isAnchored: true,
63325
+ zIndex: imgBlock.anchor?.behindDoc ? 0 : 1,
63326
+ metadata
63327
+ };
63328
+ const attrs = imgBlock.attrs;
63329
+ if (attrs?.pmStart != null) fragment.pmStart = attrs.pmStart;
63330
+ if (attrs?.pmEnd != null) fragment.pmEnd = attrs.pmEnd;
63331
+ state2.page.fragments.push(fragment);
63332
+ placedAnchoredIds.add(imgBlock.id);
63333
+ continue;
63334
+ }
62520
63335
  layoutImageBlock({
62521
63336
  block,
62522
63337
  measure,
@@ -62712,7 +63527,7 @@ const hashRuns = (block) => {
62712
63527
  const trackedMode = block.attrs && "trackedChangesMode" in block.attrs && block.attrs.trackedChangesMode || "review";
62713
63528
  const trackedEnabled = resolveTrackedChangesEnabled(block.attrs, true);
62714
63529
  const runsHash = block.runs.map((run2) => {
62715
- const text = normalizeText(run2.kind === "image" ? "" : run2.text ?? "");
63530
+ const text = normalizeText("src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "");
62716
63531
  const bold = "bold" in run2 ? run2.bold : false;
62717
63532
  const italic = "italic" in run2 ? run2.italic : false;
62718
63533
  const color = "color" in run2 ? run2.color : void 0;
@@ -62981,7 +63796,13 @@ const FeatureFlags = {
62981
63796
  * Logs cache hits, misses, invalidations, and bucket selection.
62982
63797
  * Should be disabled in production (only enabled for debugging).
62983
63798
  */
62984
- DEBUG_HF_CACHE: isEnabled("SD_DEBUG_HF_CACHE", false)
63799
+ DEBUG_HF_CACHE: isEnabled("SD_DEBUG_HF_CACHE", false),
63800
+ /**
63801
+ * Enable debug logging for layout version tracking.
63802
+ * Logs stale layout reads, geometry fallbacks, PM transactions, and layout completions.
63803
+ * Should be disabled in production (only enabled for debugging).
63804
+ */
63805
+ DEBUG_LAYOUT_VERSION: isEnabled("SD_DEBUG_LAYOUT_VERSION", false)
62985
63806
  };
62986
63807
  const PageTokenLogger = {
62987
63808
  /**
@@ -63366,7 +64187,7 @@ function fontString(run2) {
63366
64187
  return `${italic}${bold}${size2}px ${family}`.trim();
63367
64188
  }
63368
64189
  function runText(run2) {
63369
- return run2.kind === "image" ? "" : run2.text ?? "";
64190
+ return "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
63370
64191
  }
63371
64192
  function measureRunSliceWidth(run2, fromChar, toChar) {
63372
64193
  const context = getCtx();
@@ -63528,7 +64349,7 @@ const paragraphBlocksEqual = (a, b2) => {
63528
64349
  for (let i = 0; i < a.runs.length; i += 1) {
63529
64350
  const runA = a.runs[i];
63530
64351
  const runB = b2.runs[i];
63531
- if ((runA.kind === "image" ? "" : runA.text) !== (runB.kind === "image" ? "" : runB.text) || ("bold" in runA ? runA.bold : false) !== ("bold" in runB ? runB.bold : false) || ("italic" in runA ? runA.italic : false) !== ("italic" in runB ? runB.italic : false) || ("color" in runA ? runA.color : void 0) !== ("color" in runB ? runB.color : void 0) || getTrackedChangeKey(runA) !== getTrackedChangeKey(runB)) {
64352
+ if (("src" in runA || runA.kind === "lineBreak" ? "" : runA.text) !== ("src" in runB || runB.kind === "lineBreak" ? "" : runB.text) || ("bold" in runA ? runA.bold : false) !== ("bold" in runB ? runB.bold : false) || ("italic" in runA ? runA.italic : false) !== ("italic" in runB ? runB.italic : false) || ("color" in runA ? runA.color : void 0) !== ("color" in runB ? runB.color : void 0) || getTrackedChangeKey(runA) !== getTrackedChangeKey(runB)) {
63532
64353
  return false;
63533
64354
  }
63534
64355
  }
@@ -63648,7 +64469,7 @@ function computeHeaderFooterContentHash(blocks) {
63648
64469
  parts.push(block.id);
63649
64470
  if (block.kind === "paragraph") {
63650
64471
  for (const run2 of block.runs) {
63651
- if (run2.kind !== "image") {
64472
+ if (!("src" in run2) && run2.kind !== "lineBreak") {
63652
64473
  parts.push(run2.text ?? "");
63653
64474
  }
63654
64475
  if ("bold" in run2 && run2.bold) parts.push("b");
@@ -64077,6 +64898,23 @@ async function remeasureAffectedBlocks(blocks, measures, affectedBlockIds, const
64077
64898
  }
64078
64899
  return updatedMeasures;
64079
64900
  }
64901
+ var Priority = /* @__PURE__ */ ((Priority2) => {
64902
+ Priority2[Priority2["P0"] = 0] = "P0";
64903
+ Priority2[Priority2["P1"] = 1] = "P1";
64904
+ Priority2[Priority2["P2"] = 2] = "P2";
64905
+ Priority2[Priority2["P3"] = 3] = "P3";
64906
+ return Priority2;
64907
+ })(Priority || {});
64908
+ ({
64909
+ /** P0: No debounce for synchronous cursor positioning */
64910
+ [Priority.P0]: 0,
64911
+ /** P1: One animation frame (~60fps) for viewport layout */
64912
+ [Priority.P1]: 16,
64913
+ /** P2: Typing burst threshold for adjacent pages layout */
64914
+ [Priority.P2]: 50,
64915
+ /** P3: Heavy debounce for full document layout */
64916
+ [Priority.P3]: 150
64917
+ });
64080
64918
  const isAtomicFragment = (fragment) => {
64081
64919
  return fragment.kind === "drawing" || fragment.kind === "image";
64082
64920
  };
@@ -64164,6 +65002,111 @@ const hitTestAtomicFragment = (pageHit, blocks, measures, point) => {
64164
65002
  }
64165
65003
  return null;
64166
65004
  };
65005
+ const hitTestTableFragment = (pageHit, blocks, measures, point) => {
65006
+ for (const fragment of pageHit.page.fragments) {
65007
+ if (fragment.kind !== "table") continue;
65008
+ const tableFragment = fragment;
65009
+ const withinX = point.x >= tableFragment.x && point.x <= tableFragment.x + tableFragment.width;
65010
+ const withinY = point.y >= tableFragment.y && point.y <= tableFragment.y + tableFragment.height;
65011
+ if (!withinX || !withinY) continue;
65012
+ const blockIndex = blocks.findIndex((block2) => block2.id === tableFragment.blockId);
65013
+ if (blockIndex === -1) continue;
65014
+ const block = blocks[blockIndex];
65015
+ const measure = measures[blockIndex];
65016
+ if (!block || block.kind !== "table" || !measure || measure.kind !== "table") continue;
65017
+ const tableBlock = block;
65018
+ const tableMeasure = measure;
65019
+ const localX = point.x - tableFragment.x;
65020
+ const localY = point.y - tableFragment.y;
65021
+ let rowY = 0;
65022
+ let rowIndex = -1;
65023
+ if (tableMeasure.rows.length === 0 || tableBlock.rows.length === 0) continue;
65024
+ for (let r2 = tableFragment.fromRow; r2 < tableFragment.toRow && r2 < tableMeasure.rows.length; r2++) {
65025
+ const rowMeasure2 = tableMeasure.rows[r2];
65026
+ if (localY >= rowY && localY < rowY + rowMeasure2.height) {
65027
+ rowIndex = r2;
65028
+ break;
65029
+ }
65030
+ rowY += rowMeasure2.height;
65031
+ }
65032
+ if (rowIndex === -1) {
65033
+ rowIndex = Math.min(tableFragment.toRow - 1, tableMeasure.rows.length - 1);
65034
+ if (rowIndex < tableFragment.fromRow) continue;
65035
+ }
65036
+ const rowMeasure = tableMeasure.rows[rowIndex];
65037
+ const row = tableBlock.rows[rowIndex];
65038
+ if (!rowMeasure || !row) continue;
65039
+ let colX = 0;
65040
+ let colIndex = -1;
65041
+ if (rowMeasure.cells.length === 0 || row.cells.length === 0) continue;
65042
+ for (let c2 = 0; c2 < rowMeasure.cells.length; c2++) {
65043
+ const cellMeasure2 = rowMeasure.cells[c2];
65044
+ if (localX >= colX && localX < colX + cellMeasure2.width) {
65045
+ colIndex = c2;
65046
+ break;
65047
+ }
65048
+ colX += cellMeasure2.width;
65049
+ }
65050
+ if (colIndex === -1) {
65051
+ colIndex = rowMeasure.cells.length - 1;
65052
+ if (colIndex < 0) continue;
65053
+ }
65054
+ const cellMeasure = rowMeasure.cells[colIndex];
65055
+ const cell = row.cells[colIndex];
65056
+ if (!cellMeasure || !cell) continue;
65057
+ const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
65058
+ const rawMeasures = cellMeasure.blocks ?? (cellMeasure.paragraph ? [cellMeasure.paragraph] : []);
65059
+ const cellBlockMeasures = (Array.isArray(rawMeasures) ? rawMeasures : []).filter(
65060
+ (m2) => m2 != null && typeof m2 === "object" && "kind" in m2
65061
+ );
65062
+ let blockStartY = 0;
65063
+ const getBlockHeight = (m2) => {
65064
+ if (!m2) return 0;
65065
+ if ("totalHeight" in m2 && typeof m2.totalHeight === "number") {
65066
+ return m2.totalHeight;
65067
+ }
65068
+ if ("height" in m2 && typeof m2.height === "number") {
65069
+ return m2.height;
65070
+ }
65071
+ return 0;
65072
+ };
65073
+ for (let i = 0; i < cellBlocks.length && i < cellBlockMeasures.length; i++) {
65074
+ const cellBlock = cellBlocks[i];
65075
+ const cellBlockMeasure = cellBlockMeasures[i];
65076
+ if (cellBlock?.kind !== "paragraph" || cellBlockMeasure?.kind !== "paragraph") {
65077
+ blockStartY += getBlockHeight(cellBlockMeasure);
65078
+ continue;
65079
+ }
65080
+ const blockHeight = getBlockHeight(cellBlockMeasure);
65081
+ const blockEndY = blockStartY + blockHeight;
65082
+ const padding = cell.attrs?.padding ?? { top: 2, left: 4 };
65083
+ const cellLocalX = localX - colX - (padding.left ?? 4);
65084
+ const cellLocalY = localY - rowY - (padding.top ?? 2);
65085
+ const paragraphBlock = cellBlock;
65086
+ const paragraphMeasure = cellBlockMeasure;
65087
+ const isWithinBlock = cellLocalY >= blockStartY && cellLocalY < blockEndY;
65088
+ const isLastParagraph = i === Math.min(cellBlocks.length, cellBlockMeasures.length) - 1;
65089
+ if (isWithinBlock || isLastParagraph) {
65090
+ const unclampedLocalY = cellLocalY - blockStartY;
65091
+ const localYWithinBlock = Math.max(0, Math.min(unclampedLocalY, Math.max(blockHeight, 0)));
65092
+ return {
65093
+ fragment: tableFragment,
65094
+ block: tableBlock,
65095
+ measure: tableMeasure,
65096
+ pageIndex: pageHit.pageIndex,
65097
+ cellRowIndex: rowIndex,
65098
+ cellColIndex: colIndex,
65099
+ cellBlock: paragraphBlock,
65100
+ cellMeasure: paragraphMeasure,
65101
+ localX: Math.max(0, cellLocalX),
65102
+ localY: Math.max(0, localYWithinBlock)
65103
+ };
65104
+ }
65105
+ blockStartY = blockEndY;
65106
+ }
65107
+ }
65108
+ return null;
65109
+ };
64167
65110
  function clickToPosition(layout, blocks, measures, containerPoint, domContainer, clientX, clientY) {
64168
65111
  logClickStage("log", "entry", {
64169
65112
  pages: layout.pages.length
@@ -64258,6 +65201,49 @@ function clickToPosition(layout, blocks, measures, containerPoint, domContainer,
64258
65201
  // lineIndex is now already absolute (within measure.lines), no need to add fragment.fromLine
64259
65202
  };
64260
65203
  }
65204
+ const tableHit = hitTestTableFragment(pageHit, blocks, measures, pageRelativePoint);
65205
+ if (tableHit) {
65206
+ const { cellBlock, cellMeasure, localX, localY, pageIndex } = tableHit;
65207
+ const lineIndex = findLineIndexAtY(cellMeasure, localY, 0, cellMeasure.lines.length);
65208
+ if (lineIndex != null) {
65209
+ const line = cellMeasure.lines[lineIndex];
65210
+ const isRTL = isRtlBlock(cellBlock);
65211
+ const pos = mapPointToPm(cellBlock, line, localX, isRTL);
65212
+ if (pos != null) {
65213
+ logClickStage("log", "success", {
65214
+ blockId: tableHit.fragment.blockId,
65215
+ column: determineColumn(layout, tableHit.fragment.x)
65216
+ });
65217
+ return {
65218
+ pos,
65219
+ blockId: tableHit.fragment.blockId,
65220
+ pageIndex,
65221
+ column: determineColumn(layout, tableHit.fragment.x),
65222
+ lineIndex
65223
+ };
65224
+ }
65225
+ }
65226
+ const firstRun = cellBlock.runs?.[0];
65227
+ if (firstRun && firstRun.pmStart != null) {
65228
+ logClickStage("log", "success", {
65229
+ blockId: tableHit.fragment.blockId,
65230
+ pos: firstRun.pmStart,
65231
+ column: determineColumn(layout, tableHit.fragment.x)
65232
+ });
65233
+ return {
65234
+ pos: firstRun.pmStart,
65235
+ blockId: tableHit.fragment.blockId,
65236
+ pageIndex,
65237
+ column: determineColumn(layout, tableHit.fragment.x),
65238
+ lineIndex: 0
65239
+ };
65240
+ }
65241
+ logClickStage("warn", "table-cell-no-position", {
65242
+ blockId: tableHit.fragment.blockId,
65243
+ cellRow: tableHit.cellRowIndex,
65244
+ cellCol: tableHit.cellColIndex
65245
+ });
65246
+ }
64261
65247
  const atomicHit = hitTestAtomicFragment(pageHit, blocks, measures, pageRelativePoint);
64262
65248
  if (atomicHit && isAtomicFragment(atomicHit.fragment)) {
64263
65249
  const { fragment, block, pageIndex } = atomicHit;
@@ -64369,6 +65355,44 @@ function getFragmentAtPosition(layout, blocks, measures, pos) {
64369
65355
  }
64370
65356
  continue;
64371
65357
  }
65358
+ if (fragment.kind === "table") {
65359
+ if (block.kind !== "table" || measure.kind !== "table") continue;
65360
+ const tableBlock = block;
65361
+ const tableFragment = fragment;
65362
+ let tableMinPos = null;
65363
+ let tableMaxPos = null;
65364
+ for (let r2 = tableFragment.fromRow; r2 < tableFragment.toRow && r2 < tableBlock.rows.length; r2++) {
65365
+ const row = tableBlock.rows[r2];
65366
+ for (const cell of row.cells) {
65367
+ const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
65368
+ for (const cellBlock of cellBlocks) {
65369
+ if (cellBlock?.kind === "paragraph") {
65370
+ const paraBlock = cellBlock;
65371
+ for (const run2 of paraBlock.runs ?? []) {
65372
+ if (run2.pmStart != null) {
65373
+ if (tableMinPos === null || run2.pmStart < tableMinPos) tableMinPos = run2.pmStart;
65374
+ if (tableMaxPos === null || run2.pmStart > tableMaxPos) tableMaxPos = run2.pmStart;
65375
+ }
65376
+ if (run2.pmEnd != null) {
65377
+ if (tableMinPos === null || run2.pmEnd < tableMinPos) tableMinPos = run2.pmEnd;
65378
+ if (tableMaxPos === null || run2.pmEnd > tableMaxPos) tableMaxPos = run2.pmEnd;
65379
+ }
65380
+ }
65381
+ }
65382
+ }
65383
+ }
65384
+ }
65385
+ if (tableMinPos != null && tableMaxPos != null && pos >= tableMinPos && pos <= tableMaxPos) {
65386
+ return {
65387
+ fragment,
65388
+ block,
65389
+ measure,
65390
+ pageIndex,
65391
+ pageY: 0
65392
+ };
65393
+ }
65394
+ continue;
65395
+ }
64372
65396
  if (isAtomicFragment(fragment)) {
64373
65397
  const { pmStart, pmEnd } = getAtomicPmRange(fragment, block);
64374
65398
  const start2 = pmStart ?? pmEnd;
@@ -64416,7 +65440,7 @@ function computeLinePmRange$1(block, line) {
64416
65440
  for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
64417
65441
  const run2 = block.runs[runIndex];
64418
65442
  if (!run2) continue;
64419
- const text = run2.kind === "image" ? "" : run2.text ?? "";
65443
+ const text = "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
64420
65444
  const runLength = text.length;
64421
65445
  const runPmStart = run2.pmStart ?? null;
64422
65446
  const runPmEnd = run2.pmEnd ?? (runPmStart != null ? runPmStart + runLength : null);
@@ -66812,16 +67836,6 @@ const LINK_AND_TOC_STYLES = `
66812
67836
  opacity: 0.8;
66813
67837
  }
66814
67838
 
66815
- /* External link indicator (WCAG 2.4.4 Link Purpose) */
66816
- .superdoc-link[target="_blank"]::after {
66817
- content: "↗";
66818
- display: inline-block;
66819
- margin-left: 0.25em;
66820
- font-size: 0.85em;
66821
- text-decoration: none;
66822
- speak: literal-punctuation; /* Screen readers read the arrow */
66823
- }
66824
-
66825
67839
  /* Print mode: show URLs after links */
66826
67840
  @media print {
66827
67841
  .superdoc-link::after {
@@ -66834,11 +67848,6 @@ const LINK_AND_TOC_STYLES = `
66834
67848
  .superdoc-link[href^="#"]::after {
66835
67849
  content: "";
66836
67850
  }
66837
-
66838
- /* Don't show URL for external link indicator */
66839
- .superdoc-link[target="_blank"]::after {
66840
- content: " (" attr(href) ")";
66841
- }
66842
67851
  }
66843
67852
 
66844
67853
  /* High contrast mode support */
@@ -66856,13 +67865,6 @@ const LINK_AND_TOC_STYLES = `
66856
67865
  }
66857
67866
  }
66858
67867
 
66859
- /* RTL layout support */
66860
- .superdoc-layout[dir="rtl"] .superdoc-link[target="_blank"]::after {
66861
- margin-left: 0;
66862
- margin-right: 0.25em;
66863
- content: "↖"; /* Mirror the arrow for RTL */
66864
- }
66865
-
66866
67868
  /* Screen reader only content (WCAG SC 1.3.1) */
66867
67869
  .sr-only {
66868
67870
  position: absolute;
@@ -67317,7 +68319,100 @@ const renderTableFragment = (deps) => {
67317
68319
  }
67318
68320
  return container;
67319
68321
  };
68322
+ const isDevelopment = () => {
68323
+ if (typeof process$1$1 !== "undefined" && typeof process$1$1.env !== "undefined") {
68324
+ return process$1$1.env.NODE_ENV === "development";
68325
+ }
68326
+ return false;
68327
+ };
68328
+ class ValidationStatsCollector {
68329
+ constructor() {
68330
+ this.stats = {
68331
+ totalSpans: 0,
68332
+ validSpans: 0,
68333
+ missingPmStart: 0,
68334
+ missingPmEnd: 0,
68335
+ missingBoth: 0
68336
+ };
68337
+ }
68338
+ record(hasPmStart, hasPmEnd) {
68339
+ this.stats.totalSpans++;
68340
+ if (hasPmStart && hasPmEnd) {
68341
+ this.stats.validSpans++;
68342
+ } else if (!hasPmStart && !hasPmEnd) {
68343
+ this.stats.missingBoth++;
68344
+ } else if (!hasPmStart) {
68345
+ this.stats.missingPmStart++;
68346
+ } else {
68347
+ this.stats.missingPmEnd++;
68348
+ }
68349
+ }
68350
+ getStats() {
68351
+ return { ...this.stats };
68352
+ }
68353
+ reset() {
68354
+ this.stats = {
68355
+ totalSpans: 0,
68356
+ validSpans: 0,
68357
+ missingPmStart: 0,
68358
+ missingPmEnd: 0,
68359
+ missingBoth: 0
68360
+ };
68361
+ }
68362
+ getCoveragePercent() {
68363
+ if (this.stats.totalSpans === 0) return 100;
68364
+ return this.stats.validSpans / this.stats.totalSpans * 100;
68365
+ }
68366
+ logSummary() {
68367
+ if (!isDevelopment()) return;
68368
+ const coverage = this.getCoveragePercent();
68369
+ const s2 = this.stats;
68370
+ if (coverage < 100) {
68371
+ console.warn("[PmPositionValidation] PM position coverage:", {
68372
+ coverage: `${coverage.toFixed(1)}%`,
68373
+ totalSpans: s2.totalSpans,
68374
+ validSpans: s2.validSpans,
68375
+ missingPmStart: s2.missingPmStart,
68376
+ missingPmEnd: s2.missingPmEnd,
68377
+ missingBoth: s2.missingBoth
68378
+ });
68379
+ }
68380
+ }
68381
+ }
68382
+ const globalValidationStats = new ValidationStatsCollector();
68383
+ function assertPmPositions(run2, context) {
68384
+ const hasPmStart = run2.pmStart != null;
68385
+ const hasPmEnd = run2.pmEnd != null;
68386
+ globalValidationStats.record(hasPmStart, hasPmEnd);
68387
+ if (!isDevelopment()) return;
68388
+ if (!hasPmStart || !hasPmEnd) {
68389
+ const textPreview = run2.text ? run2.text.substring(0, 20) + (run2.text.length > 20 ? "..." : "") : "(no text)";
68390
+ console.warn(`[PmPositionValidation] Missing PM positions in ${context}:`, {
68391
+ hasPmStart,
68392
+ hasPmEnd,
68393
+ textPreview,
68394
+ fallback: "Will use PM DOM coordinates for cursor positioning"
68395
+ });
68396
+ }
68397
+ }
68398
+ function assertFragmentPmPositions(fragment, context) {
68399
+ const hasPmStart = fragment.pmStart != null;
68400
+ const hasPmEnd = fragment.pmEnd != null;
68401
+ globalValidationStats.record(hasPmStart, hasPmEnd);
68402
+ if (!isDevelopment()) return;
68403
+ if (!hasPmStart || !hasPmEnd) {
68404
+ console.warn(`[PmPositionValidation] Missing PM positions in ${context}:`, {
68405
+ fragmentKind: fragment.kind ?? "unknown",
68406
+ hasPmStart,
68407
+ hasPmEnd,
68408
+ fallback: "Will use PM DOM coordinates for cursor positioning"
68409
+ });
68410
+ }
68411
+ }
67320
68412
  const LIST_MARKER_GAP$1 = 8;
68413
+ const COMMENT_EXTERNAL_COLOR = "#B1124B";
68414
+ const COMMENT_INTERNAL_COLOR = "#078383";
68415
+ const COMMENT_INACTIVE_ALPHA = "22";
67321
68416
  const LINK_DATASET_KEYS = {
67322
68417
  blocked: "linkBlocked",
67323
68418
  docLocation: "linkDocLocation",
@@ -67974,7 +69069,7 @@ const _DomPainter = class _DomPainter2 {
67974
69069
  current.element = replacement;
67975
69070
  current.signature = fragmentSignature(fragment, this.blockLookup);
67976
69071
  }
67977
- this.updateFragmentElement(current.element, fragment);
69072
+ this.updateFragmentElement(current.element, fragment, contextBase.section);
67978
69073
  current.fragment = fragment;
67979
69074
  current.key = key2;
67980
69075
  current.context = contextBase;
@@ -68042,10 +69137,10 @@ const _DomPainter = class _DomPainter2 {
68042
69137
  return this.renderListItemFragment(fragment, context);
68043
69138
  }
68044
69139
  if (fragment.kind === "image") {
68045
- return this.renderImageFragment(fragment);
69140
+ return this.renderImageFragment(fragment, context);
68046
69141
  }
68047
69142
  if (fragment.kind === "drawing") {
68048
- return this.renderDrawingFragment(fragment);
69143
+ return this.renderDrawingFragment(fragment, context);
68049
69144
  }
68050
69145
  if (fragment.kind === "table") {
68051
69146
  return this.renderTableFragment(fragment, context);
@@ -68078,7 +69173,7 @@ const _DomPainter = class _DomPainter2 {
68078
69173
  const hasMarker = !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker;
68079
69174
  const styles = isTocEntry ? { ...fragmentStyles, whiteSpace: "nowrap" } : hasMarker ? { ...fragmentStyles, overflow: "visible" } : fragmentStyles;
68080
69175
  applyStyles$2(fragmentEl, styles);
68081
- this.applyFragmentFrame(fragmentEl, fragment);
69176
+ this.applyFragmentFrame(fragmentEl, fragment, context.section);
68082
69177
  if (isTocEntry) {
68083
69178
  fragmentEl.classList.add("superdoc-toc-entry");
68084
69179
  }
@@ -68096,8 +69191,32 @@ const _DomPainter = class _DomPainter2 {
68096
69191
  }
68097
69192
  this.applySdtDataset(fragmentEl, block.attrs?.sdt);
68098
69193
  this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
69194
+ const dropCapDescriptor = block.attrs?.dropCapDescriptor;
69195
+ const dropCapMeasure = measure.dropCap;
69196
+ if (dropCapDescriptor && dropCapMeasure && !fragment.continuesFromPrev) {
69197
+ const dropCapEl = this.renderDropCap(dropCapDescriptor, dropCapMeasure);
69198
+ fragmentEl.appendChild(dropCapEl);
69199
+ }
69200
+ if (fragmentEl.style.paddingLeft) fragmentEl.style.removeProperty("padding-left");
69201
+ if (fragmentEl.style.paddingRight) fragmentEl.style.removeProperty("padding-right");
69202
+ if (fragmentEl.style.textIndent) fragmentEl.style.removeProperty("text-indent");
69203
+ const paraIndent = block.attrs?.indent;
69204
+ const paraIndentLeft = paraIndent?.left ?? 0;
69205
+ const paraIndentRight = paraIndent?.right ?? 0;
69206
+ const firstLineOffset = (paraIndent?.firstLine ?? 0) - (paraIndent?.hanging ?? 0);
68099
69207
  lines.forEach((line, index2) => {
68100
69208
  const lineEl = this.renderLine(block, line, context);
69209
+ if (paraIndentLeft) {
69210
+ lineEl.style.paddingLeft = `${paraIndentLeft}px`;
69211
+ }
69212
+ if (paraIndentRight) {
69213
+ lineEl.style.paddingRight = `${paraIndentRight}px`;
69214
+ }
69215
+ if (!fragment.continuesFromPrev && index2 === 0 && firstLineOffset) {
69216
+ lineEl.style.textIndent = `${firstLineOffset}px`;
69217
+ } else if (firstLineOffset) {
69218
+ lineEl.style.textIndent = "0px";
69219
+ }
68101
69220
  if (index2 === 0 && !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker) {
68102
69221
  const markerContainer = this.doc.createElement("span");
68103
69222
  markerContainer.style.display = "inline-block";
@@ -68108,6 +69227,12 @@ const _DomPainter = class _DomPainter2 {
68108
69227
  markerEl.style.textAlign = wordLayout.marker.justification ?? "right";
68109
69228
  markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
68110
69229
  markerEl.style.pointerEvents = "none";
69230
+ const indentLeft = paraIndentLeft;
69231
+ const hanging = paraIndent?.hanging ?? 0;
69232
+ const textStartX = indentLeft - hanging;
69233
+ const markerLeftX = textStartX - fragment.markerWidth;
69234
+ markerEl.style.position = "relative";
69235
+ markerEl.style.left = `${markerLeftX}px`;
68111
69236
  markerEl.style.fontFamily = wordLayout.marker.run.fontFamily;
68112
69237
  markerEl.style.fontSize = `${wordLayout.marker.run.fontSize}px`;
68113
69238
  markerEl.style.fontWeight = wordLayout.marker.run.bold ? "bold" : "";
@@ -68166,6 +69291,53 @@ const _DomPainter = class _DomPainter2 {
68166
69291
  }
68167
69292
  return el;
68168
69293
  }
69294
+ /**
69295
+ * Renders a drop cap element as a floated span at the start of a paragraph.
69296
+ *
69297
+ * Drop caps are large initial letters that span multiple lines of text.
69298
+ * This method creates a floated element with the drop cap letter styled
69299
+ * according to the descriptor's run properties.
69300
+ *
69301
+ * @param descriptor - The drop cap descriptor with text and styling info
69302
+ * @param measure - The measured dimensions of the drop cap
69303
+ * @returns HTMLElement containing the rendered drop cap
69304
+ */
69305
+ renderDropCap(descriptor, measure) {
69306
+ const doc2 = this.doc;
69307
+ const { run: run2, mode } = descriptor;
69308
+ const dropCapEl = doc2.createElement("span");
69309
+ dropCapEl.classList.add("superdoc-drop-cap");
69310
+ dropCapEl.textContent = run2.text;
69311
+ dropCapEl.style.fontFamily = run2.fontFamily;
69312
+ dropCapEl.style.fontSize = `${run2.fontSize}px`;
69313
+ if (run2.bold) {
69314
+ dropCapEl.style.fontWeight = "bold";
69315
+ }
69316
+ if (run2.italic) {
69317
+ dropCapEl.style.fontStyle = "italic";
69318
+ }
69319
+ if (run2.color) {
69320
+ dropCapEl.style.color = run2.color;
69321
+ }
69322
+ if (mode === "drop") {
69323
+ dropCapEl.style.float = "left";
69324
+ dropCapEl.style.marginRight = "4px";
69325
+ dropCapEl.style.lineHeight = "1";
69326
+ } else if (mode === "margin") {
69327
+ dropCapEl.style.position = "absolute";
69328
+ dropCapEl.style.left = "0";
69329
+ dropCapEl.style.lineHeight = "1";
69330
+ }
69331
+ if (run2.position && run2.position !== 0) {
69332
+ dropCapEl.style.position = dropCapEl.style.position || "relative";
69333
+ dropCapEl.style.top = `${run2.position}px`;
69334
+ }
69335
+ if (measure) {
69336
+ dropCapEl.style.width = `${measure.width}px`;
69337
+ dropCapEl.style.height = `${measure.height}px`;
69338
+ }
69339
+ return dropCapEl;
69340
+ }
68169
69341
  renderListItemFragment(fragment, context) {
68170
69342
  try {
68171
69343
  const lookup2 = this.blockLookup.get(fragment.blockId);
@@ -68243,7 +69415,7 @@ const _DomPainter = class _DomPainter2 {
68243
69415
  return this.createErrorPlaceholder(fragment.blockId, error);
68244
69416
  }
68245
69417
  }
68246
- renderImageFragment(fragment) {
69418
+ renderImageFragment(fragment, context) {
68247
69419
  try {
68248
69420
  const lookup2 = this.blockLookup.get(fragment.blockId);
68249
69421
  if (!lookup2 || lookup2.block.kind !== "image" || lookup2.measure.kind !== "image") {
@@ -68256,7 +69428,7 @@ const _DomPainter = class _DomPainter2 {
68256
69428
  const fragmentEl = this.doc.createElement("div");
68257
69429
  fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-image-fragment");
68258
69430
  applyStyles$2(fragmentEl, fragmentStyles);
68259
- this.applyFragmentFrame(fragmentEl, fragment);
69431
+ this.applyFragmentFrame(fragmentEl, fragment, context.section);
68260
69432
  fragmentEl.style.height = `${fragment.height}px`;
68261
69433
  this.applySdtDataset(fragmentEl, block.attrs?.sdt);
68262
69434
  this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
@@ -68291,7 +69463,7 @@ const _DomPainter = class _DomPainter2 {
68291
69463
  return this.createErrorPlaceholder(fragment.blockId, error);
68292
69464
  }
68293
69465
  }
68294
- renderDrawingFragment(fragment) {
69466
+ renderDrawingFragment(fragment, context) {
68295
69467
  try {
68296
69468
  const lookup2 = this.blockLookup.get(fragment.blockId);
68297
69469
  if (!lookup2 || lookup2.block.kind !== "drawing" || lookup2.measure.kind !== "drawing") {
@@ -68305,7 +69477,7 @@ const _DomPainter = class _DomPainter2 {
68305
69477
  const fragmentEl = this.doc.createElement("div");
68306
69478
  fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-drawing-fragment");
68307
69479
  applyStyles$2(fragmentEl, fragmentStyles);
68308
- this.applyFragmentFrame(fragmentEl, fragment);
69480
+ this.applyFragmentFrame(fragmentEl, fragment, context.section);
68309
69481
  fragmentEl.style.height = `${fragment.height}px`;
68310
69482
  fragmentEl.style.position = "absolute";
68311
69483
  fragmentEl.style.overflow = "hidden";
@@ -68752,13 +69924,16 @@ const _DomPainter = class _DomPainter2 {
68752
69924
  if (!this.doc) {
68753
69925
  throw new Error("DomPainter: document is not available");
68754
69926
  }
69927
+ const applyFragmentFrameWithSection = (el, frag) => {
69928
+ this.applyFragmentFrame(el, frag, context.section);
69929
+ };
68755
69930
  return renderTableFragment({
68756
69931
  doc: this.doc,
68757
69932
  fragment,
68758
69933
  context,
68759
69934
  blockLookup: this.blockLookup,
68760
69935
  renderLine: this.renderLine.bind(this),
68761
- applyFragmentFrame: this.applyFragmentFrame.bind(this),
69936
+ applyFragmentFrame: applyFragmentFrameWithSection,
68762
69937
  applySdtDataset: this.applySdtDataset.bind(this),
68763
69938
  applyStyles: applyStyles$2
68764
69939
  });
@@ -68768,7 +69943,7 @@ const _DomPainter = class _DomPainter2 {
68768
69943
  * @returns Sanitized link data or null if invalid/missing
68769
69944
  */
68770
69945
  extractLinkData(run2) {
68771
- if (run2.kind === "tab") {
69946
+ if (run2.kind === "tab" || run2.kind === "image" || run2.kind === "lineBreak") {
68772
69947
  return null;
68773
69948
  }
68774
69949
  const link = run2.link;
@@ -68922,10 +70097,19 @@ const _DomPainter = class _DomPainter2 {
68922
70097
  isImageRun(run2) {
68923
70098
  return run2.kind === "image";
68924
70099
  }
70100
+ /**
70101
+ * Type guard to check if a run is a line break run.
70102
+ */
70103
+ isLineBreakRun(run2) {
70104
+ return run2.kind === "lineBreak";
70105
+ }
68925
70106
  renderRun(run2, context, trackedConfig) {
68926
70107
  if (this.isImageRun(run2)) {
68927
70108
  return this.renderImageRun(run2);
68928
70109
  }
70110
+ if (this.isLineBreakRun(run2)) {
70111
+ return null;
70112
+ }
68929
70113
  if (!run2.text || !this.doc) {
68930
70114
  return null;
68931
70115
  }
@@ -68950,8 +70134,21 @@ const _DomPainter = class _DomPainter2 {
68950
70134
  }
68951
70135
  }
68952
70136
  applyRunStyles(elem, run2, isActiveLink);
70137
+ const commentColor = getCommentHighlight(run2);
70138
+ if (commentColor && !run2.highlight) {
70139
+ elem.style.backgroundColor = commentColor;
70140
+ }
70141
+ const commentAnnotations = run2.comments;
70142
+ if (commentAnnotations?.length) {
70143
+ elem.dataset.commentIds = commentAnnotations.map((c2) => c2.commentId).join(",");
70144
+ if (commentAnnotations.some((c2) => c2.internal)) {
70145
+ elem.dataset.commentInternal = "true";
70146
+ }
70147
+ elem.classList.add("superdoc-comment-highlight");
70148
+ }
68953
70149
  elem.style.zIndex = "1";
68954
70150
  applyRunDataAttributes(elem, run2.dataAttrs);
70151
+ assertPmPositions(run2, "paragraph text run");
68955
70152
  if (run2.pmStart != null) elem.dataset.pmStart = String(run2.pmStart);
68956
70153
  if (run2.pmEnd != null) elem.dataset.pmEnd = String(run2.pmEnd);
68957
70154
  if (trackedConfig) {
@@ -69030,6 +70227,7 @@ const _DomPainter = class _DomPainter2 {
69030
70227
  img.style.marginRight = `${run2.distRight}px`;
69031
70228
  }
69032
70229
  img.style.zIndex = "1";
70230
+ assertPmPositions(run2, "inline image run");
69033
70231
  if (run2.pmStart != null) {
69034
70232
  img.dataset.pmStart = String(run2.pmStart);
69035
70233
  }
@@ -69060,9 +70258,9 @@ const _DomPainter = class _DomPainter2 {
69060
70258
  if (lineRange.pmEnd != null) {
69061
70259
  el.dataset.pmEnd = String(lineRange.pmEnd);
69062
70260
  }
69063
- const runs = sliceRunsForLine(block, line);
70261
+ const runsForLine = sliceRunsForLine(block, line);
69064
70262
  const trackedConfig = this.resolveTrackedChangesConfig(block);
69065
- if (runs.length === 0) {
70263
+ if (runsForLine.length === 0) {
69066
70264
  const span = this.doc.createElement("span");
69067
70265
  span.innerHTML = "&nbsp;";
69068
70266
  el.appendChild(span);
@@ -69110,49 +70308,109 @@ const _DomPainter = class _DomPainter2 {
69110
70308
  const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
69111
70309
  if (hasExplicitPositioning && line.segments) {
69112
70310
  let cumulativeX = 0;
69113
- line.segments.forEach((segment, _segIdx) => {
69114
- const baseRun = runs[segment.runIndex];
69115
- if (!baseRun || baseRun.kind === "tab") return;
69116
- if (this.isImageRun(baseRun)) {
69117
- const elem2 = this.renderRun(baseRun, context, trackedConfig);
69118
- if (elem2) {
69119
- if (styleId) {
69120
- elem2.setAttribute("styleid", styleId);
69121
- }
69122
- el.appendChild(elem2);
70311
+ const segmentsByRun = /* @__PURE__ */ new Map();
70312
+ line.segments.forEach((segment) => {
70313
+ const list = segmentsByRun.get(segment.runIndex);
70314
+ if (list) {
70315
+ list.push(segment);
70316
+ } else {
70317
+ segmentsByRun.set(segment.runIndex, [segment]);
70318
+ }
70319
+ });
70320
+ const findImmediateNextSegmentX = (fromRunIndex) => {
70321
+ const nextRunIdx = fromRunIndex + 1;
70322
+ if (nextRunIdx <= line.toRun) {
70323
+ const nextSegments = segmentsByRun.get(nextRunIdx);
70324
+ if (nextSegments && nextSegments.length > 0) {
70325
+ const firstSegment = nextSegments[0];
70326
+ return firstSegment.x;
69123
70327
  }
69124
- return;
69125
70328
  }
69126
- const segmentText = baseRun.text.slice(segment.fromChar, segment.toChar);
69127
- const segmentRun = { ...baseRun, text: segmentText };
69128
- const elem = this.renderRun(segmentRun, context, trackedConfig);
69129
- if (elem) {
70329
+ return void 0;
70330
+ };
70331
+ for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
70332
+ const baseRun = block.runs[runIndex];
70333
+ if (!baseRun) continue;
70334
+ if (baseRun.kind === "tab") {
70335
+ const immediateNextX = findImmediateNextSegmentX(runIndex);
70336
+ const tabStartX = cumulativeX;
70337
+ const tabEndX = immediateNextX !== void 0 ? immediateNextX : tabStartX + (baseRun.width ?? 0);
70338
+ const actualTabWidth = tabEndX - tabStartX;
70339
+ const tabEl = this.doc.createElement("span");
70340
+ tabEl.style.position = "absolute";
70341
+ tabEl.style.left = `${tabStartX}px`;
70342
+ tabEl.style.top = "0px";
70343
+ tabEl.style.width = `${actualTabWidth}px`;
70344
+ tabEl.style.height = `${line.lineHeight}px`;
70345
+ tabEl.style.display = "inline-block";
70346
+ tabEl.style.visibility = "hidden";
70347
+ tabEl.style.pointerEvents = "none";
70348
+ tabEl.style.zIndex = "1";
69130
70349
  if (styleId) {
69131
- elem.setAttribute("styleid", styleId);
70350
+ tabEl.setAttribute("styleid", styleId);
69132
70351
  }
69133
- let xPos;
69134
- if (segment.x !== void 0) {
69135
- xPos = segment.x;
69136
- } else {
69137
- xPos = cumulativeX;
70352
+ if (baseRun.pmStart != null) tabEl.dataset.pmStart = String(baseRun.pmStart);
70353
+ if (baseRun.pmEnd != null) tabEl.dataset.pmEnd = String(baseRun.pmEnd);
70354
+ el.appendChild(tabEl);
70355
+ cumulativeX = tabEndX;
70356
+ continue;
70357
+ }
70358
+ if (this.isImageRun(baseRun)) {
70359
+ const elem = this.renderRun(baseRun, context, trackedConfig);
70360
+ if (elem) {
70361
+ if (styleId) {
70362
+ elem.setAttribute("styleid", styleId);
70363
+ }
70364
+ el.appendChild(elem);
69138
70365
  }
69139
- elem.style.position = "absolute";
69140
- elem.style.left = `${xPos}px`;
69141
- el.appendChild(elem);
69142
- if (this.doc) {
69143
- const measureEl = elem.cloneNode(true);
69144
- measureEl.style.position = "absolute";
69145
- measureEl.style.visibility = "hidden";
69146
- measureEl.style.left = "-9999px";
69147
- this.doc.body.appendChild(measureEl);
69148
- const width = measureEl.offsetWidth;
69149
- this.doc.body.removeChild(measureEl);
70366
+ continue;
70367
+ }
70368
+ if (this.isLineBreakRun(baseRun)) {
70369
+ continue;
70370
+ }
70371
+ const runSegments = segmentsByRun.get(runIndex);
70372
+ if (!runSegments || runSegments.length === 0) {
70373
+ continue;
70374
+ }
70375
+ const baseText = baseRun.text ?? "";
70376
+ const runPmStart = baseRun.pmStart ?? null;
70377
+ const fallbackPmEnd = runPmStart != null && baseRun.pmEnd == null ? runPmStart + baseText.length : baseRun.pmEnd ?? null;
70378
+ runSegments.forEach((segment) => {
70379
+ const segmentText = baseText.slice(segment.fromChar, segment.toChar);
70380
+ if (!segmentText) return;
70381
+ const pmSliceStart = runPmStart != null ? runPmStart + segment.fromChar : void 0;
70382
+ const pmSliceEnd = runPmStart != null ? runPmStart + segment.toChar : fallbackPmEnd ?? void 0;
70383
+ const segmentRun = {
70384
+ ...baseRun,
70385
+ text: segmentText,
70386
+ pmStart: pmSliceStart,
70387
+ pmEnd: pmSliceEnd
70388
+ };
70389
+ const elem = this.renderRun(segmentRun, context, trackedConfig);
70390
+ if (elem) {
70391
+ if (styleId) {
70392
+ elem.setAttribute("styleid", styleId);
70393
+ }
70394
+ const xPos = segment.x !== void 0 ? segment.x : cumulativeX;
70395
+ elem.style.position = "absolute";
70396
+ elem.style.left = `${xPos}px`;
70397
+ el.appendChild(elem);
70398
+ let width = segment.width ?? 0;
70399
+ if (width <= 0 && this.doc) {
70400
+ const measureEl = elem.cloneNode(true);
70401
+ measureEl.style.position = "absolute";
70402
+ measureEl.style.visibility = "hidden";
70403
+ measureEl.style.left = "-9999px";
70404
+ this.doc.body.appendChild(measureEl);
70405
+ width = measureEl.offsetWidth;
70406
+ this.doc.body.removeChild(measureEl);
70407
+ }
69150
70408
  cumulativeX = xPos + width;
69151
70409
  }
69152
- }
69153
- });
70410
+ });
70411
+ }
69154
70412
  } else {
69155
- runs.forEach((run2) => {
70413
+ runsForLine.forEach((run2) => {
69156
70414
  const elem = this.renderRun(run2, context, trackedConfig);
69157
70415
  if (elem) {
69158
70416
  if (styleId) {
@@ -69210,8 +70468,18 @@ const _DomPainter = class _DomPainter2 {
69210
70468
  elem.dataset.trackChangeDate = meta.date;
69211
70469
  }
69212
70470
  }
69213
- updateFragmentElement(el, fragment) {
69214
- this.applyFragmentFrame(el, fragment);
70471
+ /**
70472
+ * Updates an existing fragment element's position and dimensions in place.
70473
+ * Used during incremental updates to efficiently reposition fragments without full re-render.
70474
+ *
70475
+ * @param el - The HTMLElement representing the fragment to update
70476
+ * @param fragment - The fragment data containing updated position and dimensions
70477
+ * @param section - The document section ('body', 'header', 'footer') containing this fragment.
70478
+ * Affects PM position validation - only body sections validate PM positions.
70479
+ * If undefined, defaults to 'body' section behavior.
70480
+ */
70481
+ updateFragmentElement(el, fragment, section) {
70482
+ this.applyFragmentFrame(el, fragment, section);
69215
70483
  if (fragment.kind === "image") {
69216
70484
  el.style.height = `${fragment.height}px`;
69217
70485
  }
@@ -69219,12 +70487,27 @@ const _DomPainter = class _DomPainter2 {
69219
70487
  el.style.height = `${fragment.height}px`;
69220
70488
  }
69221
70489
  }
69222
- applyFragmentFrame(el, fragment) {
70490
+ /**
70491
+ * Applies fragment positioning, dimensions, and metadata to an HTML element.
70492
+ * Sets CSS positioning, block ID, and PM position data attributes for paragraph fragments.
70493
+ *
70494
+ * @param el - The HTMLElement to apply fragment properties to
70495
+ * @param fragment - The fragment data containing position, dimensions, and PM position information
70496
+ * @param section - The document section ('body', 'header', 'footer') containing this fragment.
70497
+ * Controls PM position validation behavior:
70498
+ * - 'body' or undefined: PM positions are validated and required for paragraph fragments
70499
+ * - 'header' or 'footer': PM position validation is skipped (these sections have separate PM coordinate spaces)
70500
+ * When undefined, defaults to 'body' section behavior (validation enabled).
70501
+ */
70502
+ applyFragmentFrame(el, fragment, section) {
69223
70503
  el.style.left = `${fragment.x}px`;
69224
70504
  el.style.top = `${fragment.y}px`;
69225
70505
  el.style.width = `${fragment.width}px`;
69226
70506
  el.dataset.blockId = fragment.blockId;
69227
70507
  if (fragment.kind === "para") {
70508
+ if (section === "body" || section === void 0) {
70509
+ assertFragmentPmPositions(fragment, "paragraph fragment");
70510
+ }
69228
70511
  if (fragment.pmStart != null) {
69229
70512
  el.dataset.pmStart = String(fragment.pmStart);
69230
70513
  } else {
@@ -69471,22 +70754,29 @@ const deriveBlockVersion = (block) => {
69471
70754
  imgRun.pmEnd ?? ""
69472
70755
  ].join(",");
69473
70756
  }
70757
+ if (run2.kind === "lineBreak") {
70758
+ return ["linebreak", run2.pmStart ?? "", run2.pmEnd ?? ""].join(",");
70759
+ }
70760
+ if (run2.kind === "tab") {
70761
+ return [run2.text ?? "", "tab", run2.pmStart ?? "", run2.pmEnd ?? ""].join(",");
70762
+ }
70763
+ const textRun = run2;
69474
70764
  return [
69475
- run2.text ?? "",
69476
- run2.kind !== "tab" ? run2.fontFamily : "",
69477
- run2.kind !== "tab" ? run2.fontSize : "",
69478
- run2.kind !== "tab" && run2.bold ? 1 : 0,
69479
- run2.kind !== "tab" && run2.italic ? 1 : 0,
69480
- run2.kind !== "tab" ? run2.color ?? "" : "",
70765
+ textRun.text ?? "",
70766
+ textRun.fontFamily,
70767
+ textRun.fontSize,
70768
+ textRun.bold ? 1 : 0,
70769
+ textRun.italic ? 1 : 0,
70770
+ textRun.color ?? "",
69481
70771
  // Text decorations - ensures DOM updates when decoration properties change.
69482
- run2.kind !== "tab" ? run2.underline?.style ?? "" : "",
69483
- run2.kind !== "tab" ? run2.underline?.color ?? "" : "",
69484
- run2.kind !== "tab" && run2.strike ? 1 : 0,
69485
- run2.kind !== "tab" ? run2.highlight ?? "" : "",
69486
- run2.kind !== "tab" && run2.letterSpacing != null ? run2.letterSpacing : "",
69487
- run2.pmStart ?? "",
69488
- run2.pmEnd ?? "",
69489
- run2.kind !== "tab" ? run2.token ?? "" : ""
70772
+ textRun.underline?.style ?? "",
70773
+ textRun.underline?.color ?? "",
70774
+ textRun.strike ? 1 : 0,
70775
+ textRun.highlight ?? "",
70776
+ textRun.letterSpacing != null ? textRun.letterSpacing : "",
70777
+ textRun.pmStart ?? "",
70778
+ textRun.pmEnd ?? "",
70779
+ textRun.token ?? ""
69490
70780
  ].join(",");
69491
70781
  }).join("|");
69492
70782
  }
@@ -69537,16 +70827,57 @@ const deriveBlockVersion = (block) => {
69537
70827
  }
69538
70828
  if (block.kind === "table") {
69539
70829
  const tableBlock = block;
69540
- return [
69541
- block.id,
69542
- tableBlock.columnWidths ? JSON.stringify(tableBlock.columnWidths) : "",
69543
- tableBlock.rows.length
69544
- ].join("|");
70830
+ const hashString = (seed, value) => {
70831
+ let hash22 = seed >>> 0;
70832
+ for (let i = 0; i < value.length; i++) {
70833
+ hash22 ^= value.charCodeAt(i);
70834
+ hash22 = Math.imul(hash22, 16777619);
70835
+ }
70836
+ return hash22 >>> 0;
70837
+ };
70838
+ const hashNumber = (seed, value) => {
70839
+ const n = Number.isFinite(value) ? value : 0;
70840
+ let hash22 = seed ^ n;
70841
+ hash22 = Math.imul(hash22, 16777619);
70842
+ hash22 ^= hash22 >>> 13;
70843
+ return hash22 >>> 0;
70844
+ };
70845
+ let hash2 = 2166136261;
70846
+ hash2 = hashString(hash2, block.id);
70847
+ hash2 = hashNumber(hash2, tableBlock.rows.length);
70848
+ hash2 = (tableBlock.columnWidths ?? []).reduce((acc, width) => hashNumber(acc, Math.round(width * 1e3)), hash2);
70849
+ const rows = tableBlock.rows ?? [];
70850
+ for (const row of rows) {
70851
+ if (!row || !Array.isArray(row.cells)) continue;
70852
+ hash2 = hashNumber(hash2, row.cells.length);
70853
+ for (const cell of row.cells) {
70854
+ if (!cell) continue;
70855
+ const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
70856
+ hash2 = hashNumber(hash2, cellBlocks.length);
70857
+ hash2 = hashNumber(hash2, cell.rowSpan ?? 1);
70858
+ hash2 = hashNumber(hash2, cell.colSpan ?? 1);
70859
+ for (const cellBlock of cellBlocks) {
70860
+ hash2 = hashString(hash2, cellBlock?.kind ?? "unknown");
70861
+ if (cellBlock?.kind === "paragraph") {
70862
+ const runs = cellBlock.runs ?? [];
70863
+ hash2 = hashNumber(hash2, runs.length);
70864
+ for (const run2 of runs) {
70865
+ if ("text" in run2 && typeof run2.text === "string") {
70866
+ hash2 = hashString(hash2, run2.text);
70867
+ }
70868
+ hash2 = hashNumber(hash2, run2.pmStart ?? -1);
70869
+ hash2 = hashNumber(hash2, run2.pmEnd ?? -1);
70870
+ }
70871
+ }
70872
+ }
70873
+ }
70874
+ }
70875
+ return [block.id, tableBlock.rows.length, hash2.toString(16)].join("|");
69545
70876
  }
69546
70877
  return block.id;
69547
70878
  };
69548
70879
  const applyRunStyles = (element, run2, isLink = false) => {
69549
- if (run2.kind === "tab" || run2.kind === "image") {
70880
+ if (run2.kind === "tab" || run2.kind === "image" || run2.kind === "lineBreak") {
69550
70881
  return;
69551
70882
  }
69552
70883
  element.style.fontFamily = run2.fontFamily;
@@ -69578,6 +70909,13 @@ const applyRunStyles = (element, run2, isLink = false) => {
69578
70909
  element.style.textDecorationLine = decorations.join(" ");
69579
70910
  }
69580
70911
  };
70912
+ const getCommentHighlight = (run2) => {
70913
+ const comments = run2.comments;
70914
+ if (!comments || comments.length === 0) return void 0;
70915
+ const primary = comments[0];
70916
+ const base2 = primary.internal ? COMMENT_INTERNAL_COLOR : COMMENT_EXTERNAL_COLOR;
70917
+ return `${base2}${COMMENT_INACTIVE_ALPHA}`;
70918
+ };
69581
70919
  const applyRunDataAttributes = (element, dataAttrs) => {
69582
70920
  if (!dataAttrs) return;
69583
70921
  Object.entries(dataAttrs).forEach(([key2, value]) => {
@@ -69669,6 +71007,10 @@ const sliceRunsForLine = (block, line) => {
69669
71007
  result.push(run2);
69670
71008
  continue;
69671
71009
  }
71010
+ if (run2.kind === "lineBreak") {
71011
+ result.push(run2);
71012
+ continue;
71013
+ }
69672
71014
  const text = run2.text ?? "";
69673
71015
  const isFirstRun = runIndex === line.fromRun;
69674
71016
  const isLastRun = runIndex === line.toRun;
@@ -69691,7 +71033,8 @@ const sliceRunsForLine = (block, line) => {
69691
71033
  ...run2,
69692
71034
  text: slice2,
69693
71035
  pmStart: pmSliceStart,
69694
- pmEnd: pmSliceEnd
71036
+ pmEnd: pmSliceEnd,
71037
+ comments: run2.comments ? [...run2.comments] : void 0
69695
71038
  };
69696
71039
  result.push(sliced);
69697
71040
  }
@@ -69722,6 +71065,21 @@ const computeLinePmRange = (block, line) => {
69722
71065
  }
69723
71066
  continue;
69724
71067
  }
71068
+ if (run2.kind === "lineBreak") {
71069
+ const runPmStart2 = run2.pmStart ?? null;
71070
+ const runPmEnd = run2.pmEnd ?? null;
71071
+ if (runPmStart2 == null || runPmEnd == null) {
71072
+ continue;
71073
+ }
71074
+ if (pmStart == null) {
71075
+ pmStart = runPmStart2;
71076
+ }
71077
+ pmEnd = runPmEnd;
71078
+ if (runIndex === line.toRun) {
71079
+ break;
71080
+ }
71081
+ continue;
71082
+ }
69725
71083
  const text = run2.text ?? "";
69726
71084
  const runLength = text.length;
69727
71085
  const runPmStart = run2.pmStart ?? null;
@@ -69760,6 +71118,9 @@ const resolveRunText = (run2, context) => {
69760
71118
  if (run2.kind === "image") {
69761
71119
  return "";
69762
71120
  }
71121
+ if (run2.kind === "lineBreak") {
71122
+ return "";
71123
+ }
69763
71124
  if (!runToken) {
69764
71125
  return run2.text ?? "";
69765
71126
  }
@@ -69926,6 +71287,9 @@ function isTabRun(run2) {
69926
71287
  function isImageRun(run2) {
69927
71288
  return run2.kind === "image";
69928
71289
  }
71290
+ function isLineBreakRun(run2) {
71291
+ return run2.kind === "lineBreak";
71292
+ }
69929
71293
  async function measureBlock(block, constraints) {
69930
71294
  const normalized = normalizeConstraints(constraints);
69931
71295
  if (block.kind === "drawing") {
@@ -69963,7 +71327,7 @@ async function measureParagraphBlock(block, maxWidth) {
69963
71327
  const hanging = indent?.hanging ?? 0;
69964
71328
  const firstLineOffset = firstLine - hanging;
69965
71329
  const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
69966
- let availableWidth = Math.max(1, contentWidth - firstLineOffset);
71330
+ const initialAvailableWidth = Math.max(1, contentWidth - firstLineOffset);
69967
71331
  const tabStops = buildTabStopsPx(
69968
71332
  indent,
69969
71333
  block.attrs?.tabs,
@@ -69976,6 +71340,18 @@ async function measureParagraphBlock(block, maxWidth) {
69976
71340
  line.bars = barTabStops.map((stop) => ({ x: stop.pos }));
69977
71341
  }
69978
71342
  };
71343
+ const dropCapDescriptor = block.attrs?.dropCapDescriptor;
71344
+ let dropCapMeasure = null;
71345
+ if (dropCapDescriptor) {
71346
+ if (!dropCapDescriptor.run || !dropCapDescriptor.run.text || !dropCapDescriptor.lines) {
71347
+ console.warn("Invalid drop cap descriptor - missing required fields:", dropCapDescriptor);
71348
+ } else {
71349
+ const dropCapMeasured = measureDropCap(ctx2, dropCapDescriptor, spacing);
71350
+ dropCapMeasure = dropCapMeasured;
71351
+ dropCapDescriptor.measuredWidth = dropCapMeasured.width;
71352
+ dropCapDescriptor.measuredHeight = dropCapMeasured.height;
71353
+ }
71354
+ }
69979
71355
  if (block.runs.length === 0) {
69980
71356
  const metrics = calculateTypographyMetrics(12, spacing);
69981
71357
  const emptyLine = {
@@ -69995,6 +71371,13 @@ async function measureParagraphBlock(block, maxWidth) {
69995
71371
  };
69996
71372
  }
69997
71373
  let currentLine = null;
71374
+ const getEffectiveWidth = (baseWidth) => {
71375
+ if (dropCapMeasure && lines.length < dropCapMeasure.lines && dropCapMeasure.mode === "drop") {
71376
+ return Math.max(1, baseWidth - dropCapMeasure.width);
71377
+ }
71378
+ return baseWidth;
71379
+ };
71380
+ let lastFontSize = 12;
69998
71381
  let tabStopCursor = 0;
69999
71382
  let pendingTabAlignment = null;
70000
71383
  let lastAppliedTabAlign = null;
@@ -70031,6 +71414,47 @@ async function measureParagraphBlock(block, maxWidth) {
70031
71414
  };
70032
71415
  for (let runIndex = 0; runIndex < block.runs.length; runIndex++) {
70033
71416
  const run2 = block.runs[runIndex];
71417
+ if (isLineBreakRun(run2)) {
71418
+ if (currentLine) {
71419
+ const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
71420
+ const completedLine = {
71421
+ ...currentLine,
71422
+ ...metrics
71423
+ };
71424
+ addBarTabsToLine(completedLine);
71425
+ lines.push(completedLine);
71426
+ } else {
71427
+ const metrics = calculateTypographyMetrics(lastFontSize, spacing);
71428
+ const emptyLine = {
71429
+ fromRun: runIndex,
71430
+ fromChar: 0,
71431
+ toRun: runIndex,
71432
+ toChar: 0,
71433
+ width: 0,
71434
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
71435
+ segments: [],
71436
+ ...metrics
71437
+ };
71438
+ addBarTabsToLine(emptyLine);
71439
+ lines.push(emptyLine);
71440
+ }
71441
+ const hadPreviousLine = lines.length > 0;
71442
+ const nextLineMaxWidth = hadPreviousLine ? getEffectiveWidth(contentWidth) : getEffectiveWidth(initialAvailableWidth);
71443
+ currentLine = {
71444
+ fromRun: runIndex,
71445
+ fromChar: 0,
71446
+ toRun: runIndex,
71447
+ toChar: 0,
71448
+ width: 0,
71449
+ maxFontSize: lastFontSize,
71450
+ maxWidth: nextLineMaxWidth,
71451
+ segments: []
71452
+ };
71453
+ tabStopCursor = 0;
71454
+ pendingTabAlignment = null;
71455
+ lastAppliedTabAlign = null;
71456
+ continue;
71457
+ }
70034
71458
  if (isTabRun(run2)) {
70035
71459
  if (!currentLine) {
70036
71460
  currentLine = {
@@ -70041,7 +71465,7 @@ async function measureParagraphBlock(block, maxWidth) {
70041
71465
  width: 0,
70042
71466
  maxFontSize: 12,
70043
71467
  // Default font size for tabs
70044
- maxWidth: availableWidth,
71468
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
70045
71469
  segments: []
70046
71470
  };
70047
71471
  }
@@ -70086,7 +71510,7 @@ async function measureParagraphBlock(block, maxWidth) {
70086
71510
  width: imageWidth,
70087
71511
  maxFontSize: imageHeight,
70088
71512
  // Use image height for line height calculation
70089
- maxWidth: availableWidth,
71513
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
70090
71514
  segments: [
70091
71515
  {
70092
71516
  runIndex,
@@ -70096,7 +71520,6 @@ async function measureParagraphBlock(block, maxWidth) {
70096
71520
  }
70097
71521
  ]
70098
71522
  };
70099
- availableWidth = contentWidth;
70100
71523
  continue;
70101
71524
  }
70102
71525
  if (currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
@@ -70116,7 +71539,7 @@ async function measureParagraphBlock(block, maxWidth) {
70116
71539
  toChar: 1,
70117
71540
  width: imageWidth,
70118
71541
  maxFontSize: imageHeight,
70119
- maxWidth: contentWidth,
71542
+ maxWidth: getEffectiveWidth(contentWidth),
70120
71543
  segments: [
70121
71544
  {
70122
71545
  runIndex,
@@ -70126,7 +71549,6 @@ async function measureParagraphBlock(block, maxWidth) {
70126
71549
  }
70127
71550
  ]
70128
71551
  };
70129
- availableWidth = contentWidth;
70130
71552
  } else {
70131
71553
  currentLine.toRun = runIndex;
70132
71554
  currentLine.toChar = 1;
@@ -70142,6 +71564,7 @@ async function measureParagraphBlock(block, maxWidth) {
70142
71564
  }
70143
71565
  continue;
70144
71566
  }
71567
+ lastFontSize = run2.fontSize;
70145
71568
  const { font } = buildFontString(run2);
70146
71569
  const tabSegments = run2.text.split(" ");
70147
71570
  let charPosInRun = 0;
@@ -70176,7 +71599,7 @@ async function measureParagraphBlock(block, maxWidth) {
70176
71599
  toChar: wordEndNoSpace,
70177
71600
  width: wordOnlyWidth,
70178
71601
  maxFontSize: run2.fontSize,
70179
- maxWidth: availableWidth,
71602
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
70180
71603
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
70181
71604
  };
70182
71605
  const ls = run2.letterSpacing ?? 0;
@@ -70187,7 +71610,6 @@ async function measureParagraphBlock(block, maxWidth) {
70187
71610
  } else {
70188
71611
  charPosInRun = wordEndNoSpace;
70189
71612
  }
70190
- availableWidth = contentWidth;
70191
71613
  continue;
70192
71614
  }
70193
71615
  const isTocEntry = block.attrs?.isTocEntry;
@@ -70209,7 +71631,7 @@ async function measureParagraphBlock(block, maxWidth) {
70209
71631
  toChar: wordEndNoSpace,
70210
71632
  width: wordOnlyWidth,
70211
71633
  maxFontSize: run2.fontSize,
70212
- maxWidth: contentWidth,
71634
+ maxWidth: getEffectiveWidth(contentWidth),
70213
71635
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
70214
71636
  };
70215
71637
  if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth) {
@@ -70265,10 +71687,9 @@ async function measureParagraphBlock(block, maxWidth) {
70265
71687
  toChar: charPosInRun,
70266
71688
  width: 0,
70267
71689
  maxFontSize: run2.fontSize,
70268
- maxWidth: availableWidth,
71690
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
70269
71691
  segments: []
70270
71692
  };
70271
- availableWidth = contentWidth;
70272
71693
  }
70273
71694
  const originX = currentLine.width;
70274
71695
  const { target, nextIndex, stop } = getNextTabStopPx(currentLine.width, tabStops, tabStopCursor);
@@ -70341,7 +71762,8 @@ async function measureParagraphBlock(block, maxWidth) {
70341
71762
  kind: "paragraph",
70342
71763
  lines,
70343
71764
  totalHeight,
70344
- ...markerInfo ? { marker: markerInfo } : {}
71765
+ ...markerInfo ? { marker: markerInfo } : {},
71766
+ ...dropCapMeasure ? { dropCap: dropCapMeasure } : {}
70345
71767
  };
70346
71768
  }
70347
71769
  async function measureTableBlock(block, constraints) {
@@ -70621,7 +72043,7 @@ const getPrimaryRun = (paragraph) => {
70621
72043
  };
70622
72044
  };
70623
72045
  const measureRunWidth = (text, font, ctx2, run2) => {
70624
- const letterSpacing = run2.kind === "text" ? run2.letterSpacing || 0 : 0;
72046
+ const letterSpacing = run2.kind === "text" || run2.kind === void 0 ? run2.letterSpacing || 0 : 0;
70625
72047
  const width = getMeasuredTextWidth(text, font, letterSpacing, ctx2);
70626
72048
  return roundValue(width);
70627
72049
  };
@@ -70657,6 +72079,30 @@ const sanitizeDecimalSeparator = (value) => {
70657
72079
  if (value === ",") return ",";
70658
72080
  return DEFAULT_DECIMAL_SEPARATOR;
70659
72081
  };
72082
+ const DROP_CAP_PADDING_PX = 4;
72083
+ const measureDropCap = (ctx2, descriptor, spacing) => {
72084
+ const { run: run2, lines, mode } = descriptor;
72085
+ const { font } = buildFontString({
72086
+ fontFamily: run2.fontFamily,
72087
+ fontSize: run2.fontSize,
72088
+ bold: run2.bold,
72089
+ italic: run2.italic
72090
+ });
72091
+ ctx2.font = font;
72092
+ const metrics = ctx2.measureText(run2.text);
72093
+ const advanceWidth = metrics.width;
72094
+ const paintedWidth = (metrics.actualBoundingBoxLeft || 0) + (metrics.actualBoundingBoxRight || 0);
72095
+ const textWidth = Math.max(advanceWidth, paintedWidth);
72096
+ const width = roundValue(textWidth + DROP_CAP_PADDING_PX);
72097
+ const baseLineHeight = resolveLineHeight(spacing, run2.fontSize * 1.2);
72098
+ const height = roundValue(baseLineHeight * lines);
72099
+ return {
72100
+ width,
72101
+ height,
72102
+ lines,
72103
+ mode
72104
+ };
72105
+ };
70660
72106
  const resolveIndentLeft = (item) => {
70661
72107
  const indentLeft = sanitizePositive(item.paragraph.attrs?.indent?.left);
70662
72108
  if (indentLeft > 0) {
@@ -71733,10 +73179,7 @@ const _PresentationEditor = class _PresentationEditor2 extends EventEmitter$1 {
71733
73179
  const tr = __privateGet$1(this, _editor3).state.tr.setSelection(TextSelection$1.create(__privateGet$1(this, _editor3).state.doc, hit.pos));
71734
73180
  try {
71735
73181
  __privateGet$1(this, _editor3).view?.dispatch(tr);
71736
- } catch (error) {
71737
- if (process$1$1.env.NODE_ENV === "development") {
71738
- console.warn("[PresentationEditor] Failed to dispatch selection at position:", hit.pos, error);
71739
- }
73182
+ } catch {
71740
73183
  }
71741
73184
  }
71742
73185
  __privateMethod$1(this, _PresentationEditor_instances, scheduleSelectionUpdate_fn).call(this);
@@ -74061,10 +75504,10 @@ computeHeaderFooterCaretRect_fn = function(pos) {
74061
75504
  if (!lineInfo) return null;
74062
75505
  const { line, index: index2 } = lineInfo;
74063
75506
  const range2 = computeLinePmRange$1(block, line);
74064
- if (range2.pmStart == null) return null;
74065
- const charsInLine = Math.max(0, line.toChar - line.fromChar);
74066
- const offsetChars = Math.max(0, Math.min(charsInLine, pos - range2.pmStart));
74067
- const localX = hit.fragment.x + measureCharacterX(block, line, offsetChars);
75507
+ if (range2.pmStart == null || range2.pmEnd == null) return null;
75508
+ const pmCharsInLine = Math.max(1, range2.pmEnd - range2.pmStart);
75509
+ const pmOffset = Math.max(0, Math.min(pmCharsInLine, pos - range2.pmStart));
75510
+ const localX = hit.fragment.x + measureCharacterX(block, line, pmOffset);
74068
75511
  const lineOffset = __privateMethod$1(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, hit.fragment.fromLine, index2);
74069
75512
  const headerPageHeight = context.layout.pageSize?.h ?? context.region.height ?? 1;
74070
75513
  const headerLocalY = hit.pageIndex * headerPageHeight + (hit.fragment.y + lineOffset);
@@ -74204,23 +75647,34 @@ normalizeClientPoint_fn = function(clientX, clientY) {
74204
75647
  computeCaretLayoutRect_fn = function(pos) {
74205
75648
  const layout = __privateGet$1(this, _layoutState).layout;
74206
75649
  if (!layout) return null;
75650
+ const domResult = __privateMethod$1(this, _PresentationEditor_instances, computeCaretLayoutRectFromDOM_fn).call(this, pos);
75651
+ if (domResult) {
75652
+ return domResult;
75653
+ }
74207
75654
  const hit = getFragmentAtPosition(layout, __privateGet$1(this, _layoutState).blocks, __privateGet$1(this, _layoutState).measures, pos);
74208
- if (!hit) return null;
75655
+ if (!hit) {
75656
+ return null;
75657
+ }
74209
75658
  const block = hit.block;
74210
75659
  const measure = hit.measure;
75660
+ if (hit.fragment.kind === "table" && block?.kind === "table" && measure?.kind === "table") {
75661
+ return __privateMethod$1(this, _PresentationEditor_instances, computeTableCaretLayoutRect_fn).call(this, pos, hit.fragment, block, measure, hit.pageIndex);
75662
+ }
74211
75663
  if (!block || block.kind !== "paragraph" || measure?.kind !== "paragraph") return null;
74212
75664
  if (hit.fragment.kind !== "para") {
74213
75665
  return null;
74214
75666
  }
74215
75667
  const fragment = hit.fragment;
74216
75668
  const lineInfo = __privateMethod$1(this, _PresentationEditor_instances, findLineContainingPos_fn).call(this, block, measure, fragment.fromLine, fragment.toLine, pos);
74217
- if (!lineInfo) return null;
75669
+ if (!lineInfo) {
75670
+ return null;
75671
+ }
74218
75672
  const { line, index: index2 } = lineInfo;
74219
75673
  const range2 = computeLinePmRange$1(block, line);
74220
- if (range2.pmStart == null) return null;
74221
- const charsInLine = Math.max(0, line.toChar - line.fromChar);
74222
- const offsetChars = Math.max(0, Math.min(charsInLine, pos - range2.pmStart));
74223
- const localX = fragment.x + measureCharacterX(block, line, offsetChars);
75674
+ if (range2.pmStart == null || range2.pmEnd == null) return null;
75675
+ const pmCharsInLine = Math.max(1, range2.pmEnd - range2.pmStart);
75676
+ const pmOffset = Math.max(0, Math.min(pmCharsInLine, pos - range2.pmStart));
75677
+ const localX = fragment.x + measureCharacterX(block, line, pmOffset);
74224
75678
  const lineOffset = __privateMethod$1(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, fragment.fromLine, index2);
74225
75679
  const localY = fragment.y + lineOffset;
74226
75680
  return {
@@ -74230,17 +75684,167 @@ computeCaretLayoutRect_fn = function(pos) {
74230
75684
  height: line.lineHeight
74231
75685
  };
74232
75686
  };
75687
+ computeCaretLayoutRectFromDOM_fn = function(pos) {
75688
+ const zoom = __privateGet$1(this, _layoutOptions).zoom ?? 1;
75689
+ let targetPageEl = null;
75690
+ if (__privateGet$1(this, _layoutState).layout && __privateGet$1(this, _layoutState).blocks && __privateGet$1(this, _layoutState).measures) {
75691
+ const fragmentHit = getFragmentAtPosition(
75692
+ __privateGet$1(this, _layoutState).layout,
75693
+ __privateGet$1(this, _layoutState).blocks,
75694
+ __privateGet$1(this, _layoutState).measures,
75695
+ pos
75696
+ );
75697
+ if (fragmentHit) {
75698
+ const pageEl = __privateGet$1(this, _viewportHost).querySelector(
75699
+ `.superdoc-page[data-page-index="${fragmentHit.pageIndex}"]`
75700
+ );
75701
+ if (pageEl) {
75702
+ targetPageEl = pageEl;
75703
+ }
75704
+ }
75705
+ }
75706
+ const spanEls = Array.from(
75707
+ targetPageEl ? targetPageEl.querySelectorAll("span[data-pm-start][data-pm-end]") : __privateGet$1(this, _viewportHost).querySelectorAll("span[data-pm-start][data-pm-end]")
75708
+ );
75709
+ for (const spanEl of spanEls) {
75710
+ const pmStart = Number(spanEl.dataset.pmStart ?? "NaN");
75711
+ const pmEnd = Number(spanEl.dataset.pmEnd ?? "NaN");
75712
+ if (!Number.isFinite(pmStart) || !Number.isFinite(pmEnd)) continue;
75713
+ if (pos < pmStart || pos > pmEnd) continue;
75714
+ const pageEl = spanEl.closest(".superdoc-page");
75715
+ if (!pageEl) continue;
75716
+ const pageIndex = Number(pageEl.dataset.pageIndex ?? "0");
75717
+ const pageRect = pageEl.getBoundingClientRect();
75718
+ const textNode = spanEl.firstChild;
75719
+ if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
75720
+ const spanRect2 = spanEl.getBoundingClientRect();
75721
+ return {
75722
+ pageIndex,
75723
+ x: (spanRect2.left - pageRect.left) / zoom,
75724
+ y: (spanRect2.top - pageRect.top) / zoom,
75725
+ height: spanRect2.height / zoom
75726
+ };
75727
+ }
75728
+ const text = textNode.textContent ?? "";
75729
+ const charOffset = Math.max(0, Math.min(text.length, pos - pmStart));
75730
+ const range2 = document.createRange();
75731
+ try {
75732
+ range2.setStart(textNode, charOffset);
75733
+ range2.setEnd(textNode, charOffset);
75734
+ } catch (error) {
75735
+ if (process$1$1.env.NODE_ENV === "development") {
75736
+ console.warn("[PresentationEditor] Range.setStart/setEnd failed:", {
75737
+ error: error instanceof Error ? error.message : String(error),
75738
+ charOffset,
75739
+ textLength: text.length,
75740
+ pos,
75741
+ pmStart,
75742
+ pmEnd
75743
+ });
75744
+ }
75745
+ const spanRect2 = spanEl.getBoundingClientRect();
75746
+ return {
75747
+ pageIndex,
75748
+ x: (spanRect2.left - pageRect.left) / zoom,
75749
+ y: (spanRect2.top - pageRect.top) / zoom,
75750
+ height: spanRect2.height / zoom
75751
+ };
75752
+ }
75753
+ const rangeRect = range2.getBoundingClientRect();
75754
+ const spanRect = spanEl.getBoundingClientRect();
75755
+ const lineEl = spanEl.closest(".superdoc-line");
75756
+ const lineRect = lineEl ? lineEl.getBoundingClientRect() : spanRect;
75757
+ const caretHeight = spanRect.height;
75758
+ const verticalOffset = (lineRect.height - caretHeight) / 2;
75759
+ const caretY = lineRect.top + verticalOffset;
75760
+ return {
75761
+ pageIndex,
75762
+ x: (rangeRect.left - pageRect.left) / zoom,
75763
+ y: (caretY - pageRect.top) / zoom,
75764
+ height: caretHeight / zoom
75765
+ };
75766
+ }
75767
+ return null;
75768
+ };
75769
+ computeTableCaretLayoutRect_fn = function(pos, _fragment, _tableBlock, _tableMeasure, pageIndex) {
75770
+ const lineEls = Array.from(__privateGet$1(this, _viewportHost).querySelectorAll(".superdoc-line"));
75771
+ if (lineEls.length === 0) return null;
75772
+ for (const lineEl of lineEls) {
75773
+ const pmStart = Number(lineEl.dataset.pmStart ?? "NaN");
75774
+ const pmEnd = Number(lineEl.dataset.pmEnd ?? "NaN");
75775
+ if (!Number.isFinite(pmStart) || !Number.isFinite(pmEnd)) continue;
75776
+ if (pos < pmStart || pos > pmEnd) continue;
75777
+ const spanEls = Array.from(lineEl.querySelectorAll("span[data-pm-start]"));
75778
+ for (const spanEl of spanEls) {
75779
+ const spanStart = Number(spanEl.dataset.pmStart ?? "NaN");
75780
+ const spanEnd = Number(spanEl.dataset.pmEnd ?? "NaN");
75781
+ if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) continue;
75782
+ if (pos < spanStart || pos > spanEnd) continue;
75783
+ const textNode = spanEl.firstChild;
75784
+ if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
75785
+ const spanRect = spanEl.getBoundingClientRect();
75786
+ const viewportRect3 = __privateGet$1(this, _viewportHost).getBoundingClientRect();
75787
+ const zoom3 = __privateGet$1(this, _layoutOptions).zoom ?? 1;
75788
+ return {
75789
+ pageIndex,
75790
+ x: (spanRect.left - viewportRect3.left + __privateGet$1(this, _visibleHost).scrollLeft) / zoom3,
75791
+ y: (spanRect.top - viewportRect3.top + __privateGet$1(this, _visibleHost).scrollTop) / zoom3,
75792
+ height: spanRect.height / zoom3
75793
+ };
75794
+ }
75795
+ const text = textNode.textContent ?? "";
75796
+ const charOffset = Math.max(0, Math.min(text.length, pos - spanStart));
75797
+ const range2 = document.createRange();
75798
+ range2.setStart(textNode, charOffset);
75799
+ range2.setEnd(textNode, charOffset);
75800
+ const rangeRect = range2.getBoundingClientRect();
75801
+ const viewportRect2 = __privateGet$1(this, _viewportHost).getBoundingClientRect();
75802
+ const zoom2 = __privateGet$1(this, _layoutOptions).zoom ?? 1;
75803
+ const lineRect2 = lineEl.getBoundingClientRect();
75804
+ return {
75805
+ pageIndex,
75806
+ x: (rangeRect.left - viewportRect2.left + __privateGet$1(this, _visibleHost).scrollLeft) / zoom2,
75807
+ y: (lineRect2.top - viewportRect2.top + __privateGet$1(this, _visibleHost).scrollTop) / zoom2,
75808
+ height: lineRect2.height / zoom2
75809
+ };
75810
+ }
75811
+ const lineRect = lineEl.getBoundingClientRect();
75812
+ const viewportRect = __privateGet$1(this, _viewportHost).getBoundingClientRect();
75813
+ const zoom = __privateGet$1(this, _layoutOptions).zoom ?? 1;
75814
+ return {
75815
+ pageIndex,
75816
+ x: (lineRect.left - viewportRect.left + __privateGet$1(this, _visibleHost).scrollLeft) / zoom,
75817
+ y: (lineRect.top - viewportRect.top + __privateGet$1(this, _visibleHost).scrollTop) / zoom,
75818
+ height: lineRect.height / zoom
75819
+ };
75820
+ }
75821
+ return null;
75822
+ };
74233
75823
  findLineContainingPos_fn = function(block, measure, fromLine, toLine, pos) {
75824
+ const log2 = (...args) => {
75825
+ console.log("[LINE-SEARCH]", ...args);
75826
+ };
75827
+ log2("Searching for pos:", pos, "in lines", fromLine, "to", toLine);
74234
75828
  if (measure.kind !== "paragraph" || block.kind !== "paragraph") return null;
74235
75829
  for (let lineIndex = fromLine; lineIndex < toLine; lineIndex += 1) {
74236
75830
  const line = measure.lines[lineIndex];
74237
75831
  if (!line) continue;
74238
75832
  const range2 = computeLinePmRange$1(block, line);
75833
+ log2("Line", lineIndex, ":", {
75834
+ pmStart: range2.pmStart,
75835
+ pmEnd: range2.pmEnd,
75836
+ fromRun: line.fromRun,
75837
+ toRun: line.toRun,
75838
+ fromChar: line.fromChar,
75839
+ toChar: line.toChar
75840
+ });
74239
75841
  if (range2.pmStart == null || range2.pmEnd == null) continue;
74240
75842
  if (pos >= range2.pmStart && pos <= range2.pmEnd) {
75843
+ log2("Found line", lineIndex, "for pos", pos);
74241
75844
  return { line, index: lineIndex };
74242
75845
  }
74243
75846
  }
75847
+ log2("No line found for pos", pos);
74244
75848
  return null;
74245
75849
  };
74246
75850
  lineHeightBeforeIndex_fn = function(lines, fromLine, targetIndex) {
@@ -87649,6 +89253,49 @@ const ShapeGroup = Node$1.create({
87649
89253
  };
87650
89254
  }
87651
89255
  });
89256
+ const sharedAttributes = () => ({
89257
+ originalName: {
89258
+ default: null
89259
+ },
89260
+ originalXml: {
89261
+ default: null
89262
+ }
89263
+ });
89264
+ const hiddenRender = (type2) => ["sd-passthrough", { "data-sd-passthrough": type2, style: "display: none;" }];
89265
+ const PassthroughBlock = Node$1.create({
89266
+ name: "passthroughBlock",
89267
+ group: "block",
89268
+ atom: true,
89269
+ draggable: false,
89270
+ selectable: false,
89271
+ defining: true,
89272
+ parseDOM() {
89273
+ return [{ tag: 'sd-passthrough[data-sd-passthrough="block"]' }];
89274
+ },
89275
+ renderDOM() {
89276
+ return hiddenRender("block");
89277
+ },
89278
+ addAttributes() {
89279
+ return sharedAttributes();
89280
+ }
89281
+ });
89282
+ const PassthroughInline = Node$1.create({
89283
+ name: "passthroughInline",
89284
+ group: "inline",
89285
+ inline: true,
89286
+ atom: true,
89287
+ draggable: false,
89288
+ selectable: false,
89289
+ parseDOM() {
89290
+ return [{ tag: 'sd-passthrough[data-sd-passthrough="inline"]' }];
89291
+ },
89292
+ renderDOM() {
89293
+ return hiddenRender("inline");
89294
+ },
89295
+ addAttributes() {
89296
+ return sharedAttributes();
89297
+ }
89298
+ });
87652
89299
  const TextStyle = Mark2.create({
87653
89300
  name: "textStyle",
87654
89301
  addOptions() {
@@ -93559,7 +95206,9 @@ const getRichTextExtensions = () => {
93559
95206
  AiPlugin,
93560
95207
  Image,
93561
95208
  NodeResizer,
93562
- CustomSelection
95209
+ CustomSelection,
95210
+ PassthroughInline,
95211
+ PassthroughBlock
93563
95212
  ];
93564
95213
  };
93565
95214
  const getStarterExtensions = () => {
@@ -93631,7 +95280,9 @@ const getStarterExtensions = () => {
93631
95280
  CustomSelection,
93632
95281
  TextTransform,
93633
95282
  VectorShape,
93634
- ShapeGroup
95283
+ ShapeGroup,
95284
+ PassthroughInline,
95285
+ PassthroughBlock
93635
95286
  ];
93636
95287
  };
93637
95288
  const sanitizeNumber = (value, defaultNumber) => {
@@ -109555,7 +111206,7 @@ const _sfc_main$3 = {
109555
111206
  };
109556
111207
  }
109557
111208
  };
109558
- const TableResizeOverlay = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-d4258885"]]);
111209
+ const TableResizeOverlay = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-3f4a506b"]]);
109559
111210
  const _hoisted_1$2 = ["data-handle-position", "onMousedown"];
109560
111211
  const OVERLAY_EXPANSION_PX = 2e3;
109561
111212
  const RESIZE_HANDLE_SIZE_PX = 12;
@@ -110503,98 +112154,6 @@ const _sfc_main = {
110503
112154
  }
110504
112155
  };
110505
112156
  const SuperInput = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-4d5cff52"]]);
110506
- const additionalHandlers = Object.freeze({
110507
- "mc:AlternateContent": translator$1M,
110508
- "sd:pageReference": translator$6,
110509
- "sd:tableOfContents": translator$5,
110510
- "w:b": translator$20,
110511
- "w:bCs": translator$1$,
110512
- "w:bidiVisual": translator$q,
110513
- "w:bookmarkEnd": translator$7,
110514
- "w:bookmarkStart": translator$8,
110515
- "w:bottom": translator$1p,
110516
- "w:br": translator$23,
110517
- "w:cantSplit": translator$F,
110518
- "w:caps": translator$1R,
110519
- "w:cnfStyle": translator$1H,
110520
- "w:color": translator$1W,
110521
- "w:divId": translator$1F,
110522
- "w:drawing": translator$s,
110523
- "w:end": translator$X,
110524
- "w:gridAfter": translator$E,
110525
- "w:gridBefore": translator$D,
110526
- "w:gridCol": translator$b,
110527
- "w:hidden": translator$C,
110528
- "w:highlight": translator$22,
110529
- "w:hyperlink": translator$10,
110530
- "w:i": translator$1_,
110531
- "w:insideH": translator$V,
110532
- "w:insideV": translator$U,
110533
- "w:jc": translator$1C,
110534
- "w:left": translator$1n,
110535
- "w:p": translator$11,
110536
- "w:r": translator$$,
110537
- "w:rFonts": translator$1V,
110538
- "w:rPr": translator$1N,
110539
- "w:rStyle": translator$1U,
110540
- "w:right": translator$1l,
110541
- "w:sdt": translator$r,
110542
- "w:shd": translator$1Q,
110543
- "w:start": translator$T,
110544
- "w:strike": translator$1Y,
110545
- "w:sz": translator$1T,
110546
- "w:szCs": translator$1S,
110547
- "w:tab": translator$21,
110548
- "w:tbl": translator$9,
110549
- "w:tblBorders": translator$e,
110550
- "w:tblCaption": translator$p,
110551
- "w:tblCellMar": translator$d,
110552
- "w:tblCellSpacing": translator$B,
110553
- "w:tblDescription": translator$o,
110554
- "w:tblGrid": translator$a,
110555
- "w:tblHeader": translator$A,
110556
- "w:tblInd": translator$n,
110557
- "w:tblLayout": translator$m,
110558
- "w:tblLook": translator$l,
110559
- "w:tblOverlap": translator$k,
110560
- "w:tblPr": translator$c,
110561
- "w:tblStyle": translator$j,
110562
- "w:tblStyleColBandSize": translator$i,
110563
- "w:tblStyleRowBandSize": translator$h,
110564
- "w:tblW": translator$g,
110565
- "w:tblpPr": translator$f,
110566
- "w:tc": translator$G,
110567
- "w:top": translator$1j,
110568
- "w:tr": translator$v,
110569
- "w:trHeight": translator$z,
110570
- "w:trPr": translator$w,
110571
- "w:u": translator$1Z,
110572
- "w:wAfter": translator$y,
110573
- "w:wBefore": translator$x,
110574
- "wp:anchor": translator$u,
110575
- "wp:inline": translator$t,
110576
- "w:commentRangeStart": commentRangeStartTranslator,
110577
- "w:commentRangeEnd": commentRangeEndTranslator,
110578
- "w:vMerge": translator$Y,
110579
- "w:gridSpan": translator$Z,
110580
- "w:vAlign": translator$L,
110581
- "w:noWrap": translator$O,
110582
- "w:tcFitText": translator$M,
110583
- "w:tcW": translator$_,
110584
- "w:hideMark": translator$K,
110585
- "w:textDirection": translator$17,
110586
- "w:tl2br": translator$R,
110587
- "w:tr2bl": translator$Q,
110588
- "w:header": translator$J,
110589
- "w:headers": translator$I,
110590
- "w:tcBorders": translator$P,
110591
- "w:tcMar": translator$N,
110592
- "w:tcPr": translator$H
110593
- });
110594
- const baseHandlers = {
110595
- ...additionalHandlers
110596
- };
110597
- const registeredHandlers = Object.freeze(baseHandlers);
110598
112157
  const Extensions = {
110599
112158
  Node: Node$1,
110600
112159
  Attribute: Attribute2,