@stll/folio-core 0.6.1 → 0.8.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/blockRange.d.ts +13 -2
  2. package/dist/ai-edits/blockRange.js +23 -2
  3. package/dist/ai-edits/index.d.ts +4 -2
  4. package/dist/ai-edits/index.js +3 -1
  5. package/dist/ai-edits/scoped-reading.d.ts +9 -0
  6. package/dist/ai-edits/scoped-reading.js +60 -0
  7. package/dist/ai-edits/snapshot.js +13 -4
  8. package/dist/ai-edits/types.d.ts +44 -2
  9. package/dist/compat/eigenpal.d.ts +5 -2
  10. package/dist/compat/eigenpal.js +4 -1
  11. package/dist/controller/fontReadiness.d.ts +29 -0
  12. package/dist/controller/fontReadiness.js +139 -0
  13. package/dist/controller/layoutPipeline.js +86 -11
  14. package/dist/docx/blockContentParser.js +51 -8
  15. package/dist/docx/capabilities.d.ts +41 -0
  16. package/dist/docx/capabilities.js +322 -0
  17. package/dist/docx/compatibility.d.ts +34 -2
  18. package/dist/docx/compatibility.js +128 -38
  19. package/dist/docx/conformance.d.ts +6 -0
  20. package/dist/docx/conformance.js +18 -0
  21. package/dist/docx/ensureParaIds.d.ts +29 -0
  22. package/dist/docx/ensureParaIds.js +423 -0
  23. package/dist/docx/groupDrawingParser.d.ts +1 -1
  24. package/dist/docx/groupDrawingParser.js +49 -8
  25. package/dist/docx/numberingParser.js +1 -0
  26. package/dist/docx/paragraphParser.js +9 -0
  27. package/dist/docx/paragraphTextBoxEnrichment.js +141 -2
  28. package/dist/docx/parser.js +2 -0
  29. package/dist/docx/runParser.js +11 -2
  30. package/dist/docx/selectiveXmlPatch.d.ts +10 -1
  31. package/dist/docx/selectiveXmlPatch.js +1 -1
  32. package/dist/docx/serializer/paragraphSerializer.js +4 -0
  33. package/dist/docx/serializer/runSerializer.js +7 -2
  34. package/dist/docx/serializer/tableSerializer.js +4 -0
  35. package/dist/docx/server/boundedArchive.d.ts +24 -0
  36. package/dist/docx/server/boundedArchive.js +106 -0
  37. package/dist/docx/server/extractDocxText.d.ts +23 -0
  38. package/dist/docx/server/extractDocxText.js +154 -0
  39. package/dist/docx/tableParser.js +8 -0
  40. package/dist/docx/textBoxParser.js +6 -1
  41. package/dist/docx/vmlImageParser.js +145 -1
  42. package/dist/index.d.ts +5 -2
  43. package/dist/index.js +4 -1
  44. package/dist/layout-bridge/convert/headerFooterLayout.js +16 -2
  45. package/dist/layout-bridge/convert/paragraphFrames.d.ts +7 -0
  46. package/dist/layout-bridge/convert/paragraphFrames.js +136 -0
  47. package/dist/layout-bridge/convert/toFlowBlocks.js +106 -13
  48. package/dist/layout-bridge/engine/hitTest.js +2 -1
  49. package/dist/layout-bridge/engine/selectionRects.js +2 -1
  50. package/dist/layout-engine/headerFooterRefs.d.ts +7 -0
  51. package/dist/layout-engine/headerFooterRefs.js +40 -0
  52. package/dist/layout-engine/index.d.ts +3 -2
  53. package/dist/layout-engine/index.js +125 -72
  54. package/dist/layout-engine/keep-together.d.ts +7 -5
  55. package/dist/layout-engine/keep-together.js +20 -4
  56. package/dist/layout-engine/measure/cache.js +2 -0
  57. package/dist/layout-engine/measure/listMarkerWidth.d.ts +3 -1
  58. package/dist/layout-engine/measure/listMarkerWidth.js +23 -4
  59. package/dist/layout-engine/measure/measureBlocks.d.ts +3 -0
  60. package/dist/layout-engine/measure/measureBlocks.js +133 -51
  61. package/dist/layout-engine/measure/measureParagraph.js +42 -15
  62. package/dist/layout-engine/measure/tableCellGrid.d.ts +15 -0
  63. package/dist/layout-engine/measure/tableCellGrid.js +62 -0
  64. package/dist/layout-engine/measure/textBoxParagraphLayout.d.ts +18 -0
  65. package/dist/layout-engine/measure/textBoxParagraphLayout.js +32 -0
  66. package/dist/layout-engine/paginator.d.ts +2 -1
  67. package/dist/layout-engine/paginator.js +17 -8
  68. package/dist/layout-engine/paragraphFrame.d.ts +22 -0
  69. package/dist/layout-engine/paragraphFrame.js +17 -0
  70. package/dist/layout-engine/paragraphSequence.d.ts +7 -0
  71. package/dist/layout-engine/paragraphSequence.js +25 -0
  72. package/dist/layout-engine/paragraphSpacing.d.ts +17 -0
  73. package/dist/layout-engine/paragraphSpacing.js +30 -0
  74. package/dist/layout-engine/renderedBreakReconciliation.d.ts +58 -0
  75. package/dist/layout-engine/renderedBreakReconciliation.js +63 -0
  76. package/dist/layout-engine/types.d.ts +31 -10
  77. package/dist/layout-engine/types.js +15 -2
  78. package/dist/layout-painter/renderPage.js +2 -2
  79. package/dist/layout-painter/renderParagraph.js +94 -10
  80. package/dist/layout-painter/renderTable.js +42 -12
  81. package/dist/layout-painter/renderTextBox.js +17 -7
  82. package/dist/managers/DocumentLoaderManager.js +1 -1
  83. package/dist/paged-layout/sectionBlockWidths.d.ts +3 -0
  84. package/dist/paged-layout/sectionBlockWidths.js +9 -0
  85. package/dist/paged-layout/sectionGeometry.js +1 -1
  86. package/dist/prosemirror/attrs/index.js +11 -0
  87. package/dist/prosemirror/conversion/fromProseDoc.js +2 -0
  88. package/dist/prosemirror/conversion/toProseDoc.js +29 -23
  89. package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
  90. package/dist/prosemirror/extensions/features/ListExtension.js +1 -0
  91. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +68 -16
  92. package/dist/prosemirror/extensions/nodes/TableExtension.js +1 -0
  93. package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +2 -1
  94. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +7 -0
  95. package/dist/prosemirror/schema/nodes.d.ts +6 -3
  96. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  97. package/dist/prosemirror/utils/tabCalculator.js +1 -1
  98. package/dist/server.d.ts +6 -2
  99. package/dist/server.js +5 -1
  100. package/dist/types/index.d.ts +2 -1
  101. package/dist/utils/createDocument.js +26 -18
  102. package/dist/utils/formatToStyle.js +3 -3
  103. package/dist/utils/hexId.d.ts +8 -1
  104. package/dist/utils/hexId.js +11 -3
  105. package/dist/utils/units.d.ts +6 -6
  106. package/dist/utils/units.js +8 -8
  107. package/package.json +1 -1
@@ -19,6 +19,42 @@ import { tryBuildIncrementalMeasures } from "../paged-layout/incrementalMeasure.
19
19
  import { computePerBlockMeasureInputs } from "../paged-layout/sectionBlockWidths.js";
20
20
  import { getDocumentWatermark } from "../watermark/index.js";
21
21
  //#region src/controller/layoutPipeline.ts
22
+ function bodyMarginsClearHeaderFooter({ authoredMargins, preparedHeader, preparedFooter }) {
23
+ const headerBottom = preparedHeader ? (authoredMargins.header ?? 0) + (preparedHeader.marginPushBottom ?? preparedHeader.height) : authoredMargins.top;
24
+ const footerClearance = preparedFooter ? (authoredMargins.footer ?? 0) + (preparedFooter.marginPushBottom ?? preparedFooter.height) : authoredMargins.bottom;
25
+ const top = Math.max(authoredMargins.top, headerBottom);
26
+ const bottom = Math.max(authoredMargins.bottom, footerClearance);
27
+ if (top === authoredMargins.top && bottom === authoredMargins.bottom) return authoredMargins;
28
+ return {
29
+ ...authoredMargins,
30
+ top,
31
+ bottom
32
+ };
33
+ }
34
+ function bodyBlocksClearSectionHeaderFooter(blocks, { authoredMargins, sectionHeaderFooterRefs, headerContentByRId, footerContentByRId }) {
35
+ if (!sectionHeaderFooterRefs || !headerContentByRId && !footerContentByRId) return blocks;
36
+ let sectionIndex = 0;
37
+ let currentAuthoredMargins = authoredMargins;
38
+ let changed = false;
39
+ const nextBlocks = blocks.map((block) => {
40
+ if (block.kind !== "sectionBreak") return block;
41
+ currentAuthoredMargins = block.margins ?? currentAuthoredMargins;
42
+ const refs = sectionHeaderFooterRefs[sectionIndex];
43
+ sectionIndex += 1;
44
+ const effectiveMargins = bodyMarginsClearHeaderFooter({
45
+ authoredMargins: currentAuthoredMargins,
46
+ preparedHeader: refs?.headerDefault ? headerContentByRId?.get(refs.headerDefault) : void 0,
47
+ preparedFooter: refs?.footerDefault ? footerContentByRId?.get(refs.footerDefault) : void 0
48
+ });
49
+ if (effectiveMargins === currentAuthoredMargins && block.margins === currentAuthoredMargins) return block;
50
+ changed = true;
51
+ return {
52
+ ...block,
53
+ margins: effectiveMargins
54
+ };
55
+ });
56
+ return changed ? nextBlocks : blocks;
57
+ }
22
58
  function runLayoutPipeline(deps, state, options = {}) {
23
59
  const { contentWidth, columns, pageSize, margins, pageGap, syncCoordinator, headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, headerContentRId, footerContentRId, firstPageHeaderContentRId, firstPageFooterContentRId, sectionHeaderFooterRefs, theme: _theme, sectionProperties, document, defaultTabStop, mirrorMargins, styles, layout, hfPMs, painter, pagesContainer, session, renderHfFromContentOrPm, renderHeaderFooterContentByRId, documentFontsAreLoaded, buildFootnoteRenderItems, describeInvalidHighlightMarks, emptyTemplatePreviewEntries: EMPTY_TEMPLATE_PREVIEW_ENTRIES } = deps;
24
60
  let outcome = {};
@@ -92,17 +128,51 @@ function runLayoutPipeline(deps, state, options = {}) {
92
128
  let firstPageFooterForRender = hasTitlePg ? renderHfFromContentOrPm(firstPageFooterContent, firstPageFooterContentRId, hfPMs, contentWidth, hfMetricsFooter, hfOptions) : void 0;
93
129
  let headerContentByRId = renderHeaderFooterContentByRId(document?.package.headers, hfPMs, contentWidth, hfMetricsHeader, hfOptions);
94
130
  let footerContentByRId = renderHeaderFooterContentByRId(document?.package.footers, hfPMs, contentWidth, hfMetricsFooter, hfOptions);
131
+ const sectionPropertiesForMargins = document?.package.document.sections?.map((section) => section.properties) ?? (sectionProperties ? [sectionProperties] : []);
132
+ const sectionEvenPageMargins = sectionHeaderFooterRefs?.map((refs, index) => {
133
+ if (refs.evenAndOddHeaders !== true) return;
134
+ const properties = sectionPropertiesForMargins[index];
135
+ return bodyMarginsClearHeaderFooter({
136
+ authoredMargins: properties ? getMargins(properties) : margins,
137
+ preparedHeader: refs.headerEven ? headerContentByRId?.get(refs.headerEven) : void 0,
138
+ preparedFooter: refs.footerEven ? footerContentByRId?.get(refs.footerEven) : void 0
139
+ });
140
+ });
141
+ newBlocks = bodyBlocksClearSectionHeaderFooter(newBlocks, {
142
+ authoredMargins: margins,
143
+ sectionHeaderFooterRefs,
144
+ headerContentByRId,
145
+ footerContentByRId
146
+ });
147
+ outcome.blocks = newBlocks;
148
+ const initialBodyMargins = bodyMarginsClearHeaderFooter({
149
+ authoredMargins: margins,
150
+ preparedHeader: headerContentForRender,
151
+ preparedFooter: footerContentForRender
152
+ });
95
153
  recordPhaseDuration("header-footer", phaseStartedAt);
96
154
  phaseStartedAt = performance.now();
97
155
  const bodyLayoutConfig = {
98
156
  pageSize,
99
- margins
157
+ margins: initialBodyMargins
100
158
  };
101
159
  if (columns !== void 0) bodyLayoutConfig.columns = columns;
102
160
  const finalSectionProperties = document?.package.document.sections?.at(-1)?.properties;
161
+ const finalHeaderRId = sectionHeaderFooterRefs?.at(-1)?.headerDefault;
162
+ let finalHeaderForLayout = headerContentForRender;
163
+ if (finalHeaderRId) finalHeaderForLayout = headerContentByRId?.get(finalHeaderRId);
164
+ else if (sectionHeaderFooterRefs !== void 0) finalHeaderForLayout = void 0;
165
+ const finalFooterRId = sectionHeaderFooterRefs?.at(-1)?.footerDefault;
166
+ let finalFooterForLayout = footerContentForRender;
167
+ if (finalFooterRId) finalFooterForLayout = footerContentByRId?.get(finalFooterRId);
168
+ else if (sectionHeaderFooterRefs !== void 0) finalFooterForLayout = void 0;
103
169
  const finalLayoutConfig = finalSectionProperties ? {
104
170
  pageSize: getPageSize(finalSectionProperties),
105
- margins: getMargins(finalSectionProperties)
171
+ margins: bodyMarginsClearHeaderFooter({
172
+ authoredMargins: getMargins(finalSectionProperties),
173
+ preparedHeader: finalHeaderForLayout,
174
+ preparedFooter: finalFooterForLayout
175
+ })
106
176
  } : bodyLayoutConfig;
107
177
  const finalColumns = getColumns(finalSectionProperties);
108
178
  if (finalColumns !== void 0) finalLayoutConfig.columns = finalColumns;
@@ -123,7 +193,10 @@ function runLayoutPipeline(deps, state, options = {}) {
123
193
  measureBlock: measureSingleBlockWithoutFloatingZones
124
194
  }) : null;
125
195
  let newMeasures = incrementalResult?.measures ?? measureBlocks(newBlocks, blockWidths, blockMeasureInputs.marginTops, {
196
+ pageWidth: blockMeasureInputs.pageWidths,
126
197
  pageHeight: blockMeasureInputs.pageHeights,
198
+ marginLeft: blockMeasureInputs.marginLefts,
199
+ marginRight: blockMeasureInputs.marginRights,
127
200
  marginBottom: blockMeasureInputs.marginBottoms
128
201
  });
129
202
  pendingArtifacts = {
@@ -137,21 +210,19 @@ function runLayoutPipeline(deps, state, options = {}) {
137
210
  let newLayout;
138
211
  let pageFootnoteMap = /* @__PURE__ */ new Map();
139
212
  let footnoteContentMap = /* @__PURE__ */ new Map();
140
- const bodyBreakType = sectionProperties?.sectionStart;
213
+ const bodyBreakType = finalSectionProperties?.sectionStart;
141
214
  const buildLayoutOpts = () => {
142
215
  const nextLayoutOpts = {
143
216
  pageSize,
144
- margins,
217
+ margins: initialBodyMargins,
145
218
  pageGap,
146
219
  mirrorMargins
147
220
  };
148
- if (hasTitlePg && firstPageHeaderForRender) {
149
- const headerBottom = (margins.header ?? 0) + (firstPageHeaderForRender.marginPushBottom ?? firstPageHeaderForRender.height);
150
- if (headerBottom > margins.top) nextLayoutOpts.firstPageMargins = {
151
- ...margins,
152
- top: headerBottom
153
- };
154
- }
221
+ if (hasTitlePg) nextLayoutOpts.firstPageMargins = bodyMarginsClearHeaderFooter({
222
+ authoredMargins: margins,
223
+ preparedHeader: firstPageHeaderForRender,
224
+ preparedFooter: firstPageFooterForRender
225
+ });
155
226
  if (finalSectionProperties) {
156
227
  nextLayoutOpts.finalPageSize = finalLayoutConfig.pageSize;
157
228
  nextLayoutOpts.finalMargins = finalLayoutConfig.margins;
@@ -163,6 +234,7 @@ function runLayoutPipeline(deps, state, options = {}) {
163
234
  if (columns !== void 0) nextLayoutOpts.columns = columns;
164
235
  if (bodyBreakType !== void 0) nextLayoutOpts.bodyBreakType = bodyBreakType;
165
236
  if (sectionHeaderFooterRefs !== void 0) nextLayoutOpts.sectionHeaderFooterRefs = sectionHeaderFooterRefs;
237
+ if (sectionEvenPageMargins !== void 0) nextLayoutOpts.sectionEvenPageMargins = sectionEvenPageMargins;
166
238
  return nextLayoutOpts;
167
239
  };
168
240
  const layoutOpts = buildLayoutOpts();
@@ -229,7 +301,10 @@ function runLayoutPipeline(deps, state, options = {}) {
229
301
  previousFieldValues = values;
230
302
  stabilizedFieldValues = values;
231
303
  newMeasures = measureBlocks(newBlocks, blockWidths, blockMeasureInputs.marginTops, {
304
+ pageWidth: blockMeasureInputs.pageWidths,
232
305
  pageHeight: blockMeasureInputs.pageHeights,
306
+ marginLeft: blockMeasureInputs.marginLefts,
307
+ marginRight: blockMeasureInputs.marginRights,
233
308
  marginBottom: blockMeasureInputs.marginBottoms
234
309
  }, values);
235
310
  relayoutWithCurrentMeasures(layoutOptsUsed);
@@ -49,23 +49,42 @@ const formatNumber = (value, numFmt) => {
49
49
  case "lowerRoman": return toRoman(value).toLowerCase();
50
50
  case "upperRoman": return toRoman(value);
51
51
  case "bullet": return "•";
52
+ case "none": return "";
52
53
  default: return String(value);
53
54
  }
54
55
  };
55
- const computeListMarker = (paragraph, numbering, listCounters, abstractCounters) => {
56
+ const computeListMarker = (paragraph, { numbering, listCounters, abstractCounters, restartedNumIds, previousList }) => {
56
57
  const listRendering = paragraph.listRendering;
57
- if (!listRendering || !numbering) return;
58
+ if (!listRendering || !numbering) {
59
+ previousList.abstractNumId = null;
60
+ previousList.fromStyle = false;
61
+ previousList.numId = null;
62
+ return;
63
+ }
58
64
  const { numId, level } = listRendering;
59
- if (numId === 0) return;
60
- if (!listCounters.has(numId)) listCounters.set(numId, Array.from({ length: 9 }).fill(NaN));
65
+ if (numId === 0) {
66
+ previousList.abstractNumId = null;
67
+ previousList.fromStyle = false;
68
+ previousList.numId = null;
69
+ return;
70
+ }
71
+ const firstEncounter = !listCounters.has(numId);
72
+ if (firstEncounter) listCounters.set(numId, Array.from({ length: 9 }).fill(NaN));
61
73
  const counters = listCounters.get(numId);
62
74
  if (!counters) return;
63
75
  const abstractNumId = numbering.getAbstractNumId(numId);
64
76
  const styleNumbering = paragraph.formatting?.numPrFromStyle;
65
- if (abstractNumId !== null && styleNumbering) {
77
+ let resumedAbstractCounters;
78
+ const resumesRestartedInstance = firstEncounter && listRendering.startOverride === void 0 && abstractNumId !== null && previousList.abstractNumId === abstractNumId && previousList.numId !== null && previousList.numId !== numId && restartedNumIds.has(previousList.numId);
79
+ const resumesStyleInstance = firstEncounter && !styleNumbering && listRendering.startOverride === void 0 && abstractNumId !== null && previousList.abstractNumId === abstractNumId && previousList.fromStyle === true;
80
+ if (abstractNumId !== null && (styleNumbering || resumesRestartedInstance || resumesStyleInstance)) {
66
81
  const latestAbstractCounters = abstractCounters.get(abstractNumId);
67
- if (latestAbstractCounters) for (let i = 0; i < counters.length; i += 1) counters[i] = latestAbstractCounters[i] ?? NaN;
82
+ if (latestAbstractCounters) {
83
+ for (let i = 0; i < counters.length; i += 1) counters[i] = latestAbstractCounters[i] ?? NaN;
84
+ resumedAbstractCounters = latestAbstractCounters;
85
+ }
68
86
  }
87
+ if (listRendering.startOverride !== void 0 || resumesRestartedInstance || previousList.numId === numId && restartedNumIds.has(numId)) restartedNumIds.add(numId);
69
88
  if (abstractNumId !== null && level > 0) {
70
89
  const latestAbstractCounters = abstractCounters.get(abstractNumId);
71
90
  if (counters.slice(0, level).every(Number.isNaN)) for (let i = 0; i < level; i += 1) {
@@ -81,10 +100,22 @@ const computeListMarker = (paragraph, numbering, listCounters, abstractCounters)
81
100
  const childCounter = counters[level + 1];
82
101
  counters[level + 1] = (childCounter === void 0 || Number.isNaN(childCounter) ? 0 : childCounter) + childAdvances;
83
102
  }
84
- if (abstractNumId !== null) abstractCounters.set(abstractNumId, [...counters]);
103
+ if (abstractNumId !== null) {
104
+ if (resumedAbstractCounters) for (const [otherNumId, otherCounters] of listCounters) {
105
+ if (otherNumId === numId || numbering.getAbstractNumId(otherNumId) !== abstractNumId || !otherCounters.every((value, index) => Object.is(value, resumedAbstractCounters[index]))) continue;
106
+ for (let i = 0; i < otherCounters.length; i += 1) otherCounters[i] = counters[i] ?? NaN;
107
+ }
108
+ abstractCounters.set(abstractNumId, [...counters]);
109
+ }
110
+ previousList.abstractNumId = abstractNumId;
111
+ previousList.fromStyle = Boolean(styleNumbering);
112
+ previousList.numId = numId;
85
113
  const pattern = listRendering.marker;
86
114
  if (listRendering.isBullet) {
87
115
  listRendering.marker = convertBulletToUnicode(pattern || "");
116
+ previousList.abstractNumId = null;
117
+ previousList.fromStyle = false;
118
+ previousList.numId = null;
88
119
  return;
89
120
  }
90
121
  let computedMarker = pattern;
@@ -103,6 +134,12 @@ const computeListMarker = (paragraph, numbering, listCounters, abstractCounters)
103
134
  const parseBlockContent = (parent, styles, theme, numbering, rels, media, options) => parseBlockContentWithState(parent, styles, theme, numbering, rels, media, {
104
135
  listCounters: /* @__PURE__ */ new Map(),
105
136
  abstractCounters: /* @__PURE__ */ new Map(),
137
+ restartedNumIds: /* @__PURE__ */ new Set(),
138
+ previousList: {
139
+ abstractNumId: null,
140
+ fromStyle: false,
141
+ numId: null
142
+ },
106
143
  options: {
107
144
  ...options,
108
145
  rootXmlns: mergeXmlnsDeclarations(options?.rootXmlns ?? {}, parent)
@@ -118,7 +155,13 @@ const parseBlockContentWithState = (parent, styles, theme, numbering, rels, medi
118
155
  const paragraph = parseParagraph(child, styles, theme, numbering, rels, media, state.options);
119
156
  prependPendingBookmarkMarkers(paragraph, pendingBookmarkMarkers);
120
157
  enrichParagraphTextBoxes(paragraph, child, styles, theme, numbering, rels, media);
121
- computeListMarker(paragraph, numbering, state.listCounters, state.abstractCounters);
158
+ computeListMarker(paragraph, {
159
+ numbering,
160
+ listCounters: state.listCounters,
161
+ abstractCounters: state.abstractCounters,
162
+ restartedNumIds: state.restartedNumIds,
163
+ previousList: state.previousList
164
+ });
122
165
  content.push(paragraph);
123
166
  continue;
124
167
  }
@@ -0,0 +1,41 @@
1
+ //#region src/docx/capabilities.d.ts
2
+ declare const FOLIO_DOCX_CAPABILITY_MANIFEST_VERSION: 1;
3
+ declare const FOLIO_DOCX_CAPABILITY_HOSTS: readonly ["browser", "server"];
4
+ declare const FOLIO_DOCX_COMPATIBILITY_HOSTS: readonly ["browser", "server", "unknown"];
5
+ declare const FOLIO_DOCX_PROFILES: readonly ["strict", "transitional"];
6
+ declare const FOLIO_DOCX_COMPATIBILITY_PROFILES: readonly ["strict", "transitional", "unknown"];
7
+ declare const FOLIO_DOCX_CAPABILITY_OPERATIONS: readonly ["create", "edit", "preserve", "read", "render"];
8
+ declare const FOLIO_DOCX_SUPPORT_STATES: readonly ["supported", "partial", "unsupported"];
9
+ declare const FOLIO_DOCX_CAPABILITY_IDS: readonly ["comments", "contentControls", "fields", "headersFooters", "hyperlinks", "images", "math", "notes", "numbering", "opaqueDrawing", "paragraphs", "sections", "styles", "tables", "trackedChanges"];
10
+ type FolioDocxCapabilityHost = (typeof FOLIO_DOCX_CAPABILITY_HOSTS)[number];
11
+ type FolioDocxCompatibilityHost = (typeof FOLIO_DOCX_COMPATIBILITY_HOSTS)[number];
12
+ type FolioDocxProfile = (typeof FOLIO_DOCX_PROFILES)[number];
13
+ type FolioDocxCompatibilityProfile = (typeof FOLIO_DOCX_COMPATIBILITY_PROFILES)[number];
14
+ type FolioDocxCapabilityOperation = (typeof FOLIO_DOCX_CAPABILITY_OPERATIONS)[number];
15
+ type FolioDocxSupportState = (typeof FOLIO_DOCX_SUPPORT_STATES)[number];
16
+ type FolioDocxCapabilityId = (typeof FOLIO_DOCX_CAPABILITY_IDS)[number];
17
+ type FolioDocxFeatureCapability = {
18
+ readonly id: FolioDocxCapabilityId;
19
+ readonly feature: "comments" | "contentControls" | "drawings" | "fields" | "headersFooters" | "hyperlinks" | "images" | "math" | "notes" | "numbering" | "paragraphs" | "revisions" | "sections" | "styles" | "tables";
20
+ readonly hosts: readonly FolioDocxCapabilityHost[];
21
+ readonly profiles: readonly FolioDocxProfile[];
22
+ readonly support: Readonly<Record<FolioDocxCapabilityOperation, FolioDocxSupportState>>;
23
+ readonly evidence: readonly {
24
+ readonly type: "test";
25
+ readonly path: string;
26
+ }[];
27
+ };
28
+ type FolioDocxCapabilityManifest = {
29
+ readonly version: typeof FOLIO_DOCX_CAPABILITY_MANIFEST_VERSION;
30
+ readonly capabilities: Readonly<Record<FolioDocxCapabilityId, FolioDocxFeatureCapability>>;
31
+ };
32
+ declare const FOLIO_DOCX_CAPABILITY_MANIFEST: FolioDocxCapabilityManifest;
33
+ declare const InvalidFolioDocxCapabilityIdError_base: import("better-result").TaggedErrorClass<"InvalidFolioDocxCapabilityIdError", {
34
+ message: string;
35
+ receivedId: unknown;
36
+ }>;
37
+ declare class InvalidFolioDocxCapabilityIdError extends InvalidFolioDocxCapabilityIdError_base {}
38
+ declare const isFolioDocxCapabilityId: (value: unknown) => value is FolioDocxCapabilityId;
39
+ declare const getFolioDocxCapability: (id: unknown) => FolioDocxFeatureCapability;
40
+ //#endregion
41
+ export { FOLIO_DOCX_CAPABILITY_HOSTS, FOLIO_DOCX_CAPABILITY_IDS, FOLIO_DOCX_CAPABILITY_MANIFEST, FOLIO_DOCX_CAPABILITY_MANIFEST_VERSION, FOLIO_DOCX_CAPABILITY_OPERATIONS, FOLIO_DOCX_COMPATIBILITY_HOSTS, FOLIO_DOCX_COMPATIBILITY_PROFILES, FOLIO_DOCX_PROFILES, FOLIO_DOCX_SUPPORT_STATES, FolioDocxCapabilityHost, FolioDocxCapabilityId, FolioDocxCapabilityManifest, FolioDocxCapabilityOperation, FolioDocxCompatibilityHost, FolioDocxCompatibilityProfile, FolioDocxFeatureCapability, FolioDocxProfile, FolioDocxSupportState, InvalidFolioDocxCapabilityIdError, getFolioDocxCapability, isFolioDocxCapabilityId };
@@ -0,0 +1,322 @@
1
+ import { TaggedError } from "better-result";
2
+ //#region src/docx/capabilities.ts
3
+ const FOLIO_DOCX_CAPABILITY_MANIFEST_VERSION = 1;
4
+ const FOLIO_DOCX_CAPABILITY_HOSTS = Object.freeze(["browser", "server"]);
5
+ const FOLIO_DOCX_COMPATIBILITY_HOSTS = Object.freeze([...FOLIO_DOCX_CAPABILITY_HOSTS, "unknown"]);
6
+ const FOLIO_DOCX_PROFILES = Object.freeze(["strict", "transitional"]);
7
+ const FOLIO_DOCX_COMPATIBILITY_PROFILES = Object.freeze([...FOLIO_DOCX_PROFILES, "unknown"]);
8
+ const FOLIO_DOCX_CAPABILITY_OPERATIONS = Object.freeze([
9
+ "create",
10
+ "edit",
11
+ "preserve",
12
+ "read",
13
+ "render"
14
+ ]);
15
+ const FOLIO_DOCX_SUPPORT_STATES = Object.freeze([
16
+ "supported",
17
+ "partial",
18
+ "unsupported"
19
+ ]);
20
+ const FOLIO_DOCX_CAPABILITY_IDS = Object.freeze([
21
+ "comments",
22
+ "contentControls",
23
+ "fields",
24
+ "headersFooters",
25
+ "hyperlinks",
26
+ "images",
27
+ "math",
28
+ "notes",
29
+ "numbering",
30
+ "opaqueDrawing",
31
+ "paragraphs",
32
+ "sections",
33
+ "styles",
34
+ "tables",
35
+ "trackedChanges"
36
+ ]);
37
+ const TRANSITIONAL_PROFILE_COVERAGE = Object.freeze(["transitional"]);
38
+ const STRUCTURED_FEATURE_SUPPORT = Object.freeze({
39
+ create: "supported",
40
+ edit: "supported",
41
+ preserve: "supported",
42
+ read: "supported",
43
+ render: "partial"
44
+ });
45
+ const PARTIAL_AUTHORING_FEATURE_SUPPORT = Object.freeze({
46
+ create: "partial",
47
+ edit: "partial",
48
+ preserve: "supported",
49
+ read: "supported",
50
+ render: "partial"
51
+ });
52
+ const COMMENTS_CAPABILITY = Object.freeze({
53
+ id: "comments",
54
+ feature: "comments",
55
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
56
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
57
+ support: STRUCTURED_FEATURE_SUPPORT,
58
+ evidence: Object.freeze([{
59
+ type: "test",
60
+ path: "packages/core/src/docx/commentReplyThreads.test.ts"
61
+ }, {
62
+ type: "test",
63
+ path: "packages/core/src/prosemirror/commands/comments.test.ts"
64
+ }])
65
+ });
66
+ const CONTENT_CONTROLS_CAPABILITY = Object.freeze({
67
+ id: "contentControls",
68
+ feature: "contentControls",
69
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
70
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
71
+ support: Object.freeze({
72
+ ...PARTIAL_AUTHORING_FEATURE_SUPPORT,
73
+ edit: "supported"
74
+ }),
75
+ evidence: Object.freeze([{
76
+ type: "test",
77
+ path: "packages/core/src/content-controls/contentControls.test.ts"
78
+ }, {
79
+ type: "test",
80
+ path: "packages/core/src/docx/sdtRoundtrip.property.test.ts"
81
+ }])
82
+ });
83
+ const FIELDS_CAPABILITY = Object.freeze({
84
+ id: "fields",
85
+ feature: "fields",
86
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
87
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
88
+ support: PARTIAL_AUTHORING_FEATURE_SUPPORT,
89
+ evidence: Object.freeze([{
90
+ type: "test",
91
+ path: "packages/core/src/fields/evaluateField.test.ts"
92
+ }, {
93
+ type: "test",
94
+ path: "packages/core/src/prosemirror/extensions/nodes/FieldExtension.test.ts"
95
+ }])
96
+ });
97
+ const HEADERS_FOOTERS_CAPABILITY = Object.freeze({
98
+ id: "headersFooters",
99
+ feature: "headersFooters",
100
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
101
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
102
+ support: STRUCTURED_FEATURE_SUPPORT,
103
+ evidence: Object.freeze([{
104
+ type: "test",
105
+ path: "packages/core/src/docx/headerFooterParser.test.ts"
106
+ }, {
107
+ type: "test",
108
+ path: "packages/core/src/docx/headerFooterMaterialize.test.ts"
109
+ }])
110
+ });
111
+ const HYPERLINKS_CAPABILITY = Object.freeze({
112
+ id: "hyperlinks",
113
+ feature: "hyperlinks",
114
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
115
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
116
+ support: PARTIAL_AUTHORING_FEATURE_SUPPORT,
117
+ evidence: Object.freeze([{
118
+ type: "test",
119
+ path: "packages/core/src/docx/hyperlinkParser.test.ts"
120
+ }, {
121
+ type: "test",
122
+ path: "packages/core/src/prosemirror/conversion/toProseDoc-hyperlink-content.test.ts"
123
+ }])
124
+ });
125
+ const IMAGES_CAPABILITY = Object.freeze({
126
+ id: "images",
127
+ feature: "images",
128
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
129
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
130
+ support: Object.freeze({
131
+ ...PARTIAL_AUTHORING_FEATURE_SUPPORT,
132
+ edit: "supported"
133
+ }),
134
+ evidence: Object.freeze([{
135
+ type: "test",
136
+ path: "packages/core/src/docx/__tests__/image-crop-roundtrip.test.ts"
137
+ }, {
138
+ type: "test",
139
+ path: "packages/core/src/prosemirror/commands/image.test.ts"
140
+ }])
141
+ });
142
+ const MATH_CAPABILITY = Object.freeze({
143
+ id: "math",
144
+ feature: "math",
145
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
146
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
147
+ support: PARTIAL_AUTHORING_FEATURE_SUPPORT,
148
+ evidence: Object.freeze([{
149
+ type: "test",
150
+ path: "packages/core/src/docx/mathToMathml.test.ts"
151
+ }, {
152
+ type: "test",
153
+ path: "packages/core/src/docx/serializer/math-roundtrip.test.ts"
154
+ }])
155
+ });
156
+ const NOTES_CAPABILITY = Object.freeze({
157
+ id: "notes",
158
+ feature: "notes",
159
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
160
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
161
+ support: Object.freeze({
162
+ create: "partial",
163
+ edit: "supported",
164
+ preserve: "supported",
165
+ read: "supported",
166
+ render: "partial"
167
+ }),
168
+ evidence: Object.freeze([{
169
+ type: "test",
170
+ path: "packages/core/src/docx/noteSave.test.ts"
171
+ }, {
172
+ type: "test",
173
+ path: "packages/core/src/layout-bridge/convert/footnoteLayout-collect.test.ts"
174
+ }])
175
+ });
176
+ const NUMBERING_CAPABILITY = Object.freeze({
177
+ id: "numbering",
178
+ feature: "numbering",
179
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
180
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
181
+ support: Object.freeze({
182
+ create: "partial",
183
+ edit: "supported",
184
+ preserve: "supported",
185
+ read: "supported",
186
+ render: "partial"
187
+ }),
188
+ evidence: Object.freeze([{
189
+ type: "test",
190
+ path: "packages/core/src/docx/numberingParser-custom-format.test.ts"
191
+ }, {
192
+ type: "test",
193
+ path: "packages/core/src/docx/numberingSave.test.ts"
194
+ }])
195
+ });
196
+ const OPAQUE_DRAWING_CAPABILITY = Object.freeze({
197
+ id: "opaqueDrawing",
198
+ feature: "drawings",
199
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
200
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
201
+ support: Object.freeze({
202
+ create: "unsupported",
203
+ edit: "unsupported",
204
+ preserve: "supported",
205
+ read: "supported",
206
+ render: "partial"
207
+ }),
208
+ evidence: Object.freeze([{
209
+ type: "test",
210
+ path: "packages/core/src/docx/compatibility.test.ts"
211
+ }, {
212
+ type: "test",
213
+ path: "packages/core/src/docx/rezip.test.ts"
214
+ }])
215
+ });
216
+ const PARAGRAPHS_CAPABILITY = Object.freeze({
217
+ id: "paragraphs",
218
+ feature: "paragraphs",
219
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
220
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
221
+ support: STRUCTURED_FEATURE_SUPPORT,
222
+ evidence: Object.freeze([{
223
+ type: "test",
224
+ path: "packages/core/src/docx/paragraphParser.test.ts"
225
+ }, {
226
+ type: "test",
227
+ path: "packages/core/src/docx/serializer/paragraphSerializer.test.ts"
228
+ }])
229
+ });
230
+ const SECTIONS_CAPABILITY = Object.freeze({
231
+ id: "sections",
232
+ feature: "sections",
233
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
234
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
235
+ support: STRUCTURED_FEATURE_SUPPORT,
236
+ evidence: Object.freeze([{
237
+ type: "test",
238
+ path: "packages/core/src/docx/serializer/sectionPropertiesSerializer.test.ts"
239
+ }, {
240
+ type: "test",
241
+ path: "packages/core/src/prosemirror/commands/sectionBreak.test.ts"
242
+ }])
243
+ });
244
+ const STYLES_CAPABILITY = Object.freeze({
245
+ id: "styles",
246
+ feature: "styles",
247
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
248
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
249
+ support: Object.freeze({
250
+ create: "partial",
251
+ edit: "partial",
252
+ preserve: "supported",
253
+ read: "supported",
254
+ render: "partial"
255
+ }),
256
+ evidence: Object.freeze([{
257
+ type: "test",
258
+ path: "packages/core/src/docx/styleParser.test.ts"
259
+ }, {
260
+ type: "test",
261
+ path: "packages/core/src/prosemirror/conversion/characterStyleRoundtrip.test.ts"
262
+ }])
263
+ });
264
+ const TABLES_CAPABILITY = Object.freeze({
265
+ id: "tables",
266
+ feature: "tables",
267
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
268
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
269
+ support: STRUCTURED_FEATURE_SUPPORT,
270
+ evidence: Object.freeze([{
271
+ type: "test",
272
+ path: "packages/core/src/docx/tableParser.test.ts"
273
+ }, {
274
+ type: "test",
275
+ path: "packages/core/src/prosemirror/conversion/tableBordersRoundtrip.test.ts"
276
+ }])
277
+ });
278
+ const TRACKED_CHANGES_CAPABILITY = Object.freeze({
279
+ id: "trackedChanges",
280
+ feature: "revisions",
281
+ hosts: FOLIO_DOCX_CAPABILITY_HOSTS,
282
+ profiles: TRANSITIONAL_PROFILE_COVERAGE,
283
+ support: STRUCTURED_FEATURE_SUPPORT,
284
+ evidence: Object.freeze([{
285
+ type: "test",
286
+ path: "packages/core/src/redline.test.ts"
287
+ }, {
288
+ type: "test",
289
+ path: "packages/core/src/prosemirror/plugins/suggestionMode.test.ts"
290
+ }])
291
+ });
292
+ const FOLIO_DOCX_CAPABILITY_MANIFEST = Object.freeze({
293
+ version: 1,
294
+ capabilities: Object.freeze({
295
+ comments: COMMENTS_CAPABILITY,
296
+ contentControls: CONTENT_CONTROLS_CAPABILITY,
297
+ fields: FIELDS_CAPABILITY,
298
+ headersFooters: HEADERS_FOOTERS_CAPABILITY,
299
+ hyperlinks: HYPERLINKS_CAPABILITY,
300
+ images: IMAGES_CAPABILITY,
301
+ math: MATH_CAPABILITY,
302
+ notes: NOTES_CAPABILITY,
303
+ numbering: NUMBERING_CAPABILITY,
304
+ opaqueDrawing: OPAQUE_DRAWING_CAPABILITY,
305
+ paragraphs: PARAGRAPHS_CAPABILITY,
306
+ sections: SECTIONS_CAPABILITY,
307
+ styles: STYLES_CAPABILITY,
308
+ tables: TABLES_CAPABILITY,
309
+ trackedChanges: TRACKED_CHANGES_CAPABILITY
310
+ })
311
+ });
312
+ var InvalidFolioDocxCapabilityIdError = class extends TaggedError("InvalidFolioDocxCapabilityIdError")() {};
313
+ const isFolioDocxCapabilityId = (value) => FOLIO_DOCX_CAPABILITY_IDS.some((id) => id === value);
314
+ const getFolioDocxCapability = (id) => {
315
+ if (!isFolioDocxCapabilityId(id)) throw new InvalidFolioDocxCapabilityIdError({
316
+ message: "Invalid DOCX capability id.",
317
+ receivedId: id
318
+ });
319
+ return FOLIO_DOCX_CAPABILITY_MANIFEST.capabilities[id];
320
+ };
321
+ //#endregion
322
+ export { FOLIO_DOCX_CAPABILITY_HOSTS, FOLIO_DOCX_CAPABILITY_IDS, FOLIO_DOCX_CAPABILITY_MANIFEST, FOLIO_DOCX_CAPABILITY_MANIFEST_VERSION, FOLIO_DOCX_CAPABILITY_OPERATIONS, FOLIO_DOCX_COMPATIBILITY_HOSTS, FOLIO_DOCX_COMPATIBILITY_PROFILES, FOLIO_DOCX_PROFILES, FOLIO_DOCX_SUPPORT_STATES, InvalidFolioDocxCapabilityIdError, getFolioDocxCapability, isFolioDocxCapabilityId };
@@ -1,12 +1,44 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
+ import { FolioDocxCompatibilityHost, FolioDocxCompatibilityProfile, FolioDocxFeatureCapability } from "./capabilities.js";
2
3
 
3
4
  //#region src/docx/compatibility.d.ts
4
5
  type DocxCompatibilityReason = "opaqueDrawing";
6
+ type DocxCompatibilityContext = {
7
+ host: FolioDocxCompatibilityHost;
8
+ profile: FolioDocxCompatibilityProfile;
9
+ };
10
+ type InspectDocxCompatibilityOptions = Partial<DocxCompatibilityContext>;
11
+ type DocxCompatibilityPart = {
12
+ type: "document";
13
+ } | {
14
+ type: "header" | "footer";
15
+ relationshipId: string;
16
+ } | {
17
+ type: "footnote" | "endnote";
18
+ id: number;
19
+ };
20
+ type DocxCompatibilityLocation = {
21
+ part: DocxCompatibilityPart;
22
+ path: string;
23
+ blockId?: string;
24
+ };
25
+ type DocxCompatibilityIssue = {
26
+ code: DocxCompatibilityReason;
27
+ capability: FolioDocxFeatureCapability;
28
+ coverage: {
29
+ host: "covered" | "unknown" | "unverified";
30
+ profile: "covered" | "unknown" | "unverified";
31
+ };
32
+ location: DocxCompatibilityLocation;
33
+ };
5
34
  type DocxCompatibility = {
35
+ schemaVersion: 1;
36
+ context: DocxCompatibilityContext;
6
37
  canSafelyEdit: boolean;
38
+ issues: DocxCompatibilityIssue[];
7
39
  reasons: DocxCompatibilityReason[];
8
40
  unsupportedContentCount: number;
9
41
  };
10
- declare function inspectDocxCompatibility(doc: document_d_exports.Document): DocxCompatibility;
42
+ declare const inspectDocxCompatibility: (doc: document_d_exports.Document, options?: InspectDocxCompatibilityOptions) => DocxCompatibility;
11
43
  //#endregion
12
- export { DocxCompatibility, DocxCompatibilityReason, inspectDocxCompatibility };
44
+ export { DocxCompatibility, DocxCompatibilityContext, DocxCompatibilityIssue, DocxCompatibilityLocation, DocxCompatibilityPart, DocxCompatibilityReason, InspectDocxCompatibilityOptions, inspectDocxCompatibility };