@stll/folio-core 0.4.0 → 0.5.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 (99) hide show
  1. package/dist/ai-edits/apply.d.ts +3 -9
  2. package/dist/ai-edits/apply.js +94 -14
  3. package/dist/ai-edits/blockRange.d.ts +33 -0
  4. package/dist/ai-edits/blockRange.js +58 -0
  5. package/dist/ai-edits/headless.d.ts +33 -4
  6. package/dist/ai-edits/headless.js +83 -15
  7. package/dist/ai-edits/index.d.ts +5 -3
  8. package/dist/ai-edits/index.js +3 -2
  9. package/dist/ai-edits/snapshot.d.ts +14 -2
  10. package/dist/ai-edits/snapshot.js +12 -1
  11. package/dist/ai-edits/types.d.ts +42 -3
  12. package/dist/compat/eigenpal.d.ts +3 -2
  13. package/dist/compat/eigenpal.js +6 -5
  14. package/dist/controller/layoutPipeline.d.ts +1 -0
  15. package/dist/controller/layoutPipeline.js +35 -137
  16. package/dist/controller/layoutScheduler.d.ts +2 -1
  17. package/dist/controller/layoutScheduler.js +6 -0
  18. package/dist/document-operations.d.ts +122 -0
  19. package/dist/document-operations.js +575 -0
  20. package/dist/docx/blockContentParser.js +17 -7
  21. package/dist/docx/encryption/agileDecryption.js +2 -1
  22. package/dist/docx/encryption/compoundFile.js +4 -2
  23. package/dist/docx/footnoteParser.d.ts +1 -17
  24. package/dist/docx/footnoteParser.js +1 -27
  25. package/dist/docx/groupDrawingParser.d.ts +8 -0
  26. package/dist/docx/groupDrawingParser.js +131 -0
  27. package/dist/docx/numberingParser.d.ts +3 -1
  28. package/dist/docx/numberingParser.js +8 -2
  29. package/dist/docx/paragraphParser.js +9 -3
  30. package/dist/docx/runParser.js +8 -1
  31. package/dist/docx/selectiveXmlPatch.js +4 -10
  32. package/dist/docx/serializer/numberingSerializer.js +3 -1
  33. package/dist/docx/settingsParser.d.ts +6 -3
  34. package/dist/docx/settingsParser.js +2 -0
  35. package/dist/docx/xmlParser.js +11 -4
  36. package/dist/index.d.ts +3 -2
  37. package/dist/index.js +6 -5
  38. package/dist/layout-bridge/convert/footnoteLayout.d.ts +37 -1
  39. package/dist/layout-bridge/convert/footnoteLayout.js +138 -14
  40. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +5 -7
  41. package/dist/layout-bridge/convert/headerFooterLayout.js +5 -7
  42. package/dist/layout-bridge/convert/toFlowBlocks.js +56 -19
  43. package/dist/layout-engine/index.d.ts +6 -5
  44. package/dist/layout-engine/index.js +89 -26
  45. package/dist/layout-engine/keep-together.d.ts +13 -8
  46. package/dist/layout-engine/keep-together.js +40 -25
  47. package/dist/layout-engine/layoutInstrumentation.d.ts +11 -1
  48. package/dist/layout-engine/layoutInstrumentation.js +10 -1
  49. package/dist/layout-engine/measure/measureBlocks.js +28 -18
  50. package/dist/layout-engine/measure/measureParagraph.js +61 -15
  51. package/dist/layout-engine/paginator.d.ts +2 -1
  52. package/dist/layout-engine/paginator.js +9 -3
  53. package/dist/layout-engine/textBoxGroup.d.ts +7 -0
  54. package/dist/layout-engine/textBoxGroup.js +8 -0
  55. package/dist/layout-engine/types.d.ts +30 -9
  56. package/dist/layout-engine/types.js +20 -2
  57. package/dist/layout-painter/renderPage.d.ts +15 -1
  58. package/dist/layout-painter/renderPage.js +27 -11
  59. package/dist/layout-painter/renderParagraph.js +18 -8
  60. package/dist/layout-painter/renderTable.js +10 -7
  61. package/dist/managers/DocumentLoaderManager.js +12 -5
  62. package/dist/managers/TableSelectionManager.js +1 -1
  63. package/dist/model.js +1 -1
  64. package/dist/paged-layout/pageText.d.ts +14 -0
  65. package/dist/paged-layout/pageText.js +21 -0
  66. package/dist/prosemirror/attrs/index.js +2 -0
  67. package/dist/prosemirror/commands/comments.js +75 -5
  68. package/dist/prosemirror/commands/hyperlink.js +4 -2
  69. package/dist/prosemirror/commands/image.js +2 -1
  70. package/dist/prosemirror/commands/index.js +1 -1
  71. package/dist/prosemirror/commands/propertyChangeScope.d.ts +68 -0
  72. package/dist/prosemirror/commands/propertyChangeScope.js +242 -0
  73. package/dist/prosemirror/conversion/fromProseDoc.js +14 -3
  74. package/dist/prosemirror/conversion/toProseDoc.js +29 -8
  75. package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -0
  76. package/dist/prosemirror/extensions/features/ListExtension.js +6 -0
  77. package/dist/prosemirror/extensions/nodes/TableExtension.js +10 -11
  78. package/dist/prosemirror/findReplaceSelection.js +2 -1
  79. package/dist/prosemirror/index.js +1 -1
  80. package/dist/prosemirror/insertOperations.js +1 -1
  81. package/dist/prosemirror/schema/nodes.d.ts +10 -5
  82. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  83. package/dist/prosemirror/utils/tabCalculator.js +4 -2
  84. package/dist/redline.d.ts +20 -0
  85. package/dist/redline.js +127 -0
  86. package/dist/server.d.ts +7 -3
  87. package/dist/server.js +6 -2
  88. package/dist/symbols.d.ts +35 -0
  89. package/dist/symbols.js +512 -0
  90. package/dist/utils/clipboard.js +3 -3
  91. package/dist/utils/fontLoader.js +3 -0
  92. package/dist/utils/fontResolver.js +48 -1
  93. package/dist/utils/zoom.d.ts +21 -0
  94. package/dist/utils/zoom.js +21 -0
  95. package/dist/version-comparison.d.ts +92 -0
  96. package/dist/version-comparison.js +436 -0
  97. package/package.json +3 -3
  98. package/dist/paged-layout/headerFooterMargins.d.ts +0 -75
  99. package/dist/paged-layout/headerFooterMargins.js +0 -122
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/folio-core",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Headless, framework-neutral core of folio: the OOXML (.docx) parser, document model, ProseMirror integration, and page-layout engine. No React.",
5
5
  "keywords": [
6
6
  "document-model",
@@ -101,7 +101,7 @@
101
101
  "build": "rm -rf dist && tsdown",
102
102
  "prepack": "bun run build",
103
103
  "pack:dry-run": "bun pm pack --dry-run",
104
- "typecheck": "tsgo --noEmit -p tsconfig.build.json",
104
+ "typecheck": "bun ../../scripts/tsc-native.ts --noEmit -p tsconfig.build.json",
105
105
  "test": "bun test src",
106
106
  "test:property": "bun test $(grep -rlF 'fc.assert' src --include='*.test.ts')",
107
107
  "perf": "bun scripts/profile-editor.ts"
@@ -126,7 +126,7 @@
126
126
  "prosemirror-transform": "^1.12.0",
127
127
  "prosemirror-view": "^1.41.8",
128
128
  "utif2": "^4.1.0",
129
- "valibot": "1.4.1",
129
+ "valibot": "1.4.2",
130
130
  "y-prosemirror": "^1.3.7",
131
131
  "yjs": "^13.6.31"
132
132
  },
@@ -1,75 +0,0 @@
1
- import { HeaderFooterContent, PageMargins, SectionBreakBlock } from "../layout-engine/types.js";
2
- //#region src/paged-layout/headerFooterMargins.d.ts
3
- type EffectiveHeaderFooterMarginsInput = {
4
- margins: PageMargins;
5
- headerContent?: HeaderFooterContent | undefined;
6
- footerContent?: HeaderFooterContent | undefined;
7
- firstPageHeaderContent?: HeaderFooterContent | undefined;
8
- firstPageFooterContent?: HeaderFooterContent | undefined;
9
- pageSize?: {
10
- w: number;
11
- h: number;
12
- } | undefined;
13
- warn?: ((message: string) => void) | undefined;
14
- };
15
- /**
16
- * A function that extends a `PageMargins` to clear the HF overflow computed
17
- * from a given set of header/footer content. Returned by
18
- * `computeHeaderFooterMarginExtender` and applied at every margins site:
19
- * the body fallback, `finalMargins`, and per-section `sectionBreak.margins`.
20
- *
21
- * Eigenpal #400 — pre-PR the extension only applied to the body fallback,
22
- * so a section break carrying its own `sb.margins` from `<w:sectPr>`
23
- * silently overrode the extension and the footer rendered on top of body
24
- * text.
25
- */
26
- type PageMarginsExtender = (margins: PageMargins) => PageMargins;
27
- declare function computeHeaderFooterMarginExtender(input: Omit<EffectiveHeaderFooterMarginsInput, "margins">): PageMarginsExtender;
28
- /**
29
- * Like `computeHeaderFooterMarginExtender` but also accounts for the
30
- * first-page header/footer content. Apply this only to the margins used
31
- * for page 1 of a `<w:titlePg/>`-enabled section.
32
- */
33
- declare function computeFirstPageHeaderFooterMarginExtender(input: Omit<EffectiveHeaderFooterMarginsInput, "margins">): PageMarginsExtender;
34
- declare function computeEffectiveHeaderFooterMargins({
35
- margins,
36
- headerContent,
37
- footerContent,
38
- firstPageHeaderContent,
39
- firstPageFooterContent,
40
- pageSize,
41
- warn
42
- }: EffectiveHeaderFooterMarginsInput): PageMargins;
43
- /** Rendered header/footer content shared by every extender on a page. */
44
- type HeaderFooterExtenderContent = Omit<EffectiveHeaderFooterMarginsInput, "margins" | "pageSize" | "warn">;
45
- type ExtendSectionBreakMarginsInput = {
46
- content: HeaderFooterExtenderContent;
47
- sectionContent?: HeaderFooterExtenderContent[] | undefined; /** Body page size and effective margins — the inheritance seed. */
48
- bodyPageSize: {
49
- w: number;
50
- h: number;
51
- };
52
- bodyMargins: PageMargins;
53
- warn?: ((message: string) => void) | undefined;
54
- };
55
- /**
56
- * Extend every section break's margins to clear the same header/footer
57
- * overflow the body margins do (eigenpal #400), so an overflowing footer
58
- * never re-overlaps body text on a later section.
59
- *
60
- * The walk mirrors `collectSectionConfigs`: a break that omits its own
61
- * `pageSize` or `margins` inherits the previous section's. Each break's
62
- * authored-or-inherited margins are extended against the section's *own*
63
- * resolved page height, so a taller page never keeps a smaller page's
64
- * clamped reservation (and vice versa). Materializes `margins` on every
65
- * non-inheriting break in place.
66
- */
67
- declare function extendSectionBreakMargins(sectionBreaks: SectionBreakBlock[], {
68
- content,
69
- sectionContent,
70
- bodyPageSize,
71
- bodyMargins,
72
- warn
73
- }: ExtendSectionBreakMarginsInput): void;
74
- //#endregion
75
- export { HeaderFooterExtenderContent, PageMarginsExtender, computeEffectiveHeaderFooterMargins, computeFirstPageHeaderFooterMarginExtender, computeHeaderFooterMarginExtender, extendSectionBreakMargins };
@@ -1,122 +0,0 @@
1
- //#region src/paged-layout/headerFooterMargins.ts
2
- /**
3
- * Floor on the body content area, in pixels. Header/footer overflow can
4
- * never shrink the content band below this, so a degenerate document
5
- * (a header taller than the page) still renders some body text.
6
- */
7
- const MIN_CONTENT_HEIGHT_PX = 24;
8
- function headerHeight(content) {
9
- if (!content) return 0;
10
- return content.marginPushBottom ?? content.visualBottom ?? content.height;
11
- }
12
- function footerHeight(content) {
13
- if (!content) return 0;
14
- const bottom = content.marginPushBottom ?? content.visualBottom ?? content.height;
15
- const top = content.marginPushTop ?? content.visualTop ?? 0;
16
- return Math.max(bottom - top, content.height);
17
- }
18
- /**
19
- * Build a function that, applied to any `PageMargins`, extends `top`/`bottom`
20
- * to clear the same header/footer content the body's effective margins do.
21
- * Returns the identity function when no extension is needed.
22
- *
23
- * Header/footer distances are taken from the *given* margins (the source
24
- * paragraph's section margins), not the body's, so each section's authored
25
- * `w:header`/`w:footer` distances are honored.
26
- */
27
- /**
28
- * Build an extender that pushes body margins clear of HF content.
29
- *
30
- * `mode === "default"` ignores `firstPageHeaderContent` /
31
- * `firstPageFooterContent`. The first-page H/F only renders on page 1 of
32
- * a `<w:titlePg/>`-enabled section, so margins for pages 2+ within the
33
- * same section must NOT be extended for first-page overflow — extending
34
- * them would push body content down on every page even though only page
35
- * 1 actually carries the overflowing header. This produced visible
36
- * regressions on NVCA-style first-page-header docs, where pages 2+
37
- * inherited page 1's title-page header reservation.
38
- *
39
- * `mode === "firstPage"` uses the larger of the default and first-page
40
- * H/F heights — applied only to the first-page margins of a titlePg
41
- * section.
42
- */
43
- function buildExtender({ headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, pageSize, warn, mode }) {
44
- const headerContentHeight = mode === "firstPage" ? Math.max(headerHeight(headerContent), headerHeight(firstPageHeaderContent)) : headerHeight(headerContent);
45
- const footerContentHeight = mode === "firstPage" ? Math.max(footerHeight(footerContent), footerHeight(firstPageFooterContent)) : footerHeight(footerContent);
46
- return (margins) => {
47
- const headerDistance = margins.header ?? 48;
48
- const footerDistance = margins.footer ?? 48;
49
- const availableHeaderSpace = margins.top - headerDistance;
50
- const availableFooterSpace = margins.bottom - footerDistance;
51
- const maxMargins = pageSize ? Math.max(0, pageSize.h - MIN_CONTENT_HEIGHT_PX) : void 0;
52
- const fitsContent = headerContentHeight <= availableHeaderSpace && footerContentHeight <= availableFooterSpace;
53
- const fitsPage = maxMargins === void 0 || margins.top + margins.bottom <= maxMargins;
54
- if (fitsContent && fitsPage) return margins;
55
- const out = { ...margins };
56
- if (headerContentHeight > availableHeaderSpace) out.top = Math.max(margins.top, headerDistance + headerContentHeight);
57
- if (footerContentHeight > availableFooterSpace) out.bottom = Math.max(margins.bottom, footerDistance + footerContentHeight);
58
- if (pageSize && maxMargins !== void 0 && out.top + out.bottom > maxMargins) {
59
- if (warn) warn(`header/footer content exceeds page height; clamping margins to preserve a content area. pageHeight=${Math.round(pageSize.h)} top=${Math.round(out.top)} bottom=${Math.round(out.bottom)}`);
60
- out.bottom = Math.max(0, Math.min(out.bottom, maxMargins - out.top));
61
- if (out.top + out.bottom > maxMargins) out.top = Math.max(0, maxMargins - out.bottom);
62
- }
63
- return out;
64
- };
65
- }
66
- function computeHeaderFooterMarginExtender(input) {
67
- return buildExtender({
68
- ...input,
69
- mode: "default"
70
- });
71
- }
72
- /**
73
- * Like `computeHeaderFooterMarginExtender` but also accounts for the
74
- * first-page header/footer content. Apply this only to the margins used
75
- * for page 1 of a `<w:titlePg/>`-enabled section.
76
- */
77
- function computeFirstPageHeaderFooterMarginExtender(input) {
78
- return buildExtender({
79
- ...input,
80
- mode: "firstPage"
81
- });
82
- }
83
- function computeEffectiveHeaderFooterMargins({ margins, headerContent, footerContent, firstPageHeaderContent, firstPageFooterContent, pageSize, warn }) {
84
- return computeHeaderFooterMarginExtender({
85
- headerContent,
86
- footerContent,
87
- firstPageHeaderContent,
88
- firstPageFooterContent,
89
- pageSize,
90
- warn
91
- })(margins);
92
- }
93
- /**
94
- * Extend every section break's margins to clear the same header/footer
95
- * overflow the body margins do (eigenpal #400), so an overflowing footer
96
- * never re-overlaps body text on a later section.
97
- *
98
- * The walk mirrors `collectSectionConfigs`: a break that omits its own
99
- * `pageSize` or `margins` inherits the previous section's. Each break's
100
- * authored-or-inherited margins are extended against the section's *own*
101
- * resolved page height, so a taller page never keeps a smaller page's
102
- * clamped reservation (and vice versa). Materializes `margins` on every
103
- * non-inheriting break in place.
104
- */
105
- function extendSectionBreakMargins(sectionBreaks, { content, sectionContent, bodyPageSize, bodyMargins, warn }) {
106
- let pageSize = bodyPageSize;
107
- let margins = bodyMargins;
108
- for (let index = 0; index < sectionBreaks.length; index++) {
109
- const sb = sectionBreaks[index];
110
- if (!sb) continue;
111
- if (!sb.pageSize && !sb.margins) continue;
112
- pageSize = sb.pageSize ?? pageSize;
113
- margins = computeHeaderFooterMarginExtender({
114
- ...sectionContent?.[index + 1] ?? content,
115
- pageSize,
116
- warn
117
- })(sb.margins ?? margins);
118
- sb.margins = margins;
119
- }
120
- }
121
- //#endregion
122
- export { computeEffectiveHeaderFooterMargins, computeFirstPageHeaderFooterMarginExtender, computeHeaderFooterMarginExtender, extendSectionBreakMargins };