@stll/folio-core 0.49.0 → 0.51.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 (107) hide show
  1. package/dist/ai-edits/headless.d.ts +37 -1
  2. package/dist/ai-edits/headless.js +47 -16
  3. package/dist/ai-edits/word-diff.js +134 -1
  4. package/dist/compare/content-alignment.js +220 -5
  5. package/dist/compare/content.d.ts +1 -0
  6. package/dist/compare/content.js +51 -20
  7. package/dist/display-list/dom/renderDisplayListToDom.d.ts +10 -1
  8. package/dist/display-list/dom/renderDisplayListToDom.js +8 -7
  9. package/dist/display-list/html/renderDisplayListToHtml.d.ts +21 -0
  10. package/dist/display-list/html/renderDisplayListToHtml.js +126 -0
  11. package/dist/display-list/selectDisplayPages.d.ts +6 -0
  12. package/dist/display-list/selectDisplayPages.js +44 -0
  13. package/dist/docx/selectiveSave.d.ts +1 -1
  14. package/dist/docx/selectiveSave.js +16 -6
  15. package/dist/docx/structuralXmlPatch.d.ts +14 -0
  16. package/dist/docx/structuralXmlPatch.js +209 -0
  17. package/dist/export-pdf.d.ts +35 -2
  18. package/dist/export-pdf.js +51 -20
  19. package/dist/fonts/fontsourceFaces.d.ts +47 -0
  20. package/dist/fonts/fontsourceFaces.js +230 -0
  21. package/dist/layout-bridge/convert/flowBlockPostprocessing.d.ts +8 -0
  22. package/dist/layout-bridge/convert/flowBlockPostprocessing.js +106 -0
  23. package/dist/layout-bridge/convert/flowBorders.d.ts +17 -0
  24. package/dist/layout-bridge/convert/flowBorders.js +31 -0
  25. package/dist/layout-bridge/convert/flowConversionShared.d.ts +111 -0
  26. package/dist/layout-bridge/convert/flowConversionShared.js +23 -0
  27. package/dist/layout-bridge/convert/footnoteLayout.d.ts +2 -1
  28. package/dist/layout-bridge/convert/footnoteLayout.js +2 -1
  29. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +2 -1
  30. package/dist/layout-bridge/convert/imageConversion.d.ts +33 -0
  31. package/dist/layout-bridge/convert/imageConversion.js +118 -0
  32. package/dist/layout-bridge/convert/listMarkers.d.ts +28 -0
  33. package/dist/layout-bridge/convert/listMarkers.js +98 -0
  34. package/dist/layout-bridge/convert/noteReferences.d.ts +14 -0
  35. package/dist/layout-bridge/convert/noteReferences.js +29 -0
  36. package/dist/layout-bridge/convert/pageBreakSplitting.d.ts +16 -0
  37. package/dist/layout-bridge/convert/pageBreakSplitting.js +140 -0
  38. package/dist/layout-bridge/convert/paragraphAttrs.d.ts +20 -0
  39. package/dist/layout-bridge/convert/paragraphAttrs.js +234 -0
  40. package/dist/layout-bridge/convert/paragraphConversion.d.ts +12 -0
  41. package/dist/layout-bridge/convert/paragraphConversion.js +112 -0
  42. package/dist/layout-bridge/convert/paragraphRuns.d.ts +15 -0
  43. package/dist/layout-bridge/convert/paragraphRuns.js +281 -0
  44. package/dist/layout-bridge/convert/runFormattingMerge.d.ts +19 -0
  45. package/dist/layout-bridge/convert/runFormattingMerge.js +167 -0
  46. package/dist/layout-bridge/convert/runMarkFormatting.d.ts +11 -0
  47. package/dist/layout-bridge/convert/runMarkFormatting.js +291 -0
  48. package/dist/layout-bridge/convert/sectionBoundaries.d.ts +35 -0
  49. package/dist/layout-bridge/convert/sectionBoundaries.js +114 -0
  50. package/dist/layout-bridge/convert/tableConversion.d.ts +12 -0
  51. package/dist/layout-bridge/convert/tableConversion.js +303 -0
  52. package/dist/layout-bridge/convert/textBoxFill.d.ts +20 -0
  53. package/dist/layout-bridge/convert/textBoxFill.js +42 -0
  54. package/dist/layout-bridge/convert/textFormattingConversion.d.ts +22 -0
  55. package/dist/layout-bridge/convert/textFormattingConversion.js +120 -0
  56. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +5 -113
  57. package/dist/layout-bridge/convert/toFlowBlocks.js +11 -2082
  58. package/dist/layout-bridge/engine/hitTest.js +1 -1
  59. package/dist/layout-bridge/engine/measuring/index.d.ts +2 -1
  60. package/dist/layout-bridge/engine/measuring/index.js +2 -1
  61. package/dist/layout-bridge/engine/selectionRects.js +1 -1
  62. package/dist/layout-engine/imageLayout.d.ts +9 -0
  63. package/dist/layout-engine/imageLayout.js +48 -0
  64. package/dist/layout-engine/index.d.ts +3 -18
  65. package/dist/layout-engine/index.js +12 -937
  66. package/dist/layout-engine/layoutFlowShared.d.ts +6 -0
  67. package/dist/layout-engine/layoutFlowShared.js +8 -0
  68. package/dist/layout-engine/measure/crossRunWords.d.ts +45 -0
  69. package/dist/layout-engine/measure/crossRunWords.js +172 -0
  70. package/dist/layout-engine/measure/floatingLineClearance.d.ts +24 -0
  71. package/dist/layout-engine/measure/floatingLineClearance.js +44 -0
  72. package/dist/layout-engine/measure/inlineObjectMetrics.d.ts +6 -0
  73. package/dist/layout-engine/measure/inlineObjectMetrics.js +52 -0
  74. package/dist/layout-engine/measure/justification.d.ts +32 -0
  75. package/dist/layout-engine/measure/justification.js +83 -0
  76. package/dist/layout-engine/measure/lineFitting.d.ts +48 -0
  77. package/dist/layout-engine/measure/lineFitting.js +145 -0
  78. package/dist/layout-engine/measure/lineTypography.d.ts +44 -0
  79. package/dist/layout-engine/measure/lineTypography.js +124 -0
  80. package/dist/layout-engine/measure/measureBlocks.js +2 -1
  81. package/dist/layout-engine/measure/measureParagraph.d.ts +1 -20
  82. package/dist/layout-engine/measure/measureParagraph.js +32 -734
  83. package/dist/layout-engine/measure/paragraphMeasureShared.d.ts +109 -0
  84. package/dist/layout-engine/measure/paragraphMeasureShared.js +82 -0
  85. package/dist/layout-engine/measure/paragraphTabs.d.ts +18 -0
  86. package/dist/layout-engine/measure/paragraphTabs.js +78 -0
  87. package/dist/layout-engine/paragraphLayout.d.ts +23 -0
  88. package/dist/layout-engine/paragraphLayout.js +204 -0
  89. package/dist/layout-engine/sectionLayout.d.ts +45 -0
  90. package/dist/layout-engine/sectionLayout.js +216 -0
  91. package/dist/layout-engine/tableLayout.d.ts +17 -0
  92. package/dist/layout-engine/tableLayout.js +369 -0
  93. package/dist/layout-engine/textBoxLayout.d.ts +15 -0
  94. package/dist/layout-engine/textBoxLayout.js +137 -0
  95. package/dist/layout-painter/renderPage.js +1 -0
  96. package/dist/managers/editorShortcuts.d.ts +16 -3
  97. package/dist/managers/editorShortcuts.js +6 -4
  98. package/dist/paged-layout/sectionBlockWidths.d.ts +2 -1
  99. package/dist/paged-layout/sectionBlockWidths.js +1 -1
  100. package/dist/prosemirror/extensions/StarterKit.d.ts +3 -0
  101. package/dist/prosemirror/extensions/StarterKit.js +2 -1
  102. package/dist/prosemirror/extensions/core/HistoryExtension.d.ts +9 -1
  103. package/dist/prosemirror/extensions/core/HistoryExtension.js +4 -3
  104. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +12 -5
  105. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +91 -33
  106. package/dist/server.d.ts +3 -2
  107. package/package.json +2 -2
@@ -0,0 +1,281 @@
1
+ import { getFontAlternate } from "../../fonts/fontAlternates.js";
2
+ import { expectFieldAttrs, expectImageAttrs, expectMathAttrs, expectParagraphAttrs, expectPreservedXmlAttrs, expectSymbolAttrs } from "../../prosemirror/attrs/index.js";
3
+ import { decodeOoxmlSymbolCharacter } from "../../utils/ooxmlSymbol.js";
4
+ import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
5
+ import { buildImageRun, constrainImageToPage, hasPaintableImageSource, hasRelationshipBackedImageBox } from "./imageConversion.js";
6
+ import { isNoteReferenceMarkXml } from "./noteReferences.js";
7
+ import { applyCharacterStyleToggleFormatting, markDefaultBlackTextColorSource, mergeRunFormatting } from "./runFormattingMerge.js";
8
+ import { extractRunFormatting } from "./runMarkFormatting.js";
9
+ import { paragraphRunDefaults } from "./textFormattingConversion.js";
10
+ //#region src/layout-bridge/convert/paragraphRuns.ts
11
+ /**
12
+ * In TOC paragraphs, strip the resolved Hyperlink character-style colour and
13
+ * underline so the painter's link fallback doesn't fire. The PM doc keeps the
14
+ * original marks so copy/paste out of a TOC still carries the Hyperlink
15
+ * styling like Word does. Applies to both text and field runs — a TOC entry's
16
+ * page number is a PAGEREF field inside the entry's hyperlink.
17
+ *
18
+ * Mutates `formatting` in place; cheaper than re-cloning per run.
19
+ */
20
+ function stripTocHyperlinkStyle(formatting) {
21
+ if (!formatting.hyperlink) return;
22
+ formatting.hyperlink.noDefaultStyle = true;
23
+ delete formatting.color;
24
+ delete formatting.underline;
25
+ }
26
+ const isTrackedRunMark = ({ type }) => type.name === "insertion" || type.name === "deletion";
27
+ /**
28
+ * Inline wrappers own marks that apply to every projected descendant. A
29
+ * descendant's mark of the same type is more specific, and any descendant
30
+ * revision replaces (rather than combines with) an inherited revision.
31
+ */
32
+ const mergeProjectedInlineMarks = (inheritedMarks, ownMarks) => {
33
+ if (inheritedMarks.length === 0) return ownMarks;
34
+ const ownMarkTypes = new Set(ownMarks.map(({ type }) => type));
35
+ const hasOwnTrackedMark = ownMarks.some(isTrackedRunMark);
36
+ return [...inheritedMarks.filter((mark) => !ownMarkTypes.has(mark.type) && !(hasOwnTrackedMark && isTrackedRunMark(mark))), ...ownMarks];
37
+ };
38
+ function paragraphToRuns(node, startPos, _options, pageBreaks) {
39
+ const runs = [];
40
+ const offset = startPos + 1;
41
+ const theme = _options.theme;
42
+ const fontAlternates = _options.fontAlternates;
43
+ const pmAttrs = expectParagraphAttrs(node);
44
+ const paraDefaults = paragraphRunDefaults(pmAttrs, theme, fontAlternates);
45
+ const paragraphStyleId = pmAttrs.styleId;
46
+ const inTocParagraph = pmAttrs._tableOfContentsLevel !== void 0 || tableOfContentsStyleLevel({ styleId: paragraphStyleId }) !== void 0;
47
+ let leadingRenderedPageBreakPending = pmAttrs.renderedPageBreakBefore === true;
48
+ function pushRunsForChild(child, childPos, inheritedMarks = []) {
49
+ if (child.type.name === "bookmarkBoundary") return;
50
+ if (child.type.name === "renderedPageBreak") {
51
+ if (leadingRenderedPageBreakPending) {
52
+ leadingRenderedPageBreakPending = false;
53
+ return;
54
+ }
55
+ runs.push({
56
+ kind: "renderedPageBreak",
57
+ pmStart: childPos,
58
+ pmEnd: childPos + child.nodeSize
59
+ });
60
+ return;
61
+ }
62
+ const effectiveMarks = mergeProjectedInlineMarks(inheritedMarks, child.marks);
63
+ if (child.type.name === "pageBreakRun") {
64
+ const trackedChange = extractRunFormatting(effectiveMarks, theme, fontAlternates);
65
+ if (trackedChange.isDeletion) {
66
+ runs.push({
67
+ kind: "text",
68
+ text: "",
69
+ isDeletion: true,
70
+ ...trackedChange.changeAuthor !== void 0 ? { changeAuthor: trackedChange.changeAuthor } : {},
71
+ ...trackedChange.changeDate !== void 0 ? { changeDate: trackedChange.changeDate } : {},
72
+ ...trackedChange.changeRevisionId !== void 0 ? { changeRevisionId: trackedChange.changeRevisionId } : {},
73
+ ...trackedChange.isSuggestion === true ? { isSuggestion: true } : {},
74
+ ...trackedChange.suggestionId !== void 0 ? { suggestionId: trackedChange.suggestionId } : {},
75
+ pmStart: childPos,
76
+ pmEnd: childPos + child.nodeSize
77
+ });
78
+ return;
79
+ }
80
+ pageBreaks?.push({
81
+ pmStart: childPos,
82
+ pmEnd: childPos + child.nodeSize,
83
+ ...trackedChange.isInsertion ? { trackedChange: {
84
+ isInsertion: true,
85
+ ...trackedChange.changeAuthor !== void 0 ? { changeAuthor: trackedChange.changeAuthor } : {},
86
+ ...trackedChange.changeDate !== void 0 ? { changeDate: trackedChange.changeDate } : {},
87
+ ...trackedChange.changeRevisionId !== void 0 ? { changeRevisionId: trackedChange.changeRevisionId } : {},
88
+ ...trackedChange.isSuggestion === true ? { isSuggestion: true } : {},
89
+ ...trackedChange.suggestionId !== void 0 ? { suggestionId: trackedChange.suggestionId } : {}
90
+ } } : {}
91
+ });
92
+ return;
93
+ }
94
+ if (child.type.name !== "sdt") leadingRenderedPageBreakPending = false;
95
+ if (child.isText && child.text) {
96
+ const formatting = extractRunFormatting(effectiveMarks, theme, fontAlternates);
97
+ applyCharacterStyleToggleFormatting({
98
+ formatting,
99
+ marks: effectiveMarks,
100
+ paragraphFormatting: pmAttrs.defaultTextFormatting,
101
+ styleResolver: _options.styleResolver
102
+ });
103
+ if (inTocParagraph) stripTocHyperlinkStyle(formatting);
104
+ const run = {
105
+ kind: "text",
106
+ text: child.text,
107
+ ...mergeRunFormatting(paraDefaults, formatting),
108
+ pmStart: childPos,
109
+ pmEnd: childPos + child.nodeSize
110
+ };
111
+ runs.push(run);
112
+ return;
113
+ }
114
+ if (child.type.name === "symbol") {
115
+ const attrs = expectSymbolAttrs(child);
116
+ const text = decodeOoxmlSymbolCharacter(attrs.char);
117
+ if (text === null) return;
118
+ const formatting = extractRunFormatting(effectiveMarks, theme, fontAlternates);
119
+ applyCharacterStyleToggleFormatting({
120
+ formatting,
121
+ marks: effectiveMarks,
122
+ paragraphFormatting: pmAttrs.defaultTextFormatting,
123
+ styleResolver: _options.styleResolver
124
+ });
125
+ if (inTocParagraph) stripTocHyperlinkStyle(formatting);
126
+ const alternateFontFamily = getFontAlternate(attrs.font, fontAlternates);
127
+ formatting.fontFamily = attrs.font;
128
+ if (alternateFontFamily) formatting.alternateFontFamily = alternateFontFamily;
129
+ runs.push({
130
+ kind: "text",
131
+ text,
132
+ ...mergeRunFormatting(paraDefaults, formatting),
133
+ pmStart: childPos,
134
+ pmEnd: childPos + child.nodeSize
135
+ });
136
+ return;
137
+ }
138
+ if (child.type.name === "preservedXml") {
139
+ const { xml, text: capturedText } = expectPreservedXmlAttrs(child);
140
+ const text = capturedText === "" && _options.noteReferenceMarkText !== void 0 && isNoteReferenceMarkXml(xml) ? _options.noteReferenceMarkText : capturedText;
141
+ if (text === "") return;
142
+ const formatting = extractRunFormatting(effectiveMarks, theme, fontAlternates);
143
+ applyCharacterStyleToggleFormatting({
144
+ formatting,
145
+ marks: effectiveMarks,
146
+ paragraphFormatting: pmAttrs.defaultTextFormatting,
147
+ styleResolver: _options.styleResolver
148
+ });
149
+ runs.push({
150
+ kind: "text",
151
+ text,
152
+ ...mergeRunFormatting(paraDefaults, formatting),
153
+ pmStart: childPos,
154
+ pmEnd: childPos + child.nodeSize
155
+ });
156
+ return;
157
+ }
158
+ if (child.type.name === "hardBreak") {
159
+ runs.push({
160
+ kind: "lineBreak",
161
+ pmStart: childPos,
162
+ pmEnd: childPos + child.nodeSize
163
+ });
164
+ return;
165
+ }
166
+ if (child.type.name === "tab") {
167
+ const formatting = extractRunFormatting(effectiveMarks, theme, fontAlternates);
168
+ applyCharacterStyleToggleFormatting({
169
+ formatting,
170
+ marks: effectiveMarks,
171
+ paragraphFormatting: pmAttrs.defaultTextFormatting,
172
+ styleResolver: _options.styleResolver
173
+ });
174
+ const run = {
175
+ kind: "tab",
176
+ ...mergeRunFormatting(paraDefaults, formatting),
177
+ pmStart: childPos,
178
+ pmEnd: childPos + child.nodeSize
179
+ };
180
+ runs.push(run);
181
+ return;
182
+ }
183
+ if (child.type.name === "image") {
184
+ const attrs = expectImageAttrs(child);
185
+ if (!hasPaintableImageSource(attrs) && !hasRelationshipBackedImageBox(attrs)) return;
186
+ const constrained = constrainImageToPage(attrs.width ?? 100, attrs.height ?? 100, _options.pageContentHeight);
187
+ const trackedFmt = extractRunFormatting(effectiveMarks, theme, fontAlternates);
188
+ const run = buildImageRun(attrs, constrained, childPos, childPos + child.nodeSize, trackedFmt, _options.forceAnchorLayoutInCell);
189
+ runs.push(run);
190
+ return;
191
+ }
192
+ if (child.type.name === "structuredField") {
193
+ let containsPageBreak = false;
194
+ child.descendants((descendant) => {
195
+ if (descendant.type.name === "pageBreakRun") {
196
+ containsPageBreak = true;
197
+ return false;
198
+ }
199
+ return true;
200
+ });
201
+ if (containsPageBreak) {
202
+ const fieldContentStart = childPos + 1;
203
+ child.forEach((fieldChild, fieldChildOffset) => {
204
+ pushRunsForChild(fieldChild, fieldContentStart + fieldChildOffset, effectiveMarks);
205
+ });
206
+ return;
207
+ }
208
+ }
209
+ if (child.type.name === "field" || child.type.name === "structuredField") {
210
+ const attrs = expectFieldAttrs(child);
211
+ const ft = attrs.fieldType;
212
+ let mappedType = "OTHER";
213
+ if (ft === "PAGE") mappedType = "PAGE";
214
+ else if (ft === "NUMPAGES") mappedType = "NUMPAGES";
215
+ else if (ft === "DATE") mappedType = "DATE";
216
+ else if (ft === "TIME") mappedType = "TIME";
217
+ const extractedFieldFormatting = extractRunFormatting(effectiveMarks, theme, fontAlternates);
218
+ applyCharacterStyleToggleFormatting({
219
+ formatting: extractedFieldFormatting,
220
+ marks: effectiveMarks,
221
+ paragraphFormatting: pmAttrs.defaultTextFormatting,
222
+ styleResolver: _options.styleResolver
223
+ });
224
+ if (inTocParagraph) stripTocHyperlinkStyle(extractedFieldFormatting);
225
+ const fieldFormatting = markDefaultBlackTextColorSource(extractedFieldFormatting, paraDefaults);
226
+ const run = {
227
+ kind: "field",
228
+ fieldType: mappedType,
229
+ instruction: attrs.instruction,
230
+ fallback: _options.numberedRefResults?.get(child) ?? attrs.displayText ?? "",
231
+ ...attrs.fldLock ? { fldLock: true } : {},
232
+ pmStart: childPos,
233
+ pmEnd: childPos + child.nodeSize,
234
+ ...fieldFormatting
235
+ };
236
+ runs.push(run);
237
+ return;
238
+ }
239
+ if (child.type.name === "math") {
240
+ const attrs = expectMathAttrs(child);
241
+ const plainText = attrs.plainText || "[equation]";
242
+ runs.push({
243
+ kind: "math",
244
+ display: attrs.display ?? "inline",
245
+ ommlXml: attrs.ommlXml,
246
+ plainText,
247
+ italic: true,
248
+ fontFamily: "Cambria Math",
249
+ pmStart: childPos,
250
+ pmEnd: childPos + child.nodeSize
251
+ });
252
+ return;
253
+ }
254
+ if (child.type.name === "sdt") {
255
+ const sdtInnerOffset = childPos + 1;
256
+ child.forEach((sdtChild, sdtChildOffset) => {
257
+ pushRunsForChild(sdtChild, sdtInnerOffset + sdtChildOffset, effectiveMarks);
258
+ });
259
+ }
260
+ }
261
+ node.forEach((child, childOffset) => {
262
+ pushRunsForChild(child, offset + childOffset);
263
+ });
264
+ const { defaultFont, defaultSize } = _options;
265
+ if (defaultFont !== void 0 || defaultSize !== void 0) for (const run of runs) switch (run.kind) {
266
+ case "text":
267
+ case "tab":
268
+ case "renderedPageBreak":
269
+ case "field":
270
+ case "math":
271
+ if (defaultFont !== void 0) run.fontFamily ??= defaultFont;
272
+ if (defaultSize !== void 0) run.fontSize ??= defaultSize;
273
+ break;
274
+ case "image":
275
+ case "lineBreak": break;
276
+ default:
277
+ }
278
+ return runs;
279
+ }
280
+ //#endregion
281
+ export { paragraphToRuns };
@@ -0,0 +1,19 @@
1
+ import { document_d_exports } from "../../types/document.js";
2
+ import { RunFormattingOverrideAttrs } from "../../prosemirror/schema/marks.js";
3
+ import { RunStyleResolver } from "../../prosemirror/runStyleFormatting.js";
4
+ import { RunFormatting } from "../../layout-engine/types.js";
5
+ import { Mark } from "prosemirror-model";
6
+ //#region src/layout-bridge/convert/runFormattingMerge.d.ts
7
+ declare function markDefaultBlackTextColorSource(formatting: RunFormatting, paraDefaults: RunFormatting): RunFormatting;
8
+ declare function mergeRunFormatting(paraDefaults: RunFormatting, formatting: RunFormatting): RunFormatting;
9
+ type ApplyCharacterStyleToggleFormattingOptions = {
10
+ formatting: RunFormatting;
11
+ marks: readonly Mark[];
12
+ paragraphFormatting: document_d_exports.TextFormatting | undefined;
13
+ styleResolver: RunStyleResolver;
14
+ };
15
+ /** Restore character-style toggle values that plain visual marks cannot represent. */
16
+ declare function applyCharacterStyleToggleFormatting({ formatting, marks, paragraphFormatting, styleResolver }: ApplyCharacterStyleToggleFormattingOptions): void;
17
+ declare function applyRunFormattingOverrides(formatting: RunFormatting, attrs: RunFormattingOverrideAttrs): void;
18
+ //#endregion
19
+ export { applyCharacterStyleToggleFormatting, applyRunFormattingOverrides, markDefaultBlackTextColorSource, mergeRunFormatting };
@@ -0,0 +1,167 @@
1
+ import { expectCharacterStyleMarkAttrs } from "../../prosemirror/attrs/index.js";
2
+ import { resolveEffectiveRunStyleFormatting } from "../../prosemirror/runStyleFormatting.js";
3
+ import { STYLE_TOGGLE_KEYS } from "../../utils/textFormattingMerge.js";
4
+ //#region src/layout-bridge/convert/runFormattingMerge.ts
5
+ const DEFAULT_BLACK_TEXT_COLOR_VALUES = /* @__PURE__ */ new Set(["000000", "000"]);
6
+ function normalizeResolvedTextColor(color) {
7
+ return color.trim().toLowerCase().replace(/^#/u, "");
8
+ }
9
+ function isDefaultBlackResolvedTextColor(color) {
10
+ return DEFAULT_BLACK_TEXT_COLOR_VALUES.has(normalizeResolvedTextColor(color));
11
+ }
12
+ function areResolvedTextColorsEqual(left, right) {
13
+ return normalizeResolvedTextColor(left) === normalizeResolvedTextColor(right);
14
+ }
15
+ function markDefaultBlackTextColorSource(formatting, paraDefaults) {
16
+ if (formatting.textColorSource === "direct" || formatting.color === void 0 || paraDefaults.color === void 0 || !isDefaultBlackResolvedTextColor(formatting.color) || !areResolvedTextColorsEqual(formatting.color, paraDefaults.color)) return formatting;
17
+ return {
18
+ ...formatting,
19
+ textColorSource: "paragraphDefault"
20
+ };
21
+ }
22
+ function mergeRunFormatting(paraDefaults, formatting) {
23
+ if (formatting.isDeletion && formatting.usesHistoricalFormatting) return formatting;
24
+ const merged = {
25
+ ...paraDefaults,
26
+ ...markDefaultBlackTextColorSource(formatting, paraDefaults)
27
+ };
28
+ if (formatting.fontFamily !== void 0 && formatting.alternateFontFamily === void 0) delete merged.alternateFontFamily;
29
+ if (formatting.eastAsiaFontFamily !== void 0 && formatting.eastAsiaAlternateFontFamily === void 0) delete merged.eastAsiaAlternateFontFamily;
30
+ if (formatting.complexScriptFontFamily !== void 0 && formatting.complexScriptAlternateFontFamily === void 0) delete merged.complexScriptAlternateFontFamily;
31
+ if (merged.letterSpacing === 0) delete merged.letterSpacing;
32
+ if (formatting.horizontalScale === 100 && paraDefaults.horizontalScale === void 0) delete merged.horizontalScale;
33
+ return merged;
34
+ }
35
+ const CHARACTER_STYLE_TOGGLE_LAYOUT_PROPERTIES = {
36
+ allCaps: "allCaps",
37
+ bold: "bold",
38
+ boldCs: "complexScriptBold",
39
+ emboss: "emboss",
40
+ hidden: "hidden",
41
+ imprint: "imprint",
42
+ italic: "italic",
43
+ italicCs: "complexScriptItalic",
44
+ outline: "textOutline",
45
+ shadow: "textShadow",
46
+ smallCaps: "smallCaps",
47
+ strike: "strike"
48
+ };
49
+ /** Restore character-style toggle values that plain visual marks cannot represent. */
50
+ function applyCharacterStyleToggleFormatting({ formatting, marks, paragraphFormatting, styleResolver }) {
51
+ const characterStyleMark = marks.find((mark) => mark.type.name === "characterStyle");
52
+ const styleRPr = characterStyleMark ? styleResolver.getRunStyleOwnProperties(expectCharacterStyleMarkAttrs(characterStyleMark).styleId) : styleResolver.getDefaultCharacterStyle()?.rPr;
53
+ if (!styleRPr) return;
54
+ const effectiveStyleFormatting = resolveEffectiveRunStyleFormatting({
55
+ marks,
56
+ paragraphFormatting,
57
+ styleResolver
58
+ });
59
+ for (const property of STYLE_TOGGLE_KEYS) {
60
+ if (styleRPr[property] === void 0) continue;
61
+ const layoutProperty = CHARACTER_STYLE_TOGGLE_LAYOUT_PROPERTIES[property];
62
+ if (formatting[layoutProperty] === void 0) Reflect.set(formatting, layoutProperty, effectiveStyleFormatting?.[property] ?? false);
63
+ }
64
+ }
65
+ const suppressInheritedRunFormatting = (formatting, property) => {
66
+ Reflect.set(formatting, property, void 0);
67
+ };
68
+ const RUN_FORMATTING_OVERRIDE_HANDLER_ENTRIES = Object.entries({
69
+ _authoredOff() {},
70
+ _authoredOn() {},
71
+ _authoredValues() {},
72
+ allCaps(formatting, value) {
73
+ if (typeof value === "boolean") formatting.allCaps = value;
74
+ },
75
+ bold(formatting, value) {
76
+ if (typeof value === "boolean") formatting.bold = value;
77
+ },
78
+ boldCs(formatting, value) {
79
+ if (typeof value === "boolean") formatting.complexScriptBold = value;
80
+ },
81
+ color(formatting, value) {
82
+ if (value === "auto") {
83
+ suppressInheritedRunFormatting(formatting, "color");
84
+ suppressInheritedRunFormatting(formatting, "textColorSource");
85
+ }
86
+ },
87
+ complexScriptPropertyAbsences() {},
88
+ cs(formatting, value) {
89
+ if (typeof value === "boolean") formatting.forceComplexScript = value;
90
+ },
91
+ directFontProperties() {},
92
+ doubleStrike(formatting, value) {
93
+ if (value === false && formatting.strike === void 0) formatting.strike = false;
94
+ },
95
+ effect(formatting, value) {
96
+ if (value === "none") suppressInheritedRunFormatting(formatting, "textEffect");
97
+ },
98
+ emboss(formatting, value) {
99
+ if (typeof value === "boolean") formatting.emboss = value;
100
+ },
101
+ emphasisMark(formatting, value) {
102
+ if (value === "none") suppressInheritedRunFormatting(formatting, "emphasisMark");
103
+ },
104
+ fontSizeCs(formatting, value) {
105
+ if (typeof value === "number") formatting.complexScriptFontSize = value / 2;
106
+ },
107
+ noProof() {},
108
+ hidden(formatting, value) {
109
+ if (typeof value === "boolean") formatting.hidden = value;
110
+ },
111
+ highlight(formatting, value) {
112
+ if (value === "none") suppressInheritedRunFormatting(formatting, "highlight");
113
+ },
114
+ imprint(formatting, value) {
115
+ if (typeof value === "boolean") formatting.imprint = value;
116
+ },
117
+ italic(formatting, value) {
118
+ if (typeof value === "boolean") formatting.italic = value;
119
+ },
120
+ italicCs(formatting, value) {
121
+ if (typeof value === "boolean") formatting.complexScriptItalic = value;
122
+ },
123
+ kerning(formatting, value) {
124
+ if (value === 0) formatting.kerningMinPt = 0;
125
+ },
126
+ outline(formatting, value) {
127
+ if (typeof value === "boolean") formatting.textOutline = value;
128
+ },
129
+ position(formatting, value) {
130
+ if (value === 0) formatting.positionPx = 0;
131
+ },
132
+ rtl(formatting, value) {
133
+ if (value === false) formatting.rtl = false;
134
+ },
135
+ scale(formatting, value) {
136
+ if (value === 100) formatting.horizontalScale = 100;
137
+ },
138
+ shading(formatting, value) {
139
+ if (typeof value === "object" && value !== null && Reflect.get(value, "pattern") === "nil") suppressInheritedRunFormatting(formatting, "shading");
140
+ },
141
+ shadow(formatting, value) {
142
+ if (typeof value === "boolean") formatting.textShadow = value;
143
+ },
144
+ smallCaps(formatting, value) {
145
+ if (typeof value === "boolean") formatting.smallCaps = value;
146
+ },
147
+ spacing(formatting, value) {
148
+ if (value === 0) formatting.letterSpacing = 0;
149
+ },
150
+ strike(formatting, value) {
151
+ if (typeof value === "boolean") formatting.strike = value;
152
+ },
153
+ underline(formatting, value) {
154
+ if (value === "none") formatting.underline = false;
155
+ },
156
+ vertAlign(formatting, value) {
157
+ if (value === "baseline") {
158
+ formatting.superscript = false;
159
+ formatting.subscript = false;
160
+ }
161
+ }
162
+ });
163
+ function applyRunFormattingOverrides(formatting, attrs) {
164
+ for (const [key, handler] of RUN_FORMATTING_OVERRIDE_HANDLER_ENTRIES) handler(formatting, Reflect.get(attrs, key));
165
+ }
166
+ //#endregion
167
+ export { applyCharacterStyleToggleFormatting, applyRunFormattingOverrides, markDefaultBlackTextColorSource, mergeRunFormatting };
@@ -0,0 +1,11 @@
1
+ import { document_d_exports } from "../../types/document.js";
2
+ import { RunFormatting } from "../../layout-engine/types.js";
3
+ import { FontAlternates } from "../../fonts/fontAlternates.js";
4
+ import { Mark } from "prosemirror-model";
5
+ //#region src/layout-bridge/convert/runMarkFormatting.d.ts
6
+ /**
7
+ * Extract run formatting from ProseMirror marks.
8
+ */
9
+ declare function extractRunFormatting(marks: readonly Mark[], theme?: document_d_exports.Theme | null, fontAlternates?: FontAlternates): RunFormatting;
10
+ //#endregion
11
+ export { extractRunFormatting };