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
@@ -18984,7 +18984,6 @@
18984
18984
  }
18985
18985
  }
18986
18986
  });
18987
- console.log("subs:", subs);
18988
18987
  return subs;
18989
18988
  };
18990
18989
  function decode$D(params2) {
@@ -20143,6 +20142,51 @@
20143
20142
  if (value === "0" || value === "false" || value === "off") return "0";
20144
20143
  return "1";
20145
20144
  }
20145
+ function parseProperties(node2) {
20146
+ const marks = [];
20147
+ const unknownMarks = [];
20148
+ const { attributes = {}, elements = [] } = node2;
20149
+ const { nodes, paragraphProperties = {}, runProperties = {} } = splitElementsAndProperties(elements);
20150
+ const hasRun = elements.find((element2) => element2.name === "w:r");
20151
+ if (hasRun) paragraphProperties.elements = paragraphProperties?.elements?.filter((el) => el.name !== "w:rPr");
20152
+ if (runProperties && runProperties?.elements?.length) {
20153
+ marks.push(...parseMarks(runProperties, unknownMarks));
20154
+ }
20155
+ if (paragraphProperties && paragraphProperties.elements?.length) {
20156
+ const disallowedParagraphProperties = ["w:u"];
20157
+ const filteredParagraphProperties = {
20158
+ ...paragraphProperties,
20159
+ elements: paragraphProperties.elements?.filter((el) => !disallowedParagraphProperties.includes(el.name))
20160
+ };
20161
+ marks.push(...parseMarks(filteredParagraphProperties, unknownMarks));
20162
+ }
20163
+ marks.push(...handleStyleChangeMarks(runProperties, marks));
20164
+ if (paragraphProperties && paragraphProperties.elements?.length) {
20165
+ attributes["paragraphProperties"] = paragraphProperties;
20166
+ }
20167
+ if (marks && node2.name === "w:p") {
20168
+ marks.forEach((mark2) => {
20169
+ const attrValue = Object.keys(mark2.attrs ?? {})[0];
20170
+ if (attrValue) {
20171
+ const value = mark2.attrs[attrValue];
20172
+ attributes[attrValue] = value;
20173
+ }
20174
+ });
20175
+ }
20176
+ return { elements: nodes, attributes, marks, unknownMarks };
20177
+ }
20178
+ function splitElementsAndProperties(elements) {
20179
+ const pPr = elements.find((el) => el.name === "w:pPr");
20180
+ const rPr = elements.find((el) => el.name === "w:rPr");
20181
+ const sectPr = elements.find((el) => el.name === "w:sectPr");
20182
+ const els = elements.filter((el) => el.name !== "w:pPr" && el.name !== "w:rPr" && el.name !== "w:sectPr");
20183
+ return {
20184
+ nodes: els,
20185
+ paragraphProperties: pPr,
20186
+ runProperties: rPr,
20187
+ sectionProperties: sectPr
20188
+ };
20189
+ }
20146
20190
  function getTableStyleId(path2) {
20147
20191
  const tbl = path2.find((ancestor) => ancestor.name === "w:tbl");
20148
20192
  if (!tbl) {
@@ -20167,13 +20211,6 @@
20167
20211
  if (pPr) {
20168
20212
  inlineParagraphProperties = translator$12.encode({ ...params2, nodes: [pPr] }) || {};
20169
20213
  }
20170
- const handleStandardNode2 = nodeListHandler.handlerEntities.find(
20171
- (e) => e.handlerName === "standardNodeHandler"
20172
- )?.handler;
20173
- if (!handleStandardNode2) {
20174
- console.error("Standard node handler not found");
20175
- return null;
20176
- }
20177
20214
  const insideTable = (params2.path || []).some((ancestor) => ancestor.name === "w:tc");
20178
20215
  const tableStyleId = getTableStyleId(params2.path || []);
20179
20216
  const resolvedParagraphProperties = resolveParagraphProperties(
@@ -20182,15 +20219,29 @@
20182
20219
  insideTable,
20183
20220
  tableStyleId
20184
20221
  );
20185
- const updatedParams = {
20186
- ...params2,
20187
- nodes: [node2],
20188
- extraParams: { ...params2.extraParams, paragraphProperties: resolvedParagraphProperties }
20189
- };
20190
- const result = handleStandardNode2(updatedParams);
20191
- if (result.nodes.length === 1) {
20192
- schemaNode = result.nodes[0];
20222
+ const { elements = [], attributes = {}, marks = [] } = parseProperties(node2, params2.docx);
20223
+ const childContent = [];
20224
+ if (elements.length) {
20225
+ const updatedElements = elements.map((el) => {
20226
+ if (!el.marks) el.marks = [];
20227
+ el.marks.push(...marks);
20228
+ return el;
20229
+ });
20230
+ const childParams = {
20231
+ ...params2,
20232
+ nodes: updatedElements,
20233
+ extraParams: { ...params2.extraParams, paragraphProperties: resolvedParagraphProperties },
20234
+ path: [...params2.path || [], node2]
20235
+ };
20236
+ const translatedChildren = nodeListHandler.handler(childParams);
20237
+ childContent.push(...translatedChildren);
20193
20238
  }
20239
+ schemaNode = {
20240
+ type: "paragraph",
20241
+ content: childContent,
20242
+ attrs: { ...attributes },
20243
+ marks: []
20244
+ };
20194
20245
  schemaNode.type = "paragraph";
20195
20246
  schemaNode.attrs.paragraphProperties = inlineParagraphProperties;
20196
20247
  schemaNode.attrs.rsidRDefault = node2.attributes?.["w:rsidRDefault"];
@@ -21838,13 +21889,14 @@
21838
21889
  nodes: node2.elements,
21839
21890
  path: [...params2.path || [], node2]
21840
21891
  });
21892
+ const normalizedContent = normalizeDocPartContent(translatedContent);
21841
21893
  const sdtPr = params2.extraParams.sdtPr;
21842
21894
  const id = sdtPr.elements?.find((el) => el.name === "w:id")?.attributes["w:val"] || "";
21843
21895
  const docPartObj = sdtPr?.elements.find((el) => el.name === "w:docPartObj");
21844
21896
  const docPartUnique = docPartObj?.elements.some((el) => el.name === "w:docPartUnique") ?? false;
21845
21897
  const result = {
21846
21898
  type: "documentPartObject",
21847
- content: translatedContent,
21899
+ content: normalizedContent,
21848
21900
  attrs: {
21849
21901
  id,
21850
21902
  docPartGallery: "Table of Contents",
@@ -21884,6 +21936,22 @@
21884
21936
  const validGalleryTypeMap = {
21885
21937
  "Table of Contents": tableOfContentsHandler
21886
21938
  };
21939
+ const inlineNodeTypes = /* @__PURE__ */ new Set(["bookmarkStart", "bookmarkEnd"]);
21940
+ const wrapInlineNode = (node2) => ({
21941
+ type: "paragraph",
21942
+ content: [node2]
21943
+ });
21944
+ const normalizeDocPartContent = (nodes = []) => {
21945
+ const normalized = [];
21946
+ nodes.forEach((node2) => {
21947
+ if (inlineNodeTypes.has(node2?.type)) {
21948
+ normalized.push(wrapInlineNode(node2));
21949
+ } else {
21950
+ normalized.push(node2);
21951
+ }
21952
+ });
21953
+ return normalized;
21954
+ };
21887
21955
  function handleDocumentSectionNode$1(params2) {
21888
21956
  const { nodes, nodeListHandler } = params2;
21889
21957
  if (nodes.length === 0 || nodes[0].name !== "w:sdt") {
@@ -24962,7 +25030,8 @@
24962
25030
  horizontal: positionHValue,
24963
25031
  top: positionVValue
24964
25032
  };
24965
- const simplePos = node2.elements.find((el) => el.name === "wp:simplePos");
25033
+ const useSimplePos = attributes["simplePos"] === "1" || attributes["simplePos"] === 1;
25034
+ const simplePos = useSimplePos ? node2.elements.find((el) => el.name === "wp:simplePos") : null;
24966
25035
  const wrapNode = isAnchor ? node2.elements.find(
24967
25036
  (el) => ["wp:wrapNone", "wp:wrapSquare", "wp:wrapThrough", "wp:wrapTight", "wp:wrapTopAndBottom"].includes(el.name)
24968
25037
  ) : null;
@@ -32730,15 +32799,26 @@ Please report this to https://github.com/markedjs/marked.`, e) {
32730
32799
  }
32731
32800
  };
32732
32801
  };
32733
- const getConfig = (type2) => ({
32734
- xmlName: `${XML_NODE_NAME$7}${type2}`,
32735
- sdNodeOrKeyName: `${SD_NODE_NAME$6}${type2}`,
32736
- type: NodeTranslator.translatorTypes.NODE,
32737
- encode: () => {
32738
- },
32739
- decode: decode$7,
32740
- attributes: [attrConfig]
32741
- });
32802
+ const getConfig = (type2) => {
32803
+ const sdName = `${SD_NODE_NAME$6}${type2}`;
32804
+ const isStart = type2 === "Start";
32805
+ return {
32806
+ xmlName: `${XML_NODE_NAME$7}${type2}`,
32807
+ sdNodeOrKeyName: sdName,
32808
+ type: NodeTranslator.translatorTypes.NODE,
32809
+ encode: ({ nodes }) => {
32810
+ const node2 = nodes?.[0];
32811
+ if (!node2) return void 0;
32812
+ const attrs = node2.attributes ? { ...node2.attributes } : {};
32813
+ return {
32814
+ type: isStart ? "commentRangeStart" : "commentRangeEnd",
32815
+ attrs
32816
+ };
32817
+ },
32818
+ decode: decode$7,
32819
+ attributes: [attrConfig]
32820
+ };
32821
+ };
32742
32822
  const commentRangeStartTranslator = NodeTranslator.from(getConfig("Start"));
32743
32823
  const commentRangeEndTranslator = NodeTranslator.from(getConfig("End"));
32744
32824
  const XML_NODE_NAME$6 = "sd:pageReference";
@@ -33462,127 +33542,224 @@ Please report this to https://github.com/markedjs/marked.`, e) {
33462
33542
  handlerName: "sdtNodeHandler",
33463
33543
  handler: handleSdtNode
33464
33544
  };
33465
- function parseProperties(node2) {
33466
- const marks = [];
33467
- const unknownMarks = [];
33468
- const { attributes = {}, elements = [] } = node2;
33469
- const { nodes, paragraphProperties = {}, runProperties = {} } = splitElementsAndProperties(elements);
33470
- const hasRun = elements.find((element2) => element2.name === "w:r");
33471
- if (hasRun) paragraphProperties.elements = paragraphProperties?.elements?.filter((el) => el.name !== "w:rPr");
33472
- if (runProperties && runProperties?.elements?.length) {
33473
- marks.push(...parseMarks(runProperties, unknownMarks));
33474
- }
33475
- if (paragraphProperties && paragraphProperties.elements?.length) {
33476
- const disallowedParagraphProperties = ["w:u"];
33477
- const filteredParagraphProperties = {
33478
- ...paragraphProperties,
33479
- elements: paragraphProperties.elements?.filter((el) => !disallowedParagraphProperties.includes(el.name))
33480
- };
33481
- marks.push(...parseMarks(filteredParagraphProperties, unknownMarks));
33482
- }
33483
- marks.push(...handleStyleChangeMarks(runProperties, marks));
33484
- if (paragraphProperties && paragraphProperties.elements?.length) {
33485
- attributes["paragraphProperties"] = paragraphProperties;
33545
+ const translatorList = Array.from(
33546
+ /* @__PURE__ */ new Set([
33547
+ translator$1M,
33548
+ translator$6,
33549
+ translator$5,
33550
+ translator$4,
33551
+ translator$3,
33552
+ translator$1L,
33553
+ translator$1K,
33554
+ translator$1J,
33555
+ translator$20,
33556
+ translator$1r,
33557
+ translator$1$,
33558
+ translator$q,
33559
+ translator$7,
33560
+ translator$8,
33561
+ translator$1p,
33562
+ translator$23,
33563
+ translator$F,
33564
+ translator$1R,
33565
+ translator$1H,
33566
+ translator$1W,
33567
+ translator$1G,
33568
+ translator$2,
33569
+ translator$1F,
33570
+ translator$s,
33571
+ translator$1X,
33572
+ translator$X,
33573
+ translator$1E,
33574
+ translator$E,
33575
+ translator$D,
33576
+ translator$b,
33577
+ translator$Z,
33578
+ translator$J,
33579
+ translator$I,
33580
+ translator$C,
33581
+ translator$K,
33582
+ translator$22,
33583
+ translator$10,
33584
+ translator$1_,
33585
+ translator$1x,
33586
+ translator$1D,
33587
+ translator$1w,
33588
+ translator$V,
33589
+ translator$U,
33590
+ translator$1C,
33591
+ translator$1B,
33592
+ translator$1A,
33593
+ translator$1z,
33594
+ translator$1P,
33595
+ translator$1n,
33596
+ translator$1y,
33597
+ translator$O,
33598
+ translator$1v,
33599
+ translator$1u,
33600
+ translator$1t,
33601
+ translator$1s,
33602
+ translator$11,
33603
+ translator$1f,
33604
+ translator$1h,
33605
+ translator$12,
33606
+ translator$1g,
33607
+ translator$$,
33608
+ translator$1V,
33609
+ translator$1N,
33610
+ translator$1U,
33611
+ translator$1l,
33612
+ translator$r,
33613
+ translator$1Q,
33614
+ translator$1e,
33615
+ translator$1d,
33616
+ translator$1c,
33617
+ translator$1b,
33618
+ translator$1a,
33619
+ translator$T,
33620
+ translator$1Y,
33621
+ translator$1T,
33622
+ translator$1S,
33623
+ translator$1,
33624
+ translator$21,
33625
+ translator$19,
33626
+ translator$9,
33627
+ translator$e,
33628
+ translator$p,
33629
+ translator$d,
33630
+ translator$B,
33631
+ translator$o,
33632
+ translator$a,
33633
+ translator$A,
33634
+ translator$n,
33635
+ translator$m,
33636
+ translator$l,
33637
+ translator$k,
33638
+ translator$c,
33639
+ translator$j,
33640
+ translator$i,
33641
+ translator$h,
33642
+ translator$g,
33643
+ translator$f,
33644
+ translator$G,
33645
+ translator$P,
33646
+ translator$M,
33647
+ translator$N,
33648
+ translator$H,
33649
+ translator$_,
33650
+ translator$17,
33651
+ translator$R,
33652
+ translator$v,
33653
+ translator$Q,
33654
+ translator$z,
33655
+ translator$w,
33656
+ translator$18,
33657
+ translator$16,
33658
+ translator$15,
33659
+ translator$1j,
33660
+ translator$1Z,
33661
+ translator$L,
33662
+ translator$Y,
33663
+ translator$y,
33664
+ translator$x,
33665
+ translator$14,
33666
+ translator$13,
33667
+ translator$u,
33668
+ translator$t,
33669
+ commentRangeStartTranslator,
33670
+ commentRangeEndTranslator
33671
+ ])
33672
+ );
33673
+ const additionalHandlers = Object.freeze(
33674
+ translatorList.reduce((acc, translator2) => {
33675
+ const key2 = translator2?.xmlName;
33676
+ if (!key2) return acc;
33677
+ acc[key2] = translator2;
33678
+ return acc;
33679
+ }, {})
33680
+ );
33681
+ const baseHandlers = {
33682
+ ...additionalHandlers
33683
+ };
33684
+ const registeredHandlers = Object.freeze(baseHandlers);
33685
+ const INLINE_PARENT_NAMES = /* @__PURE__ */ new Set([
33686
+ "w:r",
33687
+ "w:hyperlink",
33688
+ "w:smartTag",
33689
+ "w:fldSimple",
33690
+ "w:proofErr",
33691
+ "w:del",
33692
+ "w:ins"
33693
+ ]);
33694
+ const INLINE_NODE_NAMES = /* @__PURE__ */ new Set([
33695
+ "m:oMathPara",
33696
+ "m:oMath",
33697
+ "m:t",
33698
+ "m:r",
33699
+ "m:ctrlPr",
33700
+ "m:sSupPr",
33701
+ "m:e",
33702
+ "m:sup",
33703
+ "m:sSup"
33704
+ ]);
33705
+ const BLOCK_BOUNDARY_NAMES = /* @__PURE__ */ new Set(["w:p", "w:body", "w:tbl", "w:tc", "w:tr"]);
33706
+ const isInlineContext = (path2 = [], currentNodeName) => {
33707
+ if (currentNodeName && INLINE_NODE_NAMES.has(currentNodeName)) {
33708
+ return true;
33486
33709
  }
33487
- if (marks && node2.name === "w:p") {
33488
- marks.forEach((mark2) => {
33489
- const attrValue = Object.keys(mark2.attrs ?? {})[0];
33490
- if (attrValue) {
33491
- const value = mark2.attrs[attrValue];
33492
- attributes[attrValue] = value;
33493
- }
33494
- });
33710
+ if (!Array.isArray(path2) || path2.length === 0) return false;
33711
+ for (let i2 = path2.length - 1; i2 >= 0; i2--) {
33712
+ const ancestorName = path2[i2]?.name;
33713
+ if (!ancestorName) continue;
33714
+ if (INLINE_NODE_NAMES.has(ancestorName) || INLINE_PARENT_NAMES.has(ancestorName)) {
33715
+ return true;
33716
+ }
33717
+ if (BLOCK_BOUNDARY_NAMES.has(ancestorName)) {
33718
+ return false;
33719
+ }
33495
33720
  }
33496
- return { elements: nodes, attributes, marks, unknownMarks };
33497
- }
33498
- function splitElementsAndProperties(elements) {
33499
- const pPr = elements.find((el) => el.name === "w:pPr");
33500
- const rPr = elements.find((el) => el.name === "w:rPr");
33501
- const sectPr = elements.find((el) => el.name === "w:sectPr");
33502
- const els = elements.filter((el) => el.name !== "w:pPr" && el.name !== "w:rPr" && el.name !== "w:sectPr");
33503
- return {
33504
- nodes: els,
33505
- paragraphProperties: pPr,
33506
- runProperties: rPr,
33507
- sectionProperties: sectPr
33508
- };
33509
- }
33510
- function getElementName(element2) {
33511
- return SuperConverter.allowedElements[element2.name || element2.type];
33512
- }
33513
- const isPropertiesElement = (element2) => {
33514
- return !!SuperConverter.propertyTypes[element2.name || element2.type];
33721
+ return false;
33515
33722
  };
33516
- const handleStandardNode = (params2) => {
33517
- const { nodes, docx, nodeListHandler } = params2;
33518
- if (!nodes || nodes.length === 0) {
33519
- return { nodes: [], consumed: 0 };
33520
- }
33723
+ const handlePassthroughNode = (params2) => {
33724
+ const { nodes = [] } = params2;
33521
33725
  const node2 = nodes[0];
33522
- const { name } = node2;
33523
- const { attributes, elements, marks = [] } = parseProperties(node2);
33524
- if (name === "w:sdt") {
33726
+ if (!node2) return { nodes: [], consumed: 0 };
33727
+ if (registeredHandlers[node2.name]) {
33525
33728
  return { nodes: [], consumed: 0 };
33526
33729
  }
33527
- if (isPropertiesElement(node2)) {
33528
- return {
33529
- nodes: [
33530
- {
33531
- type: getElementName(node2),
33532
- attrs: { ...attributes },
33533
- marks: []
33534
- }
33535
- ],
33536
- consumed: 0
33537
- };
33538
- }
33539
- if (!getElementName(node2)) {
33540
- return {
33541
- nodes: [
33542
- {
33543
- type: name,
33544
- content: elements,
33545
- attrs: { ...attributes },
33546
- marks
33547
- }
33548
- ],
33549
- consumed: 0,
33550
- unhandled: true
33551
- };
33552
- }
33553
- const content2 = [];
33554
- const parentStyleId = getParentStyleId(node2);
33555
- if (elements && elements.length) {
33556
- const updatedElements = elements.map((el) => {
33557
- if (!el.marks) el.marks = [];
33558
- el.marks.push(...marks);
33559
- return el;
33560
- });
33730
+ const originalXml = carbonCopy(node2) || {};
33731
+ const originalElementsSource = originalXml.elements;
33732
+ const originalElements = originalElementsSource ? carbonCopy(originalElementsSource) : [];
33733
+ const childElements = Array.isArray(node2.elements) ? node2.elements : [];
33734
+ let childContent = [];
33735
+ if (childElements.length && params2.nodeListHandler?.handler) {
33561
33736
  const childParams = {
33562
33737
  ...params2,
33563
- nodes: updatedElements,
33564
- parentStyleId,
33738
+ nodes: childElements,
33565
33739
  path: [...params2.path || [], node2]
33566
33740
  };
33567
- const childContent = nodeListHandler.handler(childParams);
33568
- content2.push(...childContent);
33741
+ childContent = params2.nodeListHandler.handler(childParams) || [];
33569
33742
  }
33570
- const resultNode = {
33571
- type: getElementName(node2),
33572
- content: content2,
33573
- attrs: { ...attributes },
33574
- marks: []
33743
+ if (originalElements?.length) {
33744
+ originalXml.elements = originalElements;
33745
+ }
33746
+ const passthroughNode = {
33747
+ type: isInlineContext(params2.path, node2.name) ? "passthroughInline" : "passthroughBlock",
33748
+ attrs: {
33749
+ originalName: node2.name,
33750
+ originalXml
33751
+ },
33752
+ marks: [],
33753
+ content: childContent
33754
+ };
33755
+ return {
33756
+ nodes: [passthroughNode],
33757
+ consumed: 1
33575
33758
  };
33576
- return { nodes: [resultNode], consumed: 1 };
33577
- };
33578
- const getParentStyleId = (node2) => {
33579
- const pPr = node2.elements?.find((el) => el.name === "w:pPr");
33580
- const styleTag = pPr?.elements?.find((el) => el.name === "w:pStyle");
33581
- return styleTag ? styleTag.attributes["w:val"] : null;
33582
33759
  };
33583
- const standardNodeHandlerEntity = {
33584
- handlerName: "standardNodeHandler",
33585
- handler: handleStandardNode
33760
+ const passthroughNodeHandlerEntity = {
33761
+ handlerName: "passthroughNodeHandler",
33762
+ handler: handlePassthroughNode
33586
33763
  };
33587
33764
  const handler = (params2) => {
33588
33765
  const { nodes } = params2;
@@ -33606,13 +33783,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
33606
33783
  return { nodes: [], consumed: 0 };
33607
33784
  }
33608
33785
  const node2 = nodes[0];
33609
- const handleStandardNode2 = nodeListHandler.handlerEntities.find(
33610
- (e) => e.handlerName === "standardNodeHandler"
33611
- )?.handler;
33612
- if (!handleStandardNode2) {
33613
- console.error("Standard node handler not found");
33614
- return { nodes: [], consumed: 0 };
33615
- }
33616
33786
  const customMarks = editor?.extensionService?.extensions?.filter((e) => e.isExternal === true) || [];
33617
33787
  const bookmarkName = node2.attributes["w:name"]?.split(";")[0];
33618
33788
  const customMark = customMarks.find((mark2) => mark2.name === bookmarkName);
@@ -33621,7 +33791,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
33621
33791
  (n) => n.name === "w:bookmarkEnd" && n.attributes["w:id"] === node2.attributes["w:id"]
33622
33792
  );
33623
33793
  const textNodes = nodes.slice(1, bookmarkEndIndex);
33624
- const nodeListHandler2 = params2.nodeListHandler;
33625
33794
  const attrs = {};
33626
33795
  node2.attributes["w:name"].split(";").forEach((name) => {
33627
33796
  const [key2, value] = name.split("=");
@@ -33629,7 +33798,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
33629
33798
  attrs[key2] = value;
33630
33799
  }
33631
33800
  });
33632
- const translatedText = nodeListHandler2.handler({
33801
+ const translatedText = nodeListHandler.handler({
33633
33802
  ...params2,
33634
33803
  nodes: textNodes,
33635
33804
  path: [...params2.path || [], node2]
@@ -33645,13 +33814,11 @@ Please report this to https://github.com/markedjs/marked.`, e) {
33645
33814
  consumed: translatedText.length + 2
33646
33815
  };
33647
33816
  }
33648
- const updatedParams = { ...params2, nodes: [node2] };
33649
- const result = handleStandardNode2(updatedParams);
33650
- if (result.nodes.length === 1) {
33651
- result.nodes[0].attrs.name = node2.attributes["w:name"];
33652
- result.nodes[0].attrs.id = node2.attributes["w:id"];
33817
+ const encoded = translator$8.encode({ ...params2, nodes: [node2] });
33818
+ if (!encoded) {
33819
+ return { nodes: [], consumed: 0 };
33653
33820
  }
33654
- return result;
33821
+ return { nodes: [encoded], consumed: 1 };
33655
33822
  };
33656
33823
  const handleBookmarkStartNode = (params2) => {
33657
33824
  const { nodes } = params2;
@@ -34298,18 +34465,22 @@ Please report this to https://github.com/markedjs/marked.`, e) {
34298
34465
  const preProcessNodesForFldChar = (nodes = [], docx) => {
34299
34466
  const processedNodes = [];
34300
34467
  let collectedNodesStack = [];
34468
+ let rawCollectedNodesStack = [];
34301
34469
  let currentFieldStack = [];
34302
34470
  let unpairedEnd = null;
34303
34471
  let collecting = false;
34304
34472
  const finalizeField = () => {
34305
34473
  if (collecting) {
34306
34474
  const collectedNodes = collectedNodesStack.pop().filter((n) => n !== null);
34475
+ const rawCollectedNodes = rawCollectedNodesStack.pop().filter((n) => n !== null);
34307
34476
  const currentField = currentFieldStack.pop();
34308
- const combined = _processCombinedNodesForFldChar(collectedNodes, currentField.instrText.trim(), docx);
34477
+ const combinedResult = _processCombinedNodesForFldChar(collectedNodes, currentField.instrText.trim(), docx);
34478
+ const outputNodes = combinedResult.handled ? combinedResult.nodes : rawCollectedNodes;
34309
34479
  if (collectedNodesStack.length === 0) {
34310
- processedNodes.push(...combined);
34480
+ processedNodes.push(...outputNodes);
34311
34481
  } else {
34312
- collectedNodesStack[collectedNodesStack.length - 1].push(...combined);
34482
+ collectedNodesStack[collectedNodesStack.length - 1].push(...outputNodes);
34483
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(...outputNodes);
34313
34484
  }
34314
34485
  } else {
34315
34486
  unpairedEnd = true;
@@ -34321,18 +34492,26 @@ Please report this to https://github.com/markedjs/marked.`, e) {
34321
34492
  const instrTextEl = node2.elements?.find((el) => el.name === "w:instrText");
34322
34493
  collecting = collectedNodesStack.length > 0;
34323
34494
  if (fldType === "begin") {
34324
- collectedNodesStack.push([null]);
34495
+ collectedNodesStack.push([]);
34496
+ rawCollectedNodesStack.push([node2]);
34325
34497
  currentFieldStack.push({ instrText: "" });
34326
34498
  continue;
34327
34499
  }
34328
34500
  if (instrTextEl && collecting && currentFieldStack.length > 0) {
34501
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node2);
34329
34502
  currentFieldStack[currentFieldStack.length - 1].instrText += (instrTextEl.elements?.[0]?.text || "") + " ";
34330
34503
  continue;
34331
34504
  }
34332
34505
  if (fldType === "end") {
34506
+ if (collecting) {
34507
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node2);
34508
+ }
34333
34509
  finalizeField();
34334
34510
  continue;
34335
34511
  } else if (fldType === "separate") {
34512
+ if (collecting) {
34513
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node2);
34514
+ }
34336
34515
  continue;
34337
34516
  }
34338
34517
  if (Array.isArray(node2.elements)) {
@@ -34342,17 +34521,21 @@ Please report this to https://github.com/markedjs/marked.`, e) {
34342
34521
  childResult.unpairedBegin.forEach((pendingField) => {
34343
34522
  currentFieldStack.push(pendingField.fieldInfo);
34344
34523
  collectedNodesStack.push([node2]);
34524
+ rawCollectedNodesStack.push([node2]);
34345
34525
  });
34346
34526
  } else if (childResult.unpairedEnd) {
34347
34527
  collectedNodesStack[collectedNodesStack.length - 1].push(node2);
34528
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node2);
34348
34529
  finalizeField();
34349
34530
  } else if (collecting) {
34350
34531
  collectedNodesStack[collectedNodesStack.length - 1].push(node2);
34532
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node2);
34351
34533
  } else {
34352
34534
  processedNodes.push(node2);
34353
34535
  }
34354
34536
  } else if (collecting) {
34355
34537
  collectedNodesStack[collectedNodesStack.length - 1].push(node2);
34538
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node2);
34356
34539
  } else {
34357
34540
  processedNodes.push(node2);
34358
34541
  }
@@ -34374,10 +34557,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
34374
34557
  const instructionType = instrText.trim().split(" ")[0];
34375
34558
  const instructionPreProcessor = getInstructionPreProcessor(instructionType);
34376
34559
  if (instructionPreProcessor) {
34377
- return instructionPreProcessor(nodesToCombine, instrText, docx);
34378
- } else {
34379
- return nodesToCombine;
34560
+ return { nodes: instructionPreProcessor(nodesToCombine, instrText, docx), handled: true };
34380
34561
  }
34562
+ return { nodes: nodesToCombine, handled: false };
34381
34563
  };
34382
34564
  const preProcessPageFieldsOnly = (nodes = []) => {
34383
34565
  const processedNodes = [];
@@ -34452,6 +34634,14 @@ Please report this to https://github.com/markedjs/marked.`, e) {
34452
34634
  endIndex
34453
34635
  };
34454
34636
  }
34637
+ const commentRangeStartHandlerEntity = generateV2HandlerEntity(
34638
+ "commentRangeStartHandler",
34639
+ commentRangeStartTranslator
34640
+ );
34641
+ const commentRangeEndHandlerEntity = generateV2HandlerEntity(
34642
+ "commentRangeEndHandler",
34643
+ commentRangeEndTranslator
34644
+ );
34455
34645
  const createDocumentJson = (docx, converter, editor) => {
34456
34646
  const json = carbonCopy(getInitialJSON(docx));
34457
34647
  if (!json) return null;
@@ -34513,6 +34703,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
34513
34703
  path: []
34514
34704
  });
34515
34705
  parsedContent = filterOutRootInlineNodes(parsedContent);
34706
+ collapseWhitespaceNextToInlinePassthrough(parsedContent);
34516
34707
  const result = {
34517
34708
  type: "doc",
34518
34709
  content: parsedContent,
@@ -34553,6 +34744,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
34553
34744
  bookmarkStartNodeHandlerEntity,
34554
34745
  bookmarkEndNodeHandlerEntity,
34555
34746
  hyperlinkNodeHandlerEntity,
34747
+ commentRangeStartHandlerEntity,
34748
+ commentRangeEndHandlerEntity,
34556
34749
  drawingNodeHandlerEntity,
34557
34750
  trackChangeNodeHandlerEntity,
34558
34751
  tableNodeHandlerEntity,
@@ -34561,7 +34754,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
34561
34754
  autoPageHandlerEntity,
34562
34755
  autoTotalPageCountEntity,
34563
34756
  pageReferenceEntity,
34564
- standardNodeHandlerEntity
34757
+ passthroughNodeHandlerEntity
34565
34758
  ];
34566
34759
  const handler2 = createNodeListHandler(entities);
34567
34760
  return {
@@ -34848,8 +35041,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
34848
35041
  editor.options.annotations = true;
34849
35042
  headers.forEach((header) => {
34850
35043
  const { rId, referenceFile, currentFileName } = getHeaderFooterSectionData(header, docx);
34851
- const { processedNodes: headerProcessedNodes } = preProcessPageFieldsOnly(referenceFile.elements[0].elements ?? []);
34852
- referenceFile.elements[0].elements = headerProcessedNodes;
35044
+ const headerNodes = carbonCopy(referenceFile.elements[0].elements ?? []);
35045
+ const { processedNodes: headerProcessedNodes } = preProcessPageFieldsOnly(headerNodes);
34853
35046
  const sectPrHeader = allSectPrElements.find(
34854
35047
  (el) => el.name === "w:headerReference" && el.attributes["r:id"] === rId
34855
35048
  );
@@ -34857,7 +35050,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
34857
35050
  if (converter.headerIds[sectionType]) sectionType = null;
34858
35051
  const nodeListHandler = defaultNodeListHandler();
34859
35052
  let schema = nodeListHandler.handler({
34860
- nodes: referenceFile.elements[0].elements,
35053
+ nodes: headerProcessedNodes,
34861
35054
  nodeListHandler,
34862
35055
  docx,
34863
35056
  converter,
@@ -34878,15 +35071,15 @@ Please report this to https://github.com/markedjs/marked.`, e) {
34878
35071
  if (titlePg) converter.headerIds.titlePg = true;
34879
35072
  footers.forEach((footer) => {
34880
35073
  const { rId, referenceFile, currentFileName } = getHeaderFooterSectionData(footer, docx);
34881
- const { processedNodes: footerProcessedNodes } = preProcessPageFieldsOnly(referenceFile.elements[0].elements ?? []);
34882
- referenceFile.elements[0].elements = footerProcessedNodes;
35074
+ const footerNodes = carbonCopy(referenceFile.elements[0].elements ?? []);
35075
+ const { processedNodes: footerProcessedNodes } = preProcessPageFieldsOnly(footerNodes);
34883
35076
  const sectPrFooter = allSectPrElements.find(
34884
35077
  (el) => el.name === "w:footerReference" && el.attributes["r:id"] === rId
34885
35078
  );
34886
35079
  const sectionType = sectPrFooter?.attributes["w:type"];
34887
35080
  const nodeListHandler = defaultNodeListHandler();
34888
35081
  let schema = nodeListHandler.handler({
34889
- nodes: referenceFile.elements[0].elements,
35082
+ nodes: footerProcessedNodes,
34890
35083
  nodeListHandler,
34891
35084
  docx,
34892
35085
  converter,
@@ -34949,6 +35142,51 @@ Please report this to https://github.com/markedjs/marked.`, e) {
34949
35142
  ]);
34950
35143
  return content2.filter((node2) => node2 && typeof node2.type === "string" && !INLINE_TYPES.has(node2.type));
34951
35144
  }
35145
+ function collapseWhitespaceNextToInlinePassthrough(content2 = []) {
35146
+ if (!Array.isArray(content2) || content2.length === 0) return;
35147
+ const sequence = collectInlineSequence(content2);
35148
+ sequence.forEach((entry, index2) => {
35149
+ if (entry.kind !== "passthrough") return;
35150
+ const prev = findNeighborText(sequence, index2, -1);
35151
+ const next2 = findNeighborText(sequence, index2, 1);
35152
+ if (!prev || !next2) return;
35153
+ if (!prev.node.text.endsWith(" ") || !next2.node.text.startsWith(" ")) return;
35154
+ prev.node.text = prev.node.text.replace(/ +$/, " ");
35155
+ next2.node.text = next2.node.text.replace(/^ +/, "");
35156
+ if (next2.node.text.length === 0) {
35157
+ next2.parent.splice(next2.index, 1);
35158
+ }
35159
+ });
35160
+ }
35161
+ function collectInlineSequence(nodes, result = [], insidePassthrough = false) {
35162
+ if (!Array.isArray(nodes) || nodes.length === 0) return result;
35163
+ nodes.forEach((node2, index2) => {
35164
+ if (!node2) return;
35165
+ const isPassthrough = node2.type === "passthroughInline";
35166
+ if (isPassthrough && !insidePassthrough) {
35167
+ result.push({ kind: "passthrough", parent: nodes, index: index2 });
35168
+ }
35169
+ if (node2.type === "text" && typeof node2.text === "string" && !insidePassthrough) {
35170
+ result.push({ kind: "text", node: node2, parent: nodes, index: index2 });
35171
+ }
35172
+ if (Array.isArray(node2.content) && node2.content.length) {
35173
+ const nextInside = insidePassthrough || isPassthrough;
35174
+ collectInlineSequence(node2.content, result, nextInside);
35175
+ }
35176
+ });
35177
+ return result;
35178
+ }
35179
+ function findNeighborText(sequence, startIndex, direction) {
35180
+ let cursor = startIndex + direction;
35181
+ while (cursor >= 0 && cursor < sequence.length) {
35182
+ const entry = sequence[cursor];
35183
+ if (entry.kind === "text") {
35184
+ return entry;
35185
+ }
35186
+ cursor += direction;
35187
+ }
35188
+ return null;
35189
+ }
34952
35190
  function getThemeColorPalette(docx) {
34953
35191
  const themePart = docx?.["word/theme/theme1.xml"];
34954
35192
  if (!themePart || !Array.isArray(themePart.elements)) return void 0;
@@ -35311,7 +35549,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
35311
35549
  "page-number": translator$4,
35312
35550
  "total-page-number": translator$3,
35313
35551
  pageReference: translator$6,
35314
- tableOfContents: translator$5
35552
+ tableOfContents: translator$5,
35553
+ passthroughBlock: translatePassthroughNode,
35554
+ passthroughInline: translatePassthroughNode
35315
35555
  };
35316
35556
  let handler2 = router[type2];
35317
35557
  if (handler2 && "decode" in handler2 && typeof handler2.decode === "function") {
@@ -35323,6 +35563,11 @@ Please report this to https://github.com/markedjs/marked.`, e) {
35323
35563
  }
35324
35564
  return handler2(params2);
35325
35565
  }
35566
+ function translatePassthroughNode(params2) {
35567
+ const original = params2?.node?.attrs?.originalXml;
35568
+ if (!original) return null;
35569
+ return carbonCopy(original);
35570
+ }
35326
35571
  function translateBodyNode(params2) {
35327
35572
  let sectPr = params2.bodyNode?.elements?.find((n) => n.name === "w:sectPr");
35328
35573
  if (!sectPr) {
@@ -36022,7 +36267,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
36022
36267
  static getStoredSuperdocVersion(docx) {
36023
36268
  return _SuperConverter2.getStoredCustomProperty(docx, "SuperdocVersion");
36024
36269
  }
36025
- static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.14") {
36270
+ static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.15") {
36026
36271
  return _SuperConverter2.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
36027
36272
  }
36028
36273
  /**
@@ -47079,7 +47324,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
47079
47324
  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);
47080
47325
  var __privateSet = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
47081
47326
  var __privateMethod$1 = (obj, member, method) => (__accessCheck$1(obj, member, "access private method"), method);
47082
- 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;
47327
+ 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;
47083
47328
  var GOOD_LEAF_SIZE = 200;
47084
47329
  var RopeSequence = function RopeSequence2() {
47085
47330
  };
@@ -47952,17 +48197,20 @@ Please report this to https://github.com/markedjs/marked.`, e) {
47952
48197
  }
47953
48198
  function findOffsetInText(node2, coords) {
47954
48199
  let len2 = node2.nodeValue.length;
47955
- let range2 = document.createRange();
48200
+ let range2 = document.createRange(), result;
47956
48201
  for (let i2 = 0; i2 < len2; i2++) {
47957
48202
  range2.setEnd(node2, i2 + 1);
47958
48203
  range2.setStart(node2, i2);
47959
48204
  let rect = singleRect(range2, 1);
47960
48205
  if (rect.top == rect.bottom)
47961
48206
  continue;
47962
- if (inRect(coords, rect))
47963
- return { node: node2, offset: i2 + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0) };
48207
+ if (inRect(coords, rect)) {
48208
+ result = { node: node2, offset: i2 + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0) };
48209
+ break;
48210
+ }
47964
48211
  }
47965
- return { node: node2, offset: 0 };
48212
+ range2.detach();
48213
+ return result || { node: node2, offset: 0 };
47966
48214
  }
47967
48215
  function inRect(coords, rect) {
47968
48216
  return coords.left >= rect.left - 1 && coords.left <= rect.right + 1 && coords.top >= rect.top - 1 && coords.top <= rect.bottom + 1;
@@ -50709,7 +50957,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
50709
50957
  if (!view.composing) {
50710
50958
  view.domObserver.flush();
50711
50959
  let { state: state2 } = view, $pos = state2.selection.$to;
50712
- if (state2.selection instanceof TextSelection$1 && (state2.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some((m2) => m2.type.spec.inclusive === false))) {
50960
+ 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))) {
50713
50961
  view.markCursor = view.state.storedMarks || $pos.marks();
50714
50962
  endComposition(view, true);
50715
50963
  view.markCursor = null;
@@ -50737,6 +50985,13 @@ Please report this to https://github.com/markedjs/marked.`, e) {
50737
50985
  }
50738
50986
  scheduleComposeEnd(view, timeoutComposition);
50739
50987
  };
50988
+ function selectionBeforeUneditable(view) {
50989
+ let { focusNode, focusOffset } = view.domSelectionRange();
50990
+ if (!focusNode || focusNode.nodeType != 1 || focusOffset >= focusNode.childNodes.length)
50991
+ return false;
50992
+ let next2 = focusNode.childNodes[focusOffset];
50993
+ return next2.nodeType == 1 && next2.contentEditable == "false";
50994
+ }
50740
50995
  editHandlers.compositionend = (view, event) => {
50741
50996
  if (view.composing) {
50742
50997
  view.input.composing = false;
@@ -50940,10 +51195,14 @@ Please report this to https://github.com/markedjs/marked.`, e) {
50940
51195
  }, 50);
50941
51196
  };
50942
51197
  editHandlers.dragover = editHandlers.dragenter = (_2, e) => e.preventDefault();
50943
- editHandlers.drop = (view, _event) => {
50944
- let event = _event;
50945
- let dragging = view.dragging;
50946
- view.dragging = null;
51198
+ editHandlers.drop = (view, event) => {
51199
+ try {
51200
+ handleDrop(view, event, view.dragging);
51201
+ } finally {
51202
+ view.dragging = null;
51203
+ }
51204
+ };
51205
+ function handleDrop(view, event, dragging) {
50947
51206
  if (!event.dataTransfer)
50948
51207
  return;
50949
51208
  let eventPos = view.posAtCoords(eventCoords(event));
@@ -50996,7 +51255,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
50996
51255
  }
50997
51256
  view.focus();
50998
51257
  view.dispatch(tr.setMeta("uiEvent", "drop"));
50999
- };
51258
+ }
51000
51259
  handlers$1.focus = (view) => {
51001
51260
  view.input.lastFocus = Date.now();
51002
51261
  if (!view.focused) {
@@ -51846,6 +52105,13 @@ Please report this to https://github.com/markedjs/marked.`, e) {
51846
52105
  br2.remove();
51847
52106
  }
51848
52107
  }
52108
+ } else if ((chrome || safari) && added.some((n) => n.nodeName == "BR") && (view.input.lastKeyCode == 8 || view.input.lastKeyCode == 46)) {
52109
+ for (let node2 of added)
52110
+ if (node2.nodeName == "BR" && node2.parentNode) {
52111
+ let after = node2.nextSibling;
52112
+ if (after && after.nodeType == 1 && after.contentEditable == "false")
52113
+ node2.parentNode.removeChild(node2);
52114
+ }
51849
52115
  }
51850
52116
  let readSel = null;
51851
52117
  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))) {
@@ -57029,7 +57295,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
57029
57295
  const baseKeymap = {
57030
57296
  Enter: () => handleEnter(this.editor),
57031
57297
  "Shift-Enter": () => this.editor.commands.insertLineBreak(),
57032
- "Mod-Enter": () => this.editor.commands.exitCode(),
57298
+ "Mod-Enter": () => this.editor.commands.insertPageBreak(),
57033
57299
  Backspace: () => handleBackspace(this.editor),
57034
57300
  "Mod-Backspace": () => handleBackspace(this.editor),
57035
57301
  "Shift-Backspace": () => handleBackspace(this.editor),
@@ -60586,7 +60852,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
60586
60852
  const shouldSkipNodeView = (editor) => {
60587
60853
  return isHeadless(editor);
60588
60854
  };
60589
- const summaryVersion = "1.0.0-beta.14";
60855
+ const summaryVersion = "1.0.0-beta.15";
60590
60856
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
60591
60857
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
60592
60858
  function mapAttributes(attrs) {
@@ -61365,7 +61631,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
61365
61631
  { default: remarkStringify2 },
61366
61632
  { default: remarkGfm2 }
61367
61633
  ] = await Promise.all([
61368
- Promise.resolve().then(() => indexI4Ew0HDV),
61634
+ Promise.resolve().then(() => indexBds7gW4r),
61369
61635
  Promise.resolve().then(() => indexDRCvimau),
61370
61636
  Promise.resolve().then(() => indexC_x_N6Uh),
61371
61637
  Promise.resolve().then(() => indexD_sWOSiG),
@@ -61570,7 +61836,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
61570
61836
  * Process collaboration migrations
61571
61837
  */
61572
61838
  processCollaborationMigrations() {
61573
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.14");
61839
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.15");
61574
61840
  if (!this.options.ydoc) return;
61575
61841
  const metaMap = this.options.ydoc.getMap("meta");
61576
61842
  let docVersion = metaMap.get("version");
@@ -63299,6 +63565,23 @@ Please report this to https://github.com/markedjs/marked.`, e) {
63299
63565
  const MAX_DATA_ATTR_COUNT = 50;
63300
63566
  const MAX_DATA_ATTR_VALUE_LENGTH = 1e3;
63301
63567
  const MAX_DATA_ATTR_NAME_LENGTH = 100;
63568
+ const pushCommentAnnotation = (run2, attrs) => {
63569
+ const commentId = typeof attrs?.commentId === "string" ? attrs.commentId : void 0;
63570
+ const importedId = typeof attrs?.importedId === "string" ? attrs.importedId : void 0;
63571
+ const internal = attrs?.internal === true;
63572
+ if (!commentId && !importedId) return;
63573
+ const annotations = run2.comments ? [...run2.comments] : [];
63574
+ const key2 = `${commentId ?? ""}::${importedId ?? ""}`;
63575
+ const exists2 = annotations.some((c2) => `${c2.commentId ?? ""}::${c2.importedId ?? ""}` === key2);
63576
+ if (!exists2) {
63577
+ annotations.push({
63578
+ commentId: commentId ?? importedId,
63579
+ importedId,
63580
+ internal
63581
+ });
63582
+ }
63583
+ run2.comments = annotations;
63584
+ };
63302
63585
  const extractDataAttributes = (attrs) => {
63303
63586
  if (!attrs) return void 0;
63304
63587
  const result = {};
@@ -63581,6 +63864,11 @@ Please report this to https://github.com/markedjs/marked.`, e) {
63581
63864
  case "textStyle":
63582
63865
  applyTextStyleMark(run2, mark2.attrs ?? {}, themeColors);
63583
63866
  break;
63867
+ case "commentMark":
63868
+ case "comment": {
63869
+ pushCommentAnnotation(run2, mark2.attrs ?? {});
63870
+ break;
63871
+ }
63584
63872
  case "underline": {
63585
63873
  const style2 = normalizeUnderlineStyle(mark2.attrs?.underlineType);
63586
63874
  if (style2) {
@@ -65497,10 +65785,17 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65497
65785
  }
65498
65786
  const resolvedExtended = resolved;
65499
65787
  const resolvedAsRecord = resolved;
65788
+ let resolvedIndent = cloneIfObject(resolvedAsRecord.indent);
65789
+ const styleIdLower = typeof styleId === "string" ? styleId.toLowerCase() : "";
65790
+ const isHeadingStyle = typeof resolvedExtended.outlineLvl === "number" || styleIdLower.startsWith("heading ") || styleIdLower.startsWith("heading");
65791
+ const onlyFirstLineIndent = resolvedIndent && resolvedIndent.firstLine != null && resolvedIndent.hanging == null && resolvedIndent.left == null && resolvedIndent.right == null;
65792
+ if (isHeadingStyle && (!resolvedIndent || Object.keys(resolvedIndent).length === 0 || onlyFirstLineIndent)) {
65793
+ resolvedIndent = { firstLine: 0, hanging: 0, left: resolvedIndent?.left, right: resolvedIndent?.right };
65794
+ }
65500
65795
  const hydrated = {
65501
65796
  resolved,
65502
65797
  spacing: cloneIfObject(resolvedAsRecord.spacing),
65503
- indent: cloneIfObject(resolvedAsRecord.indent),
65798
+ indent: resolvedIndent,
65504
65799
  borders: cloneIfObject(resolvedExtended.borders),
65505
65800
  shading: cloneIfObject(resolvedExtended.shading),
65506
65801
  alignment: resolvedExtended.justification,
@@ -65608,6 +65903,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65608
65903
  }
65609
65904
  if (attrs.shading) clone.shading = { ...attrs.shading };
65610
65905
  if (attrs.tabs) clone.tabs = attrs.tabs.map((tab) => ({ ...tab }));
65906
+ if (attrs.dropCapDescriptor) {
65907
+ clone.dropCapDescriptor = {
65908
+ ...attrs.dropCapDescriptor,
65909
+ run: { ...attrs.dropCapDescriptor.run }
65910
+ };
65911
+ }
65611
65912
  return clone;
65612
65913
  };
65613
65914
  const buildStyleNodeFromAttrs = (attrs, spacing, indent2) => {
@@ -65719,6 +66020,119 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65719
66020
  return void 0;
65720
66021
  }
65721
66022
  };
66023
+ const DEFAULT_DROP_CAP_FONT_SIZE_PX = 64;
66024
+ const DEFAULT_DROP_CAP_FONT_FAMILY = "Times New Roman";
66025
+ const extractDropCapRunFromParagraph = (para) => {
66026
+ const content2 = para.content;
66027
+ if (!Array.isArray(content2) || content2.length === 0) {
66028
+ return null;
66029
+ }
66030
+ let text2 = "";
66031
+ let runProperties = {};
66032
+ let textStyleMarks = {};
66033
+ const MAX_RECURSION_DEPTH = 50;
66034
+ const extractTextAndStyle = (nodes, depth = 0) => {
66035
+ if (depth > MAX_RECURSION_DEPTH) {
66036
+ console.warn(`extractTextAndStyle exceeded max recursion depth (${MAX_RECURSION_DEPTH})`);
66037
+ return false;
66038
+ }
66039
+ for (const node2 of nodes) {
66040
+ if (!node2) continue;
66041
+ if (node2.type === "text" && typeof node2.text === "string" && node2.text.length > 0) {
66042
+ text2 = node2.text;
66043
+ if (Array.isArray(node2.marks)) {
66044
+ for (const mark2 of node2.marks) {
66045
+ if (mark2?.type === "textStyle" && mark2.attrs) {
66046
+ textStyleMarks = { ...textStyleMarks, ...mark2.attrs };
66047
+ }
66048
+ }
66049
+ }
66050
+ return true;
66051
+ }
66052
+ if (node2.type === "run") {
66053
+ if (node2.attrs?.runProperties && typeof node2.attrs.runProperties === "object") {
66054
+ runProperties = { ...runProperties, ...node2.attrs.runProperties };
66055
+ }
66056
+ if (Array.isArray(node2.marks)) {
66057
+ for (const mark2 of node2.marks) {
66058
+ if (mark2?.type === "textStyle" && mark2.attrs) {
66059
+ textStyleMarks = { ...textStyleMarks, ...mark2.attrs };
66060
+ }
66061
+ }
66062
+ }
66063
+ if (Array.isArray(node2.content) && extractTextAndStyle(node2.content, depth + 1)) {
66064
+ return true;
66065
+ }
66066
+ }
66067
+ if (Array.isArray(node2.content) && extractTextAndStyle(node2.content, depth + 1)) {
66068
+ return true;
66069
+ }
66070
+ }
66071
+ return false;
66072
+ };
66073
+ extractTextAndStyle(content2);
66074
+ if (!text2) {
66075
+ return null;
66076
+ }
66077
+ const mergedStyle = { ...runProperties, ...textStyleMarks };
66078
+ let fontSizePx = DEFAULT_DROP_CAP_FONT_SIZE_PX;
66079
+ const rawFontSize = mergedStyle.fontSize ?? mergedStyle["w:sz"] ?? mergedStyle.sz;
66080
+ if (rawFontSize != null) {
66081
+ if (typeof rawFontSize === "number") {
66082
+ const converted = rawFontSize > 100 ? ptToPx(rawFontSize / 2) : rawFontSize;
66083
+ fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
66084
+ } else if (typeof rawFontSize === "string") {
66085
+ const numericPart = parseFloat(rawFontSize);
66086
+ if (Number.isFinite(numericPart)) {
66087
+ if (rawFontSize.endsWith("pt")) {
66088
+ const converted = ptToPx(numericPart);
66089
+ fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
66090
+ } else if (rawFontSize.endsWith("px")) {
66091
+ fontSizePx = numericPart;
66092
+ } else {
66093
+ const converted = numericPart > 100 ? ptToPx(numericPart / 2) : numericPart;
66094
+ fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
66095
+ }
66096
+ }
66097
+ }
66098
+ }
66099
+ let fontFamily2 = DEFAULT_DROP_CAP_FONT_FAMILY;
66100
+ const rawFontFamily = mergedStyle.fontFamily ?? mergedStyle["w:rFonts"] ?? mergedStyle.rFonts;
66101
+ if (typeof rawFontFamily === "string") {
66102
+ fontFamily2 = rawFontFamily;
66103
+ } else if (rawFontFamily && typeof rawFontFamily === "object") {
66104
+ const rFonts = rawFontFamily;
66105
+ const ascii = rFonts["w:ascii"] ?? rFonts.ascii;
66106
+ if (typeof ascii === "string") {
66107
+ fontFamily2 = ascii;
66108
+ }
66109
+ }
66110
+ const dropCapRun = {
66111
+ text: text2,
66112
+ fontFamily: fontFamily2,
66113
+ fontSize: fontSizePx
66114
+ };
66115
+ const bold = mergedStyle.bold ?? mergedStyle["w:b"] ?? mergedStyle.b;
66116
+ if (isTruthy(bold)) {
66117
+ dropCapRun.bold = true;
66118
+ }
66119
+ const italic = mergedStyle.italic ?? mergedStyle["w:i"] ?? mergedStyle.i;
66120
+ if (isTruthy(italic)) {
66121
+ dropCapRun.italic = true;
66122
+ }
66123
+ const color2 = mergedStyle.color ?? mergedStyle["w:color"] ?? mergedStyle.val;
66124
+ if (typeof color2 === "string" && color2.length > 0 && color2.toLowerCase() !== "auto") {
66125
+ dropCapRun.color = color2.startsWith("#") ? color2 : `#${color2}`;
66126
+ }
66127
+ const position2 = mergedStyle.position ?? mergedStyle["w:position"];
66128
+ if (position2 != null) {
66129
+ const posNum = pickNumber(position2);
66130
+ if (posNum != null) {
66131
+ dropCapRun.position = ptToPx(posNum / 2);
66132
+ }
66133
+ }
66134
+ return dropCapRun;
66135
+ };
65722
66136
  const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleContext, _paragraphNode) => {
65723
66137
  if (numberingProps === null) {
65724
66138
  return null;
@@ -65984,6 +66398,24 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65984
66398
  const dropCap = framePr["w:dropCap"] ?? framePr.dropCap;
65985
66399
  if (dropCap != null && (typeof dropCap === "string" || typeof dropCap === "number" || typeof dropCap === "boolean")) {
65986
66400
  paragraphAttrs.dropCap = dropCap;
66401
+ const dropCapMode = typeof dropCap === "string" ? dropCap.toLowerCase() : "drop";
66402
+ const linesValue = pickNumber(framePr["w:lines"] ?? framePr.lines);
66403
+ const wrapValue = asString(framePr["w:wrap"] ?? framePr.wrap);
66404
+ const dropCapRunInfo = extractDropCapRunFromParagraph(para);
66405
+ if (dropCapRunInfo) {
66406
+ const descriptor = {
66407
+ mode: dropCapMode === "margin" ? "margin" : "drop",
66408
+ lines: linesValue != null && linesValue > 0 ? linesValue : 3,
66409
+ run: dropCapRunInfo
66410
+ };
66411
+ if (wrapValue) {
66412
+ const normalizedWrap = wrapValue.toLowerCase();
66413
+ if (normalizedWrap === "around" || normalizedWrap === "notbeside" || normalizedWrap === "none" || normalizedWrap === "tight") {
66414
+ descriptor.wrap = normalizedWrap === "notbeside" ? "notBeside" : normalizedWrap;
66415
+ }
66416
+ }
66417
+ paragraphAttrs.dropCapDescriptor = descriptor;
66418
+ }
65987
66419
  }
65988
66420
  const frame = {};
65989
66421
  const wrap2 = asString(framePr["w:wrap"] ?? framePr.wrap);
@@ -66757,13 +67189,26 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66757
67189
  }
66758
67190
  return true;
66759
67191
  };
67192
+ const commentsCompatible = (a2, b2) => {
67193
+ const aComments = a2.comments ?? [];
67194
+ const bComments = b2.comments ?? [];
67195
+ if (aComments.length === 0 && bComments.length === 0) return true;
67196
+ if (aComments.length !== bComments.length) return false;
67197
+ const normalize2 = (c2) => `${c2.commentId ?? ""}::${c2.importedId ?? ""}::${c2.internal ? "1" : "0"}`;
67198
+ const aKeys = aComments.map(normalize2).sort();
67199
+ const bKeys = bComments.map(normalize2).sort();
67200
+ for (let i2 = 0; i2 < aKeys.length; i2++) {
67201
+ if (aKeys[i2] !== bKeys[i2]) return false;
67202
+ }
67203
+ return true;
67204
+ };
66760
67205
  function mergeAdjacentRuns(runs2) {
66761
67206
  if (runs2.length <= 1) return runs2;
66762
67207
  const merged = [];
66763
67208
  let current = runs2[0];
66764
67209
  for (let i2 = 1; i2 < runs2.length; i2++) {
66765
67210
  const next2 = runs2[i2];
66766
- const canMerge = isTextRun$1(current) && isTextRun$1(next2) && !current.token && !next2.token && current.pmStart != null && current.pmEnd != null && next2.pmStart != null && next2.pmEnd != null && current.pmEnd === next2.pmStart && current.fontFamily === next2.fontFamily && current.fontSize === next2.fontSize && current.bold === next2.bold && current.italic === next2.italic && current.underline === next2.underline && current.strike === next2.strike && current.color === next2.color && current.highlight === next2.highlight && (current.letterSpacing ?? 0) === (next2.letterSpacing ?? 0) && trackedChangesCompatible(current, next2) && dataAttrsCompatible(current, next2);
67211
+ const canMerge = isTextRun$1(current) && isTextRun$1(next2) && !current.token && !next2.token && current.pmStart != null && current.pmEnd != null && next2.pmStart != null && next2.pmEnd != null && current.pmEnd === next2.pmStart && current.fontFamily === next2.fontFamily && current.fontSize === next2.fontSize && current.bold === next2.bold && current.italic === next2.italic && current.underline === next2.underline && current.strike === next2.strike && current.color === next2.color && current.highlight === next2.highlight && (current.letterSpacing ?? 0) === (next2.letterSpacing ?? 0) && trackedChangesCompatible(current, next2) && dataAttrsCompatible(current, next2) && commentsCompatible(current, next2);
66767
67212
  if (canMerge) {
66768
67213
  const currText = current.text ?? "";
66769
67214
  const nextText = next2.text ?? "";
@@ -67245,6 +67690,22 @@ Please report this to https://github.com/markedjs/marked.`, e) {
67245
67690
  id: nextId(),
67246
67691
  attrs: node2.attrs || {}
67247
67692
  });
67693
+ } else {
67694
+ const lineBreakRun = { kind: "lineBreak", attrs: {} };
67695
+ const lbAttrs = {};
67696
+ if (attrs.lineBreakType) lbAttrs.lineBreakType = String(attrs.lineBreakType);
67697
+ if (attrs.clear) lbAttrs.clear = String(attrs.clear);
67698
+ if (Object.keys(lbAttrs).length > 0) {
67699
+ lineBreakRun.attrs = lbAttrs;
67700
+ } else {
67701
+ delete lineBreakRun.attrs;
67702
+ }
67703
+ const pos = positions.get(node2);
67704
+ if (pos) {
67705
+ lineBreakRun.pmStart = pos.start;
67706
+ lineBreakRun.pmEnd = pos.end;
67707
+ }
67708
+ currentRuns.push(lineBreakRun);
67248
67709
  }
67249
67710
  return;
67250
67711
  }
@@ -68269,7 +68730,39 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68269
68730
  }
68270
68731
  instrumentation?.log?.({ totalBlocks: blocks2.length, blockCounts, bookmarks: bookmarks.size });
68271
68732
  const hydratedBlocks = hydrateImageBlocks(blocks2, options?.mediaFiles);
68272
- return { blocks: hydratedBlocks, bookmarks };
68733
+ const mergedBlocks = mergeDropCapParagraphs(hydratedBlocks);
68734
+ return { blocks: mergedBlocks, bookmarks };
68735
+ }
68736
+ function mergeDropCapParagraphs(blocks2) {
68737
+ const result = [];
68738
+ let i2 = 0;
68739
+ while (i2 < blocks2.length) {
68740
+ const block = blocks2[i2];
68741
+ if (block.kind === "paragraph" && block.attrs?.dropCapDescriptor && i2 + 1 < blocks2.length) {
68742
+ const dropCapBlock = block;
68743
+ const nextBlock = blocks2[i2 + 1];
68744
+ if (nextBlock.kind === "paragraph") {
68745
+ const textBlock = nextBlock;
68746
+ const mergedBlock = {
68747
+ kind: "paragraph",
68748
+ id: textBlock.id,
68749
+ runs: textBlock.runs,
68750
+ attrs: {
68751
+ ...textBlock.attrs,
68752
+ dropCapDescriptor: dropCapBlock.attrs?.dropCapDescriptor,
68753
+ // Clear the legacy dropCap flag on the merged block
68754
+ dropCap: void 0
68755
+ }
68756
+ };
68757
+ result.push(mergedBlock);
68758
+ i2 += 2;
68759
+ continue;
68760
+ }
68761
+ }
68762
+ result.push(block);
68763
+ i2 += 1;
68764
+ }
68765
+ return result;
68273
68766
  }
68274
68767
  function paragraphToFlowBlocks(para, nextBlockId, positions, defaultFont, defaultSize, styleContext, listCounterContext, trackedChanges, bookmarks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors, converterContext) {
68275
68768
  return paragraphToFlowBlocks$1(
@@ -68344,7 +68837,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68344
68837
  return measurementCtx;
68345
68838
  }
68346
68839
  function getRunFontString(run2) {
68347
- if (run2.kind === "tab" || run2.kind === "image") {
68840
+ if (run2.kind === "tab" || run2.kind === "lineBreak" || "src" in run2) {
68348
68841
  return "normal normal 16px Arial";
68349
68842
  }
68350
68843
  const style2 = run2.italic ? "italic" : "normal";
@@ -68363,7 +68856,11 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68363
68856
  result.push(run2);
68364
68857
  continue;
68365
68858
  }
68366
- if (run2.kind === "image") {
68859
+ if ("src" in run2) {
68860
+ result.push(run2);
68861
+ continue;
68862
+ }
68863
+ if (run2.kind === "lineBreak") {
68367
68864
  result.push(run2);
68368
68865
  continue;
68369
68866
  }
@@ -68390,13 +68887,17 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68390
68887
  }
68391
68888
  function measureCharacterX(block, line, charOffset) {
68392
68889
  const ctx2 = getMeasurementContext();
68890
+ const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
68891
+ if (hasExplicitPositioning && line.segments && ctx2) {
68892
+ return measureCharacterXSegmentBased(block, line, charOffset, ctx2);
68893
+ }
68393
68894
  if (!ctx2) {
68394
68895
  const runs22 = sliceRunsForLine$1(block, line);
68395
68896
  const charsInLine = Math.max(
68396
68897
  1,
68397
68898
  runs22.reduce((sum, run2) => {
68398
68899
  if (isTabRun$1(run2)) return sum + TAB_CHAR_LENGTH;
68399
- if (run2.kind === "image") return sum;
68900
+ if ("src" in run2 || run2.kind === "lineBreak") return sum;
68400
68901
  return sum + (run2.text ?? "").length;
68401
68902
  }, 0)
68402
68903
  );
@@ -68417,7 +68918,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68417
68918
  currentCharOffset += runLength2;
68418
68919
  continue;
68419
68920
  }
68420
- const text2 = run2.kind === "image" ? "" : run2.text ?? "";
68921
+ const text2 = "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
68421
68922
  const runLength = text2.length;
68422
68923
  if (currentCharOffset + runLength >= charOffset) {
68423
68924
  const offsetInRun = charOffset - currentCharOffset;
@@ -68434,6 +68935,47 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68434
68935
  }
68435
68936
  return currentX;
68436
68937
  }
68938
+ function measureCharacterXSegmentBased(block, line, charOffset, ctx2) {
68939
+ if (block.kind !== "paragraph" || !line.segments) return 0;
68940
+ let lineCharCount = 0;
68941
+ for (const segment of line.segments) {
68942
+ const run2 = block.runs[segment.runIndex];
68943
+ if (!run2) continue;
68944
+ const segmentChars = segment.toChar - segment.fromChar;
68945
+ if (lineCharCount + segmentChars >= charOffset) {
68946
+ const offsetInSegment = charOffset - lineCharCount;
68947
+ let segmentBaseX = segment.x;
68948
+ if (segmentBaseX === void 0) {
68949
+ segmentBaseX = 0;
68950
+ for (const prevSeg of line.segments) {
68951
+ if (prevSeg === segment) break;
68952
+ const prevRun = block.runs[prevSeg.runIndex];
68953
+ if (!prevRun) continue;
68954
+ if (prevSeg.x !== void 0) {
68955
+ segmentBaseX = prevSeg.x + (prevSeg.width ?? 0);
68956
+ } else {
68957
+ segmentBaseX += prevSeg.width ?? 0;
68958
+ }
68959
+ }
68960
+ }
68961
+ if (isTabRun$1(run2)) {
68962
+ return segmentBaseX + (offsetInSegment > 0 ? segment.width ?? 0 : 0);
68963
+ }
68964
+ if ("src" in run2 || run2.kind === "lineBreak") {
68965
+ return segmentBaseX + (offsetInSegment >= segmentChars ? segment.width ?? 0 : 0);
68966
+ }
68967
+ const text2 = run2.text ?? "";
68968
+ const segmentText = text2.slice(segment.fromChar, segment.toChar);
68969
+ const textUpToTarget = segmentText.slice(0, offsetInSegment);
68970
+ ctx2.font = getRunFontString(run2);
68971
+ const measured = ctx2.measureText(textUpToTarget);
68972
+ const spacingWidth = computeLetterSpacingWidth(run2, offsetInSegment, segmentChars);
68973
+ return segmentBaseX + measured.width + spacingWidth;
68974
+ }
68975
+ lineCharCount += segmentChars;
68976
+ }
68977
+ return line.width;
68978
+ }
68437
68979
  function findCharacterAtX(block, line, x2, pmStart) {
68438
68980
  const ctx2 = getMeasurementContext();
68439
68981
  if (!ctx2) {
@@ -68442,7 +68984,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68442
68984
  1,
68443
68985
  runs22.reduce((sum, run2) => {
68444
68986
  if (isTabRun$1(run2)) return sum + TAB_CHAR_LENGTH;
68445
- if (run2.kind === "image") return sum;
68987
+ if ("src" in run2 || run2.kind === "lineBreak") return sum;
68446
68988
  return sum + (run2.text ?? "").length;
68447
68989
  }, 0)
68448
68990
  );
@@ -68477,7 +69019,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68477
69019
  currentCharOffset += TAB_CHAR_LENGTH;
68478
69020
  continue;
68479
69021
  }
68480
- const text2 = run2.kind === "image" ? "" : run2.text ?? "";
69022
+ const text2 = "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
68481
69023
  const runLength = text2.length;
68482
69024
  if (runLength === 0) continue;
68483
69025
  ctx2.font = getRunFontString(run2);
@@ -68514,7 +69056,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68514
69056
  };
68515
69057
  }
68516
69058
  const computeLetterSpacingWidth = (run2, precedingChars, runLength) => {
68517
- if (isTabRun$1(run2) || run2.kind === "image" || !run2.letterSpacing) {
69059
+ if (isTabRun$1(run2) || "src" in run2 || !("letterSpacing" in run2) || !run2.letterSpacing) {
68518
69060
  return 0;
68519
69061
  }
68520
69062
  const maxGaps = Math.max(runLength - 1, 0);
@@ -68524,6 +69066,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68524
69066
  const clamped = Math.min(Math.max(precedingChars, 0), maxGaps);
68525
69067
  return clamped * run2.letterSpacing;
68526
69068
  };
69069
+ const log = (...args) => {
69070
+ };
68527
69071
  const CLASS_NAMES$1 = {
68528
69072
  page: "superdoc-page",
68529
69073
  fragment: "superdoc-fragment",
@@ -68539,6 +69083,11 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68539
69083
  const pageLocalY = clientY - pageRect.top;
68540
69084
  const viewX = pageRect.left + pageLocalX;
68541
69085
  const viewY = pageRect.top + pageLocalY;
69086
+ log("Page found:", {
69087
+ pageIndex: pageEl.dataset.pageIndex,
69088
+ pageRect: { left: pageRect.left, top: pageRect.top, width: pageRect.width, height: pageRect.height },
69089
+ viewCoords: { viewX, viewY }
69090
+ });
68542
69091
  let hitChain = [];
68543
69092
  const doc2 = document;
68544
69093
  if (typeof doc2.elementsFromPoint === "function") {
@@ -68550,15 +69099,62 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68550
69099
  if (!Array.isArray(hitChain)) {
68551
69100
  return null;
68552
69101
  }
69102
+ const hitChainData = hitChain.map((el) => {
69103
+ const rect = el.getBoundingClientRect();
69104
+ return {
69105
+ tag: el.tagName,
69106
+ classes: el.className,
69107
+ blockId: el.dataset?.blockId,
69108
+ pmStart: el.dataset?.pmStart,
69109
+ pmEnd: el.dataset?.pmEnd,
69110
+ rect: {
69111
+ top: Math.round(rect.top),
69112
+ bottom: Math.round(rect.bottom),
69113
+ left: Math.round(rect.left),
69114
+ right: Math.round(rect.right),
69115
+ height: Math.round(rect.height)
69116
+ }
69117
+ };
69118
+ });
69119
+ log("Hit chain elements:", JSON.stringify(hitChainData, null, 2));
69120
+ const allFragments = Array.from(pageEl.querySelectorAll(`.${CLASS_NAMES$1.fragment}`));
69121
+ const fragmentData = allFragments.map((el) => {
69122
+ const rect = el.getBoundingClientRect();
69123
+ return {
69124
+ blockId: el.dataset.blockId,
69125
+ pmStart: el.dataset.pmStart,
69126
+ pmEnd: el.dataset.pmEnd,
69127
+ rect: {
69128
+ top: Math.round(rect.top),
69129
+ bottom: Math.round(rect.bottom),
69130
+ left: Math.round(rect.left),
69131
+ right: Math.round(rect.right),
69132
+ height: Math.round(rect.height)
69133
+ }
69134
+ };
69135
+ });
69136
+ log("All fragments on page:", JSON.stringify(fragmentData, null, 2));
68553
69137
  const fragmentEl = hitChain.find((el) => el.classList?.contains?.(CLASS_NAMES$1.fragment));
68554
69138
  if (!fragmentEl) {
68555
69139
  const fallbackFragment = pageEl.querySelector(`.${CLASS_NAMES$1.fragment}`);
68556
69140
  if (!fallbackFragment) {
68557
69141
  return null;
68558
69142
  }
68559
- return processFragment(fallbackFragment, viewX, viewY);
69143
+ log("Using fallback fragment:", {
69144
+ blockId: fallbackFragment.dataset.blockId,
69145
+ pmStart: fallbackFragment.dataset.pmStart,
69146
+ pmEnd: fallbackFragment.dataset.pmEnd
69147
+ });
69148
+ const result2 = processFragment(fallbackFragment, viewX, viewY);
69149
+ return result2;
68560
69150
  }
68561
- return processFragment(fragmentEl, viewX, viewY);
69151
+ log("Fragment found:", {
69152
+ blockId: fragmentEl.dataset.blockId,
69153
+ pmStart: fragmentEl.dataset.pmStart,
69154
+ pmEnd: fragmentEl.dataset.pmEnd
69155
+ });
69156
+ const result = processFragment(fragmentEl, viewX, viewY);
69157
+ return result;
68562
69158
  }
68563
69159
  function findPageElement(domContainer, clientX, clientY) {
68564
69160
  if (domContainer.classList?.contains?.(CLASS_NAMES$1.page)) {
@@ -68590,7 +69186,20 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68590
69186
  return null;
68591
69187
  }
68592
69188
  function processFragment(fragmentEl, viewX, viewY) {
69189
+ log("processFragment:", { viewX, viewY, blockId: fragmentEl.dataset.blockId });
68593
69190
  const lineEls = Array.from(fragmentEl.querySelectorAll(`.${CLASS_NAMES$1.line}`));
69191
+ log(
69192
+ "Lines in fragment:",
69193
+ lineEls.map((el, i2) => {
69194
+ const rect = el.getBoundingClientRect();
69195
+ return {
69196
+ index: i2,
69197
+ pmStart: el.dataset.pmStart,
69198
+ pmEnd: el.dataset.pmEnd,
69199
+ rect: { top: rect.top, bottom: rect.bottom, left: rect.left, right: rect.right }
69200
+ };
69201
+ })
69202
+ );
68594
69203
  if (lineEls.length === 0) {
68595
69204
  return null;
68596
69205
  }
@@ -68600,10 +69209,30 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68600
69209
  }
68601
69210
  const lineStart = Number(lineEl.dataset.pmStart ?? "NaN");
68602
69211
  const lineEnd = Number(lineEl.dataset.pmEnd ?? "NaN");
69212
+ const lineRect = lineEl.getBoundingClientRect();
69213
+ log("Selected line:", {
69214
+ pmStart: lineStart,
69215
+ pmEnd: lineEnd,
69216
+ rect: { top: lineRect.top, bottom: lineRect.bottom, left: lineRect.left, right: lineRect.right }
69217
+ });
68603
69218
  if (!Number.isFinite(lineStart) || !Number.isFinite(lineEnd)) {
68604
69219
  return null;
68605
69220
  }
68606
69221
  const spanEls = Array.from(lineEl.querySelectorAll("span"));
69222
+ log(
69223
+ "Spans in line:",
69224
+ spanEls.map((el, i2) => {
69225
+ const rect = el.getBoundingClientRect();
69226
+ return {
69227
+ index: i2,
69228
+ pmStart: el.dataset.pmStart,
69229
+ pmEnd: el.dataset.pmEnd,
69230
+ text: el.textContent?.substring(0, 20) + (el.textContent && el.textContent.length > 20 ? "..." : ""),
69231
+ visibility: el.style.visibility,
69232
+ rect: { left: rect.left, right: rect.right, width: rect.width }
69233
+ };
69234
+ })
69235
+ );
68607
69236
  if (spanEls.length === 0) {
68608
69237
  return lineStart;
68609
69238
  }
@@ -68621,6 +69250,14 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68621
69250
  }
68622
69251
  const spanStart = Number(targetSpan.dataset.pmStart ?? "NaN");
68623
69252
  const spanEnd = Number(targetSpan.dataset.pmEnd ?? "NaN");
69253
+ const targetRect = targetSpan.getBoundingClientRect();
69254
+ log("Target span:", {
69255
+ pmStart: spanStart,
69256
+ pmEnd: spanEnd,
69257
+ text: targetSpan.textContent?.substring(0, 30),
69258
+ visibility: targetSpan.style.visibility,
69259
+ rect: { left: targetRect.left, right: targetRect.right, width: targetRect.width }
69260
+ });
68624
69261
  if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) {
68625
69262
  return null;
68626
69263
  }
@@ -68640,28 +69277,53 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68640
69277
  if (lineEls.length === 0) {
68641
69278
  return null;
68642
69279
  }
68643
- for (const lineEl of lineEls) {
69280
+ for (let i2 = 0; i2 < lineEls.length; i2++) {
69281
+ const lineEl = lineEls[i2];
68644
69282
  const rect = lineEl.getBoundingClientRect();
68645
69283
  if (viewY >= rect.top && viewY <= rect.bottom) {
69284
+ log("findLineAtY: Found line at index", i2, {
69285
+ pmStart: lineEl.dataset.pmStart,
69286
+ pmEnd: lineEl.dataset.pmEnd,
69287
+ rect: { top: rect.top, bottom: rect.bottom },
69288
+ viewY
69289
+ });
68646
69290
  return lineEl;
68647
69291
  }
68648
69292
  }
68649
- return lineEls[lineEls.length - 1];
69293
+ const lastLine = lineEls[lineEls.length - 1];
69294
+ log("findLineAtY: Y beyond all lines, using last line:", {
69295
+ pmStart: lastLine.dataset.pmStart,
69296
+ pmEnd: lastLine.dataset.pmEnd,
69297
+ viewY
69298
+ });
69299
+ return lastLine;
68650
69300
  }
68651
69301
  function findSpanAtX(spanEls, viewX) {
68652
69302
  if (spanEls.length === 0) {
68653
69303
  return null;
68654
69304
  }
68655
69305
  let targetSpan = spanEls[0];
68656
- for (const span of spanEls) {
69306
+ for (let i2 = 0; i2 < spanEls.length; i2++) {
69307
+ const span = spanEls[i2];
68657
69308
  const rect = span.getBoundingClientRect();
68658
69309
  if (viewX >= rect.left && viewX <= rect.right) {
69310
+ log("findSpanAtX: Found containing span at index", i2, {
69311
+ pmStart: span.dataset.pmStart,
69312
+ pmEnd: span.dataset.pmEnd,
69313
+ rect: { left: rect.left, right: rect.right },
69314
+ viewX
69315
+ });
68659
69316
  return span;
68660
69317
  }
68661
69318
  if (viewX > rect.right) {
68662
69319
  targetSpan = span;
68663
69320
  }
68664
69321
  }
69322
+ log("findSpanAtX: No containing span, using nearest:", {
69323
+ pmStart: targetSpan.dataset.pmStart,
69324
+ pmEnd: targetSpan.dataset.pmEnd,
69325
+ viewX
69326
+ });
68665
69327
  return targetSpan;
68666
69328
  }
68667
69329
  function findCharIndexAtX(textNode, span, targetX) {
@@ -68791,7 +69453,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68791
69453
  zones.push(zone);
68792
69454
  },
68793
69455
  getExclusionsForLine(lineY, lineHeight2, columnIndex, pageNumber) {
68794
- return zones.filter((zone) => {
69456
+ const result = zones.filter((zone) => {
68795
69457
  if (zone.pageNumber !== pageNumber || zone.columnIndex !== columnIndex) {
68796
69458
  return false;
68797
69459
  }
@@ -68799,8 +69461,10 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68799
69461
  const lineBottom = lineY + lineHeight2;
68800
69462
  const zoneTop = zone.bounds.y - zone.distances.top;
68801
69463
  const zoneBottom = zone.bounds.y + zone.bounds.height + zone.distances.bottom;
68802
- return lineBottom > zoneTop && lineTop < zoneBottom;
69464
+ const overlaps = lineBottom > zoneTop && lineTop < zoneBottom;
69465
+ return overlaps;
68803
69466
  });
69467
+ return result;
68804
69468
  },
68805
69469
  computeAvailableWidth(lineY, lineHeight2, baseWidth, columnIndex, pageNumber) {
68806
69470
  const exclusions = this.getExclusionsForLine(lineY, lineHeight2, columnIndex, pageNumber);
@@ -68813,6 +69477,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68813
69477
  }
68814
69478
  const leftFloats = [];
68815
69479
  const rightFloats = [];
69480
+ const columnOrigin = marginLeft + columnIndex * (columns.width + columns.gap);
69481
+ const columnCenter = columnOrigin + baseWidth / 2;
68816
69482
  for (const zone of wrappingZones) {
68817
69483
  if (zone.wrapMode === "left") {
68818
69484
  leftFloats.push(zone);
@@ -68820,7 +69486,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68820
69486
  rightFloats.push(zone);
68821
69487
  } else if (zone.wrapMode === "both" || zone.wrapMode === "largest") {
68822
69488
  const zoneCenter = zone.bounds.x + zone.bounds.width / 2;
68823
- if (zoneCenter < baseWidth / 2) {
69489
+ if (zoneCenter < columnCenter) {
68824
69490
  leftFloats.push(zone);
68825
69491
  } else {
68826
69492
  rightFloats.push(zone);
@@ -68832,7 +69498,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
68832
69498
  const boundary = zone.bounds.x + zone.bounds.width + zone.distances.left + zone.distances.right;
68833
69499
  leftBoundary = Math.max(leftBoundary, boundary);
68834
69500
  }
68835
- const columnOrigin = marginLeft + columnIndex * (columns.width + columns.gap);
68836
69501
  const columnRightEdge = columnOrigin + baseWidth;
68837
69502
  let rightBoundary = columnRightEdge;
68838
69503
  for (const zone of rightFloats) {
@@ -69155,9 +69820,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
69155
69820
  pmEnd: end2 ?? (start2 != null ? start2 + 1 : void 0)
69156
69821
  };
69157
69822
  };
69158
- const anchorDebugLog = (...args) => {
69159
- return;
69160
- };
69161
69823
  function layoutParagraphBlock(ctx2, anchors) {
69162
69824
  const { block, measure, columnWidth, ensurePage, advanceColumn, columnX, floatManager } = ctx2;
69163
69825
  const remeasureParagraph2 = ctx2.remeasureParagraph;
@@ -69166,23 +69828,45 @@ Please report this to https://github.com/markedjs/marked.`, e) {
69166
69828
  for (const entry of anchors.anchoredDrawings) {
69167
69829
  if (anchors.placedAnchoredIds.has(entry.block.id)) continue;
69168
69830
  const state2 = ensurePage();
69169
- const baseAnchorY = state2.cursorY;
69170
- const firstLineHeight = measure.lines?.[0]?.lineHeight ?? 0;
69171
69831
  const vRelativeFrom = entry.block.anchor?.vRelativeFrom;
69172
- const paragraphAdjustment = vRelativeFrom === "paragraph" ? firstLineHeight / 2 : 0;
69173
- const anchorY = baseAnchorY + paragraphAdjustment;
69174
- anchorDebugLog("Positioning anchored image:", {
69175
- blockId: entry.block.id,
69176
- baseAnchorY,
69177
- paragraphAdjustment,
69178
- anchorY,
69179
- offsetV: entry.block.anchor?.offsetV,
69180
- finalY: anchorY + (entry.block.anchor?.offsetV ?? 0),
69181
- measureHeight: entry.measure.height,
69182
- measureWidth: entry.measure.width,
69183
- pageNumber: state2.page.number,
69184
- vRelativeFrom
69185
- });
69832
+ const alignV = entry.block.anchor?.alignV;
69833
+ const offsetV = entry.block.anchor?.offsetV ?? 0;
69834
+ const imageHeight = entry.measure.height;
69835
+ const contentTop = state2.topMargin;
69836
+ const contentBottom = state2.contentBottom;
69837
+ const contentHeight = Math.max(0, contentBottom - contentTop);
69838
+ let anchorY;
69839
+ if (vRelativeFrom === "margin") {
69840
+ if (alignV === "top") {
69841
+ anchorY = contentTop + offsetV;
69842
+ } else if (alignV === "bottom") {
69843
+ anchorY = contentBottom - imageHeight + offsetV;
69844
+ } else if (alignV === "center") {
69845
+ anchorY = contentTop + (contentHeight - imageHeight) / 2 + offsetV;
69846
+ } else {
69847
+ anchorY = contentTop + offsetV;
69848
+ }
69849
+ } else if (vRelativeFrom === "page") {
69850
+ if (alignV === "top") {
69851
+ anchorY = offsetV;
69852
+ } else if (alignV === "bottom") {
69853
+ const pageHeight = contentBottom + (anchors.pageMargins.bottom ?? 0);
69854
+ anchorY = pageHeight - imageHeight + offsetV;
69855
+ } else if (alignV === "center") {
69856
+ const pageHeight = contentBottom + (anchors.pageMargins.bottom ?? 0);
69857
+ anchorY = (pageHeight - imageHeight) / 2 + offsetV;
69858
+ } else {
69859
+ anchorY = offsetV;
69860
+ }
69861
+ } else if (vRelativeFrom === "paragraph") {
69862
+ const baseAnchorY = state2.cursorY;
69863
+ const firstLineHeight = measure.lines?.[0]?.lineHeight ?? 0;
69864
+ const paragraphAdjustment = firstLineHeight / 2;
69865
+ anchorY = baseAnchorY + paragraphAdjustment + offsetV;
69866
+ } else {
69867
+ const baseAnchorY = state2.cursorY;
69868
+ anchorY = baseAnchorY + offsetV;
69869
+ }
69186
69870
  floatManager.registerDrawing(entry.block, entry.measure, anchorY, state2.columnIndex, state2.page.number);
69187
69871
  const anchorX = entry.block.anchor ? computeAnchorX(
69188
69872
  entry.block.anchor,
@@ -69222,7 +69906,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
69222
69906
  kind: "image",
69223
69907
  blockId: entry.block.id,
69224
69908
  x: anchorX,
69225
- y: anchorY + (entry.block.anchor?.offsetV ?? 0),
69909
+ y: anchorY,
69226
69910
  width: entry.measure.width,
69227
69911
  height: entry.measure.height,
69228
69912
  isAnchored: true,
@@ -69238,7 +69922,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
69238
69922
  blockId: entry.block.id,
69239
69923
  drawingKind: entry.block.drawingKind,
69240
69924
  x: anchorX,
69241
- y: anchorY + (entry.block.anchor?.offsetV ?? 0),
69925
+ y: anchorY,
69242
69926
  width: entry.measure.width,
69243
69927
  height: entry.measure.height,
69244
69928
  geometry: entry.measure.geometry,
@@ -69299,7 +69983,39 @@ Please report this to https://github.com/markedjs/marked.`, e) {
69299
69983
  state2.lastParagraphStyleId = styleId;
69300
69984
  return;
69301
69985
  }
69986
+ let narrowestWidth = columnWidth;
69987
+ let narrowestOffsetX = 0;
69302
69988
  let didRemeasureForFloats = false;
69989
+ if (typeof remeasureParagraph2 === "function") {
69990
+ const tempState = ensurePage();
69991
+ let tempY = tempState.cursorY;
69992
+ if (!appliedSpacingBefore && spacingBefore > 0) {
69993
+ const prevTrailing = tempState.trailingSpacing ?? 0;
69994
+ const neededSpacingBefore = Math.max(spacingBefore - prevTrailing, 0);
69995
+ tempY += neededSpacingBefore;
69996
+ }
69997
+ for (let i2 = 0; i2 < lines.length; i2++) {
69998
+ const lineY = tempY;
69999
+ const lineHeight2 = lines[i2]?.lineHeight || 0;
70000
+ const { width: availableWidth, offsetX: computedOffset } = floatManager.computeAvailableWidth(
70001
+ lineY,
70002
+ lineHeight2,
70003
+ columnWidth,
70004
+ tempState.columnIndex,
70005
+ tempState.page.number
70006
+ );
70007
+ if (availableWidth < narrowestWidth) {
70008
+ narrowestWidth = availableWidth;
70009
+ narrowestOffsetX = computedOffset;
70010
+ }
70011
+ tempY += lineHeight2;
70012
+ }
70013
+ if (narrowestWidth < columnWidth) {
70014
+ const newMeasure = remeasureParagraph2(block, narrowestWidth);
70015
+ lines = normalizeLines(newMeasure);
70016
+ didRemeasureForFloats = true;
70017
+ }
70018
+ }
69303
70019
  while (fromLine < lines.length) {
69304
70020
  let state2 = ensurePage();
69305
70021
  if (state2.trailingSpacing == null) state2.trailingSpacing = 0;
@@ -69344,23 +70060,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
69344
70060
  }
69345
70061
  let effectiveColumnWidth = columnWidth;
69346
70062
  let offsetX = 0;
69347
- if (!didRemeasureForFloats && typeof remeasureParagraph2 === "function") {
69348
- const firstLineY = state2.cursorY;
69349
- const firstLineHeight = lines[fromLine]?.lineHeight || 0;
69350
- const { width: adjustedWidth, offsetX: computedOffset } = floatManager.computeAvailableWidth(
69351
- firstLineY,
69352
- firstLineHeight,
69353
- columnWidth,
69354
- state2.columnIndex,
69355
- state2.page.number
69356
- );
69357
- if (adjustedWidth < columnWidth) {
69358
- const newMeasure = remeasureParagraph2(block, adjustedWidth);
69359
- lines = normalizeLines(newMeasure);
69360
- didRemeasureForFloats = true;
69361
- effectiveColumnWidth = adjustedWidth;
69362
- offsetX = computedOffset;
69363
- }
70063
+ if (didRemeasureForFloats) {
70064
+ effectiveColumnWidth = narrowestWidth;
70065
+ offsetX = narrowestOffsetX;
69364
70066
  }
69365
70067
  const slice2 = sliceLines(lines, fromLine, state2.contentBottom - state2.cursorY);
69366
70068
  const fragmentHeight = slice2.height;
@@ -69374,15 +70076,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
69374
70076
  width: effectiveColumnWidth,
69375
70077
  ...computeFragmentPmRange(block, lines, fromLine, slice2.toLine)
69376
70078
  };
69377
- anchorDebugLog("Positioning paragraph fragment:", {
69378
- blockId: block.id,
69379
- fragmentY: state2.cursorY,
69380
- fragmentHeight,
69381
- firstLineHeight: lines[fromLine]?.lineHeight,
69382
- firstLineAscent: lines[fromLine]?.ascent,
69383
- firstLineDescent: lines[fromLine]?.descent,
69384
- pageNumber: state2.page.number
69385
- });
69386
70079
  if (measure.marker && fromLine === 0) {
69387
70080
  fragment.markerWidth = measure.marker.markerWidth;
69388
70081
  }
@@ -69595,9 +70288,32 @@ Please report this to https://github.com/markedjs/marked.`, e) {
69595
70288
  state2.page.fragments.push(fragment);
69596
70289
  state2.cursorY += height;
69597
70290
  }
70291
+ function isPageRelativeAnchor(block) {
70292
+ const vRelativeFrom = block.anchor?.vRelativeFrom;
70293
+ return vRelativeFrom === "margin" || vRelativeFrom === "page";
70294
+ }
70295
+ function collectPreRegisteredAnchors(blocks2, measures) {
70296
+ const result = [];
70297
+ const len2 = Math.min(blocks2.length, measures.length);
70298
+ for (let i2 = 0; i2 < len2; i2 += 1) {
70299
+ const block = blocks2[i2];
70300
+ const measure = measures[i2];
70301
+ const isImage = block.kind === "image" && measure?.kind === "image";
70302
+ const isDrawing = block.kind === "drawing" && measure?.kind === "drawing";
70303
+ if (!isImage && !isDrawing) continue;
70304
+ const drawingBlock = block;
70305
+ const drawingMeasure = measure;
70306
+ if (!drawingBlock.anchor?.isAnchored) continue;
70307
+ if (isPageRelativeAnchor(drawingBlock)) {
70308
+ result.push({ block: drawingBlock, measure: drawingMeasure });
70309
+ }
70310
+ }
70311
+ return result;
70312
+ }
69598
70313
  function collectAnchoredDrawings(blocks2, measures) {
69599
70314
  const map2 = /* @__PURE__ */ new Map();
69600
- for (let i2 = 0; i2 < blocks2.length; i2 += 1) {
70315
+ const len2 = Math.min(blocks2.length, measures.length);
70316
+ for (let i2 = 0; i2 < len2; i2 += 1) {
69601
70317
  if (blocks2[i2].kind === "paragraph") ;
69602
70318
  }
69603
70319
  const nearestPrevParagraph = (fromIndex) => {
@@ -69607,12 +70323,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
69607
70323
  return null;
69608
70324
  };
69609
70325
  const nearestNextParagraph = (fromIndex) => {
69610
- for (let i2 = fromIndex + 1; i2 < blocks2.length; i2 += 1) {
70326
+ for (let i2 = fromIndex + 1; i2 < len2; i2 += 1) {
69611
70327
  if (blocks2[i2].kind === "paragraph") return i2;
69612
70328
  }
69613
70329
  return null;
69614
70330
  };
69615
- for (let i2 = 0; i2 < blocks2.length; i2 += 1) {
70331
+ for (let i2 = 0; i2 < len2; i2 += 1) {
69616
70332
  const block = blocks2[i2];
69617
70333
  const measure = measures[i2];
69618
70334
  const isImage = block.kind === "image" && measure?.kind === "image";
@@ -69620,7 +70336,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
69620
70336
  if (!isImage && !isDrawing) continue;
69621
70337
  const drawingBlock = block;
69622
70338
  const drawingMeasure = measure;
69623
- if (!drawingBlock.anchor?.isAnchored) continue;
70339
+ if (!drawingBlock.anchor?.isAnchored) {
70340
+ continue;
70341
+ }
70342
+ if (isPageRelativeAnchor(drawingBlock)) {
70343
+ continue;
70344
+ }
69624
70345
  let anchorParaIndex = nearestPrevParagraph(i2);
69625
70346
  if (anchorParaIndex == null) anchorParaIndex = nearestNextParagraph(i2);
69626
70347
  if (anchorParaIndex == null) continue;
@@ -70216,6 +70937,54 @@ Please report this to https://github.com/markedjs/marked.`, e) {
70216
70937
  };
70217
70938
  const anchoredByParagraph = collectAnchoredDrawings(blocks2, measures);
70218
70939
  const placedAnchoredIds = /* @__PURE__ */ new Set();
70940
+ const preRegisteredAnchors = collectPreRegisteredAnchors(blocks2, measures);
70941
+ const preRegisteredPositions = /* @__PURE__ */ new Map();
70942
+ for (const entry of preRegisteredAnchors) {
70943
+ const state2 = paginator.ensurePage();
70944
+ const vRelativeFrom = entry.block.anchor?.vRelativeFrom ?? "paragraph";
70945
+ const alignV = entry.block.anchor?.alignV ?? "top";
70946
+ const offsetV = entry.block.anchor?.offsetV ?? 0;
70947
+ const imageHeight = entry.measure.height ?? 0;
70948
+ const contentTop = state2.topMargin;
70949
+ const contentBottom = state2.contentBottom;
70950
+ const contentHeight = Math.max(0, contentBottom - contentTop);
70951
+ let anchorY;
70952
+ if (vRelativeFrom === "margin") {
70953
+ if (alignV === "top") {
70954
+ anchorY = contentTop + offsetV;
70955
+ } else if (alignV === "bottom") {
70956
+ anchorY = contentBottom - imageHeight + offsetV;
70957
+ } else if (alignV === "center") {
70958
+ anchorY = contentTop + (contentHeight - imageHeight) / 2 + offsetV;
70959
+ } else {
70960
+ anchorY = contentTop + offsetV;
70961
+ }
70962
+ } else if (vRelativeFrom === "page") {
70963
+ if (alignV === "top") {
70964
+ anchorY = offsetV;
70965
+ } else if (alignV === "bottom") {
70966
+ const pageHeight = contentBottom + margins.bottom;
70967
+ anchorY = pageHeight - imageHeight + offsetV;
70968
+ } else if (alignV === "center") {
70969
+ const pageHeight = contentBottom + margins.bottom;
70970
+ anchorY = (pageHeight - imageHeight) / 2 + offsetV;
70971
+ } else {
70972
+ anchorY = offsetV;
70973
+ }
70974
+ } else {
70975
+ anchorY = contentTop + offsetV;
70976
+ }
70977
+ const anchorX = entry.block.anchor ? computeAnchorX(
70978
+ entry.block.anchor,
70979
+ state2.columnIndex,
70980
+ normalizeColumns(activeColumns, contentWidth),
70981
+ entry.measure.width,
70982
+ { left: margins.left, right: margins.right },
70983
+ activePageSize.w
70984
+ ) : margins.left;
70985
+ floatManager.registerDrawing(entry.block, entry.measure, anchorY, state2.columnIndex, state2.page.number);
70986
+ preRegisteredPositions.set(entry.block.id, { anchorX, anchorY, pageNumber: state2.page.number });
70987
+ }
70219
70988
  for (let index2 = 0; index2 < blocks2.length; index2 += 1) {
70220
70989
  const block = blocks2[index2];
70221
70990
  const measure = measures[index2];
@@ -70375,6 +71144,52 @@ Please report this to https://github.com/markedjs/marked.`, e) {
70375
71144
  if (measure.kind !== "image") {
70376
71145
  throw new Error(`layoutDocument: expected image measure for block ${block.id}`);
70377
71146
  }
71147
+ const preRegPos = preRegisteredPositions.get(block.id);
71148
+ if (preRegPos && Number.isFinite(preRegPos.anchorX) && Number.isFinite(preRegPos.anchorY) && Number.isFinite(preRegPos.pageNumber)) {
71149
+ const state2 = paginator.ensurePage();
71150
+ const imgBlock = block;
71151
+ const imgMeasure = measure;
71152
+ const pageContentHeight = Math.max(0, state2.contentBottom - state2.topMargin);
71153
+ const relativeFrom = imgBlock.anchor?.hRelativeFrom ?? "column";
71154
+ const cols = getCurrentColumns();
71155
+ let maxWidth;
71156
+ if (relativeFrom === "page") {
71157
+ maxWidth = cols.count === 1 ? activePageSize.w - margins.left - margins.right : activePageSize.w;
71158
+ } else if (relativeFrom === "margin") {
71159
+ maxWidth = activePageSize.w - margins.left - margins.right;
71160
+ } else {
71161
+ maxWidth = cols.width;
71162
+ }
71163
+ const aspectRatio = imgMeasure.width > 0 && imgMeasure.height > 0 ? imgMeasure.width / imgMeasure.height : 1;
71164
+ const minWidth = 20;
71165
+ const minHeight = minWidth / aspectRatio;
71166
+ const metadata = {
71167
+ originalWidth: imgMeasure.width,
71168
+ originalHeight: imgMeasure.height,
71169
+ maxWidth,
71170
+ maxHeight: pageContentHeight,
71171
+ aspectRatio,
71172
+ minWidth,
71173
+ minHeight
71174
+ };
71175
+ const fragment = {
71176
+ kind: "image",
71177
+ blockId: imgBlock.id,
71178
+ x: preRegPos.anchorX,
71179
+ y: preRegPos.anchorY,
71180
+ width: imgMeasure.width,
71181
+ height: imgMeasure.height,
71182
+ isAnchored: true,
71183
+ zIndex: imgBlock.anchor?.behindDoc ? 0 : 1,
71184
+ metadata
71185
+ };
71186
+ const attrs = imgBlock.attrs;
71187
+ if (attrs?.pmStart != null) fragment.pmStart = attrs.pmStart;
71188
+ if (attrs?.pmEnd != null) fragment.pmEnd = attrs.pmEnd;
71189
+ state2.page.fragments.push(fragment);
71190
+ placedAnchoredIds.add(imgBlock.id);
71191
+ continue;
71192
+ }
70378
71193
  layoutImageBlock({
70379
71194
  block,
70380
71195
  measure,
@@ -70570,7 +71385,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
70570
71385
  const trackedMode = block.attrs && "trackedChangesMode" in block.attrs && block.attrs.trackedChangesMode || "review";
70571
71386
  const trackedEnabled = resolveTrackedChangesEnabled(block.attrs, true);
70572
71387
  const runsHash = block.runs.map((run2) => {
70573
- const text2 = normalizeText(run2.kind === "image" ? "" : run2.text ?? "");
71388
+ const text2 = normalizeText("src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "");
70574
71389
  const bold = "bold" in run2 ? run2.bold : false;
70575
71390
  const italic = "italic" in run2 ? run2.italic : false;
70576
71391
  const color2 = "color" in run2 ? run2.color : void 0;
@@ -70839,7 +71654,13 @@ Please report this to https://github.com/markedjs/marked.`, e) {
70839
71654
  * Logs cache hits, misses, invalidations, and bucket selection.
70840
71655
  * Should be disabled in production (only enabled for debugging).
70841
71656
  */
70842
- DEBUG_HF_CACHE: isEnabled("SD_DEBUG_HF_CACHE", false)
71657
+ DEBUG_HF_CACHE: isEnabled("SD_DEBUG_HF_CACHE", false),
71658
+ /**
71659
+ * Enable debug logging for layout version tracking.
71660
+ * Logs stale layout reads, geometry fallbacks, PM transactions, and layout completions.
71661
+ * Should be disabled in production (only enabled for debugging).
71662
+ */
71663
+ DEBUG_LAYOUT_VERSION: isEnabled("SD_DEBUG_LAYOUT_VERSION", false)
70843
71664
  };
70844
71665
  const PageTokenLogger = {
70845
71666
  /**
@@ -71224,7 +72045,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
71224
72045
  return `${italic}${bold}${size2}px ${family}`.trim();
71225
72046
  }
71226
72047
  function runText(run2) {
71227
- return run2.kind === "image" ? "" : run2.text ?? "";
72048
+ return "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
71228
72049
  }
71229
72050
  function measureRunSliceWidth(run2, fromChar, toChar) {
71230
72051
  const context = getCtx();
@@ -71386,7 +72207,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
71386
72207
  for (let i2 = 0; i2 < a2.runs.length; i2 += 1) {
71387
72208
  const runA = a2.runs[i2];
71388
72209
  const runB = b2.runs[i2];
71389
- 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)) {
72210
+ 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)) {
71390
72211
  return false;
71391
72212
  }
71392
72213
  }
@@ -71506,7 +72327,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
71506
72327
  parts.push(block.id);
71507
72328
  if (block.kind === "paragraph") {
71508
72329
  for (const run2 of block.runs) {
71509
- if (run2.kind !== "image") {
72330
+ if (!("src" in run2) && run2.kind !== "lineBreak") {
71510
72331
  parts.push(run2.text ?? "");
71511
72332
  }
71512
72333
  if ("bold" in run2 && run2.bold) parts.push("b");
@@ -71935,6 +72756,23 @@ Please report this to https://github.com/markedjs/marked.`, e) {
71935
72756
  }
71936
72757
  return updatedMeasures;
71937
72758
  }
72759
+ var Priority = /* @__PURE__ */ ((Priority2) => {
72760
+ Priority2[Priority2["P0"] = 0] = "P0";
72761
+ Priority2[Priority2["P1"] = 1] = "P1";
72762
+ Priority2[Priority2["P2"] = 2] = "P2";
72763
+ Priority2[Priority2["P3"] = 3] = "P3";
72764
+ return Priority2;
72765
+ })(Priority || {});
72766
+ ({
72767
+ /** P0: No debounce for synchronous cursor positioning */
72768
+ [Priority.P0]: 0,
72769
+ /** P1: One animation frame (~60fps) for viewport layout */
72770
+ [Priority.P1]: 16,
72771
+ /** P2: Typing burst threshold for adjacent pages layout */
72772
+ [Priority.P2]: 50,
72773
+ /** P3: Heavy debounce for full document layout */
72774
+ [Priority.P3]: 150
72775
+ });
71938
72776
  const isAtomicFragment = (fragment) => {
71939
72777
  return fragment.kind === "drawing" || fragment.kind === "image";
71940
72778
  };
@@ -72022,6 +72860,111 @@ Please report this to https://github.com/markedjs/marked.`, e) {
72022
72860
  }
72023
72861
  return null;
72024
72862
  };
72863
+ const hitTestTableFragment = (pageHit, blocks2, measures, point2) => {
72864
+ for (const fragment of pageHit.page.fragments) {
72865
+ if (fragment.kind !== "table") continue;
72866
+ const tableFragment = fragment;
72867
+ const withinX = point2.x >= tableFragment.x && point2.x <= tableFragment.x + tableFragment.width;
72868
+ const withinY = point2.y >= tableFragment.y && point2.y <= tableFragment.y + tableFragment.height;
72869
+ if (!withinX || !withinY) continue;
72870
+ const blockIndex = blocks2.findIndex((block2) => block2.id === tableFragment.blockId);
72871
+ if (blockIndex === -1) continue;
72872
+ const block = blocks2[blockIndex];
72873
+ const measure = measures[blockIndex];
72874
+ if (!block || block.kind !== "table" || !measure || measure.kind !== "table") continue;
72875
+ const tableBlock = block;
72876
+ const tableMeasure = measure;
72877
+ const localX = point2.x - tableFragment.x;
72878
+ const localY = point2.y - tableFragment.y;
72879
+ let rowY = 0;
72880
+ let rowIndex = -1;
72881
+ if (tableMeasure.rows.length === 0 || tableBlock.rows.length === 0) continue;
72882
+ for (let r2 = tableFragment.fromRow; r2 < tableFragment.toRow && r2 < tableMeasure.rows.length; r2++) {
72883
+ const rowMeasure2 = tableMeasure.rows[r2];
72884
+ if (localY >= rowY && localY < rowY + rowMeasure2.height) {
72885
+ rowIndex = r2;
72886
+ break;
72887
+ }
72888
+ rowY += rowMeasure2.height;
72889
+ }
72890
+ if (rowIndex === -1) {
72891
+ rowIndex = Math.min(tableFragment.toRow - 1, tableMeasure.rows.length - 1);
72892
+ if (rowIndex < tableFragment.fromRow) continue;
72893
+ }
72894
+ const rowMeasure = tableMeasure.rows[rowIndex];
72895
+ const row2 = tableBlock.rows[rowIndex];
72896
+ if (!rowMeasure || !row2) continue;
72897
+ let colX = 0;
72898
+ let colIndex = -1;
72899
+ if (rowMeasure.cells.length === 0 || row2.cells.length === 0) continue;
72900
+ for (let c2 = 0; c2 < rowMeasure.cells.length; c2++) {
72901
+ const cellMeasure2 = rowMeasure.cells[c2];
72902
+ if (localX >= colX && localX < colX + cellMeasure2.width) {
72903
+ colIndex = c2;
72904
+ break;
72905
+ }
72906
+ colX += cellMeasure2.width;
72907
+ }
72908
+ if (colIndex === -1) {
72909
+ colIndex = rowMeasure.cells.length - 1;
72910
+ if (colIndex < 0) continue;
72911
+ }
72912
+ const cellMeasure = rowMeasure.cells[colIndex];
72913
+ const cell2 = row2.cells[colIndex];
72914
+ if (!cellMeasure || !cell2) continue;
72915
+ const cellBlocks = cell2.blocks ?? (cell2.paragraph ? [cell2.paragraph] : []);
72916
+ const rawMeasures = cellMeasure.blocks ?? (cellMeasure.paragraph ? [cellMeasure.paragraph] : []);
72917
+ const cellBlockMeasures = (Array.isArray(rawMeasures) ? rawMeasures : []).filter(
72918
+ (m2) => m2 != null && typeof m2 === "object" && "kind" in m2
72919
+ );
72920
+ let blockStartY = 0;
72921
+ const getBlockHeight = (m2) => {
72922
+ if (!m2) return 0;
72923
+ if ("totalHeight" in m2 && typeof m2.totalHeight === "number") {
72924
+ return m2.totalHeight;
72925
+ }
72926
+ if ("height" in m2 && typeof m2.height === "number") {
72927
+ return m2.height;
72928
+ }
72929
+ return 0;
72930
+ };
72931
+ for (let i2 = 0; i2 < cellBlocks.length && i2 < cellBlockMeasures.length; i2++) {
72932
+ const cellBlock = cellBlocks[i2];
72933
+ const cellBlockMeasure = cellBlockMeasures[i2];
72934
+ if (cellBlock?.kind !== "paragraph" || cellBlockMeasure?.kind !== "paragraph") {
72935
+ blockStartY += getBlockHeight(cellBlockMeasure);
72936
+ continue;
72937
+ }
72938
+ const blockHeight = getBlockHeight(cellBlockMeasure);
72939
+ const blockEndY = blockStartY + blockHeight;
72940
+ const padding = cell2.attrs?.padding ?? { top: 2, left: 4 };
72941
+ const cellLocalX = localX - colX - (padding.left ?? 4);
72942
+ const cellLocalY = localY - rowY - (padding.top ?? 2);
72943
+ const paragraphBlock = cellBlock;
72944
+ const paragraphMeasure = cellBlockMeasure;
72945
+ const isWithinBlock = cellLocalY >= blockStartY && cellLocalY < blockEndY;
72946
+ const isLastParagraph = i2 === Math.min(cellBlocks.length, cellBlockMeasures.length) - 1;
72947
+ if (isWithinBlock || isLastParagraph) {
72948
+ const unclampedLocalY = cellLocalY - blockStartY;
72949
+ const localYWithinBlock = Math.max(0, Math.min(unclampedLocalY, Math.max(blockHeight, 0)));
72950
+ return {
72951
+ fragment: tableFragment,
72952
+ block: tableBlock,
72953
+ measure: tableMeasure,
72954
+ pageIndex: pageHit.pageIndex,
72955
+ cellRowIndex: rowIndex,
72956
+ cellColIndex: colIndex,
72957
+ cellBlock: paragraphBlock,
72958
+ cellMeasure: paragraphMeasure,
72959
+ localX: Math.max(0, cellLocalX),
72960
+ localY: Math.max(0, localYWithinBlock)
72961
+ };
72962
+ }
72963
+ blockStartY = blockEndY;
72964
+ }
72965
+ }
72966
+ return null;
72967
+ };
72025
72968
  function clickToPosition(layout, blocks2, measures, containerPoint, domContainer, clientX, clientY) {
72026
72969
  logClickStage("log", "entry", {
72027
72970
  pages: layout.pages.length
@@ -72116,6 +73059,49 @@ Please report this to https://github.com/markedjs/marked.`, e) {
72116
73059
  // lineIndex is now already absolute (within measure.lines), no need to add fragment.fromLine
72117
73060
  };
72118
73061
  }
73062
+ const tableHit = hitTestTableFragment(pageHit, blocks2, measures, pageRelativePoint);
73063
+ if (tableHit) {
73064
+ const { cellBlock, cellMeasure, localX, localY, pageIndex } = tableHit;
73065
+ const lineIndex = findLineIndexAtY(cellMeasure, localY, 0, cellMeasure.lines.length);
73066
+ if (lineIndex != null) {
73067
+ const line = cellMeasure.lines[lineIndex];
73068
+ const isRTL = isRtlBlock(cellBlock);
73069
+ const pos = mapPointToPm(cellBlock, line, localX, isRTL);
73070
+ if (pos != null) {
73071
+ logClickStage("log", "success", {
73072
+ blockId: tableHit.fragment.blockId,
73073
+ column: determineColumn(layout, tableHit.fragment.x)
73074
+ });
73075
+ return {
73076
+ pos,
73077
+ blockId: tableHit.fragment.blockId,
73078
+ pageIndex,
73079
+ column: determineColumn(layout, tableHit.fragment.x),
73080
+ lineIndex
73081
+ };
73082
+ }
73083
+ }
73084
+ const firstRun = cellBlock.runs?.[0];
73085
+ if (firstRun && firstRun.pmStart != null) {
73086
+ logClickStage("log", "success", {
73087
+ blockId: tableHit.fragment.blockId,
73088
+ pos: firstRun.pmStart,
73089
+ column: determineColumn(layout, tableHit.fragment.x)
73090
+ });
73091
+ return {
73092
+ pos: firstRun.pmStart,
73093
+ blockId: tableHit.fragment.blockId,
73094
+ pageIndex,
73095
+ column: determineColumn(layout, tableHit.fragment.x),
73096
+ lineIndex: 0
73097
+ };
73098
+ }
73099
+ logClickStage("warn", "table-cell-no-position", {
73100
+ blockId: tableHit.fragment.blockId,
73101
+ cellRow: tableHit.cellRowIndex,
73102
+ cellCol: tableHit.cellColIndex
73103
+ });
73104
+ }
72119
73105
  const atomicHit = hitTestAtomicFragment(pageHit, blocks2, measures, pageRelativePoint);
72120
73106
  if (atomicHit && isAtomicFragment(atomicHit.fragment)) {
72121
73107
  const { fragment, block, pageIndex } = atomicHit;
@@ -72227,6 +73213,44 @@ Please report this to https://github.com/markedjs/marked.`, e) {
72227
73213
  }
72228
73214
  continue;
72229
73215
  }
73216
+ if (fragment.kind === "table") {
73217
+ if (block.kind !== "table" || measure.kind !== "table") continue;
73218
+ const tableBlock = block;
73219
+ const tableFragment = fragment;
73220
+ let tableMinPos = null;
73221
+ let tableMaxPos = null;
73222
+ for (let r2 = tableFragment.fromRow; r2 < tableFragment.toRow && r2 < tableBlock.rows.length; r2++) {
73223
+ const row2 = tableBlock.rows[r2];
73224
+ for (const cell2 of row2.cells) {
73225
+ const cellBlocks = cell2.blocks ?? (cell2.paragraph ? [cell2.paragraph] : []);
73226
+ for (const cellBlock of cellBlocks) {
73227
+ if (cellBlock?.kind === "paragraph") {
73228
+ const paraBlock = cellBlock;
73229
+ for (const run2 of paraBlock.runs ?? []) {
73230
+ if (run2.pmStart != null) {
73231
+ if (tableMinPos === null || run2.pmStart < tableMinPos) tableMinPos = run2.pmStart;
73232
+ if (tableMaxPos === null || run2.pmStart > tableMaxPos) tableMaxPos = run2.pmStart;
73233
+ }
73234
+ if (run2.pmEnd != null) {
73235
+ if (tableMinPos === null || run2.pmEnd < tableMinPos) tableMinPos = run2.pmEnd;
73236
+ if (tableMaxPos === null || run2.pmEnd > tableMaxPos) tableMaxPos = run2.pmEnd;
73237
+ }
73238
+ }
73239
+ }
73240
+ }
73241
+ }
73242
+ }
73243
+ if (tableMinPos != null && tableMaxPos != null && pos >= tableMinPos && pos <= tableMaxPos) {
73244
+ return {
73245
+ fragment,
73246
+ block,
73247
+ measure,
73248
+ pageIndex,
73249
+ pageY: 0
73250
+ };
73251
+ }
73252
+ continue;
73253
+ }
72230
73254
  if (isAtomicFragment(fragment)) {
72231
73255
  const { pmStart, pmEnd } = getAtomicPmRange(fragment, block);
72232
73256
  const start2 = pmStart ?? pmEnd;
@@ -72274,7 +73298,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
72274
73298
  for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
72275
73299
  const run2 = block.runs[runIndex];
72276
73300
  if (!run2) continue;
72277
- const text2 = run2.kind === "image" ? "" : run2.text ?? "";
73301
+ const text2 = "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
72278
73302
  const runLength = text2.length;
72279
73303
  const runPmStart = run2.pmStart ?? null;
72280
73304
  const runPmEnd = run2.pmEnd ?? (runPmStart != null ? runPmStart + runLength : null);
@@ -74670,16 +75694,6 @@ ${l}
74670
75694
  opacity: 0.8;
74671
75695
  }
74672
75696
 
74673
- /* External link indicator (WCAG 2.4.4 Link Purpose) */
74674
- .superdoc-link[target="_blank"]::after {
74675
- content: "↗";
74676
- display: inline-block;
74677
- margin-left: 0.25em;
74678
- font-size: 0.85em;
74679
- text-decoration: none;
74680
- speak: literal-punctuation; /* Screen readers read the arrow */
74681
- }
74682
-
74683
75697
  /* Print mode: show URLs after links */
74684
75698
  @media print {
74685
75699
  .superdoc-link::after {
@@ -74692,11 +75706,6 @@ ${l}
74692
75706
  .superdoc-link[href^="#"]::after {
74693
75707
  content: "";
74694
75708
  }
74695
-
74696
- /* Don't show URL for external link indicator */
74697
- .superdoc-link[target="_blank"]::after {
74698
- content: " (" attr(href) ")";
74699
- }
74700
75709
  }
74701
75710
 
74702
75711
  /* High contrast mode support */
@@ -74714,13 +75723,6 @@ ${l}
74714
75723
  }
74715
75724
  }
74716
75725
 
74717
- /* RTL layout support */
74718
- .superdoc-layout[dir="rtl"] .superdoc-link[target="_blank"]::after {
74719
- margin-left: 0;
74720
- margin-right: 0.25em;
74721
- content: "↖"; /* Mirror the arrow for RTL */
74722
- }
74723
-
74724
75726
  /* Screen reader only content (WCAG SC 1.3.1) */
74725
75727
  .sr-only {
74726
75728
  position: absolute;
@@ -75175,7 +76177,100 @@ ${l}
75175
76177
  }
75176
76178
  return container;
75177
76179
  };
76180
+ const isDevelopment = () => {
76181
+ if (typeof process$1$1 !== "undefined" && typeof process$1$1.env !== "undefined") {
76182
+ return process$1$1.env.NODE_ENV === "development";
76183
+ }
76184
+ return false;
76185
+ };
76186
+ class ValidationStatsCollector {
76187
+ constructor() {
76188
+ this.stats = {
76189
+ totalSpans: 0,
76190
+ validSpans: 0,
76191
+ missingPmStart: 0,
76192
+ missingPmEnd: 0,
76193
+ missingBoth: 0
76194
+ };
76195
+ }
76196
+ record(hasPmStart, hasPmEnd) {
76197
+ this.stats.totalSpans++;
76198
+ if (hasPmStart && hasPmEnd) {
76199
+ this.stats.validSpans++;
76200
+ } else if (!hasPmStart && !hasPmEnd) {
76201
+ this.stats.missingBoth++;
76202
+ } else if (!hasPmStart) {
76203
+ this.stats.missingPmStart++;
76204
+ } else {
76205
+ this.stats.missingPmEnd++;
76206
+ }
76207
+ }
76208
+ getStats() {
76209
+ return { ...this.stats };
76210
+ }
76211
+ reset() {
76212
+ this.stats = {
76213
+ totalSpans: 0,
76214
+ validSpans: 0,
76215
+ missingPmStart: 0,
76216
+ missingPmEnd: 0,
76217
+ missingBoth: 0
76218
+ };
76219
+ }
76220
+ getCoveragePercent() {
76221
+ if (this.stats.totalSpans === 0) return 100;
76222
+ return this.stats.validSpans / this.stats.totalSpans * 100;
76223
+ }
76224
+ logSummary() {
76225
+ if (!isDevelopment()) return;
76226
+ const coverage = this.getCoveragePercent();
76227
+ const s2 = this.stats;
76228
+ if (coverage < 100) {
76229
+ console.warn("[PmPositionValidation] PM position coverage:", {
76230
+ coverage: `${coverage.toFixed(1)}%`,
76231
+ totalSpans: s2.totalSpans,
76232
+ validSpans: s2.validSpans,
76233
+ missingPmStart: s2.missingPmStart,
76234
+ missingPmEnd: s2.missingPmEnd,
76235
+ missingBoth: s2.missingBoth
76236
+ });
76237
+ }
76238
+ }
76239
+ }
76240
+ const globalValidationStats = new ValidationStatsCollector();
76241
+ function assertPmPositions(run2, context) {
76242
+ const hasPmStart = run2.pmStart != null;
76243
+ const hasPmEnd = run2.pmEnd != null;
76244
+ globalValidationStats.record(hasPmStart, hasPmEnd);
76245
+ if (!isDevelopment()) return;
76246
+ if (!hasPmStart || !hasPmEnd) {
76247
+ const textPreview = run2.text ? run2.text.substring(0, 20) + (run2.text.length > 20 ? "..." : "") : "(no text)";
76248
+ console.warn(`[PmPositionValidation] Missing PM positions in ${context}:`, {
76249
+ hasPmStart,
76250
+ hasPmEnd,
76251
+ textPreview,
76252
+ fallback: "Will use PM DOM coordinates for cursor positioning"
76253
+ });
76254
+ }
76255
+ }
76256
+ function assertFragmentPmPositions(fragment, context) {
76257
+ const hasPmStart = fragment.pmStart != null;
76258
+ const hasPmEnd = fragment.pmEnd != null;
76259
+ globalValidationStats.record(hasPmStart, hasPmEnd);
76260
+ if (!isDevelopment()) return;
76261
+ if (!hasPmStart || !hasPmEnd) {
76262
+ console.warn(`[PmPositionValidation] Missing PM positions in ${context}:`, {
76263
+ fragmentKind: fragment.kind ?? "unknown",
76264
+ hasPmStart,
76265
+ hasPmEnd,
76266
+ fallback: "Will use PM DOM coordinates for cursor positioning"
76267
+ });
76268
+ }
76269
+ }
75178
76270
  const LIST_MARKER_GAP$1 = 8;
76271
+ const COMMENT_EXTERNAL_COLOR = "#B1124B";
76272
+ const COMMENT_INTERNAL_COLOR = "#078383";
76273
+ const COMMENT_INACTIVE_ALPHA = "22";
75179
76274
  const LINK_DATASET_KEYS = {
75180
76275
  blocked: "linkBlocked",
75181
76276
  docLocation: "linkDocLocation",
@@ -75832,7 +76927,7 @@ ${l}
75832
76927
  current.element = replacement;
75833
76928
  current.signature = fragmentSignature(fragment, this.blockLookup);
75834
76929
  }
75835
- this.updateFragmentElement(current.element, fragment);
76930
+ this.updateFragmentElement(current.element, fragment, contextBase.section);
75836
76931
  current.fragment = fragment;
75837
76932
  current.key = key2;
75838
76933
  current.context = contextBase;
@@ -75900,10 +76995,10 @@ ${l}
75900
76995
  return this.renderListItemFragment(fragment, context);
75901
76996
  }
75902
76997
  if (fragment.kind === "image") {
75903
- return this.renderImageFragment(fragment);
76998
+ return this.renderImageFragment(fragment, context);
75904
76999
  }
75905
77000
  if (fragment.kind === "drawing") {
75906
- return this.renderDrawingFragment(fragment);
77001
+ return this.renderDrawingFragment(fragment, context);
75907
77002
  }
75908
77003
  if (fragment.kind === "table") {
75909
77004
  return this.renderTableFragment(fragment, context);
@@ -75936,7 +77031,7 @@ ${l}
75936
77031
  const hasMarker = !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker;
75937
77032
  const styles = isTocEntry ? { ...fragmentStyles, whiteSpace: "nowrap" } : hasMarker ? { ...fragmentStyles, overflow: "visible" } : fragmentStyles;
75938
77033
  applyStyles$2(fragmentEl, styles);
75939
- this.applyFragmentFrame(fragmentEl, fragment);
77034
+ this.applyFragmentFrame(fragmentEl, fragment, context.section);
75940
77035
  if (isTocEntry) {
75941
77036
  fragmentEl.classList.add("superdoc-toc-entry");
75942
77037
  }
@@ -75954,8 +77049,32 @@ ${l}
75954
77049
  }
75955
77050
  this.applySdtDataset(fragmentEl, block.attrs?.sdt);
75956
77051
  this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
77052
+ const dropCapDescriptor = block.attrs?.dropCapDescriptor;
77053
+ const dropCapMeasure = measure.dropCap;
77054
+ if (dropCapDescriptor && dropCapMeasure && !fragment.continuesFromPrev) {
77055
+ const dropCapEl = this.renderDropCap(dropCapDescriptor, dropCapMeasure);
77056
+ fragmentEl.appendChild(dropCapEl);
77057
+ }
77058
+ if (fragmentEl.style.paddingLeft) fragmentEl.style.removeProperty("padding-left");
77059
+ if (fragmentEl.style.paddingRight) fragmentEl.style.removeProperty("padding-right");
77060
+ if (fragmentEl.style.textIndent) fragmentEl.style.removeProperty("text-indent");
77061
+ const paraIndent = block.attrs?.indent;
77062
+ const paraIndentLeft = paraIndent?.left ?? 0;
77063
+ const paraIndentRight = paraIndent?.right ?? 0;
77064
+ const firstLineOffset = (paraIndent?.firstLine ?? 0) - (paraIndent?.hanging ?? 0);
75957
77065
  lines.forEach((line, index2) => {
75958
77066
  const lineEl = this.renderLine(block, line, context);
77067
+ if (paraIndentLeft) {
77068
+ lineEl.style.paddingLeft = `${paraIndentLeft}px`;
77069
+ }
77070
+ if (paraIndentRight) {
77071
+ lineEl.style.paddingRight = `${paraIndentRight}px`;
77072
+ }
77073
+ if (!fragment.continuesFromPrev && index2 === 0 && firstLineOffset) {
77074
+ lineEl.style.textIndent = `${firstLineOffset}px`;
77075
+ } else if (firstLineOffset) {
77076
+ lineEl.style.textIndent = "0px";
77077
+ }
75959
77078
  if (index2 === 0 && !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker) {
75960
77079
  const markerContainer = this.doc.createElement("span");
75961
77080
  markerContainer.style.display = "inline-block";
@@ -75966,6 +77085,12 @@ ${l}
75966
77085
  markerEl.style.textAlign = wordLayout.marker.justification ?? "right";
75967
77086
  markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
75968
77087
  markerEl.style.pointerEvents = "none";
77088
+ const indentLeft = paraIndentLeft;
77089
+ const hanging = paraIndent?.hanging ?? 0;
77090
+ const textStartX = indentLeft - hanging;
77091
+ const markerLeftX = textStartX - fragment.markerWidth;
77092
+ markerEl.style.position = "relative";
77093
+ markerEl.style.left = `${markerLeftX}px`;
75969
77094
  markerEl.style.fontFamily = wordLayout.marker.run.fontFamily;
75970
77095
  markerEl.style.fontSize = `${wordLayout.marker.run.fontSize}px`;
75971
77096
  markerEl.style.fontWeight = wordLayout.marker.run.bold ? "bold" : "";
@@ -76024,6 +77149,53 @@ ${l}
76024
77149
  }
76025
77150
  return el;
76026
77151
  }
77152
+ /**
77153
+ * Renders a drop cap element as a floated span at the start of a paragraph.
77154
+ *
77155
+ * Drop caps are large initial letters that span multiple lines of text.
77156
+ * This method creates a floated element with the drop cap letter styled
77157
+ * according to the descriptor's run properties.
77158
+ *
77159
+ * @param descriptor - The drop cap descriptor with text and styling info
77160
+ * @param measure - The measured dimensions of the drop cap
77161
+ * @returns HTMLElement containing the rendered drop cap
77162
+ */
77163
+ renderDropCap(descriptor, measure) {
77164
+ const doc2 = this.doc;
77165
+ const { run: run2, mode } = descriptor;
77166
+ const dropCapEl = doc2.createElement("span");
77167
+ dropCapEl.classList.add("superdoc-drop-cap");
77168
+ dropCapEl.textContent = run2.text;
77169
+ dropCapEl.style.fontFamily = run2.fontFamily;
77170
+ dropCapEl.style.fontSize = `${run2.fontSize}px`;
77171
+ if (run2.bold) {
77172
+ dropCapEl.style.fontWeight = "bold";
77173
+ }
77174
+ if (run2.italic) {
77175
+ dropCapEl.style.fontStyle = "italic";
77176
+ }
77177
+ if (run2.color) {
77178
+ dropCapEl.style.color = run2.color;
77179
+ }
77180
+ if (mode === "drop") {
77181
+ dropCapEl.style.float = "left";
77182
+ dropCapEl.style.marginRight = "4px";
77183
+ dropCapEl.style.lineHeight = "1";
77184
+ } else if (mode === "margin") {
77185
+ dropCapEl.style.position = "absolute";
77186
+ dropCapEl.style.left = "0";
77187
+ dropCapEl.style.lineHeight = "1";
77188
+ }
77189
+ if (run2.position && run2.position !== 0) {
77190
+ dropCapEl.style.position = dropCapEl.style.position || "relative";
77191
+ dropCapEl.style.top = `${run2.position}px`;
77192
+ }
77193
+ if (measure) {
77194
+ dropCapEl.style.width = `${measure.width}px`;
77195
+ dropCapEl.style.height = `${measure.height}px`;
77196
+ }
77197
+ return dropCapEl;
77198
+ }
76027
77199
  renderListItemFragment(fragment, context) {
76028
77200
  try {
76029
77201
  const lookup2 = this.blockLookup.get(fragment.blockId);
@@ -76101,7 +77273,7 @@ ${l}
76101
77273
  return this.createErrorPlaceholder(fragment.blockId, error);
76102
77274
  }
76103
77275
  }
76104
- renderImageFragment(fragment) {
77276
+ renderImageFragment(fragment, context) {
76105
77277
  try {
76106
77278
  const lookup2 = this.blockLookup.get(fragment.blockId);
76107
77279
  if (!lookup2 || lookup2.block.kind !== "image" || lookup2.measure.kind !== "image") {
@@ -76114,7 +77286,7 @@ ${l}
76114
77286
  const fragmentEl = this.doc.createElement("div");
76115
77287
  fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-image-fragment");
76116
77288
  applyStyles$2(fragmentEl, fragmentStyles);
76117
- this.applyFragmentFrame(fragmentEl, fragment);
77289
+ this.applyFragmentFrame(fragmentEl, fragment, context.section);
76118
77290
  fragmentEl.style.height = `${fragment.height}px`;
76119
77291
  this.applySdtDataset(fragmentEl, block.attrs?.sdt);
76120
77292
  this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
@@ -76149,7 +77321,7 @@ ${l}
76149
77321
  return this.createErrorPlaceholder(fragment.blockId, error);
76150
77322
  }
76151
77323
  }
76152
- renderDrawingFragment(fragment) {
77324
+ renderDrawingFragment(fragment, context) {
76153
77325
  try {
76154
77326
  const lookup2 = this.blockLookup.get(fragment.blockId);
76155
77327
  if (!lookup2 || lookup2.block.kind !== "drawing" || lookup2.measure.kind !== "drawing") {
@@ -76163,7 +77335,7 @@ ${l}
76163
77335
  const fragmentEl = this.doc.createElement("div");
76164
77336
  fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-drawing-fragment");
76165
77337
  applyStyles$2(fragmentEl, fragmentStyles);
76166
- this.applyFragmentFrame(fragmentEl, fragment);
77338
+ this.applyFragmentFrame(fragmentEl, fragment, context.section);
76167
77339
  fragmentEl.style.height = `${fragment.height}px`;
76168
77340
  fragmentEl.style.position = "absolute";
76169
77341
  fragmentEl.style.overflow = "hidden";
@@ -76610,13 +77782,16 @@ ${l}
76610
77782
  if (!this.doc) {
76611
77783
  throw new Error("DomPainter: document is not available");
76612
77784
  }
77785
+ const applyFragmentFrameWithSection = (el, frag) => {
77786
+ this.applyFragmentFrame(el, frag, context.section);
77787
+ };
76613
77788
  return renderTableFragment({
76614
77789
  doc: this.doc,
76615
77790
  fragment,
76616
77791
  context,
76617
77792
  blockLookup: this.blockLookup,
76618
77793
  renderLine: this.renderLine.bind(this),
76619
- applyFragmentFrame: this.applyFragmentFrame.bind(this),
77794
+ applyFragmentFrame: applyFragmentFrameWithSection,
76620
77795
  applySdtDataset: this.applySdtDataset.bind(this),
76621
77796
  applyStyles: applyStyles$2
76622
77797
  });
@@ -76626,7 +77801,7 @@ ${l}
76626
77801
  * @returns Sanitized link data or null if invalid/missing
76627
77802
  */
76628
77803
  extractLinkData(run2) {
76629
- if (run2.kind === "tab") {
77804
+ if (run2.kind === "tab" || run2.kind === "image" || run2.kind === "lineBreak") {
76630
77805
  return null;
76631
77806
  }
76632
77807
  const link2 = run2.link;
@@ -76780,10 +77955,19 @@ ${l}
76780
77955
  isImageRun(run2) {
76781
77956
  return run2.kind === "image";
76782
77957
  }
77958
+ /**
77959
+ * Type guard to check if a run is a line break run.
77960
+ */
77961
+ isLineBreakRun(run2) {
77962
+ return run2.kind === "lineBreak";
77963
+ }
76783
77964
  renderRun(run2, context, trackedConfig) {
76784
77965
  if (this.isImageRun(run2)) {
76785
77966
  return this.renderImageRun(run2);
76786
77967
  }
77968
+ if (this.isLineBreakRun(run2)) {
77969
+ return null;
77970
+ }
76787
77971
  if (!run2.text || !this.doc) {
76788
77972
  return null;
76789
77973
  }
@@ -76808,8 +77992,21 @@ ${l}
76808
77992
  }
76809
77993
  }
76810
77994
  applyRunStyles(elem, run2, isActiveLink);
77995
+ const commentColor = getCommentHighlight(run2);
77996
+ if (commentColor && !run2.highlight) {
77997
+ elem.style.backgroundColor = commentColor;
77998
+ }
77999
+ const commentAnnotations = run2.comments;
78000
+ if (commentAnnotations?.length) {
78001
+ elem.dataset.commentIds = commentAnnotations.map((c2) => c2.commentId).join(",");
78002
+ if (commentAnnotations.some((c2) => c2.internal)) {
78003
+ elem.dataset.commentInternal = "true";
78004
+ }
78005
+ elem.classList.add("superdoc-comment-highlight");
78006
+ }
76811
78007
  elem.style.zIndex = "1";
76812
78008
  applyRunDataAttributes(elem, run2.dataAttrs);
78009
+ assertPmPositions(run2, "paragraph text run");
76813
78010
  if (run2.pmStart != null) elem.dataset.pmStart = String(run2.pmStart);
76814
78011
  if (run2.pmEnd != null) elem.dataset.pmEnd = String(run2.pmEnd);
76815
78012
  if (trackedConfig) {
@@ -76888,6 +78085,7 @@ ${l}
76888
78085
  img2.style.marginRight = `${run2.distRight}px`;
76889
78086
  }
76890
78087
  img2.style.zIndex = "1";
78088
+ assertPmPositions(run2, "inline image run");
76891
78089
  if (run2.pmStart != null) {
76892
78090
  img2.dataset.pmStart = String(run2.pmStart);
76893
78091
  }
@@ -76918,9 +78116,9 @@ ${l}
76918
78116
  if (lineRange.pmEnd != null) {
76919
78117
  el.dataset.pmEnd = String(lineRange.pmEnd);
76920
78118
  }
76921
- const runs2 = sliceRunsForLine(block, line);
78119
+ const runsForLine = sliceRunsForLine(block, line);
76922
78120
  const trackedConfig = this.resolveTrackedChangesConfig(block);
76923
- if (runs2.length === 0) {
78121
+ if (runsForLine.length === 0) {
76924
78122
  const span = this.doc.createElement("span");
76925
78123
  span.innerHTML = "&nbsp;";
76926
78124
  el.appendChild(span);
@@ -76968,49 +78166,109 @@ ${l}
76968
78166
  const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
76969
78167
  if (hasExplicitPositioning && line.segments) {
76970
78168
  let cumulativeX = 0;
76971
- line.segments.forEach((segment, _segIdx) => {
76972
- const baseRun = runs2[segment.runIndex];
76973
- if (!baseRun || baseRun.kind === "tab") return;
76974
- if (this.isImageRun(baseRun)) {
76975
- const elem2 = this.renderRun(baseRun, context, trackedConfig);
76976
- if (elem2) {
76977
- if (styleId) {
76978
- elem2.setAttribute("styleid", styleId);
76979
- }
76980
- el.appendChild(elem2);
78169
+ const segmentsByRun = /* @__PURE__ */ new Map();
78170
+ line.segments.forEach((segment) => {
78171
+ const list2 = segmentsByRun.get(segment.runIndex);
78172
+ if (list2) {
78173
+ list2.push(segment);
78174
+ } else {
78175
+ segmentsByRun.set(segment.runIndex, [segment]);
78176
+ }
78177
+ });
78178
+ const findImmediateNextSegmentX = (fromRunIndex) => {
78179
+ const nextRunIdx = fromRunIndex + 1;
78180
+ if (nextRunIdx <= line.toRun) {
78181
+ const nextSegments = segmentsByRun.get(nextRunIdx);
78182
+ if (nextSegments && nextSegments.length > 0) {
78183
+ const firstSegment = nextSegments[0];
78184
+ return firstSegment.x;
76981
78185
  }
76982
- return;
76983
78186
  }
76984
- const segmentText = baseRun.text.slice(segment.fromChar, segment.toChar);
76985
- const segmentRun = { ...baseRun, text: segmentText };
76986
- const elem = this.renderRun(segmentRun, context, trackedConfig);
76987
- if (elem) {
78187
+ return void 0;
78188
+ };
78189
+ for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
78190
+ const baseRun = block.runs[runIndex];
78191
+ if (!baseRun) continue;
78192
+ if (baseRun.kind === "tab") {
78193
+ const immediateNextX = findImmediateNextSegmentX(runIndex);
78194
+ const tabStartX = cumulativeX;
78195
+ const tabEndX = immediateNextX !== void 0 ? immediateNextX : tabStartX + (baseRun.width ?? 0);
78196
+ const actualTabWidth = tabEndX - tabStartX;
78197
+ const tabEl = this.doc.createElement("span");
78198
+ tabEl.style.position = "absolute";
78199
+ tabEl.style.left = `${tabStartX}px`;
78200
+ tabEl.style.top = "0px";
78201
+ tabEl.style.width = `${actualTabWidth}px`;
78202
+ tabEl.style.height = `${line.lineHeight}px`;
78203
+ tabEl.style.display = "inline-block";
78204
+ tabEl.style.visibility = "hidden";
78205
+ tabEl.style.pointerEvents = "none";
78206
+ tabEl.style.zIndex = "1";
76988
78207
  if (styleId) {
76989
- elem.setAttribute("styleid", styleId);
78208
+ tabEl.setAttribute("styleid", styleId);
76990
78209
  }
76991
- let xPos;
76992
- if (segment.x !== void 0) {
76993
- xPos = segment.x;
76994
- } else {
76995
- xPos = cumulativeX;
78210
+ if (baseRun.pmStart != null) tabEl.dataset.pmStart = String(baseRun.pmStart);
78211
+ if (baseRun.pmEnd != null) tabEl.dataset.pmEnd = String(baseRun.pmEnd);
78212
+ el.appendChild(tabEl);
78213
+ cumulativeX = tabEndX;
78214
+ continue;
78215
+ }
78216
+ if (this.isImageRun(baseRun)) {
78217
+ const elem = this.renderRun(baseRun, context, trackedConfig);
78218
+ if (elem) {
78219
+ if (styleId) {
78220
+ elem.setAttribute("styleid", styleId);
78221
+ }
78222
+ el.appendChild(elem);
76996
78223
  }
76997
- elem.style.position = "absolute";
76998
- elem.style.left = `${xPos}px`;
76999
- el.appendChild(elem);
77000
- if (this.doc) {
77001
- const measureEl = elem.cloneNode(true);
77002
- measureEl.style.position = "absolute";
77003
- measureEl.style.visibility = "hidden";
77004
- measureEl.style.left = "-9999px";
77005
- this.doc.body.appendChild(measureEl);
77006
- const width = measureEl.offsetWidth;
77007
- this.doc.body.removeChild(measureEl);
78224
+ continue;
78225
+ }
78226
+ if (this.isLineBreakRun(baseRun)) {
78227
+ continue;
78228
+ }
78229
+ const runSegments = segmentsByRun.get(runIndex);
78230
+ if (!runSegments || runSegments.length === 0) {
78231
+ continue;
78232
+ }
78233
+ const baseText = baseRun.text ?? "";
78234
+ const runPmStart = baseRun.pmStart ?? null;
78235
+ const fallbackPmEnd = runPmStart != null && baseRun.pmEnd == null ? runPmStart + baseText.length : baseRun.pmEnd ?? null;
78236
+ runSegments.forEach((segment) => {
78237
+ const segmentText = baseText.slice(segment.fromChar, segment.toChar);
78238
+ if (!segmentText) return;
78239
+ const pmSliceStart = runPmStart != null ? runPmStart + segment.fromChar : void 0;
78240
+ const pmSliceEnd = runPmStart != null ? runPmStart + segment.toChar : fallbackPmEnd ?? void 0;
78241
+ const segmentRun = {
78242
+ ...baseRun,
78243
+ text: segmentText,
78244
+ pmStart: pmSliceStart,
78245
+ pmEnd: pmSliceEnd
78246
+ };
78247
+ const elem = this.renderRun(segmentRun, context, trackedConfig);
78248
+ if (elem) {
78249
+ if (styleId) {
78250
+ elem.setAttribute("styleid", styleId);
78251
+ }
78252
+ const xPos = segment.x !== void 0 ? segment.x : cumulativeX;
78253
+ elem.style.position = "absolute";
78254
+ elem.style.left = `${xPos}px`;
78255
+ el.appendChild(elem);
78256
+ let width = segment.width ?? 0;
78257
+ if (width <= 0 && this.doc) {
78258
+ const measureEl = elem.cloneNode(true);
78259
+ measureEl.style.position = "absolute";
78260
+ measureEl.style.visibility = "hidden";
78261
+ measureEl.style.left = "-9999px";
78262
+ this.doc.body.appendChild(measureEl);
78263
+ width = measureEl.offsetWidth;
78264
+ this.doc.body.removeChild(measureEl);
78265
+ }
77008
78266
  cumulativeX = xPos + width;
77009
78267
  }
77010
- }
77011
- });
78268
+ });
78269
+ }
77012
78270
  } else {
77013
- runs2.forEach((run2) => {
78271
+ runsForLine.forEach((run2) => {
77014
78272
  const elem = this.renderRun(run2, context, trackedConfig);
77015
78273
  if (elem) {
77016
78274
  if (styleId) {
@@ -77068,8 +78326,18 @@ ${l}
77068
78326
  elem.dataset.trackChangeDate = meta2.date;
77069
78327
  }
77070
78328
  }
77071
- updateFragmentElement(el, fragment) {
77072
- this.applyFragmentFrame(el, fragment);
78329
+ /**
78330
+ * Updates an existing fragment element's position and dimensions in place.
78331
+ * Used during incremental updates to efficiently reposition fragments without full re-render.
78332
+ *
78333
+ * @param el - The HTMLElement representing the fragment to update
78334
+ * @param fragment - The fragment data containing updated position and dimensions
78335
+ * @param section - The document section ('body', 'header', 'footer') containing this fragment.
78336
+ * Affects PM position validation - only body sections validate PM positions.
78337
+ * If undefined, defaults to 'body' section behavior.
78338
+ */
78339
+ updateFragmentElement(el, fragment, section) {
78340
+ this.applyFragmentFrame(el, fragment, section);
77073
78341
  if (fragment.kind === "image") {
77074
78342
  el.style.height = `${fragment.height}px`;
77075
78343
  }
@@ -77077,12 +78345,27 @@ ${l}
77077
78345
  el.style.height = `${fragment.height}px`;
77078
78346
  }
77079
78347
  }
77080
- applyFragmentFrame(el, fragment) {
78348
+ /**
78349
+ * Applies fragment positioning, dimensions, and metadata to an HTML element.
78350
+ * Sets CSS positioning, block ID, and PM position data attributes for paragraph fragments.
78351
+ *
78352
+ * @param el - The HTMLElement to apply fragment properties to
78353
+ * @param fragment - The fragment data containing position, dimensions, and PM position information
78354
+ * @param section - The document section ('body', 'header', 'footer') containing this fragment.
78355
+ * Controls PM position validation behavior:
78356
+ * - 'body' or undefined: PM positions are validated and required for paragraph fragments
78357
+ * - 'header' or 'footer': PM position validation is skipped (these sections have separate PM coordinate spaces)
78358
+ * When undefined, defaults to 'body' section behavior (validation enabled).
78359
+ */
78360
+ applyFragmentFrame(el, fragment, section) {
77081
78361
  el.style.left = `${fragment.x}px`;
77082
78362
  el.style.top = `${fragment.y}px`;
77083
78363
  el.style.width = `${fragment.width}px`;
77084
78364
  el.dataset.blockId = fragment.blockId;
77085
78365
  if (fragment.kind === "para") {
78366
+ if (section === "body" || section === void 0) {
78367
+ assertFragmentPmPositions(fragment, "paragraph fragment");
78368
+ }
77086
78369
  if (fragment.pmStart != null) {
77087
78370
  el.dataset.pmStart = String(fragment.pmStart);
77088
78371
  } else {
@@ -77329,22 +78612,29 @@ ${l}
77329
78612
  imgRun.pmEnd ?? ""
77330
78613
  ].join(",");
77331
78614
  }
78615
+ if (run2.kind === "lineBreak") {
78616
+ return ["linebreak", run2.pmStart ?? "", run2.pmEnd ?? ""].join(",");
78617
+ }
78618
+ if (run2.kind === "tab") {
78619
+ return [run2.text ?? "", "tab", run2.pmStart ?? "", run2.pmEnd ?? ""].join(",");
78620
+ }
78621
+ const textRun = run2;
77332
78622
  return [
77333
- run2.text ?? "",
77334
- run2.kind !== "tab" ? run2.fontFamily : "",
77335
- run2.kind !== "tab" ? run2.fontSize : "",
77336
- run2.kind !== "tab" && run2.bold ? 1 : 0,
77337
- run2.kind !== "tab" && run2.italic ? 1 : 0,
77338
- run2.kind !== "tab" ? run2.color ?? "" : "",
78623
+ textRun.text ?? "",
78624
+ textRun.fontFamily,
78625
+ textRun.fontSize,
78626
+ textRun.bold ? 1 : 0,
78627
+ textRun.italic ? 1 : 0,
78628
+ textRun.color ?? "",
77339
78629
  // Text decorations - ensures DOM updates when decoration properties change.
77340
- run2.kind !== "tab" ? run2.underline?.style ?? "" : "",
77341
- run2.kind !== "tab" ? run2.underline?.color ?? "" : "",
77342
- run2.kind !== "tab" && run2.strike ? 1 : 0,
77343
- run2.kind !== "tab" ? run2.highlight ?? "" : "",
77344
- run2.kind !== "tab" && run2.letterSpacing != null ? run2.letterSpacing : "",
77345
- run2.pmStart ?? "",
77346
- run2.pmEnd ?? "",
77347
- run2.kind !== "tab" ? run2.token ?? "" : ""
78630
+ textRun.underline?.style ?? "",
78631
+ textRun.underline?.color ?? "",
78632
+ textRun.strike ? 1 : 0,
78633
+ textRun.highlight ?? "",
78634
+ textRun.letterSpacing != null ? textRun.letterSpacing : "",
78635
+ textRun.pmStart ?? "",
78636
+ textRun.pmEnd ?? "",
78637
+ textRun.token ?? ""
77348
78638
  ].join(",");
77349
78639
  }).join("|");
77350
78640
  }
@@ -77395,16 +78685,57 @@ ${l}
77395
78685
  }
77396
78686
  if (block.kind === "table") {
77397
78687
  const tableBlock = block;
77398
- return [
77399
- block.id,
77400
- tableBlock.columnWidths ? JSON.stringify(tableBlock.columnWidths) : "",
77401
- tableBlock.rows.length
77402
- ].join("|");
78688
+ const hashString = (seed, value) => {
78689
+ let hash22 = seed >>> 0;
78690
+ for (let i2 = 0; i2 < value.length; i2++) {
78691
+ hash22 ^= value.charCodeAt(i2);
78692
+ hash22 = Math.imul(hash22, 16777619);
78693
+ }
78694
+ return hash22 >>> 0;
78695
+ };
78696
+ const hashNumber = (seed, value) => {
78697
+ const n = Number.isFinite(value) ? value : 0;
78698
+ let hash22 = seed ^ n;
78699
+ hash22 = Math.imul(hash22, 16777619);
78700
+ hash22 ^= hash22 >>> 13;
78701
+ return hash22 >>> 0;
78702
+ };
78703
+ let hash2 = 2166136261;
78704
+ hash2 = hashString(hash2, block.id);
78705
+ hash2 = hashNumber(hash2, tableBlock.rows.length);
78706
+ hash2 = (tableBlock.columnWidths ?? []).reduce((acc, width) => hashNumber(acc, Math.round(width * 1e3)), hash2);
78707
+ const rows = tableBlock.rows ?? [];
78708
+ for (const row2 of rows) {
78709
+ if (!row2 || !Array.isArray(row2.cells)) continue;
78710
+ hash2 = hashNumber(hash2, row2.cells.length);
78711
+ for (const cell2 of row2.cells) {
78712
+ if (!cell2) continue;
78713
+ const cellBlocks = cell2.blocks ?? (cell2.paragraph ? [cell2.paragraph] : []);
78714
+ hash2 = hashNumber(hash2, cellBlocks.length);
78715
+ hash2 = hashNumber(hash2, cell2.rowSpan ?? 1);
78716
+ hash2 = hashNumber(hash2, cell2.colSpan ?? 1);
78717
+ for (const cellBlock of cellBlocks) {
78718
+ hash2 = hashString(hash2, cellBlock?.kind ?? "unknown");
78719
+ if (cellBlock?.kind === "paragraph") {
78720
+ const runs2 = cellBlock.runs ?? [];
78721
+ hash2 = hashNumber(hash2, runs2.length);
78722
+ for (const run2 of runs2) {
78723
+ if ("text" in run2 && typeof run2.text === "string") {
78724
+ hash2 = hashString(hash2, run2.text);
78725
+ }
78726
+ hash2 = hashNumber(hash2, run2.pmStart ?? -1);
78727
+ hash2 = hashNumber(hash2, run2.pmEnd ?? -1);
78728
+ }
78729
+ }
78730
+ }
78731
+ }
78732
+ }
78733
+ return [block.id, tableBlock.rows.length, hash2.toString(16)].join("|");
77403
78734
  }
77404
78735
  return block.id;
77405
78736
  };
77406
78737
  const applyRunStyles = (element2, run2, isLink = false) => {
77407
- if (run2.kind === "tab" || run2.kind === "image") {
78738
+ if (run2.kind === "tab" || run2.kind === "image" || run2.kind === "lineBreak") {
77408
78739
  return;
77409
78740
  }
77410
78741
  element2.style.fontFamily = run2.fontFamily;
@@ -77436,6 +78767,13 @@ ${l}
77436
78767
  element2.style.textDecorationLine = decorations.join(" ");
77437
78768
  }
77438
78769
  };
78770
+ const getCommentHighlight = (run2) => {
78771
+ const comments = run2.comments;
78772
+ if (!comments || comments.length === 0) return void 0;
78773
+ const primary = comments[0];
78774
+ const base2 = primary.internal ? COMMENT_INTERNAL_COLOR : COMMENT_EXTERNAL_COLOR;
78775
+ return `${base2}${COMMENT_INACTIVE_ALPHA}`;
78776
+ };
77439
78777
  const applyRunDataAttributes = (element2, dataAttrs) => {
77440
78778
  if (!dataAttrs) return;
77441
78779
  Object.entries(dataAttrs).forEach(([key2, value]) => {
@@ -77527,6 +78865,10 @@ ${l}
77527
78865
  result.push(run2);
77528
78866
  continue;
77529
78867
  }
78868
+ if (run2.kind === "lineBreak") {
78869
+ result.push(run2);
78870
+ continue;
78871
+ }
77530
78872
  const text2 = run2.text ?? "";
77531
78873
  const isFirstRun = runIndex === line.fromRun;
77532
78874
  const isLastRun = runIndex === line.toRun;
@@ -77549,7 +78891,8 @@ ${l}
77549
78891
  ...run2,
77550
78892
  text: slice2,
77551
78893
  pmStart: pmSliceStart,
77552
- pmEnd: pmSliceEnd
78894
+ pmEnd: pmSliceEnd,
78895
+ comments: run2.comments ? [...run2.comments] : void 0
77553
78896
  };
77554
78897
  result.push(sliced);
77555
78898
  }
@@ -77580,6 +78923,21 @@ ${l}
77580
78923
  }
77581
78924
  continue;
77582
78925
  }
78926
+ if (run2.kind === "lineBreak") {
78927
+ const runPmStart2 = run2.pmStart ?? null;
78928
+ const runPmEnd = run2.pmEnd ?? null;
78929
+ if (runPmStart2 == null || runPmEnd == null) {
78930
+ continue;
78931
+ }
78932
+ if (pmStart == null) {
78933
+ pmStart = runPmStart2;
78934
+ }
78935
+ pmEnd = runPmEnd;
78936
+ if (runIndex === line.toRun) {
78937
+ break;
78938
+ }
78939
+ continue;
78940
+ }
77583
78941
  const text2 = run2.text ?? "";
77584
78942
  const runLength = text2.length;
77585
78943
  const runPmStart = run2.pmStart ?? null;
@@ -77618,6 +78976,9 @@ ${l}
77618
78976
  if (run2.kind === "image") {
77619
78977
  return "";
77620
78978
  }
78979
+ if (run2.kind === "lineBreak") {
78980
+ return "";
78981
+ }
77621
78982
  if (!runToken) {
77622
78983
  return run2.text ?? "";
77623
78984
  }
@@ -77784,6 +79145,9 @@ ${l}
77784
79145
  function isImageRun(run2) {
77785
79146
  return run2.kind === "image";
77786
79147
  }
79148
+ function isLineBreakRun(run2) {
79149
+ return run2.kind === "lineBreak";
79150
+ }
77787
79151
  async function measureBlock(block, constraints) {
77788
79152
  const normalized = normalizeConstraints(constraints);
77789
79153
  if (block.kind === "drawing") {
@@ -77821,7 +79185,7 @@ ${l}
77821
79185
  const hanging = indent2?.hanging ?? 0;
77822
79186
  const firstLineOffset = firstLine - hanging;
77823
79187
  const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
77824
- let availableWidth = Math.max(1, contentWidth - firstLineOffset);
79188
+ const initialAvailableWidth = Math.max(1, contentWidth - firstLineOffset);
77825
79189
  const tabStops = buildTabStopsPx(
77826
79190
  indent2,
77827
79191
  block.attrs?.tabs,
@@ -77834,6 +79198,18 @@ ${l}
77834
79198
  line.bars = barTabStops.map((stop) => ({ x: stop.pos }));
77835
79199
  }
77836
79200
  };
79201
+ const dropCapDescriptor = block.attrs?.dropCapDescriptor;
79202
+ let dropCapMeasure = null;
79203
+ if (dropCapDescriptor) {
79204
+ if (!dropCapDescriptor.run || !dropCapDescriptor.run.text || !dropCapDescriptor.lines) {
79205
+ console.warn("Invalid drop cap descriptor - missing required fields:", dropCapDescriptor);
79206
+ } else {
79207
+ const dropCapMeasured = measureDropCap(ctx2, dropCapDescriptor, spacing);
79208
+ dropCapMeasure = dropCapMeasured;
79209
+ dropCapDescriptor.measuredWidth = dropCapMeasured.width;
79210
+ dropCapDescriptor.measuredHeight = dropCapMeasured.height;
79211
+ }
79212
+ }
77837
79213
  if (block.runs.length === 0) {
77838
79214
  const metrics = calculateTypographyMetrics(12, spacing);
77839
79215
  const emptyLine = {
@@ -77853,6 +79229,13 @@ ${l}
77853
79229
  };
77854
79230
  }
77855
79231
  let currentLine = null;
79232
+ const getEffectiveWidth = (baseWidth) => {
79233
+ if (dropCapMeasure && lines.length < dropCapMeasure.lines && dropCapMeasure.mode === "drop") {
79234
+ return Math.max(1, baseWidth - dropCapMeasure.width);
79235
+ }
79236
+ return baseWidth;
79237
+ };
79238
+ let lastFontSize = 12;
77856
79239
  let tabStopCursor = 0;
77857
79240
  let pendingTabAlignment = null;
77858
79241
  let lastAppliedTabAlign = null;
@@ -77889,6 +79272,47 @@ ${l}
77889
79272
  };
77890
79273
  for (let runIndex = 0; runIndex < block.runs.length; runIndex++) {
77891
79274
  const run2 = block.runs[runIndex];
79275
+ if (isLineBreakRun(run2)) {
79276
+ if (currentLine) {
79277
+ const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
79278
+ const completedLine = {
79279
+ ...currentLine,
79280
+ ...metrics
79281
+ };
79282
+ addBarTabsToLine(completedLine);
79283
+ lines.push(completedLine);
79284
+ } else {
79285
+ const metrics = calculateTypographyMetrics(lastFontSize, spacing);
79286
+ const emptyLine = {
79287
+ fromRun: runIndex,
79288
+ fromChar: 0,
79289
+ toRun: runIndex,
79290
+ toChar: 0,
79291
+ width: 0,
79292
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
79293
+ segments: [],
79294
+ ...metrics
79295
+ };
79296
+ addBarTabsToLine(emptyLine);
79297
+ lines.push(emptyLine);
79298
+ }
79299
+ const hadPreviousLine = lines.length > 0;
79300
+ const nextLineMaxWidth = hadPreviousLine ? getEffectiveWidth(contentWidth) : getEffectiveWidth(initialAvailableWidth);
79301
+ currentLine = {
79302
+ fromRun: runIndex,
79303
+ fromChar: 0,
79304
+ toRun: runIndex,
79305
+ toChar: 0,
79306
+ width: 0,
79307
+ maxFontSize: lastFontSize,
79308
+ maxWidth: nextLineMaxWidth,
79309
+ segments: []
79310
+ };
79311
+ tabStopCursor = 0;
79312
+ pendingTabAlignment = null;
79313
+ lastAppliedTabAlign = null;
79314
+ continue;
79315
+ }
77892
79316
  if (isTabRun(run2)) {
77893
79317
  if (!currentLine) {
77894
79318
  currentLine = {
@@ -77899,7 +79323,7 @@ ${l}
77899
79323
  width: 0,
77900
79324
  maxFontSize: 12,
77901
79325
  // Default font size for tabs
77902
- maxWidth: availableWidth,
79326
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
77903
79327
  segments: []
77904
79328
  };
77905
79329
  }
@@ -77944,7 +79368,7 @@ ${l}
77944
79368
  width: imageWidth,
77945
79369
  maxFontSize: imageHeight,
77946
79370
  // Use image height for line height calculation
77947
- maxWidth: availableWidth,
79371
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
77948
79372
  segments: [
77949
79373
  {
77950
79374
  runIndex,
@@ -77954,7 +79378,6 @@ ${l}
77954
79378
  }
77955
79379
  ]
77956
79380
  };
77957
- availableWidth = contentWidth;
77958
79381
  continue;
77959
79382
  }
77960
79383
  if (currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
@@ -77974,7 +79397,7 @@ ${l}
77974
79397
  toChar: 1,
77975
79398
  width: imageWidth,
77976
79399
  maxFontSize: imageHeight,
77977
- maxWidth: contentWidth,
79400
+ maxWidth: getEffectiveWidth(contentWidth),
77978
79401
  segments: [
77979
79402
  {
77980
79403
  runIndex,
@@ -77984,7 +79407,6 @@ ${l}
77984
79407
  }
77985
79408
  ]
77986
79409
  };
77987
- availableWidth = contentWidth;
77988
79410
  } else {
77989
79411
  currentLine.toRun = runIndex;
77990
79412
  currentLine.toChar = 1;
@@ -78000,6 +79422,7 @@ ${l}
78000
79422
  }
78001
79423
  continue;
78002
79424
  }
79425
+ lastFontSize = run2.fontSize;
78003
79426
  const { font } = buildFontString(run2);
78004
79427
  const tabSegments = run2.text.split(" ");
78005
79428
  let charPosInRun = 0;
@@ -78034,7 +79457,7 @@ ${l}
78034
79457
  toChar: wordEndNoSpace,
78035
79458
  width: wordOnlyWidth,
78036
79459
  maxFontSize: run2.fontSize,
78037
- maxWidth: availableWidth,
79460
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
78038
79461
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
78039
79462
  };
78040
79463
  const ls = run2.letterSpacing ?? 0;
@@ -78045,7 +79468,6 @@ ${l}
78045
79468
  } else {
78046
79469
  charPosInRun = wordEndNoSpace;
78047
79470
  }
78048
- availableWidth = contentWidth;
78049
79471
  continue;
78050
79472
  }
78051
79473
  const isTocEntry = block.attrs?.isTocEntry;
@@ -78067,7 +79489,7 @@ ${l}
78067
79489
  toChar: wordEndNoSpace,
78068
79490
  width: wordOnlyWidth,
78069
79491
  maxFontSize: run2.fontSize,
78070
- maxWidth: contentWidth,
79492
+ maxWidth: getEffectiveWidth(contentWidth),
78071
79493
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
78072
79494
  };
78073
79495
  if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth) {
@@ -78123,10 +79545,9 @@ ${l}
78123
79545
  toChar: charPosInRun,
78124
79546
  width: 0,
78125
79547
  maxFontSize: run2.fontSize,
78126
- maxWidth: availableWidth,
79548
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
78127
79549
  segments: []
78128
79550
  };
78129
- availableWidth = contentWidth;
78130
79551
  }
78131
79552
  const originX = currentLine.width;
78132
79553
  const { target, nextIndex, stop } = getNextTabStopPx(currentLine.width, tabStops, tabStopCursor);
@@ -78199,7 +79620,8 @@ ${l}
78199
79620
  kind: "paragraph",
78200
79621
  lines,
78201
79622
  totalHeight,
78202
- ...markerInfo ? { marker: markerInfo } : {}
79623
+ ...markerInfo ? { marker: markerInfo } : {},
79624
+ ...dropCapMeasure ? { dropCap: dropCapMeasure } : {}
78203
79625
  };
78204
79626
  }
78205
79627
  async function measureTableBlock(block, constraints) {
@@ -78479,7 +79901,7 @@ ${l}
78479
79901
  };
78480
79902
  };
78481
79903
  const measureRunWidth = (text2, font, ctx2, run2) => {
78482
- const letterSpacing = run2.kind === "text" ? run2.letterSpacing || 0 : 0;
79904
+ const letterSpacing = run2.kind === "text" || run2.kind === void 0 ? run2.letterSpacing || 0 : 0;
78483
79905
  const width = getMeasuredTextWidth(text2, font, letterSpacing, ctx2);
78484
79906
  return roundValue(width);
78485
79907
  };
@@ -78515,6 +79937,30 @@ ${l}
78515
79937
  if (value === ",") return ",";
78516
79938
  return DEFAULT_DECIMAL_SEPARATOR;
78517
79939
  };
79940
+ const DROP_CAP_PADDING_PX = 4;
79941
+ const measureDropCap = (ctx2, descriptor, spacing) => {
79942
+ const { run: run2, lines, mode } = descriptor;
79943
+ const { font } = buildFontString({
79944
+ fontFamily: run2.fontFamily,
79945
+ fontSize: run2.fontSize,
79946
+ bold: run2.bold,
79947
+ italic: run2.italic
79948
+ });
79949
+ ctx2.font = font;
79950
+ const metrics = ctx2.measureText(run2.text);
79951
+ const advanceWidth = metrics.width;
79952
+ const paintedWidth = (metrics.actualBoundingBoxLeft || 0) + (metrics.actualBoundingBoxRight || 0);
79953
+ const textWidth = Math.max(advanceWidth, paintedWidth);
79954
+ const width = roundValue(textWidth + DROP_CAP_PADDING_PX);
79955
+ const baseLineHeight = resolveLineHeight(spacing, run2.fontSize * 1.2);
79956
+ const height = roundValue(baseLineHeight * lines);
79957
+ return {
79958
+ width,
79959
+ height,
79960
+ lines,
79961
+ mode
79962
+ };
79963
+ };
78518
79964
  const resolveIndentLeft = (item) => {
78519
79965
  const indentLeft = sanitizePositive(item.paragraph.attrs?.indent?.left);
78520
79966
  if (indentLeft > 0) {
@@ -79591,10 +81037,7 @@ ${l}
79591
81037
  const tr = __privateGet$1(this, _editor3).state.tr.setSelection(TextSelection$1.create(__privateGet$1(this, _editor3).state.doc, hit.pos));
79592
81038
  try {
79593
81039
  __privateGet$1(this, _editor3).view?.dispatch(tr);
79594
- } catch (error) {
79595
- if (process$1$1.env.NODE_ENV === "development") {
79596
- console.warn("[PresentationEditor] Failed to dispatch selection at position:", hit.pos, error);
79597
- }
81040
+ } catch {
79598
81041
  }
79599
81042
  }
79600
81043
  __privateMethod$1(this, _PresentationEditor_instances, scheduleSelectionUpdate_fn).call(this);
@@ -81919,10 +83362,10 @@ ${l}
81919
83362
  if (!lineInfo) return null;
81920
83363
  const { line, index: index2 } = lineInfo;
81921
83364
  const range2 = computeLinePmRange$1(block, line);
81922
- if (range2.pmStart == null) return null;
81923
- const charsInLine = Math.max(0, line.toChar - line.fromChar);
81924
- const offsetChars = Math.max(0, Math.min(charsInLine, pos - range2.pmStart));
81925
- const localX = hit.fragment.x + measureCharacterX(block, line, offsetChars);
83365
+ if (range2.pmStart == null || range2.pmEnd == null) return null;
83366
+ const pmCharsInLine = Math.max(1, range2.pmEnd - range2.pmStart);
83367
+ const pmOffset = Math.max(0, Math.min(pmCharsInLine, pos - range2.pmStart));
83368
+ const localX = hit.fragment.x + measureCharacterX(block, line, pmOffset);
81926
83369
  const lineOffset = __privateMethod$1(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, hit.fragment.fromLine, index2);
81927
83370
  const headerPageHeight = context.layout.pageSize?.h ?? context.region.height ?? 1;
81928
83371
  const headerLocalY = hit.pageIndex * headerPageHeight + (hit.fragment.y + lineOffset);
@@ -82062,23 +83505,34 @@ ${l}
82062
83505
  computeCaretLayoutRect_fn = function(pos) {
82063
83506
  const layout = __privateGet$1(this, _layoutState).layout;
82064
83507
  if (!layout) return null;
83508
+ const domResult = __privateMethod$1(this, _PresentationEditor_instances, computeCaretLayoutRectFromDOM_fn).call(this, pos);
83509
+ if (domResult) {
83510
+ return domResult;
83511
+ }
82065
83512
  const hit = getFragmentAtPosition(layout, __privateGet$1(this, _layoutState).blocks, __privateGet$1(this, _layoutState).measures, pos);
82066
- if (!hit) return null;
83513
+ if (!hit) {
83514
+ return null;
83515
+ }
82067
83516
  const block = hit.block;
82068
83517
  const measure = hit.measure;
83518
+ if (hit.fragment.kind === "table" && block?.kind === "table" && measure?.kind === "table") {
83519
+ return __privateMethod$1(this, _PresentationEditor_instances, computeTableCaretLayoutRect_fn).call(this, pos, hit.fragment, block, measure, hit.pageIndex);
83520
+ }
82069
83521
  if (!block || block.kind !== "paragraph" || measure?.kind !== "paragraph") return null;
82070
83522
  if (hit.fragment.kind !== "para") {
82071
83523
  return null;
82072
83524
  }
82073
83525
  const fragment = hit.fragment;
82074
83526
  const lineInfo = __privateMethod$1(this, _PresentationEditor_instances, findLineContainingPos_fn).call(this, block, measure, fragment.fromLine, fragment.toLine, pos);
82075
- if (!lineInfo) return null;
83527
+ if (!lineInfo) {
83528
+ return null;
83529
+ }
82076
83530
  const { line, index: index2 } = lineInfo;
82077
83531
  const range2 = computeLinePmRange$1(block, line);
82078
- if (range2.pmStart == null) return null;
82079
- const charsInLine = Math.max(0, line.toChar - line.fromChar);
82080
- const offsetChars = Math.max(0, Math.min(charsInLine, pos - range2.pmStart));
82081
- const localX = fragment.x + measureCharacterX(block, line, offsetChars);
83532
+ if (range2.pmStart == null || range2.pmEnd == null) return null;
83533
+ const pmCharsInLine = Math.max(1, range2.pmEnd - range2.pmStart);
83534
+ const pmOffset = Math.max(0, Math.min(pmCharsInLine, pos - range2.pmStart));
83535
+ const localX = fragment.x + measureCharacterX(block, line, pmOffset);
82082
83536
  const lineOffset = __privateMethod$1(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, fragment.fromLine, index2);
82083
83537
  const localY = fragment.y + lineOffset;
82084
83538
  return {
@@ -82088,17 +83542,167 @@ ${l}
82088
83542
  height: line.lineHeight
82089
83543
  };
82090
83544
  };
83545
+ computeCaretLayoutRectFromDOM_fn = function(pos) {
83546
+ const zoom = __privateGet$1(this, _layoutOptions).zoom ?? 1;
83547
+ let targetPageEl = null;
83548
+ if (__privateGet$1(this, _layoutState).layout && __privateGet$1(this, _layoutState).blocks && __privateGet$1(this, _layoutState).measures) {
83549
+ const fragmentHit = getFragmentAtPosition(
83550
+ __privateGet$1(this, _layoutState).layout,
83551
+ __privateGet$1(this, _layoutState).blocks,
83552
+ __privateGet$1(this, _layoutState).measures,
83553
+ pos
83554
+ );
83555
+ if (fragmentHit) {
83556
+ const pageEl = __privateGet$1(this, _viewportHost).querySelector(
83557
+ `.superdoc-page[data-page-index="${fragmentHit.pageIndex}"]`
83558
+ );
83559
+ if (pageEl) {
83560
+ targetPageEl = pageEl;
83561
+ }
83562
+ }
83563
+ }
83564
+ const spanEls = Array.from(
83565
+ targetPageEl ? targetPageEl.querySelectorAll("span[data-pm-start][data-pm-end]") : __privateGet$1(this, _viewportHost).querySelectorAll("span[data-pm-start][data-pm-end]")
83566
+ );
83567
+ for (const spanEl of spanEls) {
83568
+ const pmStart = Number(spanEl.dataset.pmStart ?? "NaN");
83569
+ const pmEnd = Number(spanEl.dataset.pmEnd ?? "NaN");
83570
+ if (!Number.isFinite(pmStart) || !Number.isFinite(pmEnd)) continue;
83571
+ if (pos < pmStart || pos > pmEnd) continue;
83572
+ const pageEl = spanEl.closest(".superdoc-page");
83573
+ if (!pageEl) continue;
83574
+ const pageIndex = Number(pageEl.dataset.pageIndex ?? "0");
83575
+ const pageRect = pageEl.getBoundingClientRect();
83576
+ const textNode = spanEl.firstChild;
83577
+ if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
83578
+ const spanRect2 = spanEl.getBoundingClientRect();
83579
+ return {
83580
+ pageIndex,
83581
+ x: (spanRect2.left - pageRect.left) / zoom,
83582
+ y: (spanRect2.top - pageRect.top) / zoom,
83583
+ height: spanRect2.height / zoom
83584
+ };
83585
+ }
83586
+ const text2 = textNode.textContent ?? "";
83587
+ const charOffset = Math.max(0, Math.min(text2.length, pos - pmStart));
83588
+ const range2 = document.createRange();
83589
+ try {
83590
+ range2.setStart(textNode, charOffset);
83591
+ range2.setEnd(textNode, charOffset);
83592
+ } catch (error) {
83593
+ if (process$1$1.env.NODE_ENV === "development") {
83594
+ console.warn("[PresentationEditor] Range.setStart/setEnd failed:", {
83595
+ error: error instanceof Error ? error.message : String(error),
83596
+ charOffset,
83597
+ textLength: text2.length,
83598
+ pos,
83599
+ pmStart,
83600
+ pmEnd
83601
+ });
83602
+ }
83603
+ const spanRect2 = spanEl.getBoundingClientRect();
83604
+ return {
83605
+ pageIndex,
83606
+ x: (spanRect2.left - pageRect.left) / zoom,
83607
+ y: (spanRect2.top - pageRect.top) / zoom,
83608
+ height: spanRect2.height / zoom
83609
+ };
83610
+ }
83611
+ const rangeRect = range2.getBoundingClientRect();
83612
+ const spanRect = spanEl.getBoundingClientRect();
83613
+ const lineEl = spanEl.closest(".superdoc-line");
83614
+ const lineRect = lineEl ? lineEl.getBoundingClientRect() : spanRect;
83615
+ const caretHeight = spanRect.height;
83616
+ const verticalOffset = (lineRect.height - caretHeight) / 2;
83617
+ const caretY = lineRect.top + verticalOffset;
83618
+ return {
83619
+ pageIndex,
83620
+ x: (rangeRect.left - pageRect.left) / zoom,
83621
+ y: (caretY - pageRect.top) / zoom,
83622
+ height: caretHeight / zoom
83623
+ };
83624
+ }
83625
+ return null;
83626
+ };
83627
+ computeTableCaretLayoutRect_fn = function(pos, _fragment, _tableBlock, _tableMeasure, pageIndex) {
83628
+ const lineEls = Array.from(__privateGet$1(this, _viewportHost).querySelectorAll(".superdoc-line"));
83629
+ if (lineEls.length === 0) return null;
83630
+ for (const lineEl of lineEls) {
83631
+ const pmStart = Number(lineEl.dataset.pmStart ?? "NaN");
83632
+ const pmEnd = Number(lineEl.dataset.pmEnd ?? "NaN");
83633
+ if (!Number.isFinite(pmStart) || !Number.isFinite(pmEnd)) continue;
83634
+ if (pos < pmStart || pos > pmEnd) continue;
83635
+ const spanEls = Array.from(lineEl.querySelectorAll("span[data-pm-start]"));
83636
+ for (const spanEl of spanEls) {
83637
+ const spanStart = Number(spanEl.dataset.pmStart ?? "NaN");
83638
+ const spanEnd = Number(spanEl.dataset.pmEnd ?? "NaN");
83639
+ if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) continue;
83640
+ if (pos < spanStart || pos > spanEnd) continue;
83641
+ const textNode = spanEl.firstChild;
83642
+ if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
83643
+ const spanRect = spanEl.getBoundingClientRect();
83644
+ const viewportRect3 = __privateGet$1(this, _viewportHost).getBoundingClientRect();
83645
+ const zoom3 = __privateGet$1(this, _layoutOptions).zoom ?? 1;
83646
+ return {
83647
+ pageIndex,
83648
+ x: (spanRect.left - viewportRect3.left + __privateGet$1(this, _visibleHost).scrollLeft) / zoom3,
83649
+ y: (spanRect.top - viewportRect3.top + __privateGet$1(this, _visibleHost).scrollTop) / zoom3,
83650
+ height: spanRect.height / zoom3
83651
+ };
83652
+ }
83653
+ const text2 = textNode.textContent ?? "";
83654
+ const charOffset = Math.max(0, Math.min(text2.length, pos - spanStart));
83655
+ const range2 = document.createRange();
83656
+ range2.setStart(textNode, charOffset);
83657
+ range2.setEnd(textNode, charOffset);
83658
+ const rangeRect = range2.getBoundingClientRect();
83659
+ const viewportRect2 = __privateGet$1(this, _viewportHost).getBoundingClientRect();
83660
+ const zoom2 = __privateGet$1(this, _layoutOptions).zoom ?? 1;
83661
+ const lineRect2 = lineEl.getBoundingClientRect();
83662
+ return {
83663
+ pageIndex,
83664
+ x: (rangeRect.left - viewportRect2.left + __privateGet$1(this, _visibleHost).scrollLeft) / zoom2,
83665
+ y: (lineRect2.top - viewportRect2.top + __privateGet$1(this, _visibleHost).scrollTop) / zoom2,
83666
+ height: lineRect2.height / zoom2
83667
+ };
83668
+ }
83669
+ const lineRect = lineEl.getBoundingClientRect();
83670
+ const viewportRect = __privateGet$1(this, _viewportHost).getBoundingClientRect();
83671
+ const zoom = __privateGet$1(this, _layoutOptions).zoom ?? 1;
83672
+ return {
83673
+ pageIndex,
83674
+ x: (lineRect.left - viewportRect.left + __privateGet$1(this, _visibleHost).scrollLeft) / zoom,
83675
+ y: (lineRect.top - viewportRect.top + __privateGet$1(this, _visibleHost).scrollTop) / zoom,
83676
+ height: lineRect.height / zoom
83677
+ };
83678
+ }
83679
+ return null;
83680
+ };
82091
83681
  findLineContainingPos_fn = function(block, measure, fromLine, toLine, pos) {
83682
+ const log2 = (...args) => {
83683
+ console.log("[LINE-SEARCH]", ...args);
83684
+ };
83685
+ log2("Searching for pos:", pos, "in lines", fromLine, "to", toLine);
82092
83686
  if (measure.kind !== "paragraph" || block.kind !== "paragraph") return null;
82093
83687
  for (let lineIndex = fromLine; lineIndex < toLine; lineIndex += 1) {
82094
83688
  const line = measure.lines[lineIndex];
82095
83689
  if (!line) continue;
82096
83690
  const range2 = computeLinePmRange$1(block, line);
83691
+ log2("Line", lineIndex, ":", {
83692
+ pmStart: range2.pmStart,
83693
+ pmEnd: range2.pmEnd,
83694
+ fromRun: line.fromRun,
83695
+ toRun: line.toRun,
83696
+ fromChar: line.fromChar,
83697
+ toChar: line.toChar
83698
+ });
82097
83699
  if (range2.pmStart == null || range2.pmEnd == null) continue;
82098
83700
  if (pos >= range2.pmStart && pos <= range2.pmEnd) {
83701
+ log2("Found line", lineIndex, "for pos", pos);
82099
83702
  return { line, index: lineIndex };
82100
83703
  }
82101
83704
  }
83705
+ log2("No line found for pos", pos);
82102
83706
  return null;
82103
83707
  };
82104
83708
  lineHeightBeforeIndex_fn = function(lines, fromLine, targetIndex) {
@@ -95507,6 +97111,49 @@ ${l}
95507
97111
  };
95508
97112
  }
95509
97113
  });
97114
+ const sharedAttributes = () => ({
97115
+ originalName: {
97116
+ default: null
97117
+ },
97118
+ originalXml: {
97119
+ default: null
97120
+ }
97121
+ });
97122
+ const hiddenRender = (type2) => ["sd-passthrough", { "data-sd-passthrough": type2, style: "display: none;" }];
97123
+ const PassthroughBlock = Node$1.create({
97124
+ name: "passthroughBlock",
97125
+ group: "block",
97126
+ atom: true,
97127
+ draggable: false,
97128
+ selectable: false,
97129
+ defining: true,
97130
+ parseDOM() {
97131
+ return [{ tag: 'sd-passthrough[data-sd-passthrough="block"]' }];
97132
+ },
97133
+ renderDOM() {
97134
+ return hiddenRender("block");
97135
+ },
97136
+ addAttributes() {
97137
+ return sharedAttributes();
97138
+ }
97139
+ });
97140
+ const PassthroughInline = Node$1.create({
97141
+ name: "passthroughInline",
97142
+ group: "inline",
97143
+ inline: true,
97144
+ atom: true,
97145
+ draggable: false,
97146
+ selectable: false,
97147
+ parseDOM() {
97148
+ return [{ tag: 'sd-passthrough[data-sd-passthrough="inline"]' }];
97149
+ },
97150
+ renderDOM() {
97151
+ return hiddenRender("inline");
97152
+ },
97153
+ addAttributes() {
97154
+ return sharedAttributes();
97155
+ }
97156
+ });
95510
97157
  const TextStyle = Mark.create({
95511
97158
  name: "textStyle",
95512
97159
  addOptions() {
@@ -101417,7 +103064,9 @@ ${l}
101417
103064
  AiPlugin,
101418
103065
  Image,
101419
103066
  NodeResizer,
101420
- CustomSelection
103067
+ CustomSelection,
103068
+ PassthroughInline,
103069
+ PassthroughBlock
101421
103070
  ];
101422
103071
  };
101423
103072
  const getStarterExtensions = () => {
@@ -101489,7 +103138,9 @@ ${l}
101489
103138
  CustomSelection,
101490
103139
  TextTransform,
101491
103140
  VectorShape,
101492
- ShapeGroup
103141
+ ShapeGroup,
103142
+ PassthroughInline,
103143
+ PassthroughBlock
101493
103144
  ];
101494
103145
  };
101495
103146
  const sanitizeNumber = (value, defaultNumber) => {
@@ -117386,7 +119037,7 @@ ${style2}
117386
119037
  };
117387
119038
  }
117388
119039
  };
117389
- const TableResizeOverlay = /* @__PURE__ */ _export_sfc$1(_sfc_main$3$1, [["__scopeId", "data-v-d4258885"]]);
119040
+ const TableResizeOverlay = /* @__PURE__ */ _export_sfc$1(_sfc_main$3$1, [["__scopeId", "data-v-3f4a506b"]]);
117390
119041
  const _hoisted_1$2$1 = ["data-handle-position", "onMousedown"];
117391
119042
  const OVERLAY_EXPANSION_PX = 2e3;
117392
119043
  const RESIZE_HANDLE_SIZE_PX = 12;
@@ -118334,98 +119985,6 @@ ${style2}
118334
119985
  }
118335
119986
  };
118336
119987
  const SuperInput = /* @__PURE__ */ _export_sfc$1(_sfc_main$i, [["__scopeId", "data-v-4d5cff52"]]);
118337
- const additionalHandlers = Object.freeze({
118338
- "mc:AlternateContent": translator$1M,
118339
- "sd:pageReference": translator$6,
118340
- "sd:tableOfContents": translator$5,
118341
- "w:b": translator$20,
118342
- "w:bCs": translator$1$,
118343
- "w:bidiVisual": translator$q,
118344
- "w:bookmarkEnd": translator$7,
118345
- "w:bookmarkStart": translator$8,
118346
- "w:bottom": translator$1p,
118347
- "w:br": translator$23,
118348
- "w:cantSplit": translator$F,
118349
- "w:caps": translator$1R,
118350
- "w:cnfStyle": translator$1H,
118351
- "w:color": translator$1W,
118352
- "w:divId": translator$1F,
118353
- "w:drawing": translator$s,
118354
- "w:end": translator$X,
118355
- "w:gridAfter": translator$E,
118356
- "w:gridBefore": translator$D,
118357
- "w:gridCol": translator$b,
118358
- "w:hidden": translator$C,
118359
- "w:highlight": translator$22,
118360
- "w:hyperlink": translator$10,
118361
- "w:i": translator$1_,
118362
- "w:insideH": translator$V,
118363
- "w:insideV": translator$U,
118364
- "w:jc": translator$1C,
118365
- "w:left": translator$1n,
118366
- "w:p": translator$11,
118367
- "w:r": translator$$,
118368
- "w:rFonts": translator$1V,
118369
- "w:rPr": translator$1N,
118370
- "w:rStyle": translator$1U,
118371
- "w:right": translator$1l,
118372
- "w:sdt": translator$r,
118373
- "w:shd": translator$1Q,
118374
- "w:start": translator$T,
118375
- "w:strike": translator$1Y,
118376
- "w:sz": translator$1T,
118377
- "w:szCs": translator$1S,
118378
- "w:tab": translator$21,
118379
- "w:tbl": translator$9,
118380
- "w:tblBorders": translator$e,
118381
- "w:tblCaption": translator$p,
118382
- "w:tblCellMar": translator$d,
118383
- "w:tblCellSpacing": translator$B,
118384
- "w:tblDescription": translator$o,
118385
- "w:tblGrid": translator$a,
118386
- "w:tblHeader": translator$A,
118387
- "w:tblInd": translator$n,
118388
- "w:tblLayout": translator$m,
118389
- "w:tblLook": translator$l,
118390
- "w:tblOverlap": translator$k,
118391
- "w:tblPr": translator$c,
118392
- "w:tblStyle": translator$j,
118393
- "w:tblStyleColBandSize": translator$i,
118394
- "w:tblStyleRowBandSize": translator$h,
118395
- "w:tblW": translator$g,
118396
- "w:tblpPr": translator$f,
118397
- "w:tc": translator$G,
118398
- "w:top": translator$1j,
118399
- "w:tr": translator$v,
118400
- "w:trHeight": translator$z,
118401
- "w:trPr": translator$w,
118402
- "w:u": translator$1Z,
118403
- "w:wAfter": translator$y,
118404
- "w:wBefore": translator$x,
118405
- "wp:anchor": translator$u,
118406
- "wp:inline": translator$t,
118407
- "w:commentRangeStart": commentRangeStartTranslator,
118408
- "w:commentRangeEnd": commentRangeEndTranslator,
118409
- "w:vMerge": translator$Y,
118410
- "w:gridSpan": translator$Z,
118411
- "w:vAlign": translator$L,
118412
- "w:noWrap": translator$O,
118413
- "w:tcFitText": translator$M,
118414
- "w:tcW": translator$_,
118415
- "w:hideMark": translator$K,
118416
- "w:textDirection": translator$17,
118417
- "w:tl2br": translator$R,
118418
- "w:tr2bl": translator$Q,
118419
- "w:header": translator$J,
118420
- "w:headers": translator$I,
118421
- "w:tcBorders": translator$P,
118422
- "w:tcMar": translator$N,
118423
- "w:tcPr": translator$H
118424
- });
118425
- const baseHandlers = {
118426
- ...additionalHandlers
118427
- };
118428
- const registeredHandlers = Object.freeze(baseHandlers);
118429
119988
  const Extensions = {
118430
119989
  Node: Node$1,
118431
119990
  Attribute,
@@ -135477,7 +137036,7 @@ ${style2}
135477
137036
  this.config.colors = shuffleArray(this.config.colors);
135478
137037
  this.userColorMap = /* @__PURE__ */ new Map();
135479
137038
  this.colorIndex = 0;
135480
- this.version = "1.0.0-beta.14";
137039
+ this.version = "1.0.0-beta.15";
135481
137040
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
135482
137041
  this.superdocId = config2.superdocId || v4();
135483
137042
  this.colors = this.config.colors;
@@ -137920,7 +139479,7 @@ ${style2}
137920
139479
  value && typeof value === "object" && "byteLength" in value && "byteOffset" in value
137921
139480
  );
137922
139481
  }
137923
- const indexI4Ew0HDV = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
139482
+ const indexBds7gW4r = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
137924
139483
  __proto__: null,
137925
139484
  unified
137926
139485
  }, Symbol.toStringTag, { value: "Module" }));