@stll/folio-core 0.61.0 → 0.62.0

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 (59) hide show
  1. package/dist/ai-edits/headless.js +13 -12
  2. package/dist/controller/noteEditorManager.d.ts +1 -1
  3. package/dist/display-list/build/imagePrimitives.js +26 -7
  4. package/dist/display-list/build/paragraphPrimitives.js +15 -2
  5. package/dist/display-list/dom/renderDisplayListToDom.js +8 -5
  6. package/dist/display-list/types.d.ts +7 -3
  7. package/dist/docx/groupDrawingParser.js +22 -12
  8. package/dist/i18n/messages/ar.gen.js +1 -0
  9. package/dist/i18n/messages/catalogs.gen.d.ts +17 -0
  10. package/dist/i18n/messages/catalogs.gen.js +17 -0
  11. package/dist/i18n/messages/cs.gen.js +1 -0
  12. package/dist/i18n/messages/de.gen.js +1 -0
  13. package/dist/i18n/messages/en.gen.js +1 -0
  14. package/dist/i18n/messages/es.gen.js +1 -0
  15. package/dist/i18n/messages/et.gen.js +1 -0
  16. package/dist/i18n/messages/fr.gen.js +1 -0
  17. package/dist/i18n/messages/he.gen.js +1 -0
  18. package/dist/i18n/messages/hi.gen.js +1 -0
  19. package/dist/i18n/messages/hu.gen.js +1 -0
  20. package/dist/i18n/messages/lt.gen.js +1 -0
  21. package/dist/i18n/messages/lv.gen.js +1 -0
  22. package/dist/i18n/messages/messages.gen.d.ts +1 -0
  23. package/dist/i18n/messages/pl.gen.js +1 -0
  24. package/dist/i18n/messages/pt-BR.gen.js +1 -0
  25. package/dist/i18n/messages/sk.gen.js +1 -0
  26. package/dist/i18n/messages/tr.gen.js +1 -0
  27. package/dist/i18n/messages/zh-CN.gen.js +1 -0
  28. package/dist/layout-bridge/convert/endnoteLayout.d.ts +1 -1
  29. package/dist/layout-bridge/convert/endnoteLayout.js +1 -3
  30. package/dist/layout-engine/index.js +2 -2
  31. package/dist/layout-engine/noteAreaFlow.d.ts +4 -4
  32. package/dist/layout-engine/noteAreaFlow.js +12 -6
  33. package/dist/layout-engine/types.d.ts +5 -2
  34. package/dist/layout-painter/index.d.ts +1 -1
  35. package/dist/managers/FindReplaceManager.d.ts +13 -6
  36. package/dist/managers/FindReplaceManager.js +15 -9
  37. package/dist/paged-layout/editorScrollRoot.d.ts +3 -1
  38. package/dist/paged-layout/editorScrollRoot.js +2 -2
  39. package/dist/pdf/images.js +1 -0
  40. package/dist/prosemirror/commentRangeInlineAtoms.d.ts +40 -0
  41. package/dist/prosemirror/commentRangeInlineAtoms.js +33 -0
  42. package/dist/prosemirror/conversion/fromProseDoc.js +5 -4
  43. package/dist/prosemirror/conversion/toProseDoc.js +12 -19
  44. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +4 -4
  45. package/dist/prosemirror/fieldRepresentation.js +4 -2
  46. package/dist/prosemirror/findReplaceSelection.d.ts +38 -2
  47. package/dist/prosemirror/findReplaceSelection.js +143 -42
  48. package/dist/prosemirror/inlineDisplayText.d.ts +10 -0
  49. package/dist/prosemirror/inlineDisplayText.js +29 -0
  50. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -1
  51. package/dist/prosemirror/trackedRunInlineAtoms.js +1 -1
  52. package/dist/utils/findMatchView.d.ts +32 -0
  53. package/dist/utils/findMatchView.js +406 -0
  54. package/dist/utils/findReplace.d.ts +62 -4
  55. package/dist/utils/findReplace.js +359 -37
  56. package/dist/utils/findSearchKey.d.ts +29 -0
  57. package/dist/utils/findSearchKey.js +34 -0
  58. package/dist/utils/replaceText.js +138 -111
  59. package/package.json +1 -1
@@ -1,15 +1,17 @@
1
1
  import "./extensions/marks/InlineWrapperExtension.js";
2
+ import { getInlineDisplayText } from "./inlineDisplayText.js";
2
3
  //#region src/prosemirror/fieldRepresentation.ts
3
4
  /** Current children alone decide whether a field needs editable structural content. */
4
5
  const fieldRequiresStructuredContent = (children) => children.some((child) => !child.isText || child.marks.some((mark) => mark.type.name === "hyperlink" || mark.type.name === "inlineWrapper" || mark.type.name === "insertion" || mark.type.name === "deletion"));
5
6
  /** Resolution returns text-only fields to the same atom representation as initial conversion. */
6
7
  const canonicalFieldNode = (node) => {
7
8
  if (node.type.name !== "structuredField") return node;
9
+ const displayText = getInlineDisplayText(node);
8
10
  const attrs = {
9
11
  ...node.attrs,
10
- displayText: node.textContent
12
+ displayText
11
13
  };
12
- if (fieldRequiresStructuredContent(node.content.content)) return node.attrs["displayText"] === node.textContent ? node : node.type.create(attrs, node.content, node.marks);
14
+ if (fieldRequiresStructuredContent(node.content.content)) return node.attrs["displayText"] === displayText ? node : node.type.create(attrs, node.content, node.marks);
13
15
  let marks = node.marks;
14
16
  for (const mark of node.firstChild?.marks ?? []) marks = mark.addToSet(marks);
15
17
  return node.type.schema.node("field", attrs, void 0, marks);
@@ -1,5 +1,6 @@
1
+ import { document_d_exports } from "../types/document.js";
1
2
  import { DisplayMode } from "../managers/EditorModeManager.js";
2
- import { FindOptions } from "../utils/findReplace.js";
3
+ import { FindMatch, FindOptions, FindSearchContext } from "../utils/findReplace.js";
3
4
  import { Node } from "prosemirror-model";
4
5
  import { EditorState } from "prosemirror-state";
5
6
  //#region src/prosemirror/findReplaceSelection.d.ts
@@ -22,11 +23,25 @@ type FindMatchPosition = {
22
23
  type FindMatchRange = {
23
24
  from: number;
24
25
  to: number;
26
+ /** Navigation anchors inside a logical match are excluded from decorations. */
27
+ excludedRanges?: {
28
+ from: number;
29
+ to: number;
30
+ }[];
31
+ /** Character subranges inside source atoms, whose text exceeds their PM size. */
32
+ atomicTextRanges?: {
33
+ from: number;
34
+ to: number;
35
+ startOffset: number;
36
+ endOffset: number;
37
+ }[];
25
38
  };
26
39
  type ProseMirrorFindMatch = FindMatchPosition & FindMatchRange & {
27
40
  text: string;
28
41
  };
29
42
  declare function resolveFindMatchRange(doc: Node, match: FindMatchPosition): FindMatchRange | null;
43
+ /** Resolve a result set in one paragraph traversal, preserving result order. */
44
+ declare const resolveFindMatchRanges: (doc: Node, matches: readonly FindMatchPosition[]) => (FindMatchRange | null)[];
30
45
  declare function findInProseMirrorDocument(doc: Node, searchText: string, options: FindOptions): ProseMirrorFindMatch[];
31
46
  type FindInMarkupViewOptions = {
32
47
  state: EditorState;
@@ -36,5 +51,26 @@ type FindInMarkupViewOptions = {
36
51
  };
37
52
  /** Search the displayed story; returned ranges address the authored editor document. */
38
53
  declare const findInMarkupView: ({ state, markupView, searchText, options }: FindInMarkupViewOptions) => ProseMirrorFindMatch[];
54
+ type FindInDisplayedDocumentOptions = {
55
+ document: document_d_exports.Document;
56
+ /**
57
+ * Live body editor state. A review view reads its body from this state's
58
+ * projection, so null defers that search until the body editor mounts.
59
+ * Hosts without an editor state omit it and search the package model.
60
+ */
61
+ state?: EditorState | null | undefined;
62
+ searchText: string;
63
+ options: FindOptions;
64
+ context?: FindSearchContext | undefined;
65
+ };
66
+ /**
67
+ * Search every story a display mode shows. All Markup searches the package
68
+ * stories. A resolved review view searches its body through the projection the
69
+ * layout paints, so body ranges address the authored editor document; anchored
70
+ * shapes, headers, footers, notes and comments keep the package search owner
71
+ * with the same display mode. Returns null while a review view has no body
72
+ * editor state to project.
73
+ */
74
+ declare const findInDisplayedDocument: ({ document, state, searchText, options, context }: FindInDisplayedDocumentOptions) => FindMatch[] | null;
39
75
  //#endregion
40
- export { FindMatchPosition, FindMatchRange, ProseMirrorFindMatch, findInMarkupView, findInProseMirrorDocument, resolveFindMatchRange };
76
+ export { FindMatchPosition, FindMatchRange, ProseMirrorFindMatch, findInDisplayedDocument, findInMarkupView, findInProseMirrorDocument, resolveFindMatchRange, resolveFindMatchRanges };
@@ -1,6 +1,6 @@
1
- import { findAllMatches } from "../utils/findReplace.js";
2
- import { decodeOoxmlSymbolCharacter } from "../utils/ooxmlSymbol.js";
3
- import { expectSymbolAttrs } from "./attrs/index.js";
1
+ import { findAllMatches, findInDocument, isPageDependentSearchField } from "../utils/findReplace.js";
2
+ import { expectFieldAttrs } from "./attrs/index.js";
3
+ import { getInlineDisplayText, getInlineDisplayToken, isNoteReferenceText } from "./inlineDisplayText.js";
4
4
  import { projectMarkupView } from "./markupViewProjection.js";
5
5
  //#region src/prosemirror/findReplaceSelection.ts
6
6
  function resolveFindMatchRange(doc, match) {
@@ -17,11 +17,29 @@ function resolveFindMatchRange(doc, match) {
17
17
  });
18
18
  return resolved;
19
19
  }
20
+ /** Resolve a result set in one paragraph traversal, preserving result order. */
21
+ const resolveFindMatchRanges = (doc, matches) => {
22
+ const paragraphs = /* @__PURE__ */ new Map();
23
+ forEachSearchParagraph(doc, (paragraph, paragraphPos, paragraphIndex) => {
24
+ paragraphs.set(paragraphIndex, {
25
+ paragraph,
26
+ paragraphPos
27
+ });
28
+ return true;
29
+ });
30
+ return matches.map((match) => {
31
+ const paragraph = paragraphs.get(match.paragraphIndex);
32
+ return paragraph ? resolveTextRangeInParagraph({
33
+ ...paragraph,
34
+ ...match
35
+ }) : null;
36
+ });
37
+ };
20
38
  function findInProseMirrorDocument(doc, searchText, options) {
21
39
  if (!searchText) return [];
22
40
  const matches = [];
23
41
  forEachSearchParagraph(doc, (paragraph, paragraphPos, paragraphIndex) => {
24
- const text = getSearchableParagraphText(paragraph);
42
+ const text = getInlineDisplayText(paragraph);
25
43
  for (const { start, end } of findAllMatches(text, searchText, options)) {
26
44
  const range = resolveTextRangeInParagraph({
27
45
  paragraph,
@@ -45,14 +63,95 @@ function findInProseMirrorDocument(doc, searchText, options) {
45
63
  const findInMarkupView = ({ state, markupView, searchText, options }) => {
46
64
  const projection = projectMarkupView(state, markupView);
47
65
  if (projection.type === "authored") return findInProseMirrorDocument(state.doc, searchText, options);
48
- return findInProseMirrorDocument(projection.doc, searchText, options).map((match) => ({
66
+ return findInProseMirrorDocument(projection.doc, searchText, options).map((match) => toAuthoredFindMatch(projection, match));
67
+ };
68
+ /** Every view-document position a match carries, mapped to the authored editor document. */
69
+ const toAuthoredFindMatch = (projection, match) => {
70
+ const toEditorRange = ({ from, to }) => ({
71
+ from: projection.toEditor(from, 1),
72
+ to: projection.toEditor(to, -1)
73
+ });
74
+ return {
49
75
  paragraphIndex: match.paragraphIndex,
50
76
  startOffset: match.startOffset,
51
77
  endOffset: match.endOffset,
52
78
  text: match.text,
53
- from: projection.toEditor(match.from, 1),
54
- to: projection.toEditor(match.to, -1)
55
- }));
79
+ ...toEditorRange(match),
80
+ ...match.excludedRanges && { excludedRanges: match.excludedRanges.map(toEditorRange) },
81
+ ...match.atomicTextRanges && { atomicTextRanges: match.atomicTextRanges.map((atom) => ({
82
+ ...toEditorRange(atom),
83
+ startOffset: atom.startOffset,
84
+ endOffset: atom.endOffset
85
+ })) }
86
+ };
87
+ };
88
+ /** Replacement policy for a projected body match, in the shared eligibility vocabulary. */
89
+ const projectedReplacement = (state, viewMatch, authored) => {
90
+ const atom = authored.atomicTextRanges?.at(0);
91
+ if (atom) return {
92
+ status: "blocked",
93
+ reason: state.doc.nodeAt(atom.from)?.type.name === "field" ? "field-result" : "atomic-content"
94
+ };
95
+ return authored.to - authored.from === viewMatch.to - viewMatch.from ? { status: "allowed" } : {
96
+ status: "blocked",
97
+ reason: "hidden-content"
98
+ };
99
+ };
100
+ /**
101
+ * Search every story a display mode shows. All Markup searches the package
102
+ * stories. A resolved review view searches its body through the projection the
103
+ * layout paints, so body ranges address the authored editor document; anchored
104
+ * shapes, headers, footers, notes and comments keep the package search owner
105
+ * with the same display mode. Returns null while a review view has no body
106
+ * editor state to project.
107
+ */
108
+ const findInDisplayedDocument = ({ document, state, searchText, options, context }) => {
109
+ const displayMode = options.displayMode ?? "all-markup";
110
+ if (displayMode === "all-markup" || state === void 0) return findInDocument(document, searchText, options, context);
111
+ if (state === null) return null;
112
+ const packageMatches = findInDocument(document, searchText, options, context);
113
+ const projection = projectMarkupView(state, displayMode);
114
+ if (projection.type === "authored" || !searchText) return packageMatches;
115
+ const bodyMatches = findInProseMirrorDocument(projection.doc, searchText, options).map((viewMatch) => {
116
+ const authored = toAuthoredFindMatch(projection, viewMatch);
117
+ const { from, to, excludedRanges, atomicTextRanges } = authored;
118
+ return {
119
+ paragraphIndex: authored.paragraphIndex,
120
+ contentIndex: 0,
121
+ startOffset: authored.startOffset,
122
+ endOffset: authored.endOffset,
123
+ text: authored.text,
124
+ story: "main",
125
+ replacement: projectedReplacement(state, viewMatch, authored),
126
+ authoredRange: {
127
+ from,
128
+ to,
129
+ ...excludedRanges && { excludedRanges },
130
+ ...atomicTextRanges && { atomicTextRanges }
131
+ }
132
+ };
133
+ });
134
+ const anchorEnds = [];
135
+ forEachSearchParagraph(state.doc, (paragraph, paragraphPos, paragraphIndex) => {
136
+ anchorEnds[paragraphIndex] = paragraphPos + paragraph.nodeSize;
137
+ return true;
138
+ });
139
+ const bodyShapeMatches = packageMatches.filter((match) => match.story === "main" && match.textBoxIndex !== void 0);
140
+ const orderedBody = [];
141
+ let shapeIndex = 0;
142
+ const shapeAnchorEnd = (match) => match.anchorParagraphIndex !== void 0 && anchorEnds[match.anchorParagraphIndex] || Number.POSITIVE_INFINITY;
143
+ for (const bodyMatch of bodyMatches) {
144
+ const from = bodyMatch.authoredRange?.from ?? 0;
145
+ while (shapeIndex < bodyShapeMatches.length) {
146
+ const shapeMatch = bodyShapeMatches[shapeIndex];
147
+ if (!shapeMatch || shapeAnchorEnd(shapeMatch) > from) break;
148
+ orderedBody.push(shapeMatch);
149
+ shapeIndex++;
150
+ }
151
+ orderedBody.push(bodyMatch);
152
+ }
153
+ orderedBody.push(...bodyShapeMatches.slice(shapeIndex));
154
+ return [...orderedBody, ...packageMatches.filter((match) => match.story !== "main" || match.textBoxIndex === void 0 && match.commentId !== void 0)];
56
155
  };
57
156
  function forEachSearchParagraph(doc, visit) {
58
157
  let paragraphIndex = 0;
@@ -103,54 +202,56 @@ function resolveTextRangeInParagraph({ paragraph, paragraphPos, startOffset, end
103
202
  to: null
104
203
  };
105
204
  const pageBreakOffsets = [];
205
+ const excludedTextRanges = [];
206
+ const excludedRanges = [];
207
+ const atomicTextRanges = [];
106
208
  paragraph.descendants((node, pos) => {
209
+ if ((node.type.name === "field" || node.type.name === "structuredField") && isPageDependentSearchField(expectFieldAttrs(node).instruction)) {
210
+ const length = node.type.name === "field" ? expectFieldAttrs(node).displayText.length : getInlineDisplayText(node).length;
211
+ excludedTextRanges.push({
212
+ start: textOffset,
213
+ end: textOffset + length
214
+ });
215
+ }
107
216
  if (node.type.name === "pageBreakRun") {
108
217
  pageBreakOffsets.push(textOffset);
109
218
  return false;
110
219
  }
220
+ if (isNoteReferenceText(node)) {
221
+ const from = paragraphPos + 1 + pos;
222
+ excludedRanges.push({
223
+ from,
224
+ to: from + node.nodeSize
225
+ });
226
+ }
111
227
  const tokenLength = getSearchTextTokenLength(node);
112
228
  if (tokenLength === 0) return true;
113
229
  const textStart = textOffset;
114
230
  const textEnd = textStart + tokenLength;
115
231
  const nodeStart = paragraphPos + 1 + pos;
116
- if (range.from === null && startOffset >= textStart && startOffset < textEnd) range.from = nodeStart + Math.min(startOffset - textStart, node.nodeSize);
117
- if (range.to === null && endOffset > textStart && endOffset <= textEnd) range.to = nodeStart + Math.min(endOffset - textStart, node.nodeSize);
232
+ const atomic = node.type.name === "field" || node.type.name === "preservedXml";
233
+ if (atomic && textStart < endOffset && textEnd > startOffset) atomicTextRanges.push({
234
+ from: nodeStart,
235
+ to: nodeStart + node.nodeSize,
236
+ startOffset: Math.max(0, startOffset - textStart),
237
+ endOffset: Math.min(tokenLength, endOffset - textStart)
238
+ });
239
+ if (range.from === null && startOffset >= textStart && startOffset < textEnd) range.from = atomic ? nodeStart : nodeStart + Math.min(startOffset - textStart, node.nodeSize);
240
+ if (range.to === null && endOffset > textStart && endOffset <= textEnd) range.to = atomic ? nodeStart + node.nodeSize : nodeStart + Math.min(endOffset - textStart, node.nodeSize);
118
241
  textOffset = textEnd;
119
242
  return range.to === null;
120
243
  });
121
- if (range.from === null || range.to === null || range.from >= range.to || pageBreakOffsets.some((offset) => offset > startOffset && offset < endOffset)) return null;
244
+ if (range.from === null || range.to === null || range.from >= range.to || pageBreakOffsets.some((offset) => offset > startOffset && offset < endOffset) || excludedTextRanges.some(({ start, end }) => start < endOffset && end > startOffset)) return null;
245
+ const from = range.from;
246
+ const to = range.to;
247
+ const visibleExcludedRanges = excludedRanges.filter((anchor) => anchor.from < to && anchor.to > from);
122
248
  return {
123
- from: range.from,
124
- to: range.to
249
+ from,
250
+ to,
251
+ ...atomicTextRanges.length > 0 && { atomicTextRanges },
252
+ ...visibleExcludedRanges.length > 0 && { excludedRanges: visibleExcludedRanges }
125
253
  };
126
254
  }
127
- function getSearchTextTokenLength(node) {
128
- if (node.isText) return node.text?.length ?? 0;
129
- if (node.type.name === "tab" || node.type.name === "hardBreak" || node.type.name === "symbol") return 1;
130
- return 0;
131
- }
132
- function getSearchableParagraphText(paragraph) {
133
- let text = "";
134
- paragraph.descendants((node) => {
135
- if (node.isText) {
136
- text += node.text ?? "";
137
- return false;
138
- }
139
- if (node.type.name === "tab") {
140
- text += " ";
141
- return false;
142
- }
143
- if (node.type.name === "hardBreak") {
144
- text += "\n";
145
- return false;
146
- }
147
- if (node.type.name === "symbol") {
148
- text += decodeOoxmlSymbolCharacter(expectSymbolAttrs(node).char) ?? "";
149
- return false;
150
- }
151
- return true;
152
- });
153
- return text;
154
- }
255
+ const getSearchTextTokenLength = (node) => getInlineDisplayToken(node)?.length ?? 0;
155
256
  //#endregion
156
- export { findInMarkupView, findInProseMirrorDocument, resolveFindMatchRange };
257
+ export { findInDisplayedDocument, findInMarkupView, findInProseMirrorDocument, resolveFindMatchRange, resolveFindMatchRanges };
@@ -0,0 +1,10 @@
1
+ import { Node } from "prosemirror-model";
2
+ //#region src/prosemirror/inlineDisplayText.d.ts
3
+ /** Native note-reference labels are navigation anchors, outside searchable text. */
4
+ declare const isNoteReferenceText: (node: Node) => boolean;
5
+ /** A leaf's logical text; null means a transparent container to descend into. */
6
+ declare const getInlineDisplayToken: (node: Node) => string | null;
7
+ /** Visible inline text, including cached source atoms and native run tokens. */
8
+ declare const getInlineDisplayText: (paragraph: Node) => string;
9
+ //#endregion
10
+ export { getInlineDisplayText, getInlineDisplayToken, isNoteReferenceText };
@@ -0,0 +1,29 @@
1
+ import { decodeOoxmlSymbolCharacter } from "../utils/ooxmlSymbol.js";
2
+ import { expectFieldAttrs, expectPreservedXmlAttrs, expectSymbolAttrs } from "./attrs/index.js";
3
+ //#region src/prosemirror/inlineDisplayText.ts
4
+ /** Native note-reference labels are navigation anchors, outside searchable text. */
5
+ const isNoteReferenceText = (node) => node.isText && node.marks.some((mark) => mark.type.name === "footnoteRef");
6
+ /** A leaf's logical text; null means a transparent container to descend into. */
7
+ const getInlineDisplayToken = (node) => {
8
+ if (isNoteReferenceText(node)) return "";
9
+ if (node.type.name === "field") return expectFieldAttrs(node).displayText;
10
+ if (node.type.name === "preservedXml") return expectPreservedXmlAttrs(node).text;
11
+ if (node.isText) return node.text ?? "";
12
+ if (node.type.name === "tab") return " ";
13
+ if (node.type.name === "hardBreak") return "\n";
14
+ if (node.type.name === "symbol") return decodeOoxmlSymbolCharacter(expectSymbolAttrs(node).char) ?? "";
15
+ return null;
16
+ };
17
+ /** Visible inline text, including cached source atoms and native run tokens. */
18
+ const getInlineDisplayText = (paragraph) => {
19
+ let text = "";
20
+ paragraph.descendants((node) => {
21
+ const token = getInlineDisplayToken(node);
22
+ if (token === null) return true;
23
+ text += token;
24
+ return false;
25
+ });
26
+ return text;
27
+ };
28
+ //#endregion
29
+ export { getInlineDisplayText, getInlineDisplayToken, isNoteReferenceText };
@@ -21,7 +21,7 @@ declare const TRACKED_RUN_INLINE_ATOM_DISPOSITIONS: Readonly<{
21
21
  readonly pageBreakRun: "page-break-carrier";
22
22
  readonly preservedXml: "carry";
23
23
  readonly rangeAnchor: "transparent";
24
- readonly renderedPageBreak: "transparent";
24
+ readonly renderedPageBreak: "carry";
25
25
  readonly shape: "carry";
26
26
  readonly structuredField: "carry";
27
27
  readonly symbol: "carry";
@@ -20,7 +20,7 @@ const TRACKED_RUN_INLINE_ATOM_DISPOSITIONS = Object.freeze({
20
20
  pageBreakRun: "page-break-carrier",
21
21
  preservedXml: "carry",
22
22
  rangeAnchor: "transparent",
23
- renderedPageBreak: "transparent",
23
+ renderedPageBreak: "carry",
24
24
  shape: "carry",
25
25
  structuredField: "carry",
26
26
  symbol: "carry",
@@ -0,0 +1,32 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ import { Layout } from "../layout-engine/types.js";
3
+ import { FindMatch } from "./findReplace.js";
4
+ import { FindMatchRange } from "../prosemirror/findReplaceSelection.js";
5
+ import { Node } from "prosemirror-model";
6
+ import { OpStory } from "@stll/docx-core/ops";
7
+ //#region src/utils/findMatchView.d.ts
8
+ /** The same page variant selection used by the painter, including unmounted pages. */
9
+ declare const getRenderedSearchStories: (layout: Layout | null) => OpStory[];
10
+ type ResolvedMatch = FindMatchRange & {
11
+ index: number;
12
+ story: OpStory;
13
+ };
14
+ type FindMatchViewOptions = {
15
+ container: HTMLElement;
16
+ document: document_d_exports.Document;
17
+ bodyDoc?: Node | undefined;
18
+ matches: readonly FindMatch[];
19
+ commentRoot?: HTMLElement | undefined;
20
+ layout?: Layout | null | undefined;
21
+ };
22
+ /** Resolve each story once; box positions are local to their parent story. */
23
+ declare const resolveDocumentFindRanges: ({ document, bodyDoc, matches }: Omit<FindMatchViewOptions, "container" | "commentRoot" | "layout">) => ResolvedMatch[];
24
+ /** Paint search geometry over the existing page DOM, without changing editor state. */
25
+ declare const createFindMatchView: (options: FindMatchViewOptions) => {
26
+ paint: (index: number) => void;
27
+ reveal: (index: number) => boolean;
28
+ navigate: (index: number, activateComment?: (commentId: number) => void) => void;
29
+ destroy: () => void;
30
+ };
31
+ //#endregion
32
+ export { createFindMatchView, getRenderedSearchStories, resolveDocumentFindRanges };