@stll/folio-core 0.8.0 → 0.9.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 (152) hide show
  1. package/README.md +39 -0
  2. package/dist/ai-edits/apply.js +18 -4
  3. package/dist/ai-edits/headless.d.ts +31 -4
  4. package/dist/ai-edits/headless.js +148 -35
  5. package/dist/ai-edits/index.d.ts +3 -3
  6. package/dist/ai-edits/index.js +2 -1
  7. package/dist/ai-edits/snapshot.js +40 -3
  8. package/dist/ai-edits/types.d.ts +2 -1
  9. package/dist/compat/eigenpal.d.ts +6 -4
  10. package/dist/compat/eigenpal.js +5 -3
  11. package/dist/controller/latestRequestGate.d.ts +13 -0
  12. package/dist/controller/latestRequestGate.js +16 -0
  13. package/dist/controller/layoutPipeline.js +12 -1
  14. package/dist/document-operations.d.ts +10 -3
  15. package/dist/document-operations.js +29 -14
  16. package/dist/docx/blockContentParser.js +2 -2
  17. package/dist/docx/commentParser.js +1 -1
  18. package/dist/docx/compatibility.d.ts +3 -7
  19. package/dist/docx/compatibility.js +0 -11
  20. package/dist/docx/encryption/agileDecryption.js +1 -1
  21. package/dist/docx/encryption/encryptionInfo.js +1 -1
  22. package/dist/docx/encryption/openEncryptedDocx.js +1 -1
  23. package/dist/docx/fontTableParser.d.ts +6 -0
  24. package/dist/docx/fontTableParser.js +72 -0
  25. package/dist/docx/groupDrawingParser.js +7 -2
  26. package/dist/docx/headerFooterParser.js +1 -1
  27. package/dist/docx/normalizeBaseDirection.js +1 -1
  28. package/dist/docx/numberingParser.js +1 -0
  29. package/dist/docx/paragraphParser.js +12 -1
  30. package/dist/docx/parser.d.ts +1 -1
  31. package/dist/docx/parser.js +12 -9
  32. package/dist/docx/rezip.js +70 -5
  33. package/dist/docx/runConsolidator.js +4 -0
  34. package/dist/docx/runParser.js +19 -1
  35. package/dist/docx/selectiveSave.js +3 -3
  36. package/dist/docx/serializer/fontTableSerializer.d.ts +6 -0
  37. package/dist/docx/serializer/fontTableSerializer.js +26 -0
  38. package/dist/docx/serializer/headerFooterSerializer.js +1 -1
  39. package/dist/docx/serializer/paragraphSerializer.js +4 -0
  40. package/dist/docx/serializer/runSerializer.js +7 -0
  41. package/dist/docx/serializer/settingsSerializer.d.ts +6 -0
  42. package/dist/docx/serializer/settingsSerializer.js +16 -0
  43. package/dist/docx/serializer/stylesSerializer.d.ts +6 -0
  44. package/dist/docx/serializer/stylesSerializer.js +56 -0
  45. package/dist/docx/serializer/tableSerializer.js +25 -26
  46. package/dist/docx/serializer/themeSerializer.d.ts +6 -0
  47. package/dist/docx/serializer/themeSerializer.js +36 -0
  48. package/dist/docx/settingsParser.js +46 -0
  49. package/dist/docx/styleParser.js +26 -1
  50. package/dist/docx/tableParser.js +11 -1
  51. package/dist/docx/vmlImageParser.js +1 -0
  52. package/dist/i18n/messages/catalogs.gen.d.ts +5916 -5916
  53. package/dist/i18n/messages/catalogs.gen.js +5910 -5910
  54. package/dist/index.d.ts +6 -4
  55. package/dist/index.js +5 -3
  56. package/dist/layout-bridge/convert/footnoteLayout.d.ts +3 -0
  57. package/dist/layout-bridge/convert/footnoteLayout.js +3 -1
  58. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +3 -0
  59. package/dist/layout-bridge/convert/headerFooterLayout.js +6 -1
  60. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +14 -2
  61. package/dist/layout-bridge/convert/toFlowBlocks.js +51 -14
  62. package/dist/layout-bridge/engine/measuring/index.d.ts +2 -1
  63. package/dist/layout-bridge/engine/measuring/index.js +2 -1
  64. package/dist/layout-engine/index.js +36 -28
  65. package/dist/layout-engine/measure/cache.js +11 -3
  66. package/dist/layout-engine/measure/font-metrics.worker.js +1 -0
  67. package/dist/layout-engine/measure/index.d.ts +2 -1
  68. package/dist/layout-engine/measure/index.js +2 -1
  69. package/dist/layout-engine/measure/lineBreakProvider.d.ts +33 -0
  70. package/dist/layout-engine/measure/lineBreakProvider.js +252 -0
  71. package/dist/layout-engine/measure/lineBreaks.d.ts +7 -2
  72. package/dist/layout-engine/measure/lineBreaks.js +11 -18
  73. package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
  74. package/dist/layout-engine/measure/listMarkerWidth.js +12 -6
  75. package/dist/layout-engine/measure/measureBlocks.d.ts +1 -2
  76. package/dist/layout-engine/measure/measureBlocks.js +6 -36
  77. package/dist/layout-engine/measure/measureContainer.js +32 -9
  78. package/dist/layout-engine/measure/measureHelpers.js +5 -2
  79. package/dist/layout-engine/measure/measureParagraph.js +335 -72
  80. package/dist/layout-engine/measure/measureTypes.d.ts +2 -1
  81. package/dist/layout-engine/measure/measureWorker.d.ts +2 -2
  82. package/dist/layout-engine/measure/measureWorker.js +8 -19
  83. package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +3 -14
  84. package/dist/layout-engine/measure/tableCellFloating.d.ts +10 -3
  85. package/dist/layout-engine/measure/tableCellFloating.js +37 -29
  86. package/dist/layout-engine/measure/tableCellFlow.d.ts +27 -0
  87. package/dist/layout-engine/measure/tableCellFlow.js +73 -0
  88. package/dist/layout-engine/measure/tableCellGrid.js +1 -1
  89. package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +18 -0
  90. package/dist/layout-engine/measure/textMeasurementPolicy.js +24 -0
  91. package/dist/layout-engine/renderedBreakReconciliation.d.ts +6 -1
  92. package/dist/layout-engine/renderedBreakReconciliation.js +34 -11
  93. package/dist/layout-engine/tableRowBreak.d.ts +5 -2
  94. package/dist/layout-engine/tableRowBreak.js +62 -29
  95. package/dist/layout-engine/types.d.ts +40 -7
  96. package/dist/layout-painter/anchoredImagePosition.d.ts +23 -0
  97. package/dist/layout-painter/anchoredImagePosition.js +95 -0
  98. package/dist/layout-painter/borderStroke.d.ts +23 -0
  99. package/dist/layout-painter/borderStroke.js +39 -0
  100. package/dist/layout-painter/renderImage.d.ts +5 -4
  101. package/dist/layout-painter/renderImage.js +18 -4
  102. package/dist/layout-painter/renderPage.d.ts +2 -27
  103. package/dist/layout-painter/renderPage.js +13 -99
  104. package/dist/layout-painter/renderParagraph.js +41 -23
  105. package/dist/layout-painter/renderTable.d.ts +2 -0
  106. package/dist/layout-painter/renderTable.js +223 -43
  107. package/dist/managers/DocumentLoaderManager.d.ts +1 -1
  108. package/dist/managers/DocumentLoaderManager.js +2 -2
  109. package/dist/prosemirror/attrs/index.d.ts +4 -2
  110. package/dist/prosemirror/attrs/index.js +21 -2
  111. package/dist/prosemirror/commands/propertyChangeScope.js +1 -1
  112. package/dist/prosemirror/conversion/fromProseDoc.js +33 -18
  113. package/dist/prosemirror/conversion/toProseDoc.js +50 -18
  114. package/dist/prosemirror/extensions/StarterKit.js +2 -0
  115. package/dist/prosemirror/extensions/core/ParagraphExtension.js +7 -2
  116. package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +1 -1
  117. package/dist/prosemirror/extensions/features/ListExtension.js +1 -0
  118. package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +1 -0
  119. package/dist/prosemirror/extensions/marks/HighlightExtension.js +1 -1
  120. package/dist/prosemirror/extensions/marks/LanguageExtension.d.ts +7 -0
  121. package/dist/prosemirror/extensions/marks/LanguageExtension.js +30 -0
  122. package/dist/prosemirror/extensions/marks/RunShadingExtension.js +1 -1
  123. package/dist/prosemirror/extensions/marks/TextColorExtension.js +1 -1
  124. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +1 -1
  125. package/dist/prosemirror/extensions/marks/markUtils.js +12 -0
  126. package/dist/prosemirror/extensions/nodes/ImageExtension.js +2 -1
  127. package/dist/prosemirror/extensions/nodes/TableExtension.js +4 -2
  128. package/dist/prosemirror/schema/index.d.ts +2 -2
  129. package/dist/prosemirror/schema/marks.d.ts +6 -1
  130. package/dist/prosemirror/schema/nodes.d.ts +13 -11
  131. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  132. package/dist/prosemirror/utils/tabCalculator.d.ts +3 -1
  133. package/dist/prosemirror/utils/tabCalculator.js +12 -10
  134. package/dist/prosemirror/validation.js +4 -1
  135. package/dist/redline.js +13 -3
  136. package/dist/server.d.ts +6 -3
  137. package/dist/server.js +5 -2
  138. package/dist/style-sets/extract.d.ts +35 -0
  139. package/dist/style-sets/extract.js +123 -0
  140. package/dist/style-sets/stellaStyle.d.ts +13 -0
  141. package/dist/style-sets/stellaStyle.js +516 -0
  142. package/dist/style-sets/types.d.ts +31 -0
  143. package/dist/style-sets/types.js +5 -0
  144. package/dist/utils/createDocument.d.ts +12 -2
  145. package/dist/utils/createDocument.js +42 -31
  146. package/dist/utils/fontResolver.js +6 -6
  147. package/dist/utils/formatToStyle.js +1 -1
  148. package/dist/utils/paragraphFormattingMerge.d.ts +14 -3
  149. package/dist/utils/paragraphFormattingMerge.js +14 -4
  150. package/package.json +5 -1
  151. package/dist/docx/capabilities.d.ts +0 -41
  152. package/dist/docx/capabilities.js +0 -322
@@ -0,0 +1,516 @@
1
+ import "./types.js";
2
+ //#region src/style-sets/stellaStyle.ts
3
+ const CLAUSE_NUMBERING_ID = 1;
4
+ const DEFINITIONS_NUMBERING_ID = 2;
5
+ const RECITALS_NUMBERING_ID = 3;
6
+ const PARTIES_NUMBERING_ID = 4;
7
+ const BULLET_NUMBERING_ID = 5;
8
+ const CLAUSE_ABSTRACT_NUMBERING_ID = 1;
9
+ const DEFINITIONS_ABSTRACT_NUMBERING_ID = 2;
10
+ const PARENTHETICAL_ABSTRACT_NUMBERING_ID = 3;
11
+ const BULLET_ABSTRACT_NUMBERING_ID = 4;
12
+ const STELLA_STYLE_SET_NAME = "Stella Style";
13
+ /**
14
+ * A conservative legal drafting system inspired by common continental and
15
+ * common-law contract structure. It uses explicit fonts and neutral punctuation
16
+ * so the package does not depend on a locale-specific Office theme.
17
+ */
18
+ const createStellaStyleSet = () => ({
19
+ version: 1,
20
+ name: STELLA_STYLE_SET_NAME,
21
+ initialParagraphStyleId: "BodyText",
22
+ settings: { defaultTabStop: 720 },
23
+ fontTable: { fonts: [{
24
+ name: "Arial",
25
+ family: "swiss",
26
+ pitch: "variable"
27
+ }, {
28
+ name: "Georgia",
29
+ family: "roman",
30
+ pitch: "variable"
31
+ }] },
32
+ styles: {
33
+ docDefaults: { rPr: {
34
+ fontFamily: {
35
+ ascii: "Arial",
36
+ hAnsi: "Arial",
37
+ cs: "Arial"
38
+ },
39
+ fontSize: 20,
40
+ fontSizeCs: 20
41
+ } },
42
+ styles: [
43
+ {
44
+ styleId: "Normal",
45
+ type: "paragraph",
46
+ name: "Normal",
47
+ default: true,
48
+ qFormat: true,
49
+ uiPriority: 0,
50
+ pPr: {
51
+ alignment: "both",
52
+ spaceAfter: 240
53
+ },
54
+ rPr: {
55
+ fontFamily: {
56
+ ascii: "Arial",
57
+ hAnsi: "Arial",
58
+ cs: "Arial"
59
+ },
60
+ fontSize: 20,
61
+ fontSizeCs: 20
62
+ }
63
+ },
64
+ {
65
+ styleId: "DefaultParagraphFont",
66
+ type: "character",
67
+ name: "Default Paragraph Font",
68
+ default: true,
69
+ semiHidden: true,
70
+ unhideWhenUsed: true
71
+ },
72
+ {
73
+ styleId: "BodyText",
74
+ type: "paragraph",
75
+ name: "Body Text",
76
+ basedOn: "Normal",
77
+ qFormat: true,
78
+ uiPriority: 1
79
+ },
80
+ {
81
+ styleId: "Title",
82
+ type: "paragraph",
83
+ name: "Title",
84
+ basedOn: "BodyText",
85
+ next: "BodyText",
86
+ qFormat: true,
87
+ uiPriority: 2,
88
+ pPr: {
89
+ alignment: "center",
90
+ keepNext: true,
91
+ spaceAfter: 360
92
+ },
93
+ rPr: {
94
+ bold: true,
95
+ fontSize: 32,
96
+ fontSizeCs: 32
97
+ }
98
+ },
99
+ {
100
+ styleId: "TitleWithSubtitle",
101
+ type: "paragraph",
102
+ name: "Title with Subtitle",
103
+ basedOn: "Title",
104
+ next: "Subtitle",
105
+ qFormat: true,
106
+ uiPriority: 3,
107
+ pPr: { spaceAfter: 0 }
108
+ },
109
+ {
110
+ styleId: "Subtitle",
111
+ type: "paragraph",
112
+ name: "Subtitle",
113
+ basedOn: "Title",
114
+ next: "BodyText",
115
+ qFormat: true,
116
+ uiPriority: 4,
117
+ rPr: {
118
+ fontFamily: {
119
+ ascii: "Georgia",
120
+ hAnsi: "Georgia"
121
+ },
122
+ italic: true,
123
+ color: { rgb: "7F7F7F" }
124
+ }
125
+ },
126
+ {
127
+ styleId: "RecitalsHeading",
128
+ type: "paragraph",
129
+ name: "Recitals Heading",
130
+ basedOn: "BodyText",
131
+ next: "Recital",
132
+ qFormat: true,
133
+ uiPriority: 5,
134
+ pPr: { keepNext: true },
135
+ rPr: { bold: true }
136
+ },
137
+ {
138
+ styleId: "Recital",
139
+ type: "paragraph",
140
+ name: "Recital",
141
+ basedOn: "BodyText",
142
+ qFormat: true,
143
+ uiPriority: 6,
144
+ pPr: { numPr: {
145
+ numId: RECITALS_NUMBERING_ID,
146
+ ilvl: 0
147
+ } }
148
+ },
149
+ {
150
+ styleId: "AgreedTerms",
151
+ type: "paragraph",
152
+ name: "Agreed Terms",
153
+ basedOn: "BodyText",
154
+ next: "ClauseHeading1",
155
+ qFormat: true,
156
+ uiPriority: 7,
157
+ pPr: {
158
+ keepNext: true,
159
+ spaceBefore: 240
160
+ },
161
+ rPr: { bold: true }
162
+ },
163
+ ...createClauseStyles(),
164
+ ...createDefinitionStyles(),
165
+ {
166
+ styleId: "Party",
167
+ type: "paragraph",
168
+ name: "Party",
169
+ basedOn: "BodyText",
170
+ qFormat: true,
171
+ uiPriority: 30,
172
+ pPr: { numPr: {
173
+ numId: PARTIES_NUMBERING_ID,
174
+ ilvl: 0
175
+ } }
176
+ },
177
+ {
178
+ styleId: "ListParagraph",
179
+ type: "paragraph",
180
+ name: "List Paragraph",
181
+ basedOn: "BodyText",
182
+ qFormat: true,
183
+ uiPriority: 31,
184
+ pPr: { numPr: {
185
+ numId: BULLET_NUMBERING_ID,
186
+ ilvl: 0
187
+ } }
188
+ },
189
+ {
190
+ styleId: "TableText",
191
+ type: "paragraph",
192
+ name: "Table Text",
193
+ basedOn: "Normal",
194
+ qFormat: true,
195
+ uiPriority: 32,
196
+ pPr: { spaceAfter: 0 }
197
+ },
198
+ {
199
+ styleId: "ScheduleHeading",
200
+ type: "paragraph",
201
+ name: "Schedule Heading",
202
+ basedOn: "Title",
203
+ next: "BodyText",
204
+ qFormat: true,
205
+ uiPriority: 33,
206
+ pPr: {
207
+ pageBreakBefore: true,
208
+ keepNext: true,
209
+ spaceAfter: 240
210
+ }
211
+ },
212
+ {
213
+ styleId: "FootnoteText",
214
+ type: "paragraph",
215
+ name: "Footnote Text",
216
+ basedOn: "Normal",
217
+ link: "FootnoteTextChar",
218
+ semiHidden: true,
219
+ unhideWhenUsed: true,
220
+ uiPriority: 99,
221
+ pPr: { spaceAfter: 0 },
222
+ rPr: {
223
+ fontSize: 18,
224
+ fontSizeCs: 18
225
+ }
226
+ },
227
+ {
228
+ styleId: "FootnoteTextChar",
229
+ type: "character",
230
+ name: "Footnote Text Char",
231
+ basedOn: "DefaultParagraphFont",
232
+ link: "FootnoteText",
233
+ semiHidden: true,
234
+ unhideWhenUsed: true,
235
+ uiPriority: 99,
236
+ rPr: {
237
+ fontSize: 18,
238
+ fontSizeCs: 18
239
+ }
240
+ },
241
+ {
242
+ styleId: "FootnoteReference",
243
+ type: "character",
244
+ name: "Footnote Reference",
245
+ basedOn: "DefaultParagraphFont",
246
+ semiHidden: true,
247
+ unhideWhenUsed: true,
248
+ uiPriority: 99,
249
+ rPr: { vertAlign: "superscript" }
250
+ },
251
+ {
252
+ styleId: "Footer",
253
+ type: "paragraph",
254
+ name: "Footer",
255
+ basedOn: "Normal",
256
+ pPr: {
257
+ alignment: "right",
258
+ spaceAfter: 0
259
+ },
260
+ rPr: {
261
+ color: { rgb: "7F7F7F" },
262
+ fontSize: 18,
263
+ fontSizeCs: 18
264
+ }
265
+ },
266
+ {
267
+ styleId: "Hyperlink",
268
+ type: "character",
269
+ name: "Hyperlink",
270
+ basedOn: "DefaultParagraphFont",
271
+ unhideWhenUsed: true,
272
+ uiPriority: 99,
273
+ rPr: {
274
+ color: { rgb: "0563C1" },
275
+ underline: { style: "single" }
276
+ }
277
+ },
278
+ {
279
+ styleId: "TableNormal",
280
+ type: "table",
281
+ name: "Normal Table",
282
+ default: true,
283
+ semiHidden: true,
284
+ unhideWhenUsed: true,
285
+ uiPriority: 99
286
+ },
287
+ {
288
+ styleId: "TableGrid",
289
+ type: "table",
290
+ name: "Table Grid",
291
+ basedOn: "TableNormal",
292
+ qFormat: true,
293
+ uiPriority: 59,
294
+ tblPr: { borders: {
295
+ top: {
296
+ style: "single",
297
+ size: 4,
298
+ color: { rgb: "BFBFBF" }
299
+ },
300
+ left: {
301
+ style: "single",
302
+ size: 4,
303
+ color: { rgb: "BFBFBF" }
304
+ },
305
+ bottom: {
306
+ style: "single",
307
+ size: 4,
308
+ color: { rgb: "BFBFBF" }
309
+ },
310
+ right: {
311
+ style: "single",
312
+ size: 4,
313
+ color: { rgb: "BFBFBF" }
314
+ },
315
+ insideH: {
316
+ style: "single",
317
+ size: 4,
318
+ color: { rgb: "BFBFBF" }
319
+ },
320
+ insideV: {
321
+ style: "single",
322
+ size: 4,
323
+ color: { rgb: "BFBFBF" }
324
+ }
325
+ } }
326
+ }
327
+ ]
328
+ },
329
+ numbering: createLegalNumbering()
330
+ });
331
+ const createStellaStyleDocumentPreset = () => ({
332
+ version: 1,
333
+ name: STELLA_STYLE_SET_NAME,
334
+ styleSet: createStellaStyleSet(),
335
+ sectionProperties: {
336
+ pageWidth: 11906,
337
+ pageHeight: 16838,
338
+ orientation: "portrait",
339
+ marginTop: 1440,
340
+ marginBottom: 1440,
341
+ marginLeft: 1440,
342
+ marginRight: 1440,
343
+ headerDistance: 708,
344
+ footerDistance: 708,
345
+ gutter: 0,
346
+ columnCount: 1,
347
+ columnSpace: 708,
348
+ equalWidth: true,
349
+ sectionStart: "nextPage",
350
+ verticalAlign: "top"
351
+ }
352
+ });
353
+ const createClauseStyles = () => {
354
+ return [
355
+ {
356
+ styleId: "ClauseHeading1",
357
+ name: "Clause Heading",
358
+ level: 0,
359
+ bold: true,
360
+ next: "ClauseParagraph1"
361
+ },
362
+ {
363
+ styleId: "ClauseParagraph1",
364
+ name: "Clause 1.1",
365
+ level: 1,
366
+ bold: false,
367
+ next: "ClauseParagraph1"
368
+ },
369
+ {
370
+ styleId: "ClauseParagraph2",
371
+ name: "Clause (a)",
372
+ level: 2,
373
+ bold: false,
374
+ next: "ClauseParagraph2"
375
+ },
376
+ {
377
+ styleId: "ClauseParagraph3",
378
+ name: "Clause (i)",
379
+ level: 3,
380
+ bold: false,
381
+ next: "ClauseParagraph3"
382
+ },
383
+ {
384
+ styleId: "ClauseParagraph4",
385
+ name: "Clause (A)",
386
+ level: 4,
387
+ bold: false,
388
+ next: "ClauseParagraph4"
389
+ }
390
+ ].map(({ styleId, name, level, bold, next }) => {
391
+ const style = {
392
+ styleId,
393
+ type: "paragraph",
394
+ name,
395
+ basedOn: "BodyText",
396
+ next,
397
+ qFormat: true,
398
+ uiPriority: 10 + level,
399
+ pPr: {
400
+ numPr: {
401
+ numId: CLAUSE_NUMBERING_ID,
402
+ ilvl: level
403
+ },
404
+ keepNext: level < 2,
405
+ spaceBefore: clauseSpaceBefore(level)
406
+ }
407
+ };
408
+ if (bold) return Object.assign(style, { rPr: { bold: true } });
409
+ return style;
410
+ });
411
+ };
412
+ const clauseSpaceBefore = (level) => {
413
+ if (level === 0) return 360;
414
+ return 0;
415
+ };
416
+ const createDefinitionStyles = () => {
417
+ return [
418
+ {
419
+ styleId: "Definition1",
420
+ name: "Definition (a)",
421
+ level: 0
422
+ },
423
+ {
424
+ styleId: "Definition2",
425
+ name: "Definition (i)",
426
+ level: 1
427
+ },
428
+ {
429
+ styleId: "Definition3",
430
+ name: "Definition (A)",
431
+ level: 2
432
+ }
433
+ ].map(({ styleId, name, level }) => ({
434
+ styleId,
435
+ type: "paragraph",
436
+ name,
437
+ basedOn: "BodyText",
438
+ qFormat: true,
439
+ uiPriority: 20 + level,
440
+ pPr: { numPr: {
441
+ numId: DEFINITIONS_NUMBERING_ID,
442
+ ilvl: level
443
+ } }
444
+ }));
445
+ };
446
+ const createLegalNumbering = () => ({
447
+ abstractNums: [
448
+ {
449
+ abstractNumId: CLAUSE_ABSTRACT_NUMBERING_ID,
450
+ multiLevelType: "multilevel",
451
+ levels: [
452
+ legalLevel(0, "decimal", "%1", 567, 567, true),
453
+ legalLevel(1, "decimal", "%1.%2", 567, 567, true),
454
+ legalLevel(2, "lowerLetter", "(%3)", 1134, 567),
455
+ legalLevel(3, "lowerRoman", "(%4)", 1701, 567),
456
+ legalLevel(4, "upperLetter", "(%5)", 2268, 567)
457
+ ]
458
+ },
459
+ {
460
+ abstractNumId: DEFINITIONS_ABSTRACT_NUMBERING_ID,
461
+ multiLevelType: "multilevel",
462
+ levels: [
463
+ legalLevel(0, "lowerLetter", "(%1)", 720, 360),
464
+ legalLevel(1, "lowerRoman", "(%2)", 1440, 360),
465
+ legalLevel(2, "upperLetter", "(%3)", 2160, 360)
466
+ ]
467
+ },
468
+ {
469
+ abstractNumId: PARENTHETICAL_ABSTRACT_NUMBERING_ID,
470
+ multiLevelType: "singleLevel",
471
+ levels: [legalLevel(0, "upperLetter", "(%1)", 720, 360)]
472
+ },
473
+ {
474
+ abstractNumId: BULLET_ABSTRACT_NUMBERING_ID,
475
+ multiLevelType: "singleLevel",
476
+ levels: [legalLevel(0, "bullet", "•", 720, 360)]
477
+ }
478
+ ],
479
+ nums: [
480
+ {
481
+ numId: CLAUSE_NUMBERING_ID,
482
+ abstractNumId: CLAUSE_ABSTRACT_NUMBERING_ID
483
+ },
484
+ {
485
+ numId: DEFINITIONS_NUMBERING_ID,
486
+ abstractNumId: DEFINITIONS_ABSTRACT_NUMBERING_ID
487
+ },
488
+ {
489
+ numId: RECITALS_NUMBERING_ID,
490
+ abstractNumId: PARENTHETICAL_ABSTRACT_NUMBERING_ID
491
+ },
492
+ {
493
+ numId: PARTIES_NUMBERING_ID,
494
+ abstractNumId: PARENTHETICAL_ABSTRACT_NUMBERING_ID
495
+ },
496
+ {
497
+ numId: BULLET_NUMBERING_ID,
498
+ abstractNumId: BULLET_ABSTRACT_NUMBERING_ID
499
+ }
500
+ ]
501
+ });
502
+ const legalLevel = (ilvl, numFmt, lvlText, indentLeft, hangingIndent, isLegal = false) => ({
503
+ ilvl,
504
+ start: 1,
505
+ numFmt,
506
+ lvlText,
507
+ suffix: "tab",
508
+ ...isLegal ? { isLgl: true } : {},
509
+ pPr: {
510
+ indentLeft,
511
+ indentFirstLine: hangingIndent,
512
+ hangingIndent: true
513
+ }
514
+ });
515
+ //#endregion
516
+ export { STELLA_STYLE_SET_NAME, createStellaStyleDocumentPreset, createStellaStyleSet };
@@ -0,0 +1,31 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+
3
+ //#region src/style-sets/types.d.ts
4
+ declare const DOCUMENT_STYLE_SET_VERSION: 1;
5
+ declare const DOCUMENT_PRESET_VERSION: 1;
6
+ /**
7
+ * A content-free, portable set of DOCX formatting resources.
8
+ *
9
+ * Source document content, properties, relationships, media, comments, and
10
+ * revision data are deliberately excluded. Numbering and theme resources live
11
+ * beside styles because paragraph styles can depend on them for their meaning.
12
+ */
13
+ type DocumentStyleSet = {
14
+ version: typeof DOCUMENT_STYLE_SET_VERSION;
15
+ name: string;
16
+ initialParagraphStyleId: string;
17
+ styles: document_d_exports.StyleDefinitions;
18
+ numbering?: document_d_exports.NumberingDefinitions;
19
+ theme?: document_d_exports.Theme;
20
+ fontTable?: document_d_exports.FontTable;
21
+ settings?: document_d_exports.DocumentSettings;
22
+ };
23
+ /** Page-level choices are separate from reusable style resources. */
24
+ type DocumentPreset = {
25
+ version: typeof DOCUMENT_PRESET_VERSION;
26
+ name: string;
27
+ styleSet: DocumentStyleSet;
28
+ sectionProperties: document_d_exports.SectionProperties;
29
+ };
30
+ //#endregion
31
+ export { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DocumentPreset, DocumentStyleSet };
@@ -0,0 +1,5 @@
1
+ //#region src/style-sets/types.ts
2
+ const DOCUMENT_STYLE_SET_VERSION = 1;
3
+ const DOCUMENT_PRESET_VERSION = 1;
4
+ //#endregion
5
+ export { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION };
@@ -1,10 +1,11 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
+ import { DocumentPreset, DocumentStyleSet } from "../style-sets/types.js";
2
3
 
3
4
  //#region src/utils/createDocument.d.ts
4
5
  /**
5
6
  * Options for creating an empty document
6
7
  */
7
- type CreateEmptyDocumentOptions = {
8
+ type CreateEmptyDocumentBaseOptions = {
8
9
  /** Page width in twips (default: 12240 = 8.5 inches) */pageWidth?: number; /** Page height in twips (default: 15840 = 11 inches) */
9
10
  pageHeight?: number; /** Page orientation (default: 'portrait') */
10
11
  orientation?: "portrait" | "landscape"; /** Top margin in twips (default: 1440 = 1 inch) */
@@ -14,6 +15,15 @@ type CreateEmptyDocumentOptions = {
14
15
  marginRight?: number; /** Initial text content (default: empty string) */
15
16
  initialText?: string;
16
17
  };
18
+ type CreateEmptyDocumentStyleOptions = {
19
+ /** Reusable formatting resources for the new document. */styleSet?: DocumentStyleSet;
20
+ preset?: never;
21
+ } | {
22
+ /** Style resources plus page-level defaults for the new document. */preset: DocumentPreset;
23
+ styleSet?: never;
24
+ };
25
+ type CreateEmptyDocumentOptions = CreateEmptyDocumentBaseOptions & CreateEmptyDocumentStyleOptions;
26
+ type CreateDocumentWithTextOptions = Omit<CreateEmptyDocumentBaseOptions, "initialText"> & CreateEmptyDocumentStyleOptions;
17
27
  /**
18
28
  * Create an empty document with a single paragraph
19
29
  *
@@ -45,6 +55,6 @@ declare function createEmptyDocument(options?: CreateEmptyDocumentOptions): docu
45
55
  * @param options - Optional configuration for the document
46
56
  * @returns A new Document object with the specified text
47
57
  */
48
- declare function createDocumentWithText(text: string, options?: Omit<CreateEmptyDocumentOptions, "initialText">): document_d_exports.Document;
58
+ declare function createDocumentWithText(text: string, options?: CreateDocumentWithTextOptions): document_d_exports.Document;
49
59
  //#endregion
50
60
  export { CreateEmptyDocumentOptions, createDocumentWithText, createEmptyDocument };
@@ -1,3 +1,5 @@
1
+ import "../style-sets/types.js";
2
+ import { panic } from "better-result";
1
3
  import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
2
4
  //#region src/utils/createDocument.ts
3
5
  /**
@@ -201,7 +203,10 @@ function getDefaultSectionProperties() {
201
203
  * ```
202
204
  */
203
205
  function createEmptyDocument(options = {}) {
204
- const sectionProps = getDefaultSectionProperties();
206
+ const styleSet = options.preset?.styleSet ?? options.styleSet;
207
+ validateDocumentStyleSet(styleSet);
208
+ if (options.preset?.version !== void 0 && options.preset.version !== 1) return panic(`Unsupported document preset version: ${options.preset.version}`);
209
+ const sectionProps = structuredClone(options.preset?.sectionProperties ?? getDefaultSectionProperties());
205
210
  if (options.pageWidth !== void 0) sectionProps.pageWidth = Math.round(options.pageWidth);
206
211
  if (options.pageHeight !== void 0) sectionProps.pageHeight = Math.round(options.pageHeight);
207
212
  if (options.orientation !== void 0) sectionProps.orientation = options.orientation;
@@ -209,50 +214,56 @@ function createEmptyDocument(options = {}) {
209
214
  if (options.marginBottom !== void 0) sectionProps.marginBottom = Math.round(options.marginBottom);
210
215
  if (options.marginLeft !== void 0) sectionProps.marginLeft = Math.round(options.marginLeft);
211
216
  if (options.marginRight !== void 0) sectionProps.marginRight = Math.round(options.marginRight);
212
- const textContent = {
213
- type: "text",
214
- text: options.initialText || ""
215
- };
217
+ const initialText = options.initialText ?? "";
216
218
  const documentBody = {
217
219
  content: [{
218
220
  type: "paragraph",
219
221
  content: [{
220
222
  type: "run",
221
- content: options.initialText ? [textContent] : [],
222
- formatting: {
223
- fontSize: 22,
224
- fontFamily: {
225
- ascii: "Arial",
226
- hAnsi: "Arial"
227
- }
228
- }
223
+ content: initialText ? [{
224
+ type: "text",
225
+ text: initialText
226
+ }] : [],
227
+ formatting: {}
229
228
  }],
230
- formatting: { lineSpacing: 276 }
229
+ formatting: { styleId: styleSet?.initialParagraphStyleId ?? "Normal" }
231
230
  }],
232
231
  finalSectionProperties: sectionProps
233
232
  };
234
- return {
235
- package: {
236
- conformanceClass: DOCX_CONFORMANCE_CLASSES.TRANSITIONAL,
237
- document: documentBody,
238
- styles: {
239
- docDefaults: {
240
- rPr: {
241
- fontSize: 22,
242
- fontFamily: {
243
- ascii: "Arial",
244
- hAnsi: "Arial"
245
- }
246
- },
247
- pPr: { lineSpacing: 276 }
248
- },
249
- styles: getDefaultStyles()
250
- }
233
+ const defaultStyleDefinitions = {
234
+ docDefaults: {
235
+ rPr: {
236
+ fontSize: 22,
237
+ fontFamily: {
238
+ ascii: "Arial",
239
+ hAnsi: "Arial"
240
+ }
241
+ },
242
+ pPr: { lineSpacing: 276 }
251
243
  },
244
+ styles: getDefaultStyles()
245
+ };
246
+ const docxPackage = {
247
+ conformanceClass: DOCX_CONFORMANCE_CLASSES.TRANSITIONAL,
248
+ document: documentBody,
249
+ styles: structuredClone(styleSet?.styles ?? defaultStyleDefinitions)
250
+ };
251
+ if (styleSet?.numbering) docxPackage.numbering = structuredClone(styleSet.numbering);
252
+ if (styleSet?.theme) docxPackage.theme = structuredClone(styleSet.theme);
253
+ if (styleSet?.fontTable) docxPackage.fontTable = structuredClone(styleSet.fontTable);
254
+ if (styleSet?.settings) docxPackage.settings = structuredClone(styleSet.settings);
255
+ return {
256
+ package: docxPackage,
252
257
  templateVariables: [],
253
258
  warnings: []
254
259
  };
255
260
  }
261
+ const validateDocumentStyleSet = (styleSet) => {
262
+ if (!styleSet) return;
263
+ if (styleSet.version !== 1) return panic(`Unsupported document style set version: ${styleSet.version}`);
264
+ if (styleSet.name.trim().length === 0) return panic("Document style set name cannot be empty");
265
+ if (styleSet.styles.styles.find((style) => style.styleId === styleSet.initialParagraphStyleId)?.type !== "paragraph") return panic(`Initial paragraph style "${styleSet.initialParagraphStyleId}" is missing from style set "${styleSet.name}"`);
266
+ };
256
267
  /**
257
268
  * Create a document with a single paragraph containing the given text
258
269
  *