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
@@ -18966,7 +18966,6 @@ const encode$B = (params2, encodedAttrs = {}) => {
18966
18966
  }
18967
18967
  }
18968
18968
  });
18969
- console.log("subs:", subs);
18970
18969
  return subs;
18971
18970
  };
18972
18971
  function decode$D(params2) {
@@ -20125,6 +20124,51 @@ function getStrikeValue(attributes) {
20125
20124
  if (value === "0" || value === "false" || value === "off") return "0";
20126
20125
  return "1";
20127
20126
  }
20127
+ function parseProperties(node) {
20128
+ const marks = [];
20129
+ const unknownMarks = [];
20130
+ const { attributes = {}, elements = [] } = node;
20131
+ const { nodes, paragraphProperties = {}, runProperties = {} } = splitElementsAndProperties(elements);
20132
+ const hasRun = elements.find((element) => element.name === "w:r");
20133
+ if (hasRun) paragraphProperties.elements = paragraphProperties?.elements?.filter((el) => el.name !== "w:rPr");
20134
+ if (runProperties && runProperties?.elements?.length) {
20135
+ marks.push(...parseMarks(runProperties, unknownMarks));
20136
+ }
20137
+ if (paragraphProperties && paragraphProperties.elements?.length) {
20138
+ const disallowedParagraphProperties = ["w:u"];
20139
+ const filteredParagraphProperties = {
20140
+ ...paragraphProperties,
20141
+ elements: paragraphProperties.elements?.filter((el) => !disallowedParagraphProperties.includes(el.name))
20142
+ };
20143
+ marks.push(...parseMarks(filteredParagraphProperties, unknownMarks));
20144
+ }
20145
+ marks.push(...handleStyleChangeMarks(runProperties, marks));
20146
+ if (paragraphProperties && paragraphProperties.elements?.length) {
20147
+ attributes["paragraphProperties"] = paragraphProperties;
20148
+ }
20149
+ if (marks && node.name === "w:p") {
20150
+ marks.forEach((mark) => {
20151
+ const attrValue = Object.keys(mark.attrs ?? {})[0];
20152
+ if (attrValue) {
20153
+ const value = mark.attrs[attrValue];
20154
+ attributes[attrValue] = value;
20155
+ }
20156
+ });
20157
+ }
20158
+ return { elements: nodes, attributes, marks, unknownMarks };
20159
+ }
20160
+ function splitElementsAndProperties(elements) {
20161
+ const pPr = elements.find((el) => el.name === "w:pPr");
20162
+ const rPr = elements.find((el) => el.name === "w:rPr");
20163
+ const sectPr = elements.find((el) => el.name === "w:sectPr");
20164
+ const els = elements.filter((el) => el.name !== "w:pPr" && el.name !== "w:rPr" && el.name !== "w:sectPr");
20165
+ return {
20166
+ nodes: els,
20167
+ paragraphProperties: pPr,
20168
+ runProperties: rPr,
20169
+ sectionProperties: sectPr
20170
+ };
20171
+ }
20128
20172
  function getTableStyleId(path) {
20129
20173
  const tbl = path.find((ancestor) => ancestor.name === "w:tbl");
20130
20174
  if (!tbl) {
@@ -20149,13 +20193,6 @@ const handleParagraphNode$1 = (params2) => {
20149
20193
  if (pPr) {
20150
20194
  inlineParagraphProperties = translator$12.encode({ ...params2, nodes: [pPr] }) || {};
20151
20195
  }
20152
- const handleStandardNode2 = nodeListHandler.handlerEntities.find(
20153
- (e) => e.handlerName === "standardNodeHandler"
20154
- )?.handler;
20155
- if (!handleStandardNode2) {
20156
- console.error("Standard node handler not found");
20157
- return null;
20158
- }
20159
20196
  const insideTable = (params2.path || []).some((ancestor) => ancestor.name === "w:tc");
20160
20197
  const tableStyleId = getTableStyleId(params2.path || []);
20161
20198
  const resolvedParagraphProperties = resolveParagraphProperties(
@@ -20164,15 +20201,29 @@ const handleParagraphNode$1 = (params2) => {
20164
20201
  insideTable,
20165
20202
  tableStyleId
20166
20203
  );
20167
- const updatedParams = {
20168
- ...params2,
20169
- nodes: [node],
20170
- extraParams: { ...params2.extraParams, paragraphProperties: resolvedParagraphProperties }
20171
- };
20172
- const result = handleStandardNode2(updatedParams);
20173
- if (result.nodes.length === 1) {
20174
- schemaNode = result.nodes[0];
20204
+ const { elements = [], attributes = {}, marks = [] } = parseProperties(node, params2.docx);
20205
+ const childContent = [];
20206
+ if (elements.length) {
20207
+ const updatedElements = elements.map((el) => {
20208
+ if (!el.marks) el.marks = [];
20209
+ el.marks.push(...marks);
20210
+ return el;
20211
+ });
20212
+ const childParams = {
20213
+ ...params2,
20214
+ nodes: updatedElements,
20215
+ extraParams: { ...params2.extraParams, paragraphProperties: resolvedParagraphProperties },
20216
+ path: [...params2.path || [], node]
20217
+ };
20218
+ const translatedChildren = nodeListHandler.handler(childParams);
20219
+ childContent.push(...translatedChildren);
20175
20220
  }
20221
+ schemaNode = {
20222
+ type: "paragraph",
20223
+ content: childContent,
20224
+ attrs: { ...attributes },
20225
+ marks: []
20226
+ };
20176
20227
  schemaNode.type = "paragraph";
20177
20228
  schemaNode.attrs.paragraphProperties = inlineParagraphProperties;
20178
20229
  schemaNode.attrs.rsidRDefault = node.attributes?.["w:rsidRDefault"];
@@ -21820,13 +21871,14 @@ const tableOfContentsHandler = (params2) => {
21820
21871
  nodes: node.elements,
21821
21872
  path: [...params2.path || [], node]
21822
21873
  });
21874
+ const normalizedContent = normalizeDocPartContent(translatedContent);
21823
21875
  const sdtPr = params2.extraParams.sdtPr;
21824
21876
  const id = sdtPr.elements?.find((el) => el.name === "w:id")?.attributes["w:val"] || "";
21825
21877
  const docPartObj = sdtPr?.elements.find((el) => el.name === "w:docPartObj");
21826
21878
  const docPartUnique = docPartObj?.elements.some((el) => el.name === "w:docPartUnique") ?? false;
21827
21879
  const result = {
21828
21880
  type: "documentPartObject",
21829
- content: translatedContent,
21881
+ content: normalizedContent,
21830
21882
  attrs: {
21831
21883
  id,
21832
21884
  docPartGallery: "Table of Contents",
@@ -21866,6 +21918,22 @@ const genericDocPartHandler = (params2) => {
21866
21918
  const validGalleryTypeMap = {
21867
21919
  "Table of Contents": tableOfContentsHandler
21868
21920
  };
21921
+ const inlineNodeTypes = /* @__PURE__ */ new Set(["bookmarkStart", "bookmarkEnd"]);
21922
+ const wrapInlineNode = (node) => ({
21923
+ type: "paragraph",
21924
+ content: [node]
21925
+ });
21926
+ const normalizeDocPartContent = (nodes = []) => {
21927
+ const normalized = [];
21928
+ nodes.forEach((node) => {
21929
+ if (inlineNodeTypes.has(node?.type)) {
21930
+ normalized.push(wrapInlineNode(node));
21931
+ } else {
21932
+ normalized.push(node);
21933
+ }
21934
+ });
21935
+ return normalized;
21936
+ };
21869
21937
  function handleDocumentSectionNode$1(params2) {
21870
21938
  const { nodes, nodeListHandler } = params2;
21871
21939
  if (nodes.length === 0 || nodes[0].name !== "w:sdt") {
@@ -24944,7 +25012,8 @@ function handleImageNode$1(node, params2, isAnchor) {
24944
25012
  horizontal: positionHValue,
24945
25013
  top: positionVValue
24946
25014
  };
24947
- const simplePos = node.elements.find((el) => el.name === "wp:simplePos");
25015
+ const useSimplePos = attributes["simplePos"] === "1" || attributes["simplePos"] === 1;
25016
+ const simplePos = useSimplePos ? node.elements.find((el) => el.name === "wp:simplePos") : null;
24948
25017
  const wrapNode = isAnchor ? node.elements.find(
24949
25018
  (el) => ["wp:wrapNone", "wp:wrapSquare", "wp:wrapThrough", "wp:wrapTight", "wp:wrapTopAndBottom"].includes(el.name)
24950
25019
  ) : null;
@@ -32712,15 +32781,26 @@ const getCommentSchema = (type2, commentIndex) => {
32712
32781
  }
32713
32782
  };
32714
32783
  };
32715
- const getConfig = (type2) => ({
32716
- xmlName: `${XML_NODE_NAME$7}${type2}`,
32717
- sdNodeOrKeyName: `${SD_NODE_NAME$6}${type2}`,
32718
- type: NodeTranslator.translatorTypes.NODE,
32719
- encode: () => {
32720
- },
32721
- decode: decode$7,
32722
- attributes: [attrConfig]
32723
- });
32784
+ const getConfig = (type2) => {
32785
+ const sdName = `${SD_NODE_NAME$6}${type2}`;
32786
+ const isStart = type2 === "Start";
32787
+ return {
32788
+ xmlName: `${XML_NODE_NAME$7}${type2}`,
32789
+ sdNodeOrKeyName: sdName,
32790
+ type: NodeTranslator.translatorTypes.NODE,
32791
+ encode: ({ nodes }) => {
32792
+ const node = nodes?.[0];
32793
+ if (!node) return void 0;
32794
+ const attrs = node.attributes ? { ...node.attributes } : {};
32795
+ return {
32796
+ type: isStart ? "commentRangeStart" : "commentRangeEnd",
32797
+ attrs
32798
+ };
32799
+ },
32800
+ decode: decode$7,
32801
+ attributes: [attrConfig]
32802
+ };
32803
+ };
32724
32804
  const commentRangeStartTranslator = NodeTranslator.from(getConfig("Start"));
32725
32805
  const commentRangeEndTranslator = NodeTranslator.from(getConfig("End"));
32726
32806
  const XML_NODE_NAME$6 = "sd:pageReference";
@@ -33444,127 +33524,224 @@ const sdtNodeHandlerEntity = {
33444
33524
  handlerName: "sdtNodeHandler",
33445
33525
  handler: handleSdtNode
33446
33526
  };
33447
- function parseProperties(node) {
33448
- const marks = [];
33449
- const unknownMarks = [];
33450
- const { attributes = {}, elements = [] } = node;
33451
- const { nodes, paragraphProperties = {}, runProperties = {} } = splitElementsAndProperties(elements);
33452
- const hasRun = elements.find((element) => element.name === "w:r");
33453
- if (hasRun) paragraphProperties.elements = paragraphProperties?.elements?.filter((el) => el.name !== "w:rPr");
33454
- if (runProperties && runProperties?.elements?.length) {
33455
- marks.push(...parseMarks(runProperties, unknownMarks));
33456
- }
33457
- if (paragraphProperties && paragraphProperties.elements?.length) {
33458
- const disallowedParagraphProperties = ["w:u"];
33459
- const filteredParagraphProperties = {
33460
- ...paragraphProperties,
33461
- elements: paragraphProperties.elements?.filter((el) => !disallowedParagraphProperties.includes(el.name))
33462
- };
33463
- marks.push(...parseMarks(filteredParagraphProperties, unknownMarks));
33464
- }
33465
- marks.push(...handleStyleChangeMarks(runProperties, marks));
33466
- if (paragraphProperties && paragraphProperties.elements?.length) {
33467
- attributes["paragraphProperties"] = paragraphProperties;
33527
+ const translatorList = Array.from(
33528
+ /* @__PURE__ */ new Set([
33529
+ translator$1M,
33530
+ translator$6,
33531
+ translator$5,
33532
+ translator$4,
33533
+ translator$3,
33534
+ translator$1L,
33535
+ translator$1K,
33536
+ translator$1J,
33537
+ translator$20,
33538
+ translator$1r,
33539
+ translator$1$,
33540
+ translator$q,
33541
+ translator$7,
33542
+ translator$8,
33543
+ translator$1p,
33544
+ translator$23,
33545
+ translator$F,
33546
+ translator$1R,
33547
+ translator$1H,
33548
+ translator$1W,
33549
+ translator$1G,
33550
+ translator$2,
33551
+ translator$1F,
33552
+ translator$s,
33553
+ translator$1X,
33554
+ translator$X,
33555
+ translator$1E,
33556
+ translator$E,
33557
+ translator$D,
33558
+ translator$b,
33559
+ translator$Z,
33560
+ translator$J,
33561
+ translator$I,
33562
+ translator$C,
33563
+ translator$K,
33564
+ translator$22,
33565
+ translator$10,
33566
+ translator$1_,
33567
+ translator$1x,
33568
+ translator$1D,
33569
+ translator$1w,
33570
+ translator$V,
33571
+ translator$U,
33572
+ translator$1C,
33573
+ translator$1B,
33574
+ translator$1A,
33575
+ translator$1z,
33576
+ translator$1P,
33577
+ translator$1n,
33578
+ translator$1y,
33579
+ translator$O,
33580
+ translator$1v,
33581
+ translator$1u,
33582
+ translator$1t,
33583
+ translator$1s,
33584
+ translator$11,
33585
+ translator$1f,
33586
+ translator$1h,
33587
+ translator$12,
33588
+ translator$1g,
33589
+ translator$$,
33590
+ translator$1V,
33591
+ translator$1N,
33592
+ translator$1U,
33593
+ translator$1l,
33594
+ translator$r,
33595
+ translator$1Q,
33596
+ translator$1e,
33597
+ translator$1d,
33598
+ translator$1c,
33599
+ translator$1b,
33600
+ translator$1a,
33601
+ translator$T,
33602
+ translator$1Y,
33603
+ translator$1T,
33604
+ translator$1S,
33605
+ translator$1,
33606
+ translator$21,
33607
+ translator$19,
33608
+ translator$9,
33609
+ translator$e,
33610
+ translator$p,
33611
+ translator$d,
33612
+ translator$B,
33613
+ translator$o,
33614
+ translator$a,
33615
+ translator$A,
33616
+ translator$n,
33617
+ translator$m,
33618
+ translator$l,
33619
+ translator$k,
33620
+ translator$c,
33621
+ translator$j,
33622
+ translator$i,
33623
+ translator$h,
33624
+ translator$g,
33625
+ translator$f,
33626
+ translator$G,
33627
+ translator$P,
33628
+ translator$M,
33629
+ translator$N,
33630
+ translator$H,
33631
+ translator$_,
33632
+ translator$17,
33633
+ translator$R,
33634
+ translator$v,
33635
+ translator$Q,
33636
+ translator$z,
33637
+ translator$w,
33638
+ translator$18,
33639
+ translator$16,
33640
+ translator$15,
33641
+ translator$1j,
33642
+ translator$1Z,
33643
+ translator$L,
33644
+ translator$Y,
33645
+ translator$y,
33646
+ translator$x,
33647
+ translator$14,
33648
+ translator$13,
33649
+ translator$u,
33650
+ translator$t,
33651
+ commentRangeStartTranslator,
33652
+ commentRangeEndTranslator
33653
+ ])
33654
+ );
33655
+ const additionalHandlers = Object.freeze(
33656
+ translatorList.reduce((acc, translator2) => {
33657
+ const key2 = translator2?.xmlName;
33658
+ if (!key2) return acc;
33659
+ acc[key2] = translator2;
33660
+ return acc;
33661
+ }, {})
33662
+ );
33663
+ const baseHandlers = {
33664
+ ...additionalHandlers
33665
+ };
33666
+ const registeredHandlers = Object.freeze(baseHandlers);
33667
+ const INLINE_PARENT_NAMES = /* @__PURE__ */ new Set([
33668
+ "w:r",
33669
+ "w:hyperlink",
33670
+ "w:smartTag",
33671
+ "w:fldSimple",
33672
+ "w:proofErr",
33673
+ "w:del",
33674
+ "w:ins"
33675
+ ]);
33676
+ const INLINE_NODE_NAMES = /* @__PURE__ */ new Set([
33677
+ "m:oMathPara",
33678
+ "m:oMath",
33679
+ "m:t",
33680
+ "m:r",
33681
+ "m:ctrlPr",
33682
+ "m:sSupPr",
33683
+ "m:e",
33684
+ "m:sup",
33685
+ "m:sSup"
33686
+ ]);
33687
+ const BLOCK_BOUNDARY_NAMES = /* @__PURE__ */ new Set(["w:p", "w:body", "w:tbl", "w:tc", "w:tr"]);
33688
+ const isInlineContext = (path = [], currentNodeName) => {
33689
+ if (currentNodeName && INLINE_NODE_NAMES.has(currentNodeName)) {
33690
+ return true;
33468
33691
  }
33469
- if (marks && node.name === "w:p") {
33470
- marks.forEach((mark) => {
33471
- const attrValue = Object.keys(mark.attrs ?? {})[0];
33472
- if (attrValue) {
33473
- const value = mark.attrs[attrValue];
33474
- attributes[attrValue] = value;
33475
- }
33476
- });
33692
+ if (!Array.isArray(path) || path.length === 0) return false;
33693
+ for (let i = path.length - 1; i >= 0; i--) {
33694
+ const ancestorName = path[i]?.name;
33695
+ if (!ancestorName) continue;
33696
+ if (INLINE_NODE_NAMES.has(ancestorName) || INLINE_PARENT_NAMES.has(ancestorName)) {
33697
+ return true;
33698
+ }
33699
+ if (BLOCK_BOUNDARY_NAMES.has(ancestorName)) {
33700
+ return false;
33701
+ }
33477
33702
  }
33478
- return { elements: nodes, attributes, marks, unknownMarks };
33479
- }
33480
- function splitElementsAndProperties(elements) {
33481
- const pPr = elements.find((el) => el.name === "w:pPr");
33482
- const rPr = elements.find((el) => el.name === "w:rPr");
33483
- const sectPr = elements.find((el) => el.name === "w:sectPr");
33484
- const els = elements.filter((el) => el.name !== "w:pPr" && el.name !== "w:rPr" && el.name !== "w:sectPr");
33485
- return {
33486
- nodes: els,
33487
- paragraphProperties: pPr,
33488
- runProperties: rPr,
33489
- sectionProperties: sectPr
33490
- };
33491
- }
33492
- function getElementName(element) {
33493
- return SuperConverter.allowedElements[element.name || element.type];
33494
- }
33495
- const isPropertiesElement = (element) => {
33496
- return !!SuperConverter.propertyTypes[element.name || element.type];
33703
+ return false;
33497
33704
  };
33498
- const handleStandardNode = (params2) => {
33499
- const { nodes, docx, nodeListHandler } = params2;
33500
- if (!nodes || nodes.length === 0) {
33501
- return { nodes: [], consumed: 0 };
33502
- }
33705
+ const handlePassthroughNode = (params2) => {
33706
+ const { nodes = [] } = params2;
33503
33707
  const node = nodes[0];
33504
- const { name } = node;
33505
- const { attributes, elements, marks = [] } = parseProperties(node);
33506
- if (name === "w:sdt") {
33708
+ if (!node) return { nodes: [], consumed: 0 };
33709
+ if (registeredHandlers[node.name]) {
33507
33710
  return { nodes: [], consumed: 0 };
33508
33711
  }
33509
- if (isPropertiesElement(node)) {
33510
- return {
33511
- nodes: [
33512
- {
33513
- type: getElementName(node),
33514
- attrs: { ...attributes },
33515
- marks: []
33516
- }
33517
- ],
33518
- consumed: 0
33519
- };
33520
- }
33521
- if (!getElementName(node)) {
33522
- return {
33523
- nodes: [
33524
- {
33525
- type: name,
33526
- content: elements,
33527
- attrs: { ...attributes },
33528
- marks
33529
- }
33530
- ],
33531
- consumed: 0,
33532
- unhandled: true
33533
- };
33534
- }
33535
- const content = [];
33536
- const parentStyleId = getParentStyleId(node);
33537
- if (elements && elements.length) {
33538
- const updatedElements = elements.map((el) => {
33539
- if (!el.marks) el.marks = [];
33540
- el.marks.push(...marks);
33541
- return el;
33542
- });
33712
+ const originalXml = carbonCopy(node) || {};
33713
+ const originalElementsSource = originalXml.elements;
33714
+ const originalElements = originalElementsSource ? carbonCopy(originalElementsSource) : [];
33715
+ const childElements = Array.isArray(node.elements) ? node.elements : [];
33716
+ let childContent = [];
33717
+ if (childElements.length && params2.nodeListHandler?.handler) {
33543
33718
  const childParams = {
33544
33719
  ...params2,
33545
- nodes: updatedElements,
33546
- parentStyleId,
33720
+ nodes: childElements,
33547
33721
  path: [...params2.path || [], node]
33548
33722
  };
33549
- const childContent = nodeListHandler.handler(childParams);
33550
- content.push(...childContent);
33723
+ childContent = params2.nodeListHandler.handler(childParams) || [];
33551
33724
  }
33552
- const resultNode = {
33553
- type: getElementName(node),
33554
- content,
33555
- attrs: { ...attributes },
33556
- marks: []
33725
+ if (originalElements?.length) {
33726
+ originalXml.elements = originalElements;
33727
+ }
33728
+ const passthroughNode = {
33729
+ type: isInlineContext(params2.path, node.name) ? "passthroughInline" : "passthroughBlock",
33730
+ attrs: {
33731
+ originalName: node.name,
33732
+ originalXml
33733
+ },
33734
+ marks: [],
33735
+ content: childContent
33736
+ };
33737
+ return {
33738
+ nodes: [passthroughNode],
33739
+ consumed: 1
33557
33740
  };
33558
- return { nodes: [resultNode], consumed: 1 };
33559
- };
33560
- const getParentStyleId = (node) => {
33561
- const pPr = node.elements?.find((el) => el.name === "w:pPr");
33562
- const styleTag = pPr?.elements?.find((el) => el.name === "w:pStyle");
33563
- return styleTag ? styleTag.attributes["w:val"] : null;
33564
33741
  };
33565
- const standardNodeHandlerEntity = {
33566
- handlerName: "standardNodeHandler",
33567
- handler: handleStandardNode
33742
+ const passthroughNodeHandlerEntity = {
33743
+ handlerName: "passthroughNodeHandler",
33744
+ handler: handlePassthroughNode
33568
33745
  };
33569
33746
  const handler = (params2) => {
33570
33747
  const { nodes } = params2;
@@ -33588,13 +33765,6 @@ const handleBookmarkNode = (params2) => {
33588
33765
  return { nodes: [], consumed: 0 };
33589
33766
  }
33590
33767
  const node = nodes[0];
33591
- const handleStandardNode2 = nodeListHandler.handlerEntities.find(
33592
- (e) => e.handlerName === "standardNodeHandler"
33593
- )?.handler;
33594
- if (!handleStandardNode2) {
33595
- console.error("Standard node handler not found");
33596
- return { nodes: [], consumed: 0 };
33597
- }
33598
33768
  const customMarks = editor?.extensionService?.extensions?.filter((e) => e.isExternal === true) || [];
33599
33769
  const bookmarkName = node.attributes["w:name"]?.split(";")[0];
33600
33770
  const customMark = customMarks.find((mark) => mark.name === bookmarkName);
@@ -33603,7 +33773,6 @@ const handleBookmarkNode = (params2) => {
33603
33773
  (n) => n.name === "w:bookmarkEnd" && n.attributes["w:id"] === node.attributes["w:id"]
33604
33774
  );
33605
33775
  const textNodes = nodes.slice(1, bookmarkEndIndex);
33606
- const nodeListHandler2 = params2.nodeListHandler;
33607
33776
  const attrs = {};
33608
33777
  node.attributes["w:name"].split(";").forEach((name) => {
33609
33778
  const [key2, value] = name.split("=");
@@ -33611,7 +33780,7 @@ const handleBookmarkNode = (params2) => {
33611
33780
  attrs[key2] = value;
33612
33781
  }
33613
33782
  });
33614
- const translatedText = nodeListHandler2.handler({
33783
+ const translatedText = nodeListHandler.handler({
33615
33784
  ...params2,
33616
33785
  nodes: textNodes,
33617
33786
  path: [...params2.path || [], node]
@@ -33627,13 +33796,11 @@ const handleBookmarkNode = (params2) => {
33627
33796
  consumed: translatedText.length + 2
33628
33797
  };
33629
33798
  }
33630
- const updatedParams = { ...params2, nodes: [node] };
33631
- const result = handleStandardNode2(updatedParams);
33632
- if (result.nodes.length === 1) {
33633
- result.nodes[0].attrs.name = node.attributes["w:name"];
33634
- result.nodes[0].attrs.id = node.attributes["w:id"];
33799
+ const encoded = translator$8.encode({ ...params2, nodes: [node] });
33800
+ if (!encoded) {
33801
+ return { nodes: [], consumed: 0 };
33635
33802
  }
33636
- return result;
33803
+ return { nodes: [encoded], consumed: 1 };
33637
33804
  };
33638
33805
  const handleBookmarkStartNode = (params2) => {
33639
33806
  const { nodes } = params2;
@@ -34280,18 +34447,22 @@ const getInstructionPreProcessor = (instruction) => {
34280
34447
  const preProcessNodesForFldChar = (nodes = [], docx) => {
34281
34448
  const processedNodes = [];
34282
34449
  let collectedNodesStack = [];
34450
+ let rawCollectedNodesStack = [];
34283
34451
  let currentFieldStack = [];
34284
34452
  let unpairedEnd = null;
34285
34453
  let collecting = false;
34286
34454
  const finalizeField = () => {
34287
34455
  if (collecting) {
34288
34456
  const collectedNodes = collectedNodesStack.pop().filter((n) => n !== null);
34457
+ const rawCollectedNodes = rawCollectedNodesStack.pop().filter((n) => n !== null);
34289
34458
  const currentField = currentFieldStack.pop();
34290
- const combined = _processCombinedNodesForFldChar(collectedNodes, currentField.instrText.trim(), docx);
34459
+ const combinedResult = _processCombinedNodesForFldChar(collectedNodes, currentField.instrText.trim(), docx);
34460
+ const outputNodes = combinedResult.handled ? combinedResult.nodes : rawCollectedNodes;
34291
34461
  if (collectedNodesStack.length === 0) {
34292
- processedNodes.push(...combined);
34462
+ processedNodes.push(...outputNodes);
34293
34463
  } else {
34294
- collectedNodesStack[collectedNodesStack.length - 1].push(...combined);
34464
+ collectedNodesStack[collectedNodesStack.length - 1].push(...outputNodes);
34465
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(...outputNodes);
34295
34466
  }
34296
34467
  } else {
34297
34468
  unpairedEnd = true;
@@ -34303,18 +34474,26 @@ const preProcessNodesForFldChar = (nodes = [], docx) => {
34303
34474
  const instrTextEl = node.elements?.find((el) => el.name === "w:instrText");
34304
34475
  collecting = collectedNodesStack.length > 0;
34305
34476
  if (fldType === "begin") {
34306
- collectedNodesStack.push([null]);
34477
+ collectedNodesStack.push([]);
34478
+ rawCollectedNodesStack.push([node]);
34307
34479
  currentFieldStack.push({ instrText: "" });
34308
34480
  continue;
34309
34481
  }
34310
34482
  if (instrTextEl && collecting && currentFieldStack.length > 0) {
34483
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node);
34311
34484
  currentFieldStack[currentFieldStack.length - 1].instrText += (instrTextEl.elements?.[0]?.text || "") + " ";
34312
34485
  continue;
34313
34486
  }
34314
34487
  if (fldType === "end") {
34488
+ if (collecting) {
34489
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node);
34490
+ }
34315
34491
  finalizeField();
34316
34492
  continue;
34317
34493
  } else if (fldType === "separate") {
34494
+ if (collecting) {
34495
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node);
34496
+ }
34318
34497
  continue;
34319
34498
  }
34320
34499
  if (Array.isArray(node.elements)) {
@@ -34324,17 +34503,21 @@ const preProcessNodesForFldChar = (nodes = [], docx) => {
34324
34503
  childResult.unpairedBegin.forEach((pendingField) => {
34325
34504
  currentFieldStack.push(pendingField.fieldInfo);
34326
34505
  collectedNodesStack.push([node]);
34506
+ rawCollectedNodesStack.push([node]);
34327
34507
  });
34328
34508
  } else if (childResult.unpairedEnd) {
34329
34509
  collectedNodesStack[collectedNodesStack.length - 1].push(node);
34510
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node);
34330
34511
  finalizeField();
34331
34512
  } else if (collecting) {
34332
34513
  collectedNodesStack[collectedNodesStack.length - 1].push(node);
34514
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node);
34333
34515
  } else {
34334
34516
  processedNodes.push(node);
34335
34517
  }
34336
34518
  } else if (collecting) {
34337
34519
  collectedNodesStack[collectedNodesStack.length - 1].push(node);
34520
+ rawCollectedNodesStack[rawCollectedNodesStack.length - 1].push(node);
34338
34521
  } else {
34339
34522
  processedNodes.push(node);
34340
34523
  }
@@ -34356,10 +34539,9 @@ const _processCombinedNodesForFldChar = (nodesToCombine = [], instrText, docx) =
34356
34539
  const instructionType = instrText.trim().split(" ")[0];
34357
34540
  const instructionPreProcessor = getInstructionPreProcessor(instructionType);
34358
34541
  if (instructionPreProcessor) {
34359
- return instructionPreProcessor(nodesToCombine, instrText, docx);
34360
- } else {
34361
- return nodesToCombine;
34542
+ return { nodes: instructionPreProcessor(nodesToCombine, instrText, docx), handled: true };
34362
34543
  }
34544
+ return { nodes: nodesToCombine, handled: false };
34363
34545
  };
34364
34546
  const preProcessPageFieldsOnly = (nodes = []) => {
34365
34547
  const processedNodes = [];
@@ -34434,6 +34616,14 @@ function scanFieldSequence(nodes, beginIndex) {
34434
34616
  endIndex
34435
34617
  };
34436
34618
  }
34619
+ const commentRangeStartHandlerEntity = generateV2HandlerEntity(
34620
+ "commentRangeStartHandler",
34621
+ commentRangeStartTranslator
34622
+ );
34623
+ const commentRangeEndHandlerEntity = generateV2HandlerEntity(
34624
+ "commentRangeEndHandler",
34625
+ commentRangeEndTranslator
34626
+ );
34437
34627
  const createDocumentJson = (docx, converter, editor) => {
34438
34628
  const json = carbonCopy(getInitialJSON(docx));
34439
34629
  if (!json) return null;
@@ -34495,6 +34685,7 @@ const createDocumentJson = (docx, converter, editor) => {
34495
34685
  path: []
34496
34686
  });
34497
34687
  parsedContent = filterOutRootInlineNodes(parsedContent);
34688
+ collapseWhitespaceNextToInlinePassthrough(parsedContent);
34498
34689
  const result = {
34499
34690
  type: "doc",
34500
34691
  content: parsedContent,
@@ -34535,6 +34726,8 @@ const defaultNodeListHandler = () => {
34535
34726
  bookmarkStartNodeHandlerEntity,
34536
34727
  bookmarkEndNodeHandlerEntity,
34537
34728
  hyperlinkNodeHandlerEntity,
34729
+ commentRangeStartHandlerEntity,
34730
+ commentRangeEndHandlerEntity,
34538
34731
  drawingNodeHandlerEntity,
34539
34732
  trackChangeNodeHandlerEntity,
34540
34733
  tableNodeHandlerEntity,
@@ -34543,7 +34736,7 @@ const defaultNodeListHandler = () => {
34543
34736
  autoPageHandlerEntity,
34544
34737
  autoTotalPageCountEntity,
34545
34738
  pageReferenceEntity,
34546
- standardNodeHandlerEntity
34739
+ passthroughNodeHandlerEntity
34547
34740
  ];
34548
34741
  const handler2 = createNodeListHandler(entities);
34549
34742
  return {
@@ -34830,8 +35023,8 @@ const importHeadersFooters = (docx, converter, mainEditor) => {
34830
35023
  editor.options.annotations = true;
34831
35024
  headers.forEach((header) => {
34832
35025
  const { rId, referenceFile, currentFileName } = getHeaderFooterSectionData(header, docx);
34833
- const { processedNodes: headerProcessedNodes } = preProcessPageFieldsOnly(referenceFile.elements[0].elements ?? []);
34834
- referenceFile.elements[0].elements = headerProcessedNodes;
35026
+ const headerNodes = carbonCopy(referenceFile.elements[0].elements ?? []);
35027
+ const { processedNodes: headerProcessedNodes } = preProcessPageFieldsOnly(headerNodes);
34835
35028
  const sectPrHeader = allSectPrElements.find(
34836
35029
  (el) => el.name === "w:headerReference" && el.attributes["r:id"] === rId
34837
35030
  );
@@ -34839,7 +35032,7 @@ const importHeadersFooters = (docx, converter, mainEditor) => {
34839
35032
  if (converter.headerIds[sectionType]) sectionType = null;
34840
35033
  const nodeListHandler = defaultNodeListHandler();
34841
35034
  let schema = nodeListHandler.handler({
34842
- nodes: referenceFile.elements[0].elements,
35035
+ nodes: headerProcessedNodes,
34843
35036
  nodeListHandler,
34844
35037
  docx,
34845
35038
  converter,
@@ -34860,15 +35053,15 @@ const importHeadersFooters = (docx, converter, mainEditor) => {
34860
35053
  if (titlePg) converter.headerIds.titlePg = true;
34861
35054
  footers.forEach((footer) => {
34862
35055
  const { rId, referenceFile, currentFileName } = getHeaderFooterSectionData(footer, docx);
34863
- const { processedNodes: footerProcessedNodes } = preProcessPageFieldsOnly(referenceFile.elements[0].elements ?? []);
34864
- referenceFile.elements[0].elements = footerProcessedNodes;
35056
+ const footerNodes = carbonCopy(referenceFile.elements[0].elements ?? []);
35057
+ const { processedNodes: footerProcessedNodes } = preProcessPageFieldsOnly(footerNodes);
34865
35058
  const sectPrFooter = allSectPrElements.find(
34866
35059
  (el) => el.name === "w:footerReference" && el.attributes["r:id"] === rId
34867
35060
  );
34868
35061
  const sectionType = sectPrFooter?.attributes["w:type"];
34869
35062
  const nodeListHandler = defaultNodeListHandler();
34870
35063
  let schema = nodeListHandler.handler({
34871
- nodes: referenceFile.elements[0].elements,
35064
+ nodes: footerProcessedNodes,
34872
35065
  nodeListHandler,
34873
35066
  docx,
34874
35067
  converter,
@@ -34931,6 +35124,51 @@ function filterOutRootInlineNodes(content = []) {
34931
35124
  ]);
34932
35125
  return content.filter((node) => node && typeof node.type === "string" && !INLINE_TYPES.has(node.type));
34933
35126
  }
35127
+ function collapseWhitespaceNextToInlinePassthrough(content = []) {
35128
+ if (!Array.isArray(content) || content.length === 0) return;
35129
+ const sequence = collectInlineSequence(content);
35130
+ sequence.forEach((entry, index2) => {
35131
+ if (entry.kind !== "passthrough") return;
35132
+ const prev = findNeighborText(sequence, index2, -1);
35133
+ const next = findNeighborText(sequence, index2, 1);
35134
+ if (!prev || !next) return;
35135
+ if (!prev.node.text.endsWith(" ") || !next.node.text.startsWith(" ")) return;
35136
+ prev.node.text = prev.node.text.replace(/ +$/, " ");
35137
+ next.node.text = next.node.text.replace(/^ +/, "");
35138
+ if (next.node.text.length === 0) {
35139
+ next.parent.splice(next.index, 1);
35140
+ }
35141
+ });
35142
+ }
35143
+ function collectInlineSequence(nodes, result = [], insidePassthrough = false) {
35144
+ if (!Array.isArray(nodes) || nodes.length === 0) return result;
35145
+ nodes.forEach((node, index2) => {
35146
+ if (!node) return;
35147
+ const isPassthrough = node.type === "passthroughInline";
35148
+ if (isPassthrough && !insidePassthrough) {
35149
+ result.push({ kind: "passthrough", parent: nodes, index: index2 });
35150
+ }
35151
+ if (node.type === "text" && typeof node.text === "string" && !insidePassthrough) {
35152
+ result.push({ kind: "text", node, parent: nodes, index: index2 });
35153
+ }
35154
+ if (Array.isArray(node.content) && node.content.length) {
35155
+ const nextInside = insidePassthrough || isPassthrough;
35156
+ collectInlineSequence(node.content, result, nextInside);
35157
+ }
35158
+ });
35159
+ return result;
35160
+ }
35161
+ function findNeighborText(sequence, startIndex, direction) {
35162
+ let cursor = startIndex + direction;
35163
+ while (cursor >= 0 && cursor < sequence.length) {
35164
+ const entry = sequence[cursor];
35165
+ if (entry.kind === "text") {
35166
+ return entry;
35167
+ }
35168
+ cursor += direction;
35169
+ }
35170
+ return null;
35171
+ }
34934
35172
  function getThemeColorPalette(docx) {
34935
35173
  const themePart = docx?.["word/theme/theme1.xml"];
34936
35174
  if (!themePart || !Array.isArray(themePart.elements)) return void 0;
@@ -35293,7 +35531,9 @@ function exportSchemaToJson(params2) {
35293
35531
  "page-number": translator$4,
35294
35532
  "total-page-number": translator$3,
35295
35533
  pageReference: translator$6,
35296
- tableOfContents: translator$5
35534
+ tableOfContents: translator$5,
35535
+ passthroughBlock: translatePassthroughNode,
35536
+ passthroughInline: translatePassthroughNode
35297
35537
  };
35298
35538
  let handler2 = router[type2];
35299
35539
  if (handler2 && "decode" in handler2 && typeof handler2.decode === "function") {
@@ -35305,6 +35545,11 @@ function exportSchemaToJson(params2) {
35305
35545
  }
35306
35546
  return handler2(params2);
35307
35547
  }
35548
+ function translatePassthroughNode(params2) {
35549
+ const original = params2?.node?.attrs?.originalXml;
35550
+ if (!original) return null;
35551
+ return carbonCopy(original);
35552
+ }
35308
35553
  function translateBodyNode(params2) {
35309
35554
  let sectPr = params2.bodyNode?.elements?.find((n) => n.name === "w:sectPr");
35310
35555
  if (!sectPr) {
@@ -36004,7 +36249,7 @@ const _SuperConverter = class _SuperConverter2 {
36004
36249
  static getStoredSuperdocVersion(docx) {
36005
36250
  return _SuperConverter2.getStoredCustomProperty(docx, "SuperdocVersion");
36006
36251
  }
36007
- static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.14") {
36252
+ static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-beta.15") {
36008
36253
  return _SuperConverter2.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
36009
36254
  }
36010
36255
  /**
@@ -39204,7 +39449,7 @@ var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "rea
39204
39449
  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);
39205
39450
  var __privateSet = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
39206
39451
  var __privateMethod$1 = (obj, member, method) => (__accessCheck$1(obj, member, "access private method"), method);
39207
- 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;
39452
+ 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;
39208
39453
  var GOOD_LEAF_SIZE = 200;
39209
39454
  var RopeSequence = function RopeSequence2() {
39210
39455
  };
@@ -40077,17 +40322,20 @@ function findOffsetInNode(node, coords) {
40077
40322
  }
40078
40323
  function findOffsetInText(node, coords) {
40079
40324
  let len = node.nodeValue.length;
40080
- let range2 = document.createRange();
40325
+ let range2 = document.createRange(), result;
40081
40326
  for (let i = 0; i < len; i++) {
40082
40327
  range2.setEnd(node, i + 1);
40083
40328
  range2.setStart(node, i);
40084
40329
  let rect = singleRect(range2, 1);
40085
40330
  if (rect.top == rect.bottom)
40086
40331
  continue;
40087
- if (inRect(coords, rect))
40088
- return { node, offset: i + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0) };
40332
+ if (inRect(coords, rect)) {
40333
+ result = { node, offset: i + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0) };
40334
+ break;
40335
+ }
40089
40336
  }
40090
- return { node, offset: 0 };
40337
+ range2.detach();
40338
+ return result || { node, offset: 0 };
40091
40339
  }
40092
40340
  function inRect(coords, rect) {
40093
40341
  return coords.left >= rect.left - 1 && coords.left <= rect.right + 1 && coords.top >= rect.top - 1 && coords.top <= rect.bottom + 1;
@@ -42834,7 +43082,7 @@ editHandlers.compositionstart = editHandlers.compositionupdate = (view) => {
42834
43082
  if (!view.composing) {
42835
43083
  view.domObserver.flush();
42836
43084
  let { state: state2 } = view, $pos = state2.selection.$to;
42837
- if (state2.selection instanceof TextSelection$1 && (state2.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some((m2) => m2.type.spec.inclusive === false))) {
43085
+ 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))) {
42838
43086
  view.markCursor = view.state.storedMarks || $pos.marks();
42839
43087
  endComposition(view, true);
42840
43088
  view.markCursor = null;
@@ -42862,6 +43110,13 @@ editHandlers.compositionstart = editHandlers.compositionupdate = (view) => {
42862
43110
  }
42863
43111
  scheduleComposeEnd(view, timeoutComposition);
42864
43112
  };
43113
+ function selectionBeforeUneditable(view) {
43114
+ let { focusNode, focusOffset } = view.domSelectionRange();
43115
+ if (!focusNode || focusNode.nodeType != 1 || focusOffset >= focusNode.childNodes.length)
43116
+ return false;
43117
+ let next = focusNode.childNodes[focusOffset];
43118
+ return next.nodeType == 1 && next.contentEditable == "false";
43119
+ }
42865
43120
  editHandlers.compositionend = (view, event) => {
42866
43121
  if (view.composing) {
42867
43122
  view.input.composing = false;
@@ -43065,10 +43320,14 @@ handlers.dragend = (view) => {
43065
43320
  }, 50);
43066
43321
  };
43067
43322
  editHandlers.dragover = editHandlers.dragenter = (_2, e) => e.preventDefault();
43068
- editHandlers.drop = (view, _event) => {
43069
- let event = _event;
43070
- let dragging = view.dragging;
43071
- view.dragging = null;
43323
+ editHandlers.drop = (view, event) => {
43324
+ try {
43325
+ handleDrop(view, event, view.dragging);
43326
+ } finally {
43327
+ view.dragging = null;
43328
+ }
43329
+ };
43330
+ function handleDrop(view, event, dragging) {
43072
43331
  if (!event.dataTransfer)
43073
43332
  return;
43074
43333
  let eventPos = view.posAtCoords(eventCoords(event));
@@ -43121,7 +43380,7 @@ editHandlers.drop = (view, _event) => {
43121
43380
  }
43122
43381
  view.focus();
43123
43382
  view.dispatch(tr.setMeta("uiEvent", "drop"));
43124
- };
43383
+ }
43125
43384
  handlers.focus = (view) => {
43126
43385
  view.input.lastFocus = Date.now();
43127
43386
  if (!view.focused) {
@@ -43971,6 +44230,13 @@ class DOMObserver {
43971
44230
  br.remove();
43972
44231
  }
43973
44232
  }
44233
+ } else if ((chrome || safari) && added.some((n) => n.nodeName == "BR") && (view.input.lastKeyCode == 8 || view.input.lastKeyCode == 46)) {
44234
+ for (let node of added)
44235
+ if (node.nodeName == "BR" && node.parentNode) {
44236
+ let after = node.nextSibling;
44237
+ if (after && after.nodeType == 1 && after.contentEditable == "false")
44238
+ node.parentNode.removeChild(node);
44239
+ }
43974
44240
  }
43975
44241
  let readSel = null;
43976
44242
  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))) {
@@ -49154,7 +49420,7 @@ const Keymap = Extension.create({
49154
49420
  const baseKeymap = {
49155
49421
  Enter: () => handleEnter(this.editor),
49156
49422
  "Shift-Enter": () => this.editor.commands.insertLineBreak(),
49157
- "Mod-Enter": () => this.editor.commands.exitCode(),
49423
+ "Mod-Enter": () => this.editor.commands.insertPageBreak(),
49158
49424
  Backspace: () => handleBackspace(this.editor),
49159
49425
  "Mod-Backspace": () => handleBackspace(this.editor),
49160
49426
  "Shift-Backspace": () => handleBackspace(this.editor),
@@ -52711,7 +52977,7 @@ const isHeadless = (editor) => {
52711
52977
  const shouldSkipNodeView = (editor) => {
52712
52978
  return isHeadless(editor);
52713
52979
  };
52714
- const summaryVersion = "1.0.0-beta.14";
52980
+ const summaryVersion = "1.0.0-beta.15";
52715
52981
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
52716
52982
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
52717
52983
  function mapAttributes(attrs) {
@@ -53490,7 +53756,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
53490
53756
  { default: remarkStringify },
53491
53757
  { default: remarkGfm }
53492
53758
  ] = await Promise.all([
53493
- import("./index-I4Ew0HDV-Bht7-IGi.es.js"),
53759
+ import("./index-Bds7gW4r-Pk_xAuWe.es.js"),
53494
53760
  import("./index-DRCvimau-Cw339678.es.js"),
53495
53761
  import("./index-C_x_N6Uh-DJn8hIEt.es.js"),
53496
53762
  import("./index-D_sWOSiG-DE96TaT5.es.js"),
@@ -53695,7 +53961,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
53695
53961
  * Process collaboration migrations
53696
53962
  */
53697
53963
  processCollaborationMigrations() {
53698
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.14");
53964
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.15");
53699
53965
  if (!this.options.ydoc) return;
53700
53966
  const metaMap = this.options.ydoc.getMap("meta");
53701
53967
  let docVersion = metaMap.get("version");
@@ -55424,6 +55690,23 @@ const resolveColorFromAttributes = (attrs, themeColors) => {
55424
55690
  const MAX_DATA_ATTR_COUNT = 50;
55425
55691
  const MAX_DATA_ATTR_VALUE_LENGTH = 1e3;
55426
55692
  const MAX_DATA_ATTR_NAME_LENGTH = 100;
55693
+ const pushCommentAnnotation = (run2, attrs) => {
55694
+ const commentId = typeof attrs?.commentId === "string" ? attrs.commentId : void 0;
55695
+ const importedId = typeof attrs?.importedId === "string" ? attrs.importedId : void 0;
55696
+ const internal = attrs?.internal === true;
55697
+ if (!commentId && !importedId) return;
55698
+ const annotations = run2.comments ? [...run2.comments] : [];
55699
+ const key2 = `${commentId ?? ""}::${importedId ?? ""}`;
55700
+ const exists2 = annotations.some((c2) => `${c2.commentId ?? ""}::${c2.importedId ?? ""}` === key2);
55701
+ if (!exists2) {
55702
+ annotations.push({
55703
+ commentId: commentId ?? importedId,
55704
+ importedId,
55705
+ internal
55706
+ });
55707
+ }
55708
+ run2.comments = annotations;
55709
+ };
55427
55710
  const extractDataAttributes = (attrs) => {
55428
55711
  if (!attrs) return void 0;
55429
55712
  const result = {};
@@ -55706,6 +55989,11 @@ const applyMarksToRun = (run2, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG
55706
55989
  case "textStyle":
55707
55990
  applyTextStyleMark(run2, mark.attrs ?? {}, themeColors);
55708
55991
  break;
55992
+ case "commentMark":
55993
+ case "comment": {
55994
+ pushCommentAnnotation(run2, mark.attrs ?? {});
55995
+ break;
55996
+ }
55709
55997
  case "underline": {
55710
55998
  const style2 = normalizeUnderlineStyle(mark.attrs?.underlineType);
55711
55999
  if (style2) {
@@ -57622,10 +57910,17 @@ const hydrateParagraphStyleAttrs = (para, context, preResolved) => {
57622
57910
  }
57623
57911
  const resolvedExtended = resolved;
57624
57912
  const resolvedAsRecord = resolved;
57913
+ let resolvedIndent = cloneIfObject(resolvedAsRecord.indent);
57914
+ const styleIdLower = typeof styleId === "string" ? styleId.toLowerCase() : "";
57915
+ const isHeadingStyle = typeof resolvedExtended.outlineLvl === "number" || styleIdLower.startsWith("heading ") || styleIdLower.startsWith("heading");
57916
+ const onlyFirstLineIndent = resolvedIndent && resolvedIndent.firstLine != null && resolvedIndent.hanging == null && resolvedIndent.left == null && resolvedIndent.right == null;
57917
+ if (isHeadingStyle && (!resolvedIndent || Object.keys(resolvedIndent).length === 0 || onlyFirstLineIndent)) {
57918
+ resolvedIndent = { firstLine: 0, hanging: 0, left: resolvedIndent?.left, right: resolvedIndent?.right };
57919
+ }
57625
57920
  const hydrated = {
57626
57921
  resolved,
57627
57922
  spacing: cloneIfObject(resolvedAsRecord.spacing),
57628
- indent: cloneIfObject(resolvedAsRecord.indent),
57923
+ indent: resolvedIndent,
57629
57924
  borders: cloneIfObject(resolvedExtended.borders),
57630
57925
  shading: cloneIfObject(resolvedExtended.shading),
57631
57926
  alignment: resolvedExtended.justification,
@@ -57733,6 +58028,12 @@ const cloneParagraphAttrs = (attrs) => {
57733
58028
  }
57734
58029
  if (attrs.shading) clone.shading = { ...attrs.shading };
57735
58030
  if (attrs.tabs) clone.tabs = attrs.tabs.map((tab) => ({ ...tab }));
58031
+ if (attrs.dropCapDescriptor) {
58032
+ clone.dropCapDescriptor = {
58033
+ ...attrs.dropCapDescriptor,
58034
+ run: { ...attrs.dropCapDescriptor.run }
58035
+ };
58036
+ }
57736
58037
  return clone;
57737
58038
  };
57738
58039
  const buildStyleNodeFromAttrs = (attrs, spacing, indent) => {
@@ -57844,6 +58145,119 @@ const normalizeResolvedTabAlignment = (value) => {
57844
58145
  return void 0;
57845
58146
  }
57846
58147
  };
58148
+ const DEFAULT_DROP_CAP_FONT_SIZE_PX = 64;
58149
+ const DEFAULT_DROP_CAP_FONT_FAMILY = "Times New Roman";
58150
+ const extractDropCapRunFromParagraph = (para) => {
58151
+ const content = para.content;
58152
+ if (!Array.isArray(content) || content.length === 0) {
58153
+ return null;
58154
+ }
58155
+ let text = "";
58156
+ let runProperties = {};
58157
+ let textStyleMarks = {};
58158
+ const MAX_RECURSION_DEPTH = 50;
58159
+ const extractTextAndStyle = (nodes, depth = 0) => {
58160
+ if (depth > MAX_RECURSION_DEPTH) {
58161
+ console.warn(`extractTextAndStyle exceeded max recursion depth (${MAX_RECURSION_DEPTH})`);
58162
+ return false;
58163
+ }
58164
+ for (const node of nodes) {
58165
+ if (!node) continue;
58166
+ if (node.type === "text" && typeof node.text === "string" && node.text.length > 0) {
58167
+ text = node.text;
58168
+ if (Array.isArray(node.marks)) {
58169
+ for (const mark of node.marks) {
58170
+ if (mark?.type === "textStyle" && mark.attrs) {
58171
+ textStyleMarks = { ...textStyleMarks, ...mark.attrs };
58172
+ }
58173
+ }
58174
+ }
58175
+ return true;
58176
+ }
58177
+ if (node.type === "run") {
58178
+ if (node.attrs?.runProperties && typeof node.attrs.runProperties === "object") {
58179
+ runProperties = { ...runProperties, ...node.attrs.runProperties };
58180
+ }
58181
+ if (Array.isArray(node.marks)) {
58182
+ for (const mark of node.marks) {
58183
+ if (mark?.type === "textStyle" && mark.attrs) {
58184
+ textStyleMarks = { ...textStyleMarks, ...mark.attrs };
58185
+ }
58186
+ }
58187
+ }
58188
+ if (Array.isArray(node.content) && extractTextAndStyle(node.content, depth + 1)) {
58189
+ return true;
58190
+ }
58191
+ }
58192
+ if (Array.isArray(node.content) && extractTextAndStyle(node.content, depth + 1)) {
58193
+ return true;
58194
+ }
58195
+ }
58196
+ return false;
58197
+ };
58198
+ extractTextAndStyle(content);
58199
+ if (!text) {
58200
+ return null;
58201
+ }
58202
+ const mergedStyle = { ...runProperties, ...textStyleMarks };
58203
+ let fontSizePx = DEFAULT_DROP_CAP_FONT_SIZE_PX;
58204
+ const rawFontSize = mergedStyle.fontSize ?? mergedStyle["w:sz"] ?? mergedStyle.sz;
58205
+ if (rawFontSize != null) {
58206
+ if (typeof rawFontSize === "number") {
58207
+ const converted = rawFontSize > 100 ? ptToPx(rawFontSize / 2) : rawFontSize;
58208
+ fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
58209
+ } else if (typeof rawFontSize === "string") {
58210
+ const numericPart = parseFloat(rawFontSize);
58211
+ if (Number.isFinite(numericPart)) {
58212
+ if (rawFontSize.endsWith("pt")) {
58213
+ const converted = ptToPx(numericPart);
58214
+ fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
58215
+ } else if (rawFontSize.endsWith("px")) {
58216
+ fontSizePx = numericPart;
58217
+ } else {
58218
+ const converted = numericPart > 100 ? ptToPx(numericPart / 2) : numericPart;
58219
+ fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
58220
+ }
58221
+ }
58222
+ }
58223
+ }
58224
+ let fontFamily2 = DEFAULT_DROP_CAP_FONT_FAMILY;
58225
+ const rawFontFamily = mergedStyle.fontFamily ?? mergedStyle["w:rFonts"] ?? mergedStyle.rFonts;
58226
+ if (typeof rawFontFamily === "string") {
58227
+ fontFamily2 = rawFontFamily;
58228
+ } else if (rawFontFamily && typeof rawFontFamily === "object") {
58229
+ const rFonts = rawFontFamily;
58230
+ const ascii = rFonts["w:ascii"] ?? rFonts.ascii;
58231
+ if (typeof ascii === "string") {
58232
+ fontFamily2 = ascii;
58233
+ }
58234
+ }
58235
+ const dropCapRun = {
58236
+ text,
58237
+ fontFamily: fontFamily2,
58238
+ fontSize: fontSizePx
58239
+ };
58240
+ const bold = mergedStyle.bold ?? mergedStyle["w:b"] ?? mergedStyle.b;
58241
+ if (isTruthy(bold)) {
58242
+ dropCapRun.bold = true;
58243
+ }
58244
+ const italic = mergedStyle.italic ?? mergedStyle["w:i"] ?? mergedStyle.i;
58245
+ if (isTruthy(italic)) {
58246
+ dropCapRun.italic = true;
58247
+ }
58248
+ const color = mergedStyle.color ?? mergedStyle["w:color"] ?? mergedStyle.val;
58249
+ if (typeof color === "string" && color.length > 0 && color.toLowerCase() !== "auto") {
58250
+ dropCapRun.color = color.startsWith("#") ? color : `#${color}`;
58251
+ }
58252
+ const position = mergedStyle.position ?? mergedStyle["w:position"];
58253
+ if (position != null) {
58254
+ const posNum = pickNumber(position);
58255
+ if (posNum != null) {
58256
+ dropCapRun.position = ptToPx(posNum / 2);
58257
+ }
58258
+ }
58259
+ return dropCapRun;
58260
+ };
57847
58261
  const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleContext, _paragraphNode) => {
57848
58262
  if (numberingProps === null) {
57849
58263
  return null;
@@ -58109,6 +58523,24 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
58109
58523
  const dropCap = framePr["w:dropCap"] ?? framePr.dropCap;
58110
58524
  if (dropCap != null && (typeof dropCap === "string" || typeof dropCap === "number" || typeof dropCap === "boolean")) {
58111
58525
  paragraphAttrs.dropCap = dropCap;
58526
+ const dropCapMode = typeof dropCap === "string" ? dropCap.toLowerCase() : "drop";
58527
+ const linesValue = pickNumber(framePr["w:lines"] ?? framePr.lines);
58528
+ const wrapValue = asString(framePr["w:wrap"] ?? framePr.wrap);
58529
+ const dropCapRunInfo = extractDropCapRunFromParagraph(para);
58530
+ if (dropCapRunInfo) {
58531
+ const descriptor = {
58532
+ mode: dropCapMode === "margin" ? "margin" : "drop",
58533
+ lines: linesValue != null && linesValue > 0 ? linesValue : 3,
58534
+ run: dropCapRunInfo
58535
+ };
58536
+ if (wrapValue) {
58537
+ const normalizedWrap = wrapValue.toLowerCase();
58538
+ if (normalizedWrap === "around" || normalizedWrap === "notbeside" || normalizedWrap === "none" || normalizedWrap === "tight") {
58539
+ descriptor.wrap = normalizedWrap === "notbeside" ? "notBeside" : normalizedWrap;
58540
+ }
58541
+ }
58542
+ paragraphAttrs.dropCapDescriptor = descriptor;
58543
+ }
58112
58544
  }
58113
58545
  const frame = {};
58114
58546
  const wrap2 = asString(framePr["w:wrap"] ?? framePr.wrap);
@@ -58882,13 +59314,26 @@ const dataAttrsCompatible = (a, b2) => {
58882
59314
  }
58883
59315
  return true;
58884
59316
  };
59317
+ const commentsCompatible = (a, b2) => {
59318
+ const aComments = a.comments ?? [];
59319
+ const bComments = b2.comments ?? [];
59320
+ if (aComments.length === 0 && bComments.length === 0) return true;
59321
+ if (aComments.length !== bComments.length) return false;
59322
+ const normalize2 = (c2) => `${c2.commentId ?? ""}::${c2.importedId ?? ""}::${c2.internal ? "1" : "0"}`;
59323
+ const aKeys = aComments.map(normalize2).sort();
59324
+ const bKeys = bComments.map(normalize2).sort();
59325
+ for (let i = 0; i < aKeys.length; i++) {
59326
+ if (aKeys[i] !== bKeys[i]) return false;
59327
+ }
59328
+ return true;
59329
+ };
58885
59330
  function mergeAdjacentRuns(runs) {
58886
59331
  if (runs.length <= 1) return runs;
58887
59332
  const merged = [];
58888
59333
  let current = runs[0];
58889
59334
  for (let i = 1; i < runs.length; i++) {
58890
59335
  const next = runs[i];
58891
- const canMerge = isTextRun$1(current) && isTextRun$1(next) && !current.token && !next.token && current.pmStart != null && current.pmEnd != null && next.pmStart != null && next.pmEnd != null && current.pmEnd === next.pmStart && current.fontFamily === next.fontFamily && current.fontSize === next.fontSize && current.bold === next.bold && current.italic === next.italic && current.underline === next.underline && current.strike === next.strike && current.color === next.color && current.highlight === next.highlight && (current.letterSpacing ?? 0) === (next.letterSpacing ?? 0) && trackedChangesCompatible(current, next) && dataAttrsCompatible(current, next);
59336
+ const canMerge = isTextRun$1(current) && isTextRun$1(next) && !current.token && !next.token && current.pmStart != null && current.pmEnd != null && next.pmStart != null && next.pmEnd != null && current.pmEnd === next.pmStart && current.fontFamily === next.fontFamily && current.fontSize === next.fontSize && current.bold === next.bold && current.italic === next.italic && current.underline === next.underline && current.strike === next.strike && current.color === next.color && current.highlight === next.highlight && (current.letterSpacing ?? 0) === (next.letterSpacing ?? 0) && trackedChangesCompatible(current, next) && dataAttrsCompatible(current, next) && commentsCompatible(current, next);
58892
59337
  if (canMerge) {
58893
59338
  const currText = current.text ?? "";
58894
59339
  const nextText = next.text ?? "";
@@ -59370,6 +59815,22 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
59370
59815
  id: nextId(),
59371
59816
  attrs: node.attrs || {}
59372
59817
  });
59818
+ } else {
59819
+ const lineBreakRun = { kind: "lineBreak", attrs: {} };
59820
+ const lbAttrs = {};
59821
+ if (attrs.lineBreakType) lbAttrs.lineBreakType = String(attrs.lineBreakType);
59822
+ if (attrs.clear) lbAttrs.clear = String(attrs.clear);
59823
+ if (Object.keys(lbAttrs).length > 0) {
59824
+ lineBreakRun.attrs = lbAttrs;
59825
+ } else {
59826
+ delete lineBreakRun.attrs;
59827
+ }
59828
+ const pos = positions.get(node);
59829
+ if (pos) {
59830
+ lineBreakRun.pmStart = pos.start;
59831
+ lineBreakRun.pmEnd = pos.end;
59832
+ }
59833
+ currentRuns.push(lineBreakRun);
59373
59834
  }
59374
59835
  return;
59375
59836
  }
@@ -60394,7 +60855,39 @@ function toFlowBlocks(pmDoc, options) {
60394
60855
  }
60395
60856
  instrumentation?.log?.({ totalBlocks: blocks.length, blockCounts, bookmarks: bookmarks.size });
60396
60857
  const hydratedBlocks = hydrateImageBlocks(blocks, options?.mediaFiles);
60397
- return { blocks: hydratedBlocks, bookmarks };
60858
+ const mergedBlocks = mergeDropCapParagraphs(hydratedBlocks);
60859
+ return { blocks: mergedBlocks, bookmarks };
60860
+ }
60861
+ function mergeDropCapParagraphs(blocks) {
60862
+ const result = [];
60863
+ let i = 0;
60864
+ while (i < blocks.length) {
60865
+ const block = blocks[i];
60866
+ if (block.kind === "paragraph" && block.attrs?.dropCapDescriptor && i + 1 < blocks.length) {
60867
+ const dropCapBlock = block;
60868
+ const nextBlock = blocks[i + 1];
60869
+ if (nextBlock.kind === "paragraph") {
60870
+ const textBlock = nextBlock;
60871
+ const mergedBlock = {
60872
+ kind: "paragraph",
60873
+ id: textBlock.id,
60874
+ runs: textBlock.runs,
60875
+ attrs: {
60876
+ ...textBlock.attrs,
60877
+ dropCapDescriptor: dropCapBlock.attrs?.dropCapDescriptor,
60878
+ // Clear the legacy dropCap flag on the merged block
60879
+ dropCap: void 0
60880
+ }
60881
+ };
60882
+ result.push(mergedBlock);
60883
+ i += 2;
60884
+ continue;
60885
+ }
60886
+ }
60887
+ result.push(block);
60888
+ i += 1;
60889
+ }
60890
+ return result;
60398
60891
  }
60399
60892
  function paragraphToFlowBlocks(para, nextBlockId, positions, defaultFont, defaultSize, styleContext, listCounterContext, trackedChanges, bookmarks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors, converterContext) {
60400
60893
  return paragraphToFlowBlocks$1(
@@ -60469,7 +60962,7 @@ function getMeasurementContext() {
60469
60962
  return measurementCtx;
60470
60963
  }
60471
60964
  function getRunFontString(run2) {
60472
- if (run2.kind === "tab" || run2.kind === "image") {
60965
+ if (run2.kind === "tab" || run2.kind === "lineBreak" || "src" in run2) {
60473
60966
  return "normal normal 16px Arial";
60474
60967
  }
60475
60968
  const style2 = run2.italic ? "italic" : "normal";
@@ -60488,7 +60981,11 @@ function sliceRunsForLine$1(block, line) {
60488
60981
  result.push(run2);
60489
60982
  continue;
60490
60983
  }
60491
- if (run2.kind === "image") {
60984
+ if ("src" in run2) {
60985
+ result.push(run2);
60986
+ continue;
60987
+ }
60988
+ if (run2.kind === "lineBreak") {
60492
60989
  result.push(run2);
60493
60990
  continue;
60494
60991
  }
@@ -60515,13 +61012,17 @@ function sliceRunsForLine$1(block, line) {
60515
61012
  }
60516
61013
  function measureCharacterX(block, line, charOffset) {
60517
61014
  const ctx2 = getMeasurementContext();
61015
+ const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
61016
+ if (hasExplicitPositioning && line.segments && ctx2) {
61017
+ return measureCharacterXSegmentBased(block, line, charOffset, ctx2);
61018
+ }
60518
61019
  if (!ctx2) {
60519
61020
  const runs2 = sliceRunsForLine$1(block, line);
60520
61021
  const charsInLine = Math.max(
60521
61022
  1,
60522
61023
  runs2.reduce((sum, run2) => {
60523
61024
  if (isTabRun$1(run2)) return sum + TAB_CHAR_LENGTH;
60524
- if (run2.kind === "image") return sum;
61025
+ if ("src" in run2 || run2.kind === "lineBreak") return sum;
60525
61026
  return sum + (run2.text ?? "").length;
60526
61027
  }, 0)
60527
61028
  );
@@ -60542,7 +61043,7 @@ function measureCharacterX(block, line, charOffset) {
60542
61043
  currentCharOffset += runLength2;
60543
61044
  continue;
60544
61045
  }
60545
- const text = run2.kind === "image" ? "" : run2.text ?? "";
61046
+ const text = "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
60546
61047
  const runLength = text.length;
60547
61048
  if (currentCharOffset + runLength >= charOffset) {
60548
61049
  const offsetInRun = charOffset - currentCharOffset;
@@ -60559,6 +61060,47 @@ function measureCharacterX(block, line, charOffset) {
60559
61060
  }
60560
61061
  return currentX;
60561
61062
  }
61063
+ function measureCharacterXSegmentBased(block, line, charOffset, ctx2) {
61064
+ if (block.kind !== "paragraph" || !line.segments) return 0;
61065
+ let lineCharCount = 0;
61066
+ for (const segment of line.segments) {
61067
+ const run2 = block.runs[segment.runIndex];
61068
+ if (!run2) continue;
61069
+ const segmentChars = segment.toChar - segment.fromChar;
61070
+ if (lineCharCount + segmentChars >= charOffset) {
61071
+ const offsetInSegment = charOffset - lineCharCount;
61072
+ let segmentBaseX = segment.x;
61073
+ if (segmentBaseX === void 0) {
61074
+ segmentBaseX = 0;
61075
+ for (const prevSeg of line.segments) {
61076
+ if (prevSeg === segment) break;
61077
+ const prevRun = block.runs[prevSeg.runIndex];
61078
+ if (!prevRun) continue;
61079
+ if (prevSeg.x !== void 0) {
61080
+ segmentBaseX = prevSeg.x + (prevSeg.width ?? 0);
61081
+ } else {
61082
+ segmentBaseX += prevSeg.width ?? 0;
61083
+ }
61084
+ }
61085
+ }
61086
+ if (isTabRun$1(run2)) {
61087
+ return segmentBaseX + (offsetInSegment > 0 ? segment.width ?? 0 : 0);
61088
+ }
61089
+ if ("src" in run2 || run2.kind === "lineBreak") {
61090
+ return segmentBaseX + (offsetInSegment >= segmentChars ? segment.width ?? 0 : 0);
61091
+ }
61092
+ const text = run2.text ?? "";
61093
+ const segmentText = text.slice(segment.fromChar, segment.toChar);
61094
+ const textUpToTarget = segmentText.slice(0, offsetInSegment);
61095
+ ctx2.font = getRunFontString(run2);
61096
+ const measured = ctx2.measureText(textUpToTarget);
61097
+ const spacingWidth = computeLetterSpacingWidth(run2, offsetInSegment, segmentChars);
61098
+ return segmentBaseX + measured.width + spacingWidth;
61099
+ }
61100
+ lineCharCount += segmentChars;
61101
+ }
61102
+ return line.width;
61103
+ }
60562
61104
  function findCharacterAtX(block, line, x2, pmStart) {
60563
61105
  const ctx2 = getMeasurementContext();
60564
61106
  if (!ctx2) {
@@ -60567,7 +61109,7 @@ function findCharacterAtX(block, line, x2, pmStart) {
60567
61109
  1,
60568
61110
  runs2.reduce((sum, run2) => {
60569
61111
  if (isTabRun$1(run2)) return sum + TAB_CHAR_LENGTH;
60570
- if (run2.kind === "image") return sum;
61112
+ if ("src" in run2 || run2.kind === "lineBreak") return sum;
60571
61113
  return sum + (run2.text ?? "").length;
60572
61114
  }, 0)
60573
61115
  );
@@ -60602,7 +61144,7 @@ function findCharacterAtX(block, line, x2, pmStart) {
60602
61144
  currentCharOffset += TAB_CHAR_LENGTH;
60603
61145
  continue;
60604
61146
  }
60605
- const text = run2.kind === "image" ? "" : run2.text ?? "";
61147
+ const text = "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
60606
61148
  const runLength = text.length;
60607
61149
  if (runLength === 0) continue;
60608
61150
  ctx2.font = getRunFontString(run2);
@@ -60639,7 +61181,7 @@ function findCharacterAtX(block, line, x2, pmStart) {
60639
61181
  };
60640
61182
  }
60641
61183
  const computeLetterSpacingWidth = (run2, precedingChars, runLength) => {
60642
- if (isTabRun$1(run2) || run2.kind === "image" || !run2.letterSpacing) {
61184
+ if (isTabRun$1(run2) || "src" in run2 || !("letterSpacing" in run2) || !run2.letterSpacing) {
60643
61185
  return 0;
60644
61186
  }
60645
61187
  const maxGaps = Math.max(runLength - 1, 0);
@@ -60649,6 +61191,8 @@ const computeLetterSpacingWidth = (run2, precedingChars, runLength) => {
60649
61191
  const clamped = Math.min(Math.max(precedingChars, 0), maxGaps);
60650
61192
  return clamped * run2.letterSpacing;
60651
61193
  };
61194
+ const log = (...args) => {
61195
+ };
60652
61196
  const CLASS_NAMES$1 = {
60653
61197
  page: "superdoc-page",
60654
61198
  fragment: "superdoc-fragment",
@@ -60664,6 +61208,11 @@ function clickToPositionDom(domContainer, clientX, clientY) {
60664
61208
  const pageLocalY = clientY - pageRect.top;
60665
61209
  const viewX = pageRect.left + pageLocalX;
60666
61210
  const viewY = pageRect.top + pageLocalY;
61211
+ log("Page found:", {
61212
+ pageIndex: pageEl.dataset.pageIndex,
61213
+ pageRect: { left: pageRect.left, top: pageRect.top, width: pageRect.width, height: pageRect.height },
61214
+ viewCoords: { viewX, viewY }
61215
+ });
60667
61216
  let hitChain = [];
60668
61217
  const doc2 = document;
60669
61218
  if (typeof doc2.elementsFromPoint === "function") {
@@ -60675,15 +61224,62 @@ function clickToPositionDom(domContainer, clientX, clientY) {
60675
61224
  if (!Array.isArray(hitChain)) {
60676
61225
  return null;
60677
61226
  }
61227
+ const hitChainData = hitChain.map((el) => {
61228
+ const rect = el.getBoundingClientRect();
61229
+ return {
61230
+ tag: el.tagName,
61231
+ classes: el.className,
61232
+ blockId: el.dataset?.blockId,
61233
+ pmStart: el.dataset?.pmStart,
61234
+ pmEnd: el.dataset?.pmEnd,
61235
+ rect: {
61236
+ top: Math.round(rect.top),
61237
+ bottom: Math.round(rect.bottom),
61238
+ left: Math.round(rect.left),
61239
+ right: Math.round(rect.right),
61240
+ height: Math.round(rect.height)
61241
+ }
61242
+ };
61243
+ });
61244
+ log("Hit chain elements:", JSON.stringify(hitChainData, null, 2));
61245
+ const allFragments = Array.from(pageEl.querySelectorAll(`.${CLASS_NAMES$1.fragment}`));
61246
+ const fragmentData = allFragments.map((el) => {
61247
+ const rect = el.getBoundingClientRect();
61248
+ return {
61249
+ blockId: el.dataset.blockId,
61250
+ pmStart: el.dataset.pmStart,
61251
+ pmEnd: el.dataset.pmEnd,
61252
+ rect: {
61253
+ top: Math.round(rect.top),
61254
+ bottom: Math.round(rect.bottom),
61255
+ left: Math.round(rect.left),
61256
+ right: Math.round(rect.right),
61257
+ height: Math.round(rect.height)
61258
+ }
61259
+ };
61260
+ });
61261
+ log("All fragments on page:", JSON.stringify(fragmentData, null, 2));
60678
61262
  const fragmentEl = hitChain.find((el) => el.classList?.contains?.(CLASS_NAMES$1.fragment));
60679
61263
  if (!fragmentEl) {
60680
61264
  const fallbackFragment = pageEl.querySelector(`.${CLASS_NAMES$1.fragment}`);
60681
61265
  if (!fallbackFragment) {
60682
61266
  return null;
60683
61267
  }
60684
- return processFragment(fallbackFragment, viewX, viewY);
61268
+ log("Using fallback fragment:", {
61269
+ blockId: fallbackFragment.dataset.blockId,
61270
+ pmStart: fallbackFragment.dataset.pmStart,
61271
+ pmEnd: fallbackFragment.dataset.pmEnd
61272
+ });
61273
+ const result2 = processFragment(fallbackFragment, viewX, viewY);
61274
+ return result2;
60685
61275
  }
60686
- return processFragment(fragmentEl, viewX, viewY);
61276
+ log("Fragment found:", {
61277
+ blockId: fragmentEl.dataset.blockId,
61278
+ pmStart: fragmentEl.dataset.pmStart,
61279
+ pmEnd: fragmentEl.dataset.pmEnd
61280
+ });
61281
+ const result = processFragment(fragmentEl, viewX, viewY);
61282
+ return result;
60687
61283
  }
60688
61284
  function findPageElement(domContainer, clientX, clientY) {
60689
61285
  if (domContainer.classList?.contains?.(CLASS_NAMES$1.page)) {
@@ -60715,7 +61311,20 @@ function findPageElement(domContainer, clientX, clientY) {
60715
61311
  return null;
60716
61312
  }
60717
61313
  function processFragment(fragmentEl, viewX, viewY) {
61314
+ log("processFragment:", { viewX, viewY, blockId: fragmentEl.dataset.blockId });
60718
61315
  const lineEls = Array.from(fragmentEl.querySelectorAll(`.${CLASS_NAMES$1.line}`));
61316
+ log(
61317
+ "Lines in fragment:",
61318
+ lineEls.map((el, i) => {
61319
+ const rect = el.getBoundingClientRect();
61320
+ return {
61321
+ index: i,
61322
+ pmStart: el.dataset.pmStart,
61323
+ pmEnd: el.dataset.pmEnd,
61324
+ rect: { top: rect.top, bottom: rect.bottom, left: rect.left, right: rect.right }
61325
+ };
61326
+ })
61327
+ );
60719
61328
  if (lineEls.length === 0) {
60720
61329
  return null;
60721
61330
  }
@@ -60725,10 +61334,30 @@ function processFragment(fragmentEl, viewX, viewY) {
60725
61334
  }
60726
61335
  const lineStart = Number(lineEl.dataset.pmStart ?? "NaN");
60727
61336
  const lineEnd = Number(lineEl.dataset.pmEnd ?? "NaN");
61337
+ const lineRect = lineEl.getBoundingClientRect();
61338
+ log("Selected line:", {
61339
+ pmStart: lineStart,
61340
+ pmEnd: lineEnd,
61341
+ rect: { top: lineRect.top, bottom: lineRect.bottom, left: lineRect.left, right: lineRect.right }
61342
+ });
60728
61343
  if (!Number.isFinite(lineStart) || !Number.isFinite(lineEnd)) {
60729
61344
  return null;
60730
61345
  }
60731
61346
  const spanEls = Array.from(lineEl.querySelectorAll("span"));
61347
+ log(
61348
+ "Spans in line:",
61349
+ spanEls.map((el, i) => {
61350
+ const rect = el.getBoundingClientRect();
61351
+ return {
61352
+ index: i,
61353
+ pmStart: el.dataset.pmStart,
61354
+ pmEnd: el.dataset.pmEnd,
61355
+ text: el.textContent?.substring(0, 20) + (el.textContent && el.textContent.length > 20 ? "..." : ""),
61356
+ visibility: el.style.visibility,
61357
+ rect: { left: rect.left, right: rect.right, width: rect.width }
61358
+ };
61359
+ })
61360
+ );
60732
61361
  if (spanEls.length === 0) {
60733
61362
  return lineStart;
60734
61363
  }
@@ -60746,6 +61375,14 @@ function processFragment(fragmentEl, viewX, viewY) {
60746
61375
  }
60747
61376
  const spanStart = Number(targetSpan.dataset.pmStart ?? "NaN");
60748
61377
  const spanEnd = Number(targetSpan.dataset.pmEnd ?? "NaN");
61378
+ const targetRect = targetSpan.getBoundingClientRect();
61379
+ log("Target span:", {
61380
+ pmStart: spanStart,
61381
+ pmEnd: spanEnd,
61382
+ text: targetSpan.textContent?.substring(0, 30),
61383
+ visibility: targetSpan.style.visibility,
61384
+ rect: { left: targetRect.left, right: targetRect.right, width: targetRect.width }
61385
+ });
60749
61386
  if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) {
60750
61387
  return null;
60751
61388
  }
@@ -60765,28 +61402,53 @@ function findLineAtY(lineEls, viewY) {
60765
61402
  if (lineEls.length === 0) {
60766
61403
  return null;
60767
61404
  }
60768
- for (const lineEl of lineEls) {
61405
+ for (let i = 0; i < lineEls.length; i++) {
61406
+ const lineEl = lineEls[i];
60769
61407
  const rect = lineEl.getBoundingClientRect();
60770
61408
  if (viewY >= rect.top && viewY <= rect.bottom) {
61409
+ log("findLineAtY: Found line at index", i, {
61410
+ pmStart: lineEl.dataset.pmStart,
61411
+ pmEnd: lineEl.dataset.pmEnd,
61412
+ rect: { top: rect.top, bottom: rect.bottom },
61413
+ viewY
61414
+ });
60771
61415
  return lineEl;
60772
61416
  }
60773
61417
  }
60774
- return lineEls[lineEls.length - 1];
61418
+ const lastLine = lineEls[lineEls.length - 1];
61419
+ log("findLineAtY: Y beyond all lines, using last line:", {
61420
+ pmStart: lastLine.dataset.pmStart,
61421
+ pmEnd: lastLine.dataset.pmEnd,
61422
+ viewY
61423
+ });
61424
+ return lastLine;
60775
61425
  }
60776
61426
  function findSpanAtX(spanEls, viewX) {
60777
61427
  if (spanEls.length === 0) {
60778
61428
  return null;
60779
61429
  }
60780
61430
  let targetSpan = spanEls[0];
60781
- for (const span of spanEls) {
61431
+ for (let i = 0; i < spanEls.length; i++) {
61432
+ const span = spanEls[i];
60782
61433
  const rect = span.getBoundingClientRect();
60783
61434
  if (viewX >= rect.left && viewX <= rect.right) {
61435
+ log("findSpanAtX: Found containing span at index", i, {
61436
+ pmStart: span.dataset.pmStart,
61437
+ pmEnd: span.dataset.pmEnd,
61438
+ rect: { left: rect.left, right: rect.right },
61439
+ viewX
61440
+ });
60784
61441
  return span;
60785
61442
  }
60786
61443
  if (viewX > rect.right) {
60787
61444
  targetSpan = span;
60788
61445
  }
60789
61446
  }
61447
+ log("findSpanAtX: No containing span, using nearest:", {
61448
+ pmStart: targetSpan.dataset.pmStart,
61449
+ pmEnd: targetSpan.dataset.pmEnd,
61450
+ viewX
61451
+ });
60790
61452
  return targetSpan;
60791
61453
  }
60792
61454
  function findCharIndexAtX(textNode, span, targetX) {
@@ -60916,7 +61578,7 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
60916
61578
  zones.push(zone);
60917
61579
  },
60918
61580
  getExclusionsForLine(lineY, lineHeight2, columnIndex, pageNumber) {
60919
- return zones.filter((zone) => {
61581
+ const result = zones.filter((zone) => {
60920
61582
  if (zone.pageNumber !== pageNumber || zone.columnIndex !== columnIndex) {
60921
61583
  return false;
60922
61584
  }
@@ -60924,8 +61586,10 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
60924
61586
  const lineBottom = lineY + lineHeight2;
60925
61587
  const zoneTop = zone.bounds.y - zone.distances.top;
60926
61588
  const zoneBottom = zone.bounds.y + zone.bounds.height + zone.distances.bottom;
60927
- return lineBottom > zoneTop && lineTop < zoneBottom;
61589
+ const overlaps = lineBottom > zoneTop && lineTop < zoneBottom;
61590
+ return overlaps;
60928
61591
  });
61592
+ return result;
60929
61593
  },
60930
61594
  computeAvailableWidth(lineY, lineHeight2, baseWidth, columnIndex, pageNumber) {
60931
61595
  const exclusions = this.getExclusionsForLine(lineY, lineHeight2, columnIndex, pageNumber);
@@ -60938,6 +61602,8 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
60938
61602
  }
60939
61603
  const leftFloats = [];
60940
61604
  const rightFloats = [];
61605
+ const columnOrigin = marginLeft + columnIndex * (columns.width + columns.gap);
61606
+ const columnCenter = columnOrigin + baseWidth / 2;
60941
61607
  for (const zone of wrappingZones) {
60942
61608
  if (zone.wrapMode === "left") {
60943
61609
  leftFloats.push(zone);
@@ -60945,7 +61611,7 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
60945
61611
  rightFloats.push(zone);
60946
61612
  } else if (zone.wrapMode === "both" || zone.wrapMode === "largest") {
60947
61613
  const zoneCenter = zone.bounds.x + zone.bounds.width / 2;
60948
- if (zoneCenter < baseWidth / 2) {
61614
+ if (zoneCenter < columnCenter) {
60949
61615
  leftFloats.push(zone);
60950
61616
  } else {
60951
61617
  rightFloats.push(zone);
@@ -60957,7 +61623,6 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
60957
61623
  const boundary = zone.bounds.x + zone.bounds.width + zone.distances.left + zone.distances.right;
60958
61624
  leftBoundary = Math.max(leftBoundary, boundary);
60959
61625
  }
60960
- const columnOrigin = marginLeft + columnIndex * (columns.width + columns.gap);
60961
61626
  const columnRightEdge = columnOrigin + baseWidth;
60962
61627
  let rightBoundary = columnRightEdge;
60963
61628
  for (const zone of rightFloats) {
@@ -61280,9 +61945,6 @@ const extractBlockPmRange = (block) => {
61280
61945
  pmEnd: end2 ?? (start2 != null ? start2 + 1 : void 0)
61281
61946
  };
61282
61947
  };
61283
- const anchorDebugLog = (...args) => {
61284
- return;
61285
- };
61286
61948
  function layoutParagraphBlock(ctx2, anchors) {
61287
61949
  const { block, measure, columnWidth, ensurePage, advanceColumn, columnX, floatManager } = ctx2;
61288
61950
  const remeasureParagraph2 = ctx2.remeasureParagraph;
@@ -61291,23 +61953,45 @@ function layoutParagraphBlock(ctx2, anchors) {
61291
61953
  for (const entry of anchors.anchoredDrawings) {
61292
61954
  if (anchors.placedAnchoredIds.has(entry.block.id)) continue;
61293
61955
  const state2 = ensurePage();
61294
- const baseAnchorY = state2.cursorY;
61295
- const firstLineHeight = measure.lines?.[0]?.lineHeight ?? 0;
61296
61956
  const vRelativeFrom = entry.block.anchor?.vRelativeFrom;
61297
- const paragraphAdjustment = vRelativeFrom === "paragraph" ? firstLineHeight / 2 : 0;
61298
- const anchorY = baseAnchorY + paragraphAdjustment;
61299
- anchorDebugLog("Positioning anchored image:", {
61300
- blockId: entry.block.id,
61301
- baseAnchorY,
61302
- paragraphAdjustment,
61303
- anchorY,
61304
- offsetV: entry.block.anchor?.offsetV,
61305
- finalY: anchorY + (entry.block.anchor?.offsetV ?? 0),
61306
- measureHeight: entry.measure.height,
61307
- measureWidth: entry.measure.width,
61308
- pageNumber: state2.page.number,
61309
- vRelativeFrom
61310
- });
61957
+ const alignV = entry.block.anchor?.alignV;
61958
+ const offsetV = entry.block.anchor?.offsetV ?? 0;
61959
+ const imageHeight = entry.measure.height;
61960
+ const contentTop = state2.topMargin;
61961
+ const contentBottom = state2.contentBottom;
61962
+ const contentHeight = Math.max(0, contentBottom - contentTop);
61963
+ let anchorY;
61964
+ if (vRelativeFrom === "margin") {
61965
+ if (alignV === "top") {
61966
+ anchorY = contentTop + offsetV;
61967
+ } else if (alignV === "bottom") {
61968
+ anchorY = contentBottom - imageHeight + offsetV;
61969
+ } else if (alignV === "center") {
61970
+ anchorY = contentTop + (contentHeight - imageHeight) / 2 + offsetV;
61971
+ } else {
61972
+ anchorY = contentTop + offsetV;
61973
+ }
61974
+ } else if (vRelativeFrom === "page") {
61975
+ if (alignV === "top") {
61976
+ anchorY = offsetV;
61977
+ } else if (alignV === "bottom") {
61978
+ const pageHeight = contentBottom + (anchors.pageMargins.bottom ?? 0);
61979
+ anchorY = pageHeight - imageHeight + offsetV;
61980
+ } else if (alignV === "center") {
61981
+ const pageHeight = contentBottom + (anchors.pageMargins.bottom ?? 0);
61982
+ anchorY = (pageHeight - imageHeight) / 2 + offsetV;
61983
+ } else {
61984
+ anchorY = offsetV;
61985
+ }
61986
+ } else if (vRelativeFrom === "paragraph") {
61987
+ const baseAnchorY = state2.cursorY;
61988
+ const firstLineHeight = measure.lines?.[0]?.lineHeight ?? 0;
61989
+ const paragraphAdjustment = firstLineHeight / 2;
61990
+ anchorY = baseAnchorY + paragraphAdjustment + offsetV;
61991
+ } else {
61992
+ const baseAnchorY = state2.cursorY;
61993
+ anchorY = baseAnchorY + offsetV;
61994
+ }
61311
61995
  floatManager.registerDrawing(entry.block, entry.measure, anchorY, state2.columnIndex, state2.page.number);
61312
61996
  const anchorX = entry.block.anchor ? computeAnchorX(
61313
61997
  entry.block.anchor,
@@ -61347,7 +62031,7 @@ function layoutParagraphBlock(ctx2, anchors) {
61347
62031
  kind: "image",
61348
62032
  blockId: entry.block.id,
61349
62033
  x: anchorX,
61350
- y: anchorY + (entry.block.anchor?.offsetV ?? 0),
62034
+ y: anchorY,
61351
62035
  width: entry.measure.width,
61352
62036
  height: entry.measure.height,
61353
62037
  isAnchored: true,
@@ -61363,7 +62047,7 @@ function layoutParagraphBlock(ctx2, anchors) {
61363
62047
  blockId: entry.block.id,
61364
62048
  drawingKind: entry.block.drawingKind,
61365
62049
  x: anchorX,
61366
- y: anchorY + (entry.block.anchor?.offsetV ?? 0),
62050
+ y: anchorY,
61367
62051
  width: entry.measure.width,
61368
62052
  height: entry.measure.height,
61369
62053
  geometry: entry.measure.geometry,
@@ -61424,7 +62108,39 @@ function layoutParagraphBlock(ctx2, anchors) {
61424
62108
  state2.lastParagraphStyleId = styleId;
61425
62109
  return;
61426
62110
  }
62111
+ let narrowestWidth = columnWidth;
62112
+ let narrowestOffsetX = 0;
61427
62113
  let didRemeasureForFloats = false;
62114
+ if (typeof remeasureParagraph2 === "function") {
62115
+ const tempState = ensurePage();
62116
+ let tempY = tempState.cursorY;
62117
+ if (!appliedSpacingBefore && spacingBefore > 0) {
62118
+ const prevTrailing = tempState.trailingSpacing ?? 0;
62119
+ const neededSpacingBefore = Math.max(spacingBefore - prevTrailing, 0);
62120
+ tempY += neededSpacingBefore;
62121
+ }
62122
+ for (let i = 0; i < lines.length; i++) {
62123
+ const lineY = tempY;
62124
+ const lineHeight2 = lines[i]?.lineHeight || 0;
62125
+ const { width: availableWidth, offsetX: computedOffset } = floatManager.computeAvailableWidth(
62126
+ lineY,
62127
+ lineHeight2,
62128
+ columnWidth,
62129
+ tempState.columnIndex,
62130
+ tempState.page.number
62131
+ );
62132
+ if (availableWidth < narrowestWidth) {
62133
+ narrowestWidth = availableWidth;
62134
+ narrowestOffsetX = computedOffset;
62135
+ }
62136
+ tempY += lineHeight2;
62137
+ }
62138
+ if (narrowestWidth < columnWidth) {
62139
+ const newMeasure = remeasureParagraph2(block, narrowestWidth);
62140
+ lines = normalizeLines(newMeasure);
62141
+ didRemeasureForFloats = true;
62142
+ }
62143
+ }
61428
62144
  while (fromLine < lines.length) {
61429
62145
  let state2 = ensurePage();
61430
62146
  if (state2.trailingSpacing == null) state2.trailingSpacing = 0;
@@ -61469,23 +62185,9 @@ function layoutParagraphBlock(ctx2, anchors) {
61469
62185
  }
61470
62186
  let effectiveColumnWidth = columnWidth;
61471
62187
  let offsetX = 0;
61472
- if (!didRemeasureForFloats && typeof remeasureParagraph2 === "function") {
61473
- const firstLineY = state2.cursorY;
61474
- const firstLineHeight = lines[fromLine]?.lineHeight || 0;
61475
- const { width: adjustedWidth, offsetX: computedOffset } = floatManager.computeAvailableWidth(
61476
- firstLineY,
61477
- firstLineHeight,
61478
- columnWidth,
61479
- state2.columnIndex,
61480
- state2.page.number
61481
- );
61482
- if (adjustedWidth < columnWidth) {
61483
- const newMeasure = remeasureParagraph2(block, adjustedWidth);
61484
- lines = normalizeLines(newMeasure);
61485
- didRemeasureForFloats = true;
61486
- effectiveColumnWidth = adjustedWidth;
61487
- offsetX = computedOffset;
61488
- }
62188
+ if (didRemeasureForFloats) {
62189
+ effectiveColumnWidth = narrowestWidth;
62190
+ offsetX = narrowestOffsetX;
61489
62191
  }
61490
62192
  const slice2 = sliceLines(lines, fromLine, state2.contentBottom - state2.cursorY);
61491
62193
  const fragmentHeight = slice2.height;
@@ -61499,15 +62201,6 @@ function layoutParagraphBlock(ctx2, anchors) {
61499
62201
  width: effectiveColumnWidth,
61500
62202
  ...computeFragmentPmRange(block, lines, fromLine, slice2.toLine)
61501
62203
  };
61502
- anchorDebugLog("Positioning paragraph fragment:", {
61503
- blockId: block.id,
61504
- fragmentY: state2.cursorY,
61505
- fragmentHeight,
61506
- firstLineHeight: lines[fromLine]?.lineHeight,
61507
- firstLineAscent: lines[fromLine]?.ascent,
61508
- firstLineDescent: lines[fromLine]?.descent,
61509
- pageNumber: state2.page.number
61510
- });
61511
62204
  if (measure.marker && fromLine === 0) {
61512
62205
  fragment.markerWidth = measure.marker.markerWidth;
61513
62206
  }
@@ -61720,9 +62413,32 @@ function layoutTableBlock({
61720
62413
  state2.page.fragments.push(fragment);
61721
62414
  state2.cursorY += height;
61722
62415
  }
62416
+ function isPageRelativeAnchor(block) {
62417
+ const vRelativeFrom = block.anchor?.vRelativeFrom;
62418
+ return vRelativeFrom === "margin" || vRelativeFrom === "page";
62419
+ }
62420
+ function collectPreRegisteredAnchors(blocks, measures) {
62421
+ const result = [];
62422
+ const len = Math.min(blocks.length, measures.length);
62423
+ for (let i = 0; i < len; i += 1) {
62424
+ const block = blocks[i];
62425
+ const measure = measures[i];
62426
+ const isImage = block.kind === "image" && measure?.kind === "image";
62427
+ const isDrawing = block.kind === "drawing" && measure?.kind === "drawing";
62428
+ if (!isImage && !isDrawing) continue;
62429
+ const drawingBlock = block;
62430
+ const drawingMeasure = measure;
62431
+ if (!drawingBlock.anchor?.isAnchored) continue;
62432
+ if (isPageRelativeAnchor(drawingBlock)) {
62433
+ result.push({ block: drawingBlock, measure: drawingMeasure });
62434
+ }
62435
+ }
62436
+ return result;
62437
+ }
61723
62438
  function collectAnchoredDrawings(blocks, measures) {
61724
62439
  const map22 = /* @__PURE__ */ new Map();
61725
- for (let i = 0; i < blocks.length; i += 1) {
62440
+ const len = Math.min(blocks.length, measures.length);
62441
+ for (let i = 0; i < len; i += 1) {
61726
62442
  if (blocks[i].kind === "paragraph") ;
61727
62443
  }
61728
62444
  const nearestPrevParagraph = (fromIndex) => {
@@ -61732,12 +62448,12 @@ function collectAnchoredDrawings(blocks, measures) {
61732
62448
  return null;
61733
62449
  };
61734
62450
  const nearestNextParagraph = (fromIndex) => {
61735
- for (let i = fromIndex + 1; i < blocks.length; i += 1) {
62451
+ for (let i = fromIndex + 1; i < len; i += 1) {
61736
62452
  if (blocks[i].kind === "paragraph") return i;
61737
62453
  }
61738
62454
  return null;
61739
62455
  };
61740
- for (let i = 0; i < blocks.length; i += 1) {
62456
+ for (let i = 0; i < len; i += 1) {
61741
62457
  const block = blocks[i];
61742
62458
  const measure = measures[i];
61743
62459
  const isImage = block.kind === "image" && measure?.kind === "image";
@@ -61745,7 +62461,12 @@ function collectAnchoredDrawings(blocks, measures) {
61745
62461
  if (!isImage && !isDrawing) continue;
61746
62462
  const drawingBlock = block;
61747
62463
  const drawingMeasure = measure;
61748
- if (!drawingBlock.anchor?.isAnchored) continue;
62464
+ if (!drawingBlock.anchor?.isAnchored) {
62465
+ continue;
62466
+ }
62467
+ if (isPageRelativeAnchor(drawingBlock)) {
62468
+ continue;
62469
+ }
61749
62470
  let anchorParaIndex = nearestPrevParagraph(i);
61750
62471
  if (anchorParaIndex == null) anchorParaIndex = nearestNextParagraph(i);
61751
62472
  if (anchorParaIndex == null) continue;
@@ -62341,6 +63062,54 @@ function layoutDocument(blocks, measures, options = {}) {
62341
63062
  };
62342
63063
  const anchoredByParagraph = collectAnchoredDrawings(blocks, measures);
62343
63064
  const placedAnchoredIds = /* @__PURE__ */ new Set();
63065
+ const preRegisteredAnchors = collectPreRegisteredAnchors(blocks, measures);
63066
+ const preRegisteredPositions = /* @__PURE__ */ new Map();
63067
+ for (const entry of preRegisteredAnchors) {
63068
+ const state2 = paginator.ensurePage();
63069
+ const vRelativeFrom = entry.block.anchor?.vRelativeFrom ?? "paragraph";
63070
+ const alignV = entry.block.anchor?.alignV ?? "top";
63071
+ const offsetV = entry.block.anchor?.offsetV ?? 0;
63072
+ const imageHeight = entry.measure.height ?? 0;
63073
+ const contentTop = state2.topMargin;
63074
+ const contentBottom = state2.contentBottom;
63075
+ const contentHeight = Math.max(0, contentBottom - contentTop);
63076
+ let anchorY;
63077
+ if (vRelativeFrom === "margin") {
63078
+ if (alignV === "top") {
63079
+ anchorY = contentTop + offsetV;
63080
+ } else if (alignV === "bottom") {
63081
+ anchorY = contentBottom - imageHeight + offsetV;
63082
+ } else if (alignV === "center") {
63083
+ anchorY = contentTop + (contentHeight - imageHeight) / 2 + offsetV;
63084
+ } else {
63085
+ anchorY = contentTop + offsetV;
63086
+ }
63087
+ } else if (vRelativeFrom === "page") {
63088
+ if (alignV === "top") {
63089
+ anchorY = offsetV;
63090
+ } else if (alignV === "bottom") {
63091
+ const pageHeight = contentBottom + margins.bottom;
63092
+ anchorY = pageHeight - imageHeight + offsetV;
63093
+ } else if (alignV === "center") {
63094
+ const pageHeight = contentBottom + margins.bottom;
63095
+ anchorY = (pageHeight - imageHeight) / 2 + offsetV;
63096
+ } else {
63097
+ anchorY = offsetV;
63098
+ }
63099
+ } else {
63100
+ anchorY = contentTop + offsetV;
63101
+ }
63102
+ const anchorX = entry.block.anchor ? computeAnchorX(
63103
+ entry.block.anchor,
63104
+ state2.columnIndex,
63105
+ normalizeColumns(activeColumns, contentWidth),
63106
+ entry.measure.width,
63107
+ { left: margins.left, right: margins.right },
63108
+ activePageSize.w
63109
+ ) : margins.left;
63110
+ floatManager.registerDrawing(entry.block, entry.measure, anchorY, state2.columnIndex, state2.page.number);
63111
+ preRegisteredPositions.set(entry.block.id, { anchorX, anchorY, pageNumber: state2.page.number });
63112
+ }
62344
63113
  for (let index2 = 0; index2 < blocks.length; index2 += 1) {
62345
63114
  const block = blocks[index2];
62346
63115
  const measure = measures[index2];
@@ -62500,6 +63269,52 @@ function layoutDocument(blocks, measures, options = {}) {
62500
63269
  if (measure.kind !== "image") {
62501
63270
  throw new Error(`layoutDocument: expected image measure for block ${block.id}`);
62502
63271
  }
63272
+ const preRegPos = preRegisteredPositions.get(block.id);
63273
+ if (preRegPos && Number.isFinite(preRegPos.anchorX) && Number.isFinite(preRegPos.anchorY) && Number.isFinite(preRegPos.pageNumber)) {
63274
+ const state2 = paginator.ensurePage();
63275
+ const imgBlock = block;
63276
+ const imgMeasure = measure;
63277
+ const pageContentHeight = Math.max(0, state2.contentBottom - state2.topMargin);
63278
+ const relativeFrom = imgBlock.anchor?.hRelativeFrom ?? "column";
63279
+ const cols = getCurrentColumns();
63280
+ let maxWidth;
63281
+ if (relativeFrom === "page") {
63282
+ maxWidth = cols.count === 1 ? activePageSize.w - margins.left - margins.right : activePageSize.w;
63283
+ } else if (relativeFrom === "margin") {
63284
+ maxWidth = activePageSize.w - margins.left - margins.right;
63285
+ } else {
63286
+ maxWidth = cols.width;
63287
+ }
63288
+ const aspectRatio = imgMeasure.width > 0 && imgMeasure.height > 0 ? imgMeasure.width / imgMeasure.height : 1;
63289
+ const minWidth = 20;
63290
+ const minHeight = minWidth / aspectRatio;
63291
+ const metadata = {
63292
+ originalWidth: imgMeasure.width,
63293
+ originalHeight: imgMeasure.height,
63294
+ maxWidth,
63295
+ maxHeight: pageContentHeight,
63296
+ aspectRatio,
63297
+ minWidth,
63298
+ minHeight
63299
+ };
63300
+ const fragment = {
63301
+ kind: "image",
63302
+ blockId: imgBlock.id,
63303
+ x: preRegPos.anchorX,
63304
+ y: preRegPos.anchorY,
63305
+ width: imgMeasure.width,
63306
+ height: imgMeasure.height,
63307
+ isAnchored: true,
63308
+ zIndex: imgBlock.anchor?.behindDoc ? 0 : 1,
63309
+ metadata
63310
+ };
63311
+ const attrs = imgBlock.attrs;
63312
+ if (attrs?.pmStart != null) fragment.pmStart = attrs.pmStart;
63313
+ if (attrs?.pmEnd != null) fragment.pmEnd = attrs.pmEnd;
63314
+ state2.page.fragments.push(fragment);
63315
+ placedAnchoredIds.add(imgBlock.id);
63316
+ continue;
63317
+ }
62503
63318
  layoutImageBlock({
62504
63319
  block,
62505
63320
  measure,
@@ -62695,7 +63510,7 @@ const hashRuns = (block) => {
62695
63510
  const trackedMode = block.attrs && "trackedChangesMode" in block.attrs && block.attrs.trackedChangesMode || "review";
62696
63511
  const trackedEnabled = resolveTrackedChangesEnabled(block.attrs, true);
62697
63512
  const runsHash = block.runs.map((run2) => {
62698
- const text = normalizeText(run2.kind === "image" ? "" : run2.text ?? "");
63513
+ const text = normalizeText("src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "");
62699
63514
  const bold = "bold" in run2 ? run2.bold : false;
62700
63515
  const italic = "italic" in run2 ? run2.italic : false;
62701
63516
  const color = "color" in run2 ? run2.color : void 0;
@@ -62964,7 +63779,13 @@ const FeatureFlags = {
62964
63779
  * Logs cache hits, misses, invalidations, and bucket selection.
62965
63780
  * Should be disabled in production (only enabled for debugging).
62966
63781
  */
62967
- DEBUG_HF_CACHE: isEnabled("SD_DEBUG_HF_CACHE", false)
63782
+ DEBUG_HF_CACHE: isEnabled("SD_DEBUG_HF_CACHE", false),
63783
+ /**
63784
+ * Enable debug logging for layout version tracking.
63785
+ * Logs stale layout reads, geometry fallbacks, PM transactions, and layout completions.
63786
+ * Should be disabled in production (only enabled for debugging).
63787
+ */
63788
+ DEBUG_LAYOUT_VERSION: isEnabled("SD_DEBUG_LAYOUT_VERSION", false)
62968
63789
  };
62969
63790
  const PageTokenLogger = {
62970
63791
  /**
@@ -63349,7 +64170,7 @@ function fontString(run2) {
63349
64170
  return `${italic}${bold}${size2}px ${family}`.trim();
63350
64171
  }
63351
64172
  function runText(run2) {
63352
- return run2.kind === "image" ? "" : run2.text ?? "";
64173
+ return "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
63353
64174
  }
63354
64175
  function measureRunSliceWidth(run2, fromChar, toChar) {
63355
64176
  const context = getCtx();
@@ -63511,7 +64332,7 @@ const paragraphBlocksEqual = (a, b2) => {
63511
64332
  for (let i = 0; i < a.runs.length; i += 1) {
63512
64333
  const runA = a.runs[i];
63513
64334
  const runB = b2.runs[i];
63514
- 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)) {
64335
+ 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)) {
63515
64336
  return false;
63516
64337
  }
63517
64338
  }
@@ -63631,7 +64452,7 @@ function computeHeaderFooterContentHash(blocks) {
63631
64452
  parts.push(block.id);
63632
64453
  if (block.kind === "paragraph") {
63633
64454
  for (const run2 of block.runs) {
63634
- if (run2.kind !== "image") {
64455
+ if (!("src" in run2) && run2.kind !== "lineBreak") {
63635
64456
  parts.push(run2.text ?? "");
63636
64457
  }
63637
64458
  if ("bold" in run2 && run2.bold) parts.push("b");
@@ -64060,6 +64881,23 @@ async function remeasureAffectedBlocks(blocks, measures, affectedBlockIds, const
64060
64881
  }
64061
64882
  return updatedMeasures;
64062
64883
  }
64884
+ var Priority = /* @__PURE__ */ ((Priority2) => {
64885
+ Priority2[Priority2["P0"] = 0] = "P0";
64886
+ Priority2[Priority2["P1"] = 1] = "P1";
64887
+ Priority2[Priority2["P2"] = 2] = "P2";
64888
+ Priority2[Priority2["P3"] = 3] = "P3";
64889
+ return Priority2;
64890
+ })(Priority || {});
64891
+ ({
64892
+ /** P0: No debounce for synchronous cursor positioning */
64893
+ [Priority.P0]: 0,
64894
+ /** P1: One animation frame (~60fps) for viewport layout */
64895
+ [Priority.P1]: 16,
64896
+ /** P2: Typing burst threshold for adjacent pages layout */
64897
+ [Priority.P2]: 50,
64898
+ /** P3: Heavy debounce for full document layout */
64899
+ [Priority.P3]: 150
64900
+ });
64063
64901
  const isAtomicFragment = (fragment) => {
64064
64902
  return fragment.kind === "drawing" || fragment.kind === "image";
64065
64903
  };
@@ -64147,6 +64985,111 @@ const hitTestAtomicFragment = (pageHit, blocks, measures, point) => {
64147
64985
  }
64148
64986
  return null;
64149
64987
  };
64988
+ const hitTestTableFragment = (pageHit, blocks, measures, point) => {
64989
+ for (const fragment of pageHit.page.fragments) {
64990
+ if (fragment.kind !== "table") continue;
64991
+ const tableFragment = fragment;
64992
+ const withinX = point.x >= tableFragment.x && point.x <= tableFragment.x + tableFragment.width;
64993
+ const withinY = point.y >= tableFragment.y && point.y <= tableFragment.y + tableFragment.height;
64994
+ if (!withinX || !withinY) continue;
64995
+ const blockIndex = blocks.findIndex((block2) => block2.id === tableFragment.blockId);
64996
+ if (blockIndex === -1) continue;
64997
+ const block = blocks[blockIndex];
64998
+ const measure = measures[blockIndex];
64999
+ if (!block || block.kind !== "table" || !measure || measure.kind !== "table") continue;
65000
+ const tableBlock = block;
65001
+ const tableMeasure = measure;
65002
+ const localX = point.x - tableFragment.x;
65003
+ const localY = point.y - tableFragment.y;
65004
+ let rowY = 0;
65005
+ let rowIndex = -1;
65006
+ if (tableMeasure.rows.length === 0 || tableBlock.rows.length === 0) continue;
65007
+ for (let r2 = tableFragment.fromRow; r2 < tableFragment.toRow && r2 < tableMeasure.rows.length; r2++) {
65008
+ const rowMeasure2 = tableMeasure.rows[r2];
65009
+ if (localY >= rowY && localY < rowY + rowMeasure2.height) {
65010
+ rowIndex = r2;
65011
+ break;
65012
+ }
65013
+ rowY += rowMeasure2.height;
65014
+ }
65015
+ if (rowIndex === -1) {
65016
+ rowIndex = Math.min(tableFragment.toRow - 1, tableMeasure.rows.length - 1);
65017
+ if (rowIndex < tableFragment.fromRow) continue;
65018
+ }
65019
+ const rowMeasure = tableMeasure.rows[rowIndex];
65020
+ const row = tableBlock.rows[rowIndex];
65021
+ if (!rowMeasure || !row) continue;
65022
+ let colX = 0;
65023
+ let colIndex = -1;
65024
+ if (rowMeasure.cells.length === 0 || row.cells.length === 0) continue;
65025
+ for (let c2 = 0; c2 < rowMeasure.cells.length; c2++) {
65026
+ const cellMeasure2 = rowMeasure.cells[c2];
65027
+ if (localX >= colX && localX < colX + cellMeasure2.width) {
65028
+ colIndex = c2;
65029
+ break;
65030
+ }
65031
+ colX += cellMeasure2.width;
65032
+ }
65033
+ if (colIndex === -1) {
65034
+ colIndex = rowMeasure.cells.length - 1;
65035
+ if (colIndex < 0) continue;
65036
+ }
65037
+ const cellMeasure = rowMeasure.cells[colIndex];
65038
+ const cell = row.cells[colIndex];
65039
+ if (!cellMeasure || !cell) continue;
65040
+ const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
65041
+ const rawMeasures = cellMeasure.blocks ?? (cellMeasure.paragraph ? [cellMeasure.paragraph] : []);
65042
+ const cellBlockMeasures = (Array.isArray(rawMeasures) ? rawMeasures : []).filter(
65043
+ (m2) => m2 != null && typeof m2 === "object" && "kind" in m2
65044
+ );
65045
+ let blockStartY = 0;
65046
+ const getBlockHeight = (m2) => {
65047
+ if (!m2) return 0;
65048
+ if ("totalHeight" in m2 && typeof m2.totalHeight === "number") {
65049
+ return m2.totalHeight;
65050
+ }
65051
+ if ("height" in m2 && typeof m2.height === "number") {
65052
+ return m2.height;
65053
+ }
65054
+ return 0;
65055
+ };
65056
+ for (let i = 0; i < cellBlocks.length && i < cellBlockMeasures.length; i++) {
65057
+ const cellBlock = cellBlocks[i];
65058
+ const cellBlockMeasure = cellBlockMeasures[i];
65059
+ if (cellBlock?.kind !== "paragraph" || cellBlockMeasure?.kind !== "paragraph") {
65060
+ blockStartY += getBlockHeight(cellBlockMeasure);
65061
+ continue;
65062
+ }
65063
+ const blockHeight = getBlockHeight(cellBlockMeasure);
65064
+ const blockEndY = blockStartY + blockHeight;
65065
+ const padding = cell.attrs?.padding ?? { top: 2, left: 4 };
65066
+ const cellLocalX = localX - colX - (padding.left ?? 4);
65067
+ const cellLocalY = localY - rowY - (padding.top ?? 2);
65068
+ const paragraphBlock = cellBlock;
65069
+ const paragraphMeasure = cellBlockMeasure;
65070
+ const isWithinBlock = cellLocalY >= blockStartY && cellLocalY < blockEndY;
65071
+ const isLastParagraph = i === Math.min(cellBlocks.length, cellBlockMeasures.length) - 1;
65072
+ if (isWithinBlock || isLastParagraph) {
65073
+ const unclampedLocalY = cellLocalY - blockStartY;
65074
+ const localYWithinBlock = Math.max(0, Math.min(unclampedLocalY, Math.max(blockHeight, 0)));
65075
+ return {
65076
+ fragment: tableFragment,
65077
+ block: tableBlock,
65078
+ measure: tableMeasure,
65079
+ pageIndex: pageHit.pageIndex,
65080
+ cellRowIndex: rowIndex,
65081
+ cellColIndex: colIndex,
65082
+ cellBlock: paragraphBlock,
65083
+ cellMeasure: paragraphMeasure,
65084
+ localX: Math.max(0, cellLocalX),
65085
+ localY: Math.max(0, localYWithinBlock)
65086
+ };
65087
+ }
65088
+ blockStartY = blockEndY;
65089
+ }
65090
+ }
65091
+ return null;
65092
+ };
64150
65093
  function clickToPosition(layout, blocks, measures, containerPoint, domContainer, clientX, clientY) {
64151
65094
  logClickStage("log", "entry", {
64152
65095
  pages: layout.pages.length
@@ -64241,6 +65184,49 @@ function clickToPosition(layout, blocks, measures, containerPoint, domContainer,
64241
65184
  // lineIndex is now already absolute (within measure.lines), no need to add fragment.fromLine
64242
65185
  };
64243
65186
  }
65187
+ const tableHit = hitTestTableFragment(pageHit, blocks, measures, pageRelativePoint);
65188
+ if (tableHit) {
65189
+ const { cellBlock, cellMeasure, localX, localY, pageIndex } = tableHit;
65190
+ const lineIndex = findLineIndexAtY(cellMeasure, localY, 0, cellMeasure.lines.length);
65191
+ if (lineIndex != null) {
65192
+ const line = cellMeasure.lines[lineIndex];
65193
+ const isRTL = isRtlBlock(cellBlock);
65194
+ const pos = mapPointToPm(cellBlock, line, localX, isRTL);
65195
+ if (pos != null) {
65196
+ logClickStage("log", "success", {
65197
+ blockId: tableHit.fragment.blockId,
65198
+ column: determineColumn(layout, tableHit.fragment.x)
65199
+ });
65200
+ return {
65201
+ pos,
65202
+ blockId: tableHit.fragment.blockId,
65203
+ pageIndex,
65204
+ column: determineColumn(layout, tableHit.fragment.x),
65205
+ lineIndex
65206
+ };
65207
+ }
65208
+ }
65209
+ const firstRun = cellBlock.runs?.[0];
65210
+ if (firstRun && firstRun.pmStart != null) {
65211
+ logClickStage("log", "success", {
65212
+ blockId: tableHit.fragment.blockId,
65213
+ pos: firstRun.pmStart,
65214
+ column: determineColumn(layout, tableHit.fragment.x)
65215
+ });
65216
+ return {
65217
+ pos: firstRun.pmStart,
65218
+ blockId: tableHit.fragment.blockId,
65219
+ pageIndex,
65220
+ column: determineColumn(layout, tableHit.fragment.x),
65221
+ lineIndex: 0
65222
+ };
65223
+ }
65224
+ logClickStage("warn", "table-cell-no-position", {
65225
+ blockId: tableHit.fragment.blockId,
65226
+ cellRow: tableHit.cellRowIndex,
65227
+ cellCol: tableHit.cellColIndex
65228
+ });
65229
+ }
64244
65230
  const atomicHit = hitTestAtomicFragment(pageHit, blocks, measures, pageRelativePoint);
64245
65231
  if (atomicHit && isAtomicFragment(atomicHit.fragment)) {
64246
65232
  const { fragment, block, pageIndex } = atomicHit;
@@ -64352,6 +65338,44 @@ function getFragmentAtPosition(layout, blocks, measures, pos) {
64352
65338
  }
64353
65339
  continue;
64354
65340
  }
65341
+ if (fragment.kind === "table") {
65342
+ if (block.kind !== "table" || measure.kind !== "table") continue;
65343
+ const tableBlock = block;
65344
+ const tableFragment = fragment;
65345
+ let tableMinPos = null;
65346
+ let tableMaxPos = null;
65347
+ for (let r2 = tableFragment.fromRow; r2 < tableFragment.toRow && r2 < tableBlock.rows.length; r2++) {
65348
+ const row = tableBlock.rows[r2];
65349
+ for (const cell of row.cells) {
65350
+ const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
65351
+ for (const cellBlock of cellBlocks) {
65352
+ if (cellBlock?.kind === "paragraph") {
65353
+ const paraBlock = cellBlock;
65354
+ for (const run2 of paraBlock.runs ?? []) {
65355
+ if (run2.pmStart != null) {
65356
+ if (tableMinPos === null || run2.pmStart < tableMinPos) tableMinPos = run2.pmStart;
65357
+ if (tableMaxPos === null || run2.pmStart > tableMaxPos) tableMaxPos = run2.pmStart;
65358
+ }
65359
+ if (run2.pmEnd != null) {
65360
+ if (tableMinPos === null || run2.pmEnd < tableMinPos) tableMinPos = run2.pmEnd;
65361
+ if (tableMaxPos === null || run2.pmEnd > tableMaxPos) tableMaxPos = run2.pmEnd;
65362
+ }
65363
+ }
65364
+ }
65365
+ }
65366
+ }
65367
+ }
65368
+ if (tableMinPos != null && tableMaxPos != null && pos >= tableMinPos && pos <= tableMaxPos) {
65369
+ return {
65370
+ fragment,
65371
+ block,
65372
+ measure,
65373
+ pageIndex,
65374
+ pageY: 0
65375
+ };
65376
+ }
65377
+ continue;
65378
+ }
64355
65379
  if (isAtomicFragment(fragment)) {
64356
65380
  const { pmStart, pmEnd } = getAtomicPmRange(fragment, block);
64357
65381
  const start2 = pmStart ?? pmEnd;
@@ -64399,7 +65423,7 @@ function computeLinePmRange$1(block, line) {
64399
65423
  for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
64400
65424
  const run2 = block.runs[runIndex];
64401
65425
  if (!run2) continue;
64402
- const text = run2.kind === "image" ? "" : run2.text ?? "";
65426
+ const text = "src" in run2 || run2.kind === "lineBreak" ? "" : run2.text ?? "";
64403
65427
  const runLength = text.length;
64404
65428
  const runPmStart = run2.pmStart ?? null;
64405
65429
  const runPmEnd = run2.pmEnd ?? (runPmStart != null ? runPmStart + runLength : null);
@@ -66795,16 +67819,6 @@ const LINK_AND_TOC_STYLES = `
66795
67819
  opacity: 0.8;
66796
67820
  }
66797
67821
 
66798
- /* External link indicator (WCAG 2.4.4 Link Purpose) */
66799
- .superdoc-link[target="_blank"]::after {
66800
- content: "↗";
66801
- display: inline-block;
66802
- margin-left: 0.25em;
66803
- font-size: 0.85em;
66804
- text-decoration: none;
66805
- speak: literal-punctuation; /* Screen readers read the arrow */
66806
- }
66807
-
66808
67822
  /* Print mode: show URLs after links */
66809
67823
  @media print {
66810
67824
  .superdoc-link::after {
@@ -66817,11 +67831,6 @@ const LINK_AND_TOC_STYLES = `
66817
67831
  .superdoc-link[href^="#"]::after {
66818
67832
  content: "";
66819
67833
  }
66820
-
66821
- /* Don't show URL for external link indicator */
66822
- .superdoc-link[target="_blank"]::after {
66823
- content: " (" attr(href) ")";
66824
- }
66825
67834
  }
66826
67835
 
66827
67836
  /* High contrast mode support */
@@ -66839,13 +67848,6 @@ const LINK_AND_TOC_STYLES = `
66839
67848
  }
66840
67849
  }
66841
67850
 
66842
- /* RTL layout support */
66843
- .superdoc-layout[dir="rtl"] .superdoc-link[target="_blank"]::after {
66844
- margin-left: 0;
66845
- margin-right: 0.25em;
66846
- content: "↖"; /* Mirror the arrow for RTL */
66847
- }
66848
-
66849
67851
  /* Screen reader only content (WCAG SC 1.3.1) */
66850
67852
  .sr-only {
66851
67853
  position: absolute;
@@ -67300,7 +68302,100 @@ const renderTableFragment = (deps) => {
67300
68302
  }
67301
68303
  return container;
67302
68304
  };
68305
+ const isDevelopment = () => {
68306
+ if (typeof process$1$1 !== "undefined" && typeof process$1$1.env !== "undefined") {
68307
+ return process$1$1.env.NODE_ENV === "development";
68308
+ }
68309
+ return false;
68310
+ };
68311
+ class ValidationStatsCollector {
68312
+ constructor() {
68313
+ this.stats = {
68314
+ totalSpans: 0,
68315
+ validSpans: 0,
68316
+ missingPmStart: 0,
68317
+ missingPmEnd: 0,
68318
+ missingBoth: 0
68319
+ };
68320
+ }
68321
+ record(hasPmStart, hasPmEnd) {
68322
+ this.stats.totalSpans++;
68323
+ if (hasPmStart && hasPmEnd) {
68324
+ this.stats.validSpans++;
68325
+ } else if (!hasPmStart && !hasPmEnd) {
68326
+ this.stats.missingBoth++;
68327
+ } else if (!hasPmStart) {
68328
+ this.stats.missingPmStart++;
68329
+ } else {
68330
+ this.stats.missingPmEnd++;
68331
+ }
68332
+ }
68333
+ getStats() {
68334
+ return { ...this.stats };
68335
+ }
68336
+ reset() {
68337
+ this.stats = {
68338
+ totalSpans: 0,
68339
+ validSpans: 0,
68340
+ missingPmStart: 0,
68341
+ missingPmEnd: 0,
68342
+ missingBoth: 0
68343
+ };
68344
+ }
68345
+ getCoveragePercent() {
68346
+ if (this.stats.totalSpans === 0) return 100;
68347
+ return this.stats.validSpans / this.stats.totalSpans * 100;
68348
+ }
68349
+ logSummary() {
68350
+ if (!isDevelopment()) return;
68351
+ const coverage = this.getCoveragePercent();
68352
+ const s2 = this.stats;
68353
+ if (coverage < 100) {
68354
+ console.warn("[PmPositionValidation] PM position coverage:", {
68355
+ coverage: `${coverage.toFixed(1)}%`,
68356
+ totalSpans: s2.totalSpans,
68357
+ validSpans: s2.validSpans,
68358
+ missingPmStart: s2.missingPmStart,
68359
+ missingPmEnd: s2.missingPmEnd,
68360
+ missingBoth: s2.missingBoth
68361
+ });
68362
+ }
68363
+ }
68364
+ }
68365
+ const globalValidationStats = new ValidationStatsCollector();
68366
+ function assertPmPositions(run2, context) {
68367
+ const hasPmStart = run2.pmStart != null;
68368
+ const hasPmEnd = run2.pmEnd != null;
68369
+ globalValidationStats.record(hasPmStart, hasPmEnd);
68370
+ if (!isDevelopment()) return;
68371
+ if (!hasPmStart || !hasPmEnd) {
68372
+ const textPreview = run2.text ? run2.text.substring(0, 20) + (run2.text.length > 20 ? "..." : "") : "(no text)";
68373
+ console.warn(`[PmPositionValidation] Missing PM positions in ${context}:`, {
68374
+ hasPmStart,
68375
+ hasPmEnd,
68376
+ textPreview,
68377
+ fallback: "Will use PM DOM coordinates for cursor positioning"
68378
+ });
68379
+ }
68380
+ }
68381
+ function assertFragmentPmPositions(fragment, context) {
68382
+ const hasPmStart = fragment.pmStart != null;
68383
+ const hasPmEnd = fragment.pmEnd != null;
68384
+ globalValidationStats.record(hasPmStart, hasPmEnd);
68385
+ if (!isDevelopment()) return;
68386
+ if (!hasPmStart || !hasPmEnd) {
68387
+ console.warn(`[PmPositionValidation] Missing PM positions in ${context}:`, {
68388
+ fragmentKind: fragment.kind ?? "unknown",
68389
+ hasPmStart,
68390
+ hasPmEnd,
68391
+ fallback: "Will use PM DOM coordinates for cursor positioning"
68392
+ });
68393
+ }
68394
+ }
67303
68395
  const LIST_MARKER_GAP$1 = 8;
68396
+ const COMMENT_EXTERNAL_COLOR = "#B1124B";
68397
+ const COMMENT_INTERNAL_COLOR = "#078383";
68398
+ const COMMENT_INACTIVE_ALPHA = "22";
67304
68399
  const LINK_DATASET_KEYS = {
67305
68400
  blocked: "linkBlocked",
67306
68401
  docLocation: "linkDocLocation",
@@ -67957,7 +69052,7 @@ const _DomPainter = class _DomPainter2 {
67957
69052
  current.element = replacement;
67958
69053
  current.signature = fragmentSignature(fragment, this.blockLookup);
67959
69054
  }
67960
- this.updateFragmentElement(current.element, fragment);
69055
+ this.updateFragmentElement(current.element, fragment, contextBase.section);
67961
69056
  current.fragment = fragment;
67962
69057
  current.key = key2;
67963
69058
  current.context = contextBase;
@@ -68025,10 +69120,10 @@ const _DomPainter = class _DomPainter2 {
68025
69120
  return this.renderListItemFragment(fragment, context);
68026
69121
  }
68027
69122
  if (fragment.kind === "image") {
68028
- return this.renderImageFragment(fragment);
69123
+ return this.renderImageFragment(fragment, context);
68029
69124
  }
68030
69125
  if (fragment.kind === "drawing") {
68031
- return this.renderDrawingFragment(fragment);
69126
+ return this.renderDrawingFragment(fragment, context);
68032
69127
  }
68033
69128
  if (fragment.kind === "table") {
68034
69129
  return this.renderTableFragment(fragment, context);
@@ -68061,7 +69156,7 @@ const _DomPainter = class _DomPainter2 {
68061
69156
  const hasMarker = !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker;
68062
69157
  const styles = isTocEntry ? { ...fragmentStyles, whiteSpace: "nowrap" } : hasMarker ? { ...fragmentStyles, overflow: "visible" } : fragmentStyles;
68063
69158
  applyStyles$2(fragmentEl, styles);
68064
- this.applyFragmentFrame(fragmentEl, fragment);
69159
+ this.applyFragmentFrame(fragmentEl, fragment, context.section);
68065
69160
  if (isTocEntry) {
68066
69161
  fragmentEl.classList.add("superdoc-toc-entry");
68067
69162
  }
@@ -68079,8 +69174,32 @@ const _DomPainter = class _DomPainter2 {
68079
69174
  }
68080
69175
  this.applySdtDataset(fragmentEl, block.attrs?.sdt);
68081
69176
  this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
69177
+ const dropCapDescriptor = block.attrs?.dropCapDescriptor;
69178
+ const dropCapMeasure = measure.dropCap;
69179
+ if (dropCapDescriptor && dropCapMeasure && !fragment.continuesFromPrev) {
69180
+ const dropCapEl = this.renderDropCap(dropCapDescriptor, dropCapMeasure);
69181
+ fragmentEl.appendChild(dropCapEl);
69182
+ }
69183
+ if (fragmentEl.style.paddingLeft) fragmentEl.style.removeProperty("padding-left");
69184
+ if (fragmentEl.style.paddingRight) fragmentEl.style.removeProperty("padding-right");
69185
+ if (fragmentEl.style.textIndent) fragmentEl.style.removeProperty("text-indent");
69186
+ const paraIndent = block.attrs?.indent;
69187
+ const paraIndentLeft = paraIndent?.left ?? 0;
69188
+ const paraIndentRight = paraIndent?.right ?? 0;
69189
+ const firstLineOffset = (paraIndent?.firstLine ?? 0) - (paraIndent?.hanging ?? 0);
68082
69190
  lines.forEach((line, index2) => {
68083
69191
  const lineEl = this.renderLine(block, line, context);
69192
+ if (paraIndentLeft) {
69193
+ lineEl.style.paddingLeft = `${paraIndentLeft}px`;
69194
+ }
69195
+ if (paraIndentRight) {
69196
+ lineEl.style.paddingRight = `${paraIndentRight}px`;
69197
+ }
69198
+ if (!fragment.continuesFromPrev && index2 === 0 && firstLineOffset) {
69199
+ lineEl.style.textIndent = `${firstLineOffset}px`;
69200
+ } else if (firstLineOffset) {
69201
+ lineEl.style.textIndent = "0px";
69202
+ }
68084
69203
  if (index2 === 0 && !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker) {
68085
69204
  const markerContainer = this.doc.createElement("span");
68086
69205
  markerContainer.style.display = "inline-block";
@@ -68091,6 +69210,12 @@ const _DomPainter = class _DomPainter2 {
68091
69210
  markerEl.style.textAlign = wordLayout.marker.justification ?? "right";
68092
69211
  markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
68093
69212
  markerEl.style.pointerEvents = "none";
69213
+ const indentLeft = paraIndentLeft;
69214
+ const hanging = paraIndent?.hanging ?? 0;
69215
+ const textStartX = indentLeft - hanging;
69216
+ const markerLeftX = textStartX - fragment.markerWidth;
69217
+ markerEl.style.position = "relative";
69218
+ markerEl.style.left = `${markerLeftX}px`;
68094
69219
  markerEl.style.fontFamily = wordLayout.marker.run.fontFamily;
68095
69220
  markerEl.style.fontSize = `${wordLayout.marker.run.fontSize}px`;
68096
69221
  markerEl.style.fontWeight = wordLayout.marker.run.bold ? "bold" : "";
@@ -68149,6 +69274,53 @@ const _DomPainter = class _DomPainter2 {
68149
69274
  }
68150
69275
  return el;
68151
69276
  }
69277
+ /**
69278
+ * Renders a drop cap element as a floated span at the start of a paragraph.
69279
+ *
69280
+ * Drop caps are large initial letters that span multiple lines of text.
69281
+ * This method creates a floated element with the drop cap letter styled
69282
+ * according to the descriptor's run properties.
69283
+ *
69284
+ * @param descriptor - The drop cap descriptor with text and styling info
69285
+ * @param measure - The measured dimensions of the drop cap
69286
+ * @returns HTMLElement containing the rendered drop cap
69287
+ */
69288
+ renderDropCap(descriptor, measure) {
69289
+ const doc2 = this.doc;
69290
+ const { run: run2, mode } = descriptor;
69291
+ const dropCapEl = doc2.createElement("span");
69292
+ dropCapEl.classList.add("superdoc-drop-cap");
69293
+ dropCapEl.textContent = run2.text;
69294
+ dropCapEl.style.fontFamily = run2.fontFamily;
69295
+ dropCapEl.style.fontSize = `${run2.fontSize}px`;
69296
+ if (run2.bold) {
69297
+ dropCapEl.style.fontWeight = "bold";
69298
+ }
69299
+ if (run2.italic) {
69300
+ dropCapEl.style.fontStyle = "italic";
69301
+ }
69302
+ if (run2.color) {
69303
+ dropCapEl.style.color = run2.color;
69304
+ }
69305
+ if (mode === "drop") {
69306
+ dropCapEl.style.float = "left";
69307
+ dropCapEl.style.marginRight = "4px";
69308
+ dropCapEl.style.lineHeight = "1";
69309
+ } else if (mode === "margin") {
69310
+ dropCapEl.style.position = "absolute";
69311
+ dropCapEl.style.left = "0";
69312
+ dropCapEl.style.lineHeight = "1";
69313
+ }
69314
+ if (run2.position && run2.position !== 0) {
69315
+ dropCapEl.style.position = dropCapEl.style.position || "relative";
69316
+ dropCapEl.style.top = `${run2.position}px`;
69317
+ }
69318
+ if (measure) {
69319
+ dropCapEl.style.width = `${measure.width}px`;
69320
+ dropCapEl.style.height = `${measure.height}px`;
69321
+ }
69322
+ return dropCapEl;
69323
+ }
68152
69324
  renderListItemFragment(fragment, context) {
68153
69325
  try {
68154
69326
  const lookup2 = this.blockLookup.get(fragment.blockId);
@@ -68226,7 +69398,7 @@ const _DomPainter = class _DomPainter2 {
68226
69398
  return this.createErrorPlaceholder(fragment.blockId, error);
68227
69399
  }
68228
69400
  }
68229
- renderImageFragment(fragment) {
69401
+ renderImageFragment(fragment, context) {
68230
69402
  try {
68231
69403
  const lookup2 = this.blockLookup.get(fragment.blockId);
68232
69404
  if (!lookup2 || lookup2.block.kind !== "image" || lookup2.measure.kind !== "image") {
@@ -68239,7 +69411,7 @@ const _DomPainter = class _DomPainter2 {
68239
69411
  const fragmentEl = this.doc.createElement("div");
68240
69412
  fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-image-fragment");
68241
69413
  applyStyles$2(fragmentEl, fragmentStyles);
68242
- this.applyFragmentFrame(fragmentEl, fragment);
69414
+ this.applyFragmentFrame(fragmentEl, fragment, context.section);
68243
69415
  fragmentEl.style.height = `${fragment.height}px`;
68244
69416
  this.applySdtDataset(fragmentEl, block.attrs?.sdt);
68245
69417
  this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
@@ -68274,7 +69446,7 @@ const _DomPainter = class _DomPainter2 {
68274
69446
  return this.createErrorPlaceholder(fragment.blockId, error);
68275
69447
  }
68276
69448
  }
68277
- renderDrawingFragment(fragment) {
69449
+ renderDrawingFragment(fragment, context) {
68278
69450
  try {
68279
69451
  const lookup2 = this.blockLookup.get(fragment.blockId);
68280
69452
  if (!lookup2 || lookup2.block.kind !== "drawing" || lookup2.measure.kind !== "drawing") {
@@ -68288,7 +69460,7 @@ const _DomPainter = class _DomPainter2 {
68288
69460
  const fragmentEl = this.doc.createElement("div");
68289
69461
  fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-drawing-fragment");
68290
69462
  applyStyles$2(fragmentEl, fragmentStyles);
68291
- this.applyFragmentFrame(fragmentEl, fragment);
69463
+ this.applyFragmentFrame(fragmentEl, fragment, context.section);
68292
69464
  fragmentEl.style.height = `${fragment.height}px`;
68293
69465
  fragmentEl.style.position = "absolute";
68294
69466
  fragmentEl.style.overflow = "hidden";
@@ -68735,13 +69907,16 @@ const _DomPainter = class _DomPainter2 {
68735
69907
  if (!this.doc) {
68736
69908
  throw new Error("DomPainter: document is not available");
68737
69909
  }
69910
+ const applyFragmentFrameWithSection = (el, frag) => {
69911
+ this.applyFragmentFrame(el, frag, context.section);
69912
+ };
68738
69913
  return renderTableFragment({
68739
69914
  doc: this.doc,
68740
69915
  fragment,
68741
69916
  context,
68742
69917
  blockLookup: this.blockLookup,
68743
69918
  renderLine: this.renderLine.bind(this),
68744
- applyFragmentFrame: this.applyFragmentFrame.bind(this),
69919
+ applyFragmentFrame: applyFragmentFrameWithSection,
68745
69920
  applySdtDataset: this.applySdtDataset.bind(this),
68746
69921
  applyStyles: applyStyles$2
68747
69922
  });
@@ -68751,7 +69926,7 @@ const _DomPainter = class _DomPainter2 {
68751
69926
  * @returns Sanitized link data or null if invalid/missing
68752
69927
  */
68753
69928
  extractLinkData(run2) {
68754
- if (run2.kind === "tab") {
69929
+ if (run2.kind === "tab" || run2.kind === "image" || run2.kind === "lineBreak") {
68755
69930
  return null;
68756
69931
  }
68757
69932
  const link = run2.link;
@@ -68905,10 +70080,19 @@ const _DomPainter = class _DomPainter2 {
68905
70080
  isImageRun(run2) {
68906
70081
  return run2.kind === "image";
68907
70082
  }
70083
+ /**
70084
+ * Type guard to check if a run is a line break run.
70085
+ */
70086
+ isLineBreakRun(run2) {
70087
+ return run2.kind === "lineBreak";
70088
+ }
68908
70089
  renderRun(run2, context, trackedConfig) {
68909
70090
  if (this.isImageRun(run2)) {
68910
70091
  return this.renderImageRun(run2);
68911
70092
  }
70093
+ if (this.isLineBreakRun(run2)) {
70094
+ return null;
70095
+ }
68912
70096
  if (!run2.text || !this.doc) {
68913
70097
  return null;
68914
70098
  }
@@ -68933,8 +70117,21 @@ const _DomPainter = class _DomPainter2 {
68933
70117
  }
68934
70118
  }
68935
70119
  applyRunStyles(elem, run2, isActiveLink);
70120
+ const commentColor = getCommentHighlight(run2);
70121
+ if (commentColor && !run2.highlight) {
70122
+ elem.style.backgroundColor = commentColor;
70123
+ }
70124
+ const commentAnnotations = run2.comments;
70125
+ if (commentAnnotations?.length) {
70126
+ elem.dataset.commentIds = commentAnnotations.map((c2) => c2.commentId).join(",");
70127
+ if (commentAnnotations.some((c2) => c2.internal)) {
70128
+ elem.dataset.commentInternal = "true";
70129
+ }
70130
+ elem.classList.add("superdoc-comment-highlight");
70131
+ }
68936
70132
  elem.style.zIndex = "1";
68937
70133
  applyRunDataAttributes(elem, run2.dataAttrs);
70134
+ assertPmPositions(run2, "paragraph text run");
68938
70135
  if (run2.pmStart != null) elem.dataset.pmStart = String(run2.pmStart);
68939
70136
  if (run2.pmEnd != null) elem.dataset.pmEnd = String(run2.pmEnd);
68940
70137
  if (trackedConfig) {
@@ -69013,6 +70210,7 @@ const _DomPainter = class _DomPainter2 {
69013
70210
  img.style.marginRight = `${run2.distRight}px`;
69014
70211
  }
69015
70212
  img.style.zIndex = "1";
70213
+ assertPmPositions(run2, "inline image run");
69016
70214
  if (run2.pmStart != null) {
69017
70215
  img.dataset.pmStart = String(run2.pmStart);
69018
70216
  }
@@ -69043,9 +70241,9 @@ const _DomPainter = class _DomPainter2 {
69043
70241
  if (lineRange.pmEnd != null) {
69044
70242
  el.dataset.pmEnd = String(lineRange.pmEnd);
69045
70243
  }
69046
- const runs = sliceRunsForLine(block, line);
70244
+ const runsForLine = sliceRunsForLine(block, line);
69047
70245
  const trackedConfig = this.resolveTrackedChangesConfig(block);
69048
- if (runs.length === 0) {
70246
+ if (runsForLine.length === 0) {
69049
70247
  const span = this.doc.createElement("span");
69050
70248
  span.innerHTML = "&nbsp;";
69051
70249
  el.appendChild(span);
@@ -69093,49 +70291,109 @@ const _DomPainter = class _DomPainter2 {
69093
70291
  const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
69094
70292
  if (hasExplicitPositioning && line.segments) {
69095
70293
  let cumulativeX = 0;
69096
- line.segments.forEach((segment, _segIdx) => {
69097
- const baseRun = runs[segment.runIndex];
69098
- if (!baseRun || baseRun.kind === "tab") return;
69099
- if (this.isImageRun(baseRun)) {
69100
- const elem2 = this.renderRun(baseRun, context, trackedConfig);
69101
- if (elem2) {
69102
- if (styleId) {
69103
- elem2.setAttribute("styleid", styleId);
69104
- }
69105
- el.appendChild(elem2);
70294
+ const segmentsByRun = /* @__PURE__ */ new Map();
70295
+ line.segments.forEach((segment) => {
70296
+ const list = segmentsByRun.get(segment.runIndex);
70297
+ if (list) {
70298
+ list.push(segment);
70299
+ } else {
70300
+ segmentsByRun.set(segment.runIndex, [segment]);
70301
+ }
70302
+ });
70303
+ const findImmediateNextSegmentX = (fromRunIndex) => {
70304
+ const nextRunIdx = fromRunIndex + 1;
70305
+ if (nextRunIdx <= line.toRun) {
70306
+ const nextSegments = segmentsByRun.get(nextRunIdx);
70307
+ if (nextSegments && nextSegments.length > 0) {
70308
+ const firstSegment = nextSegments[0];
70309
+ return firstSegment.x;
69106
70310
  }
69107
- return;
69108
70311
  }
69109
- const segmentText = baseRun.text.slice(segment.fromChar, segment.toChar);
69110
- const segmentRun = { ...baseRun, text: segmentText };
69111
- const elem = this.renderRun(segmentRun, context, trackedConfig);
69112
- if (elem) {
70312
+ return void 0;
70313
+ };
70314
+ for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
70315
+ const baseRun = block.runs[runIndex];
70316
+ if (!baseRun) continue;
70317
+ if (baseRun.kind === "tab") {
70318
+ const immediateNextX = findImmediateNextSegmentX(runIndex);
70319
+ const tabStartX = cumulativeX;
70320
+ const tabEndX = immediateNextX !== void 0 ? immediateNextX : tabStartX + (baseRun.width ?? 0);
70321
+ const actualTabWidth = tabEndX - tabStartX;
70322
+ const tabEl = this.doc.createElement("span");
70323
+ tabEl.style.position = "absolute";
70324
+ tabEl.style.left = `${tabStartX}px`;
70325
+ tabEl.style.top = "0px";
70326
+ tabEl.style.width = `${actualTabWidth}px`;
70327
+ tabEl.style.height = `${line.lineHeight}px`;
70328
+ tabEl.style.display = "inline-block";
70329
+ tabEl.style.visibility = "hidden";
70330
+ tabEl.style.pointerEvents = "none";
70331
+ tabEl.style.zIndex = "1";
69113
70332
  if (styleId) {
69114
- elem.setAttribute("styleid", styleId);
70333
+ tabEl.setAttribute("styleid", styleId);
69115
70334
  }
69116
- let xPos;
69117
- if (segment.x !== void 0) {
69118
- xPos = segment.x;
69119
- } else {
69120
- xPos = cumulativeX;
70335
+ if (baseRun.pmStart != null) tabEl.dataset.pmStart = String(baseRun.pmStart);
70336
+ if (baseRun.pmEnd != null) tabEl.dataset.pmEnd = String(baseRun.pmEnd);
70337
+ el.appendChild(tabEl);
70338
+ cumulativeX = tabEndX;
70339
+ continue;
70340
+ }
70341
+ if (this.isImageRun(baseRun)) {
70342
+ const elem = this.renderRun(baseRun, context, trackedConfig);
70343
+ if (elem) {
70344
+ if (styleId) {
70345
+ elem.setAttribute("styleid", styleId);
70346
+ }
70347
+ el.appendChild(elem);
69121
70348
  }
69122
- elem.style.position = "absolute";
69123
- elem.style.left = `${xPos}px`;
69124
- el.appendChild(elem);
69125
- if (this.doc) {
69126
- const measureEl = elem.cloneNode(true);
69127
- measureEl.style.position = "absolute";
69128
- measureEl.style.visibility = "hidden";
69129
- measureEl.style.left = "-9999px";
69130
- this.doc.body.appendChild(measureEl);
69131
- const width = measureEl.offsetWidth;
69132
- this.doc.body.removeChild(measureEl);
70349
+ continue;
70350
+ }
70351
+ if (this.isLineBreakRun(baseRun)) {
70352
+ continue;
70353
+ }
70354
+ const runSegments = segmentsByRun.get(runIndex);
70355
+ if (!runSegments || runSegments.length === 0) {
70356
+ continue;
70357
+ }
70358
+ const baseText = baseRun.text ?? "";
70359
+ const runPmStart = baseRun.pmStart ?? null;
70360
+ const fallbackPmEnd = runPmStart != null && baseRun.pmEnd == null ? runPmStart + baseText.length : baseRun.pmEnd ?? null;
70361
+ runSegments.forEach((segment) => {
70362
+ const segmentText = baseText.slice(segment.fromChar, segment.toChar);
70363
+ if (!segmentText) return;
70364
+ const pmSliceStart = runPmStart != null ? runPmStart + segment.fromChar : void 0;
70365
+ const pmSliceEnd = runPmStart != null ? runPmStart + segment.toChar : fallbackPmEnd ?? void 0;
70366
+ const segmentRun = {
70367
+ ...baseRun,
70368
+ text: segmentText,
70369
+ pmStart: pmSliceStart,
70370
+ pmEnd: pmSliceEnd
70371
+ };
70372
+ const elem = this.renderRun(segmentRun, context, trackedConfig);
70373
+ if (elem) {
70374
+ if (styleId) {
70375
+ elem.setAttribute("styleid", styleId);
70376
+ }
70377
+ const xPos = segment.x !== void 0 ? segment.x : cumulativeX;
70378
+ elem.style.position = "absolute";
70379
+ elem.style.left = `${xPos}px`;
70380
+ el.appendChild(elem);
70381
+ let width = segment.width ?? 0;
70382
+ if (width <= 0 && this.doc) {
70383
+ const measureEl = elem.cloneNode(true);
70384
+ measureEl.style.position = "absolute";
70385
+ measureEl.style.visibility = "hidden";
70386
+ measureEl.style.left = "-9999px";
70387
+ this.doc.body.appendChild(measureEl);
70388
+ width = measureEl.offsetWidth;
70389
+ this.doc.body.removeChild(measureEl);
70390
+ }
69133
70391
  cumulativeX = xPos + width;
69134
70392
  }
69135
- }
69136
- });
70393
+ });
70394
+ }
69137
70395
  } else {
69138
- runs.forEach((run2) => {
70396
+ runsForLine.forEach((run2) => {
69139
70397
  const elem = this.renderRun(run2, context, trackedConfig);
69140
70398
  if (elem) {
69141
70399
  if (styleId) {
@@ -69193,8 +70451,18 @@ const _DomPainter = class _DomPainter2 {
69193
70451
  elem.dataset.trackChangeDate = meta.date;
69194
70452
  }
69195
70453
  }
69196
- updateFragmentElement(el, fragment) {
69197
- this.applyFragmentFrame(el, fragment);
70454
+ /**
70455
+ * Updates an existing fragment element's position and dimensions in place.
70456
+ * Used during incremental updates to efficiently reposition fragments without full re-render.
70457
+ *
70458
+ * @param el - The HTMLElement representing the fragment to update
70459
+ * @param fragment - The fragment data containing updated position and dimensions
70460
+ * @param section - The document section ('body', 'header', 'footer') containing this fragment.
70461
+ * Affects PM position validation - only body sections validate PM positions.
70462
+ * If undefined, defaults to 'body' section behavior.
70463
+ */
70464
+ updateFragmentElement(el, fragment, section) {
70465
+ this.applyFragmentFrame(el, fragment, section);
69198
70466
  if (fragment.kind === "image") {
69199
70467
  el.style.height = `${fragment.height}px`;
69200
70468
  }
@@ -69202,12 +70470,27 @@ const _DomPainter = class _DomPainter2 {
69202
70470
  el.style.height = `${fragment.height}px`;
69203
70471
  }
69204
70472
  }
69205
- applyFragmentFrame(el, fragment) {
70473
+ /**
70474
+ * Applies fragment positioning, dimensions, and metadata to an HTML element.
70475
+ * Sets CSS positioning, block ID, and PM position data attributes for paragraph fragments.
70476
+ *
70477
+ * @param el - The HTMLElement to apply fragment properties to
70478
+ * @param fragment - The fragment data containing position, dimensions, and PM position information
70479
+ * @param section - The document section ('body', 'header', 'footer') containing this fragment.
70480
+ * Controls PM position validation behavior:
70481
+ * - 'body' or undefined: PM positions are validated and required for paragraph fragments
70482
+ * - 'header' or 'footer': PM position validation is skipped (these sections have separate PM coordinate spaces)
70483
+ * When undefined, defaults to 'body' section behavior (validation enabled).
70484
+ */
70485
+ applyFragmentFrame(el, fragment, section) {
69206
70486
  el.style.left = `${fragment.x}px`;
69207
70487
  el.style.top = `${fragment.y}px`;
69208
70488
  el.style.width = `${fragment.width}px`;
69209
70489
  el.dataset.blockId = fragment.blockId;
69210
70490
  if (fragment.kind === "para") {
70491
+ if (section === "body" || section === void 0) {
70492
+ assertFragmentPmPositions(fragment, "paragraph fragment");
70493
+ }
69211
70494
  if (fragment.pmStart != null) {
69212
70495
  el.dataset.pmStart = String(fragment.pmStart);
69213
70496
  } else {
@@ -69454,22 +70737,29 @@ const deriveBlockVersion = (block) => {
69454
70737
  imgRun.pmEnd ?? ""
69455
70738
  ].join(",");
69456
70739
  }
70740
+ if (run2.kind === "lineBreak") {
70741
+ return ["linebreak", run2.pmStart ?? "", run2.pmEnd ?? ""].join(",");
70742
+ }
70743
+ if (run2.kind === "tab") {
70744
+ return [run2.text ?? "", "tab", run2.pmStart ?? "", run2.pmEnd ?? ""].join(",");
70745
+ }
70746
+ const textRun = run2;
69457
70747
  return [
69458
- run2.text ?? "",
69459
- run2.kind !== "tab" ? run2.fontFamily : "",
69460
- run2.kind !== "tab" ? run2.fontSize : "",
69461
- run2.kind !== "tab" && run2.bold ? 1 : 0,
69462
- run2.kind !== "tab" && run2.italic ? 1 : 0,
69463
- run2.kind !== "tab" ? run2.color ?? "" : "",
70748
+ textRun.text ?? "",
70749
+ textRun.fontFamily,
70750
+ textRun.fontSize,
70751
+ textRun.bold ? 1 : 0,
70752
+ textRun.italic ? 1 : 0,
70753
+ textRun.color ?? "",
69464
70754
  // Text decorations - ensures DOM updates when decoration properties change.
69465
- run2.kind !== "tab" ? run2.underline?.style ?? "" : "",
69466
- run2.kind !== "tab" ? run2.underline?.color ?? "" : "",
69467
- run2.kind !== "tab" && run2.strike ? 1 : 0,
69468
- run2.kind !== "tab" ? run2.highlight ?? "" : "",
69469
- run2.kind !== "tab" && run2.letterSpacing != null ? run2.letterSpacing : "",
69470
- run2.pmStart ?? "",
69471
- run2.pmEnd ?? "",
69472
- run2.kind !== "tab" ? run2.token ?? "" : ""
70755
+ textRun.underline?.style ?? "",
70756
+ textRun.underline?.color ?? "",
70757
+ textRun.strike ? 1 : 0,
70758
+ textRun.highlight ?? "",
70759
+ textRun.letterSpacing != null ? textRun.letterSpacing : "",
70760
+ textRun.pmStart ?? "",
70761
+ textRun.pmEnd ?? "",
70762
+ textRun.token ?? ""
69473
70763
  ].join(",");
69474
70764
  }).join("|");
69475
70765
  }
@@ -69520,16 +70810,57 @@ const deriveBlockVersion = (block) => {
69520
70810
  }
69521
70811
  if (block.kind === "table") {
69522
70812
  const tableBlock = block;
69523
- return [
69524
- block.id,
69525
- tableBlock.columnWidths ? JSON.stringify(tableBlock.columnWidths) : "",
69526
- tableBlock.rows.length
69527
- ].join("|");
70813
+ const hashString = (seed, value) => {
70814
+ let hash22 = seed >>> 0;
70815
+ for (let i = 0; i < value.length; i++) {
70816
+ hash22 ^= value.charCodeAt(i);
70817
+ hash22 = Math.imul(hash22, 16777619);
70818
+ }
70819
+ return hash22 >>> 0;
70820
+ };
70821
+ const hashNumber = (seed, value) => {
70822
+ const n = Number.isFinite(value) ? value : 0;
70823
+ let hash22 = seed ^ n;
70824
+ hash22 = Math.imul(hash22, 16777619);
70825
+ hash22 ^= hash22 >>> 13;
70826
+ return hash22 >>> 0;
70827
+ };
70828
+ let hash2 = 2166136261;
70829
+ hash2 = hashString(hash2, block.id);
70830
+ hash2 = hashNumber(hash2, tableBlock.rows.length);
70831
+ hash2 = (tableBlock.columnWidths ?? []).reduce((acc, width) => hashNumber(acc, Math.round(width * 1e3)), hash2);
70832
+ const rows = tableBlock.rows ?? [];
70833
+ for (const row of rows) {
70834
+ if (!row || !Array.isArray(row.cells)) continue;
70835
+ hash2 = hashNumber(hash2, row.cells.length);
70836
+ for (const cell of row.cells) {
70837
+ if (!cell) continue;
70838
+ const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
70839
+ hash2 = hashNumber(hash2, cellBlocks.length);
70840
+ hash2 = hashNumber(hash2, cell.rowSpan ?? 1);
70841
+ hash2 = hashNumber(hash2, cell.colSpan ?? 1);
70842
+ for (const cellBlock of cellBlocks) {
70843
+ hash2 = hashString(hash2, cellBlock?.kind ?? "unknown");
70844
+ if (cellBlock?.kind === "paragraph") {
70845
+ const runs = cellBlock.runs ?? [];
70846
+ hash2 = hashNumber(hash2, runs.length);
70847
+ for (const run2 of runs) {
70848
+ if ("text" in run2 && typeof run2.text === "string") {
70849
+ hash2 = hashString(hash2, run2.text);
70850
+ }
70851
+ hash2 = hashNumber(hash2, run2.pmStart ?? -1);
70852
+ hash2 = hashNumber(hash2, run2.pmEnd ?? -1);
70853
+ }
70854
+ }
70855
+ }
70856
+ }
70857
+ }
70858
+ return [block.id, tableBlock.rows.length, hash2.toString(16)].join("|");
69528
70859
  }
69529
70860
  return block.id;
69530
70861
  };
69531
70862
  const applyRunStyles = (element, run2, isLink = false) => {
69532
- if (run2.kind === "tab" || run2.kind === "image") {
70863
+ if (run2.kind === "tab" || run2.kind === "image" || run2.kind === "lineBreak") {
69533
70864
  return;
69534
70865
  }
69535
70866
  element.style.fontFamily = run2.fontFamily;
@@ -69561,6 +70892,13 @@ const applyRunStyles = (element, run2, isLink = false) => {
69561
70892
  element.style.textDecorationLine = decorations.join(" ");
69562
70893
  }
69563
70894
  };
70895
+ const getCommentHighlight = (run2) => {
70896
+ const comments = run2.comments;
70897
+ if (!comments || comments.length === 0) return void 0;
70898
+ const primary = comments[0];
70899
+ const base2 = primary.internal ? COMMENT_INTERNAL_COLOR : COMMENT_EXTERNAL_COLOR;
70900
+ return `${base2}${COMMENT_INACTIVE_ALPHA}`;
70901
+ };
69564
70902
  const applyRunDataAttributes = (element, dataAttrs) => {
69565
70903
  if (!dataAttrs) return;
69566
70904
  Object.entries(dataAttrs).forEach(([key2, value]) => {
@@ -69652,6 +70990,10 @@ const sliceRunsForLine = (block, line) => {
69652
70990
  result.push(run2);
69653
70991
  continue;
69654
70992
  }
70993
+ if (run2.kind === "lineBreak") {
70994
+ result.push(run2);
70995
+ continue;
70996
+ }
69655
70997
  const text = run2.text ?? "";
69656
70998
  const isFirstRun = runIndex === line.fromRun;
69657
70999
  const isLastRun = runIndex === line.toRun;
@@ -69674,7 +71016,8 @@ const sliceRunsForLine = (block, line) => {
69674
71016
  ...run2,
69675
71017
  text: slice2,
69676
71018
  pmStart: pmSliceStart,
69677
- pmEnd: pmSliceEnd
71019
+ pmEnd: pmSliceEnd,
71020
+ comments: run2.comments ? [...run2.comments] : void 0
69678
71021
  };
69679
71022
  result.push(sliced);
69680
71023
  }
@@ -69705,6 +71048,21 @@ const computeLinePmRange = (block, line) => {
69705
71048
  }
69706
71049
  continue;
69707
71050
  }
71051
+ if (run2.kind === "lineBreak") {
71052
+ const runPmStart2 = run2.pmStart ?? null;
71053
+ const runPmEnd = run2.pmEnd ?? null;
71054
+ if (runPmStart2 == null || runPmEnd == null) {
71055
+ continue;
71056
+ }
71057
+ if (pmStart == null) {
71058
+ pmStart = runPmStart2;
71059
+ }
71060
+ pmEnd = runPmEnd;
71061
+ if (runIndex === line.toRun) {
71062
+ break;
71063
+ }
71064
+ continue;
71065
+ }
69708
71066
  const text = run2.text ?? "";
69709
71067
  const runLength = text.length;
69710
71068
  const runPmStart = run2.pmStart ?? null;
@@ -69743,6 +71101,9 @@ const resolveRunText = (run2, context) => {
69743
71101
  if (run2.kind === "image") {
69744
71102
  return "";
69745
71103
  }
71104
+ if (run2.kind === "lineBreak") {
71105
+ return "";
71106
+ }
69746
71107
  if (!runToken) {
69747
71108
  return run2.text ?? "";
69748
71109
  }
@@ -69909,6 +71270,9 @@ function isTabRun(run2) {
69909
71270
  function isImageRun(run2) {
69910
71271
  return run2.kind === "image";
69911
71272
  }
71273
+ function isLineBreakRun(run2) {
71274
+ return run2.kind === "lineBreak";
71275
+ }
69912
71276
  async function measureBlock(block, constraints) {
69913
71277
  const normalized = normalizeConstraints(constraints);
69914
71278
  if (block.kind === "drawing") {
@@ -69946,7 +71310,7 @@ async function measureParagraphBlock(block, maxWidth) {
69946
71310
  const hanging = indent?.hanging ?? 0;
69947
71311
  const firstLineOffset = firstLine - hanging;
69948
71312
  const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
69949
- let availableWidth = Math.max(1, contentWidth - firstLineOffset);
71313
+ const initialAvailableWidth = Math.max(1, contentWidth - firstLineOffset);
69950
71314
  const tabStops = buildTabStopsPx(
69951
71315
  indent,
69952
71316
  block.attrs?.tabs,
@@ -69959,6 +71323,18 @@ async function measureParagraphBlock(block, maxWidth) {
69959
71323
  line.bars = barTabStops.map((stop) => ({ x: stop.pos }));
69960
71324
  }
69961
71325
  };
71326
+ const dropCapDescriptor = block.attrs?.dropCapDescriptor;
71327
+ let dropCapMeasure = null;
71328
+ if (dropCapDescriptor) {
71329
+ if (!dropCapDescriptor.run || !dropCapDescriptor.run.text || !dropCapDescriptor.lines) {
71330
+ console.warn("Invalid drop cap descriptor - missing required fields:", dropCapDescriptor);
71331
+ } else {
71332
+ const dropCapMeasured = measureDropCap(ctx2, dropCapDescriptor, spacing);
71333
+ dropCapMeasure = dropCapMeasured;
71334
+ dropCapDescriptor.measuredWidth = dropCapMeasured.width;
71335
+ dropCapDescriptor.measuredHeight = dropCapMeasured.height;
71336
+ }
71337
+ }
69962
71338
  if (block.runs.length === 0) {
69963
71339
  const metrics = calculateTypographyMetrics(12, spacing);
69964
71340
  const emptyLine = {
@@ -69978,6 +71354,13 @@ async function measureParagraphBlock(block, maxWidth) {
69978
71354
  };
69979
71355
  }
69980
71356
  let currentLine = null;
71357
+ const getEffectiveWidth = (baseWidth) => {
71358
+ if (dropCapMeasure && lines.length < dropCapMeasure.lines && dropCapMeasure.mode === "drop") {
71359
+ return Math.max(1, baseWidth - dropCapMeasure.width);
71360
+ }
71361
+ return baseWidth;
71362
+ };
71363
+ let lastFontSize = 12;
69981
71364
  let tabStopCursor = 0;
69982
71365
  let pendingTabAlignment = null;
69983
71366
  let lastAppliedTabAlign = null;
@@ -70014,6 +71397,47 @@ async function measureParagraphBlock(block, maxWidth) {
70014
71397
  };
70015
71398
  for (let runIndex = 0; runIndex < block.runs.length; runIndex++) {
70016
71399
  const run2 = block.runs[runIndex];
71400
+ if (isLineBreakRun(run2)) {
71401
+ if (currentLine) {
71402
+ const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
71403
+ const completedLine = {
71404
+ ...currentLine,
71405
+ ...metrics
71406
+ };
71407
+ addBarTabsToLine(completedLine);
71408
+ lines.push(completedLine);
71409
+ } else {
71410
+ const metrics = calculateTypographyMetrics(lastFontSize, spacing);
71411
+ const emptyLine = {
71412
+ fromRun: runIndex,
71413
+ fromChar: 0,
71414
+ toRun: runIndex,
71415
+ toChar: 0,
71416
+ width: 0,
71417
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
71418
+ segments: [],
71419
+ ...metrics
71420
+ };
71421
+ addBarTabsToLine(emptyLine);
71422
+ lines.push(emptyLine);
71423
+ }
71424
+ const hadPreviousLine = lines.length > 0;
71425
+ const nextLineMaxWidth = hadPreviousLine ? getEffectiveWidth(contentWidth) : getEffectiveWidth(initialAvailableWidth);
71426
+ currentLine = {
71427
+ fromRun: runIndex,
71428
+ fromChar: 0,
71429
+ toRun: runIndex,
71430
+ toChar: 0,
71431
+ width: 0,
71432
+ maxFontSize: lastFontSize,
71433
+ maxWidth: nextLineMaxWidth,
71434
+ segments: []
71435
+ };
71436
+ tabStopCursor = 0;
71437
+ pendingTabAlignment = null;
71438
+ lastAppliedTabAlign = null;
71439
+ continue;
71440
+ }
70017
71441
  if (isTabRun(run2)) {
70018
71442
  if (!currentLine) {
70019
71443
  currentLine = {
@@ -70024,7 +71448,7 @@ async function measureParagraphBlock(block, maxWidth) {
70024
71448
  width: 0,
70025
71449
  maxFontSize: 12,
70026
71450
  // Default font size for tabs
70027
- maxWidth: availableWidth,
71451
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
70028
71452
  segments: []
70029
71453
  };
70030
71454
  }
@@ -70069,7 +71493,7 @@ async function measureParagraphBlock(block, maxWidth) {
70069
71493
  width: imageWidth,
70070
71494
  maxFontSize: imageHeight,
70071
71495
  // Use image height for line height calculation
70072
- maxWidth: availableWidth,
71496
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
70073
71497
  segments: [
70074
71498
  {
70075
71499
  runIndex,
@@ -70079,7 +71503,6 @@ async function measureParagraphBlock(block, maxWidth) {
70079
71503
  }
70080
71504
  ]
70081
71505
  };
70082
- availableWidth = contentWidth;
70083
71506
  continue;
70084
71507
  }
70085
71508
  if (currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
@@ -70099,7 +71522,7 @@ async function measureParagraphBlock(block, maxWidth) {
70099
71522
  toChar: 1,
70100
71523
  width: imageWidth,
70101
71524
  maxFontSize: imageHeight,
70102
- maxWidth: contentWidth,
71525
+ maxWidth: getEffectiveWidth(contentWidth),
70103
71526
  segments: [
70104
71527
  {
70105
71528
  runIndex,
@@ -70109,7 +71532,6 @@ async function measureParagraphBlock(block, maxWidth) {
70109
71532
  }
70110
71533
  ]
70111
71534
  };
70112
- availableWidth = contentWidth;
70113
71535
  } else {
70114
71536
  currentLine.toRun = runIndex;
70115
71537
  currentLine.toChar = 1;
@@ -70125,6 +71547,7 @@ async function measureParagraphBlock(block, maxWidth) {
70125
71547
  }
70126
71548
  continue;
70127
71549
  }
71550
+ lastFontSize = run2.fontSize;
70128
71551
  const { font } = buildFontString(run2);
70129
71552
  const tabSegments = run2.text.split(" ");
70130
71553
  let charPosInRun = 0;
@@ -70159,7 +71582,7 @@ async function measureParagraphBlock(block, maxWidth) {
70159
71582
  toChar: wordEndNoSpace,
70160
71583
  width: wordOnlyWidth,
70161
71584
  maxFontSize: run2.fontSize,
70162
- maxWidth: availableWidth,
71585
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
70163
71586
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
70164
71587
  };
70165
71588
  const ls = run2.letterSpacing ?? 0;
@@ -70170,7 +71593,6 @@ async function measureParagraphBlock(block, maxWidth) {
70170
71593
  } else {
70171
71594
  charPosInRun = wordEndNoSpace;
70172
71595
  }
70173
- availableWidth = contentWidth;
70174
71596
  continue;
70175
71597
  }
70176
71598
  const isTocEntry = block.attrs?.isTocEntry;
@@ -70192,7 +71614,7 @@ async function measureParagraphBlock(block, maxWidth) {
70192
71614
  toChar: wordEndNoSpace,
70193
71615
  width: wordOnlyWidth,
70194
71616
  maxFontSize: run2.fontSize,
70195
- maxWidth: contentWidth,
71617
+ maxWidth: getEffectiveWidth(contentWidth),
70196
71618
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
70197
71619
  };
70198
71620
  if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth) {
@@ -70248,10 +71670,9 @@ async function measureParagraphBlock(block, maxWidth) {
70248
71670
  toChar: charPosInRun,
70249
71671
  width: 0,
70250
71672
  maxFontSize: run2.fontSize,
70251
- maxWidth: availableWidth,
71673
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
70252
71674
  segments: []
70253
71675
  };
70254
- availableWidth = contentWidth;
70255
71676
  }
70256
71677
  const originX = currentLine.width;
70257
71678
  const { target, nextIndex, stop } = getNextTabStopPx(currentLine.width, tabStops, tabStopCursor);
@@ -70324,7 +71745,8 @@ async function measureParagraphBlock(block, maxWidth) {
70324
71745
  kind: "paragraph",
70325
71746
  lines,
70326
71747
  totalHeight,
70327
- ...markerInfo ? { marker: markerInfo } : {}
71748
+ ...markerInfo ? { marker: markerInfo } : {},
71749
+ ...dropCapMeasure ? { dropCap: dropCapMeasure } : {}
70328
71750
  };
70329
71751
  }
70330
71752
  async function measureTableBlock(block, constraints) {
@@ -70604,7 +72026,7 @@ const getPrimaryRun = (paragraph) => {
70604
72026
  };
70605
72027
  };
70606
72028
  const measureRunWidth = (text, font, ctx2, run2) => {
70607
- const letterSpacing = run2.kind === "text" ? run2.letterSpacing || 0 : 0;
72029
+ const letterSpacing = run2.kind === "text" || run2.kind === void 0 ? run2.letterSpacing || 0 : 0;
70608
72030
  const width = getMeasuredTextWidth(text, font, letterSpacing, ctx2);
70609
72031
  return roundValue(width);
70610
72032
  };
@@ -70640,6 +72062,30 @@ const sanitizeDecimalSeparator = (value) => {
70640
72062
  if (value === ",") return ",";
70641
72063
  return DEFAULT_DECIMAL_SEPARATOR;
70642
72064
  };
72065
+ const DROP_CAP_PADDING_PX = 4;
72066
+ const measureDropCap = (ctx2, descriptor, spacing) => {
72067
+ const { run: run2, lines, mode } = descriptor;
72068
+ const { font } = buildFontString({
72069
+ fontFamily: run2.fontFamily,
72070
+ fontSize: run2.fontSize,
72071
+ bold: run2.bold,
72072
+ italic: run2.italic
72073
+ });
72074
+ ctx2.font = font;
72075
+ const metrics = ctx2.measureText(run2.text);
72076
+ const advanceWidth = metrics.width;
72077
+ const paintedWidth = (metrics.actualBoundingBoxLeft || 0) + (metrics.actualBoundingBoxRight || 0);
72078
+ const textWidth = Math.max(advanceWidth, paintedWidth);
72079
+ const width = roundValue(textWidth + DROP_CAP_PADDING_PX);
72080
+ const baseLineHeight = resolveLineHeight(spacing, run2.fontSize * 1.2);
72081
+ const height = roundValue(baseLineHeight * lines);
72082
+ return {
72083
+ width,
72084
+ height,
72085
+ lines,
72086
+ mode
72087
+ };
72088
+ };
70643
72089
  const resolveIndentLeft = (item) => {
70644
72090
  const indentLeft = sanitizePositive(item.paragraph.attrs?.indent?.left);
70645
72091
  if (indentLeft > 0) {
@@ -71716,10 +73162,7 @@ const _PresentationEditor = class _PresentationEditor2 extends EventEmitter$1 {
71716
73162
  const tr = __privateGet$1(this, _editor3).state.tr.setSelection(TextSelection$1.create(__privateGet$1(this, _editor3).state.doc, hit.pos));
71717
73163
  try {
71718
73164
  __privateGet$1(this, _editor3).view?.dispatch(tr);
71719
- } catch (error) {
71720
- if (process$1$1.env.NODE_ENV === "development") {
71721
- console.warn("[PresentationEditor] Failed to dispatch selection at position:", hit.pos, error);
71722
- }
73165
+ } catch {
71723
73166
  }
71724
73167
  }
71725
73168
  __privateMethod$1(this, _PresentationEditor_instances, scheduleSelectionUpdate_fn).call(this);
@@ -74044,10 +75487,10 @@ computeHeaderFooterCaretRect_fn = function(pos) {
74044
75487
  if (!lineInfo) return null;
74045
75488
  const { line, index: index2 } = lineInfo;
74046
75489
  const range2 = computeLinePmRange$1(block, line);
74047
- if (range2.pmStart == null) return null;
74048
- const charsInLine = Math.max(0, line.toChar - line.fromChar);
74049
- const offsetChars = Math.max(0, Math.min(charsInLine, pos - range2.pmStart));
74050
- const localX = hit.fragment.x + measureCharacterX(block, line, offsetChars);
75490
+ if (range2.pmStart == null || range2.pmEnd == null) return null;
75491
+ const pmCharsInLine = Math.max(1, range2.pmEnd - range2.pmStart);
75492
+ const pmOffset = Math.max(0, Math.min(pmCharsInLine, pos - range2.pmStart));
75493
+ const localX = hit.fragment.x + measureCharacterX(block, line, pmOffset);
74051
75494
  const lineOffset = __privateMethod$1(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, hit.fragment.fromLine, index2);
74052
75495
  const headerPageHeight = context.layout.pageSize?.h ?? context.region.height ?? 1;
74053
75496
  const headerLocalY = hit.pageIndex * headerPageHeight + (hit.fragment.y + lineOffset);
@@ -74187,23 +75630,34 @@ normalizeClientPoint_fn = function(clientX, clientY) {
74187
75630
  computeCaretLayoutRect_fn = function(pos) {
74188
75631
  const layout = __privateGet$1(this, _layoutState).layout;
74189
75632
  if (!layout) return null;
75633
+ const domResult = __privateMethod$1(this, _PresentationEditor_instances, computeCaretLayoutRectFromDOM_fn).call(this, pos);
75634
+ if (domResult) {
75635
+ return domResult;
75636
+ }
74190
75637
  const hit = getFragmentAtPosition(layout, __privateGet$1(this, _layoutState).blocks, __privateGet$1(this, _layoutState).measures, pos);
74191
- if (!hit) return null;
75638
+ if (!hit) {
75639
+ return null;
75640
+ }
74192
75641
  const block = hit.block;
74193
75642
  const measure = hit.measure;
75643
+ if (hit.fragment.kind === "table" && block?.kind === "table" && measure?.kind === "table") {
75644
+ return __privateMethod$1(this, _PresentationEditor_instances, computeTableCaretLayoutRect_fn).call(this, pos, hit.fragment, block, measure, hit.pageIndex);
75645
+ }
74194
75646
  if (!block || block.kind !== "paragraph" || measure?.kind !== "paragraph") return null;
74195
75647
  if (hit.fragment.kind !== "para") {
74196
75648
  return null;
74197
75649
  }
74198
75650
  const fragment = hit.fragment;
74199
75651
  const lineInfo = __privateMethod$1(this, _PresentationEditor_instances, findLineContainingPos_fn).call(this, block, measure, fragment.fromLine, fragment.toLine, pos);
74200
- if (!lineInfo) return null;
75652
+ if (!lineInfo) {
75653
+ return null;
75654
+ }
74201
75655
  const { line, index: index2 } = lineInfo;
74202
75656
  const range2 = computeLinePmRange$1(block, line);
74203
- if (range2.pmStart == null) return null;
74204
- const charsInLine = Math.max(0, line.toChar - line.fromChar);
74205
- const offsetChars = Math.max(0, Math.min(charsInLine, pos - range2.pmStart));
74206
- const localX = fragment.x + measureCharacterX(block, line, offsetChars);
75657
+ if (range2.pmStart == null || range2.pmEnd == null) return null;
75658
+ const pmCharsInLine = Math.max(1, range2.pmEnd - range2.pmStart);
75659
+ const pmOffset = Math.max(0, Math.min(pmCharsInLine, pos - range2.pmStart));
75660
+ const localX = fragment.x + measureCharacterX(block, line, pmOffset);
74207
75661
  const lineOffset = __privateMethod$1(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, fragment.fromLine, index2);
74208
75662
  const localY = fragment.y + lineOffset;
74209
75663
  return {
@@ -74213,17 +75667,167 @@ computeCaretLayoutRect_fn = function(pos) {
74213
75667
  height: line.lineHeight
74214
75668
  };
74215
75669
  };
75670
+ computeCaretLayoutRectFromDOM_fn = function(pos) {
75671
+ const zoom = __privateGet$1(this, _layoutOptions).zoom ?? 1;
75672
+ let targetPageEl = null;
75673
+ if (__privateGet$1(this, _layoutState).layout && __privateGet$1(this, _layoutState).blocks && __privateGet$1(this, _layoutState).measures) {
75674
+ const fragmentHit = getFragmentAtPosition(
75675
+ __privateGet$1(this, _layoutState).layout,
75676
+ __privateGet$1(this, _layoutState).blocks,
75677
+ __privateGet$1(this, _layoutState).measures,
75678
+ pos
75679
+ );
75680
+ if (fragmentHit) {
75681
+ const pageEl = __privateGet$1(this, _viewportHost).querySelector(
75682
+ `.superdoc-page[data-page-index="${fragmentHit.pageIndex}"]`
75683
+ );
75684
+ if (pageEl) {
75685
+ targetPageEl = pageEl;
75686
+ }
75687
+ }
75688
+ }
75689
+ const spanEls = Array.from(
75690
+ targetPageEl ? targetPageEl.querySelectorAll("span[data-pm-start][data-pm-end]") : __privateGet$1(this, _viewportHost).querySelectorAll("span[data-pm-start][data-pm-end]")
75691
+ );
75692
+ for (const spanEl of spanEls) {
75693
+ const pmStart = Number(spanEl.dataset.pmStart ?? "NaN");
75694
+ const pmEnd = Number(spanEl.dataset.pmEnd ?? "NaN");
75695
+ if (!Number.isFinite(pmStart) || !Number.isFinite(pmEnd)) continue;
75696
+ if (pos < pmStart || pos > pmEnd) continue;
75697
+ const pageEl = spanEl.closest(".superdoc-page");
75698
+ if (!pageEl) continue;
75699
+ const pageIndex = Number(pageEl.dataset.pageIndex ?? "0");
75700
+ const pageRect = pageEl.getBoundingClientRect();
75701
+ const textNode = spanEl.firstChild;
75702
+ if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
75703
+ const spanRect2 = spanEl.getBoundingClientRect();
75704
+ return {
75705
+ pageIndex,
75706
+ x: (spanRect2.left - pageRect.left) / zoom,
75707
+ y: (spanRect2.top - pageRect.top) / zoom,
75708
+ height: spanRect2.height / zoom
75709
+ };
75710
+ }
75711
+ const text = textNode.textContent ?? "";
75712
+ const charOffset = Math.max(0, Math.min(text.length, pos - pmStart));
75713
+ const range2 = document.createRange();
75714
+ try {
75715
+ range2.setStart(textNode, charOffset);
75716
+ range2.setEnd(textNode, charOffset);
75717
+ } catch (error) {
75718
+ if (process$1$1.env.NODE_ENV === "development") {
75719
+ console.warn("[PresentationEditor] Range.setStart/setEnd failed:", {
75720
+ error: error instanceof Error ? error.message : String(error),
75721
+ charOffset,
75722
+ textLength: text.length,
75723
+ pos,
75724
+ pmStart,
75725
+ pmEnd
75726
+ });
75727
+ }
75728
+ const spanRect2 = spanEl.getBoundingClientRect();
75729
+ return {
75730
+ pageIndex,
75731
+ x: (spanRect2.left - pageRect.left) / zoom,
75732
+ y: (spanRect2.top - pageRect.top) / zoom,
75733
+ height: spanRect2.height / zoom
75734
+ };
75735
+ }
75736
+ const rangeRect = range2.getBoundingClientRect();
75737
+ const spanRect = spanEl.getBoundingClientRect();
75738
+ const lineEl = spanEl.closest(".superdoc-line");
75739
+ const lineRect = lineEl ? lineEl.getBoundingClientRect() : spanRect;
75740
+ const caretHeight = spanRect.height;
75741
+ const verticalOffset = (lineRect.height - caretHeight) / 2;
75742
+ const caretY = lineRect.top + verticalOffset;
75743
+ return {
75744
+ pageIndex,
75745
+ x: (rangeRect.left - pageRect.left) / zoom,
75746
+ y: (caretY - pageRect.top) / zoom,
75747
+ height: caretHeight / zoom
75748
+ };
75749
+ }
75750
+ return null;
75751
+ };
75752
+ computeTableCaretLayoutRect_fn = function(pos, _fragment, _tableBlock, _tableMeasure, pageIndex) {
75753
+ const lineEls = Array.from(__privateGet$1(this, _viewportHost).querySelectorAll(".superdoc-line"));
75754
+ if (lineEls.length === 0) return null;
75755
+ for (const lineEl of lineEls) {
75756
+ const pmStart = Number(lineEl.dataset.pmStart ?? "NaN");
75757
+ const pmEnd = Number(lineEl.dataset.pmEnd ?? "NaN");
75758
+ if (!Number.isFinite(pmStart) || !Number.isFinite(pmEnd)) continue;
75759
+ if (pos < pmStart || pos > pmEnd) continue;
75760
+ const spanEls = Array.from(lineEl.querySelectorAll("span[data-pm-start]"));
75761
+ for (const spanEl of spanEls) {
75762
+ const spanStart = Number(spanEl.dataset.pmStart ?? "NaN");
75763
+ const spanEnd = Number(spanEl.dataset.pmEnd ?? "NaN");
75764
+ if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) continue;
75765
+ if (pos < spanStart || pos > spanEnd) continue;
75766
+ const textNode = spanEl.firstChild;
75767
+ if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
75768
+ const spanRect = spanEl.getBoundingClientRect();
75769
+ const viewportRect3 = __privateGet$1(this, _viewportHost).getBoundingClientRect();
75770
+ const zoom3 = __privateGet$1(this, _layoutOptions).zoom ?? 1;
75771
+ return {
75772
+ pageIndex,
75773
+ x: (spanRect.left - viewportRect3.left + __privateGet$1(this, _visibleHost).scrollLeft) / zoom3,
75774
+ y: (spanRect.top - viewportRect3.top + __privateGet$1(this, _visibleHost).scrollTop) / zoom3,
75775
+ height: spanRect.height / zoom3
75776
+ };
75777
+ }
75778
+ const text = textNode.textContent ?? "";
75779
+ const charOffset = Math.max(0, Math.min(text.length, pos - spanStart));
75780
+ const range2 = document.createRange();
75781
+ range2.setStart(textNode, charOffset);
75782
+ range2.setEnd(textNode, charOffset);
75783
+ const rangeRect = range2.getBoundingClientRect();
75784
+ const viewportRect2 = __privateGet$1(this, _viewportHost).getBoundingClientRect();
75785
+ const zoom2 = __privateGet$1(this, _layoutOptions).zoom ?? 1;
75786
+ const lineRect2 = lineEl.getBoundingClientRect();
75787
+ return {
75788
+ pageIndex,
75789
+ x: (rangeRect.left - viewportRect2.left + __privateGet$1(this, _visibleHost).scrollLeft) / zoom2,
75790
+ y: (lineRect2.top - viewportRect2.top + __privateGet$1(this, _visibleHost).scrollTop) / zoom2,
75791
+ height: lineRect2.height / zoom2
75792
+ };
75793
+ }
75794
+ const lineRect = lineEl.getBoundingClientRect();
75795
+ const viewportRect = __privateGet$1(this, _viewportHost).getBoundingClientRect();
75796
+ const zoom = __privateGet$1(this, _layoutOptions).zoom ?? 1;
75797
+ return {
75798
+ pageIndex,
75799
+ x: (lineRect.left - viewportRect.left + __privateGet$1(this, _visibleHost).scrollLeft) / zoom,
75800
+ y: (lineRect.top - viewportRect.top + __privateGet$1(this, _visibleHost).scrollTop) / zoom,
75801
+ height: lineRect.height / zoom
75802
+ };
75803
+ }
75804
+ return null;
75805
+ };
74216
75806
  findLineContainingPos_fn = function(block, measure, fromLine, toLine, pos) {
75807
+ const log2 = (...args) => {
75808
+ console.log("[LINE-SEARCH]", ...args);
75809
+ };
75810
+ log2("Searching for pos:", pos, "in lines", fromLine, "to", toLine);
74217
75811
  if (measure.kind !== "paragraph" || block.kind !== "paragraph") return null;
74218
75812
  for (let lineIndex = fromLine; lineIndex < toLine; lineIndex += 1) {
74219
75813
  const line = measure.lines[lineIndex];
74220
75814
  if (!line) continue;
74221
75815
  const range2 = computeLinePmRange$1(block, line);
75816
+ log2("Line", lineIndex, ":", {
75817
+ pmStart: range2.pmStart,
75818
+ pmEnd: range2.pmEnd,
75819
+ fromRun: line.fromRun,
75820
+ toRun: line.toRun,
75821
+ fromChar: line.fromChar,
75822
+ toChar: line.toChar
75823
+ });
74222
75824
  if (range2.pmStart == null || range2.pmEnd == null) continue;
74223
75825
  if (pos >= range2.pmStart && pos <= range2.pmEnd) {
75826
+ log2("Found line", lineIndex, "for pos", pos);
74224
75827
  return { line, index: lineIndex };
74225
75828
  }
74226
75829
  }
75830
+ log2("No line found for pos", pos);
74227
75831
  return null;
74228
75832
  };
74229
75833
  lineHeightBeforeIndex_fn = function(lines, fromLine, targetIndex) {
@@ -87632,6 +89236,49 @@ const ShapeGroup = Node$1.create({
87632
89236
  };
87633
89237
  }
87634
89238
  });
89239
+ const sharedAttributes = () => ({
89240
+ originalName: {
89241
+ default: null
89242
+ },
89243
+ originalXml: {
89244
+ default: null
89245
+ }
89246
+ });
89247
+ const hiddenRender = (type2) => ["sd-passthrough", { "data-sd-passthrough": type2, style: "display: none;" }];
89248
+ const PassthroughBlock = Node$1.create({
89249
+ name: "passthroughBlock",
89250
+ group: "block",
89251
+ atom: true,
89252
+ draggable: false,
89253
+ selectable: false,
89254
+ defining: true,
89255
+ parseDOM() {
89256
+ return [{ tag: 'sd-passthrough[data-sd-passthrough="block"]' }];
89257
+ },
89258
+ renderDOM() {
89259
+ return hiddenRender("block");
89260
+ },
89261
+ addAttributes() {
89262
+ return sharedAttributes();
89263
+ }
89264
+ });
89265
+ const PassthroughInline = Node$1.create({
89266
+ name: "passthroughInline",
89267
+ group: "inline",
89268
+ inline: true,
89269
+ atom: true,
89270
+ draggable: false,
89271
+ selectable: false,
89272
+ parseDOM() {
89273
+ return [{ tag: 'sd-passthrough[data-sd-passthrough="inline"]' }];
89274
+ },
89275
+ renderDOM() {
89276
+ return hiddenRender("inline");
89277
+ },
89278
+ addAttributes() {
89279
+ return sharedAttributes();
89280
+ }
89281
+ });
87635
89282
  const TextStyle = Mark2.create({
87636
89283
  name: "textStyle",
87637
89284
  addOptions() {
@@ -93542,7 +95189,9 @@ const getRichTextExtensions = () => {
93542
95189
  AiPlugin,
93543
95190
  Image,
93544
95191
  NodeResizer,
93545
- CustomSelection
95192
+ CustomSelection,
95193
+ PassthroughInline,
95194
+ PassthroughBlock
93546
95195
  ];
93547
95196
  };
93548
95197
  const getStarterExtensions = () => {
@@ -93614,7 +95263,9 @@ const getStarterExtensions = () => {
93614
95263
  CustomSelection,
93615
95264
  TextTransform,
93616
95265
  VectorShape,
93617
- ShapeGroup
95266
+ ShapeGroup,
95267
+ PassthroughInline,
95268
+ PassthroughBlock
93618
95269
  ];
93619
95270
  };
93620
95271
  const sanitizeNumber = (value, defaultNumber) => {
@@ -109538,7 +111189,7 @@ const _sfc_main$3 = {
109538
111189
  };
109539
111190
  }
109540
111191
  };
109541
- const TableResizeOverlay = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-d4258885"]]);
111192
+ const TableResizeOverlay = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-3f4a506b"]]);
109542
111193
  const _hoisted_1$2 = ["data-handle-position", "onMousedown"];
109543
111194
  const OVERLAY_EXPANSION_PX = 2e3;
109544
111195
  const RESIZE_HANDLE_SIZE_PX = 12;
@@ -110486,98 +112137,6 @@ const _sfc_main = {
110486
112137
  }
110487
112138
  };
110488
112139
  const SuperInput = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-4d5cff52"]]);
110489
- const additionalHandlers = Object.freeze({
110490
- "mc:AlternateContent": translator$1M,
110491
- "sd:pageReference": translator$6,
110492
- "sd:tableOfContents": translator$5,
110493
- "w:b": translator$20,
110494
- "w:bCs": translator$1$,
110495
- "w:bidiVisual": translator$q,
110496
- "w:bookmarkEnd": translator$7,
110497
- "w:bookmarkStart": translator$8,
110498
- "w:bottom": translator$1p,
110499
- "w:br": translator$23,
110500
- "w:cantSplit": translator$F,
110501
- "w:caps": translator$1R,
110502
- "w:cnfStyle": translator$1H,
110503
- "w:color": translator$1W,
110504
- "w:divId": translator$1F,
110505
- "w:drawing": translator$s,
110506
- "w:end": translator$X,
110507
- "w:gridAfter": translator$E,
110508
- "w:gridBefore": translator$D,
110509
- "w:gridCol": translator$b,
110510
- "w:hidden": translator$C,
110511
- "w:highlight": translator$22,
110512
- "w:hyperlink": translator$10,
110513
- "w:i": translator$1_,
110514
- "w:insideH": translator$V,
110515
- "w:insideV": translator$U,
110516
- "w:jc": translator$1C,
110517
- "w:left": translator$1n,
110518
- "w:p": translator$11,
110519
- "w:r": translator$$,
110520
- "w:rFonts": translator$1V,
110521
- "w:rPr": translator$1N,
110522
- "w:rStyle": translator$1U,
110523
- "w:right": translator$1l,
110524
- "w:sdt": translator$r,
110525
- "w:shd": translator$1Q,
110526
- "w:start": translator$T,
110527
- "w:strike": translator$1Y,
110528
- "w:sz": translator$1T,
110529
- "w:szCs": translator$1S,
110530
- "w:tab": translator$21,
110531
- "w:tbl": translator$9,
110532
- "w:tblBorders": translator$e,
110533
- "w:tblCaption": translator$p,
110534
- "w:tblCellMar": translator$d,
110535
- "w:tblCellSpacing": translator$B,
110536
- "w:tblDescription": translator$o,
110537
- "w:tblGrid": translator$a,
110538
- "w:tblHeader": translator$A,
110539
- "w:tblInd": translator$n,
110540
- "w:tblLayout": translator$m,
110541
- "w:tblLook": translator$l,
110542
- "w:tblOverlap": translator$k,
110543
- "w:tblPr": translator$c,
110544
- "w:tblStyle": translator$j,
110545
- "w:tblStyleColBandSize": translator$i,
110546
- "w:tblStyleRowBandSize": translator$h,
110547
- "w:tblW": translator$g,
110548
- "w:tblpPr": translator$f,
110549
- "w:tc": translator$G,
110550
- "w:top": translator$1j,
110551
- "w:tr": translator$v,
110552
- "w:trHeight": translator$z,
110553
- "w:trPr": translator$w,
110554
- "w:u": translator$1Z,
110555
- "w:wAfter": translator$y,
110556
- "w:wBefore": translator$x,
110557
- "wp:anchor": translator$u,
110558
- "wp:inline": translator$t,
110559
- "w:commentRangeStart": commentRangeStartTranslator,
110560
- "w:commentRangeEnd": commentRangeEndTranslator,
110561
- "w:vMerge": translator$Y,
110562
- "w:gridSpan": translator$Z,
110563
- "w:vAlign": translator$L,
110564
- "w:noWrap": translator$O,
110565
- "w:tcFitText": translator$M,
110566
- "w:tcW": translator$_,
110567
- "w:hideMark": translator$K,
110568
- "w:textDirection": translator$17,
110569
- "w:tl2br": translator$R,
110570
- "w:tr2bl": translator$Q,
110571
- "w:header": translator$J,
110572
- "w:headers": translator$I,
110573
- "w:tcBorders": translator$P,
110574
- "w:tcMar": translator$N,
110575
- "w:tcPr": translator$H
110576
- });
110577
- const baseHandlers = {
110578
- ...additionalHandlers
110579
- };
110580
- const registeredHandlers = Object.freeze(baseHandlers);
110581
112140
  const Extensions = {
110582
112141
  Node: Node$1,
110583
112142
  Attribute: Attribute2,