@docx4j/core-ts 0.6.0 → 0.7.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 (119) hide show
  1. package/README.md +60 -0
  2. package/dist/model/content/Body.mjs +6 -17
  3. package/dist/model/content/Comment.d.mts +2 -2
  4. package/dist/model/content/Comment.mjs +12 -7
  5. package/dist/model/content/ContentControl.d.mts +1 -1
  6. package/dist/model/content/ContentControl.mjs +8 -4
  7. package/dist/model/content/Font.d.mts +4 -1
  8. package/dist/model/content/Font.mjs +6 -2
  9. package/dist/model/content/List.d.mts +6 -3
  10. package/dist/model/content/List.mjs +15 -8
  11. package/dist/model/content/Paragraph.d.mts +12 -2
  12. package/dist/model/content/Paragraph.mjs +31 -11
  13. package/dist/model/content/Table.mjs +26 -16
  14. package/dist/model/content/TrackedChange.d.mts +2 -2
  15. package/dist/model/content/TrackedChange.mjs +6 -3
  16. package/dist/model/content/index.d.mts +3 -1
  17. package/dist/model/content/index.mjs +4 -1
  18. package/dist/model/content/ooxml.mjs +12 -1
  19. package/dist/model/content/paraIds.d.mts +5 -0
  20. package/dist/model/content/paraIds.mjs +54 -0
  21. package/dist/model/content/search.d.mts +2 -0
  22. package/dist/model/content/search.mjs +51 -7
  23. package/dist/model/content/story.d.mts +5 -2
  24. package/dist/model/content/story.mjs +6 -3
  25. package/dist/model/content/tableRules.mjs +2 -0
  26. package/dist/model/content/tracking.d.mts +35 -6
  27. package/dist/model/content/tracking.mjs +93 -12
  28. package/dist/model/content/tree.d.mts +7 -8
  29. package/dist/model/content/tree.mjs +7 -9
  30. package/dist/model/content/wordRange.d.mts +48 -0
  31. package/dist/model/content/wordRange.mjs +97 -0
  32. package/dist/model/customxml/CustomXmlPartCollection.d.mts +22 -1
  33. package/dist/model/customxml/CustomXmlPartCollection.mjs +48 -2
  34. package/dist/model/customxml/XmlMapping.d.mts +31 -7
  35. package/dist/model/customxml/XmlMapping.mjs +53 -10
  36. package/dist/model/customxml/bindings.d.mts +12 -2
  37. package/dist/model/customxml/bindings.mjs +98 -16
  38. package/dist/model/customxml/index.d.mts +1 -0
  39. package/dist/model/customxml/index.mjs +1 -0
  40. package/dist/model/customxml/opendope.d.mts +4 -1
  41. package/dist/model/customxml/opendope.mjs +9 -6
  42. package/dist/model/customxml/pictures.mjs +5 -3
  43. package/dist/model/customxml/storeItems.d.mts +57 -0
  44. package/dist/model/customxml/storeItems.mjs +122 -0
  45. package/dist/model/customxml/xhtml.mjs +15 -20
  46. package/dist/model/dateZone.d.mts +25 -0
  47. package/dist/model/dateZone.mjs +57 -0
  48. package/dist/model/index.d.mts +1 -0
  49. package/dist/model/index.mjs +1 -0
  50. package/dist/model/properties/PropertyResolver.d.mts +14 -1
  51. package/dist/model/properties/PropertyResolver.mjs +18 -3
  52. package/dist/model/properties/index.d.mts +1 -1
  53. package/dist/model/properties/log.mjs +2 -2
  54. package/dist/model/properties/styleUtil.d.mts +3 -1
  55. package/dist/model/properties/styleUtil.mjs +20 -24
  56. package/dist/model/text/CaseMapping.d.mts +38 -0
  57. package/dist/model/text/CaseMapping.mjs +86 -0
  58. package/dist/model/text/Extractor.d.mts +66 -6
  59. package/dist/model/text/Extractor.mjs +300 -56
  60. package/dist/model/text/PlainText.mjs +7 -4
  61. package/dist/model/text/TextContext.d.mts +103 -8
  62. package/dist/model/text/TextContext.mjs +228 -53
  63. package/dist/model/text/TextOptions.d.mts +88 -5
  64. package/dist/model/text/TextOptions.mjs +158 -17
  65. package/dist/model/text/TextResult.d.mts +126 -9
  66. package/dist/model/text/TextResult.mjs +115 -12
  67. package/dist/model/text/WmlToMarkdown.mjs +32 -7
  68. package/dist/model/text/caseMapping.generated.d.mts +7 -0
  69. package/dist/model/text/caseMapping.generated.mjs +214 -0
  70. package/dist/model/text/index.d.mts +3 -2
  71. package/dist/model/text/index.mjs +1 -0
  72. package/dist/model/wordIntegers.d.mts +29 -0
  73. package/dist/model/wordIntegers.mjs +78 -0
  74. package/dist/office-js/document.mjs +15 -1
  75. package/dist/office-js/toApiScript.mjs +8 -7
  76. package/dist/opc/DirectoryPartStore.d.mts +6 -2
  77. package/dist/opc/DirectoryPartStore.mjs +11 -4
  78. package/dist/opc/FlatOpcPartStore.d.mts +4 -2
  79. package/dist/opc/FlatOpcPartStore.mjs +11 -8
  80. package/dist/opc/Load.d.mts +32 -0
  81. package/dist/opc/Load.mjs +115 -5
  82. package/dist/opc/PartStore.d.mts +34 -1
  83. package/dist/opc/PartStore.mjs +71 -8
  84. package/dist/opc/Save.d.mts +17 -2
  85. package/dist/opc/Save.mjs +100 -4
  86. package/dist/opc/ZipPartStore.d.mts +4 -2
  87. package/dist/opc/ZipPartStore.mjs +12 -7
  88. package/dist/opc/exceptions.d.mts +140 -0
  89. package/dist/opc/exceptions.mjs +108 -0
  90. package/dist/opc/index.d.mts +7 -4
  91. package/dist/opc/index.mjs +5 -3
  92. package/dist/opc/mce/preprocessor.d.mts +121 -10
  93. package/dist/opc/mce/preprocessor.mjs +122 -21
  94. package/dist/opc/mce/understood.d.mts +3 -35
  95. package/dist/opc/mce/understood.mjs +27 -53
  96. package/dist/opc/repair/breaks.d.mts +23 -0
  97. package/dist/opc/repair/breaks.mjs +288 -0
  98. package/dist/opc/repair/hosts.d.mts +12 -0
  99. package/dist/opc/repair/hosts.mjs +33 -0
  100. package/dist/opc/repair/mainRoot.d.mts +19 -0
  101. package/dist/opc/repair/mainRoot.mjs +168 -0
  102. package/dist/opc/repair/unknownElements.d.mts +8 -0
  103. package/dist/opc/repair/unknownElements.mjs +180 -0
  104. package/dist/opc/repair/wmlNames.generated.d.mts +2 -0
  105. package/dist/opc/repair/wmlNames.generated.mjs +80 -0
  106. package/dist/opc/skipped.d.mts +50 -0
  107. package/dist/opc/skipped.mjs +140 -0
  108. package/dist/packages/OpcPackage.d.mts +98 -5
  109. package/dist/packages/OpcPackage.mjs +122 -7
  110. package/dist/packages/WordprocessingMLPackage.mjs +3 -1
  111. package/dist/packages/index.d.mts +1 -1
  112. package/dist/parts/Part.d.mts +5 -1
  113. package/dist/parts/RelationshipsPart.d.mts +15 -0
  114. package/dist/parts/RelationshipsPart.mjs +66 -1
  115. package/dist/parts/XmlPart.d.mts +54 -5
  116. package/dist/parts/XmlPart.mjs +203 -10
  117. package/dist/parts/wml/index.d.mts +12 -1
  118. package/dist/parts/wml/index.mjs +25 -1
  119. package/package.json +2 -2
@@ -0,0 +1,214 @@
1
+ // The simple uppercase mapping of Unicode 15.0.0 (UnicodeData.txt field 12; Java's Character.toUpperCase(int)), for
2
+ // CaseMapping (CR-012 section 24.1, D4).
3
+ //
4
+ // Generated by scripts/generate-case-mapping.mjs from https://www.unicode.org/Public/15.0.0/ucd/UnicodeData.txt
5
+ // (SHA-256 806e9aed65037197f1ec85e12be6e8cd870fc5608b4de0fffd990f689f376a73): 1450 code points in 200 runs.
6
+ // Do not edit; run the script instead.
7
+ /** The Unicode version of the table: a later case pair is unmapped until the table is regenerated (WD 0.52's REQ-607). */
8
+ export const CASE_MAPPING_UNICODE_VERSION = '15.0.0';
9
+ /**
10
+ * Runs of code points mapped by one delta: `start, end, delta, stride` each, by `start`; `end` is the run's last code
11
+ * point, and every `stride`th code point from `start` to it maps to itself plus `delta`.
12
+ */
13
+ export const UPPERCASE_RUNS = [
14
+ 0x61, 0x7A, -32, 1,
15
+ 0xB5, 0xB5, 743, 1,
16
+ 0xE0, 0xF6, -32, 1,
17
+ 0xF8, 0xFE, -32, 1,
18
+ 0xFF, 0xFF, 121, 1,
19
+ 0x101, 0x12F, -1, 2,
20
+ 0x131, 0x131, -232, 1,
21
+ 0x133, 0x137, -1, 2,
22
+ 0x13A, 0x148, -1, 2,
23
+ 0x14B, 0x177, -1, 2,
24
+ 0x17A, 0x17E, -1, 2,
25
+ 0x17F, 0x17F, -300, 1,
26
+ 0x180, 0x180, 195, 1,
27
+ 0x183, 0x185, -1, 2,
28
+ 0x188, 0x188, -1, 1,
29
+ 0x18C, 0x18C, -1, 1,
30
+ 0x192, 0x192, -1, 1,
31
+ 0x195, 0x195, 97, 1,
32
+ 0x199, 0x199, -1, 1,
33
+ 0x19A, 0x19A, 163, 1,
34
+ 0x19E, 0x19E, 130, 1,
35
+ 0x1A1, 0x1A5, -1, 2,
36
+ 0x1A8, 0x1A8, -1, 1,
37
+ 0x1AD, 0x1AD, -1, 1,
38
+ 0x1B0, 0x1B0, -1, 1,
39
+ 0x1B4, 0x1B6, -1, 2,
40
+ 0x1B9, 0x1B9, -1, 1,
41
+ 0x1BD, 0x1BD, -1, 1,
42
+ 0x1BF, 0x1BF, 56, 1,
43
+ 0x1C5, 0x1C5, -1, 1,
44
+ 0x1C6, 0x1C6, -2, 1,
45
+ 0x1C8, 0x1C8, -1, 1,
46
+ 0x1C9, 0x1C9, -2, 1,
47
+ 0x1CB, 0x1CB, -1, 1,
48
+ 0x1CC, 0x1CC, -2, 1,
49
+ 0x1CE, 0x1DC, -1, 2,
50
+ 0x1DD, 0x1DD, -79, 1,
51
+ 0x1DF, 0x1EF, -1, 2,
52
+ 0x1F2, 0x1F2, -1, 1,
53
+ 0x1F3, 0x1F3, -2, 1,
54
+ 0x1F5, 0x1F5, -1, 1,
55
+ 0x1F9, 0x21F, -1, 2,
56
+ 0x223, 0x233, -1, 2,
57
+ 0x23C, 0x23C, -1, 1,
58
+ 0x23F, 0x240, 10815, 1,
59
+ 0x242, 0x242, -1, 1,
60
+ 0x247, 0x24F, -1, 2,
61
+ 0x250, 0x250, 10783, 1,
62
+ 0x251, 0x251, 10780, 1,
63
+ 0x252, 0x252, 10782, 1,
64
+ 0x253, 0x253, -210, 1,
65
+ 0x254, 0x254, -206, 1,
66
+ 0x256, 0x257, -205, 1,
67
+ 0x259, 0x259, -202, 1,
68
+ 0x25B, 0x25B, -203, 1,
69
+ 0x25C, 0x25C, 42319, 1,
70
+ 0x260, 0x260, -205, 1,
71
+ 0x261, 0x261, 42315, 1,
72
+ 0x263, 0x263, -207, 1,
73
+ 0x265, 0x265, 42280, 1,
74
+ 0x266, 0x266, 42308, 1,
75
+ 0x268, 0x268, -209, 1,
76
+ 0x269, 0x269, -211, 1,
77
+ 0x26A, 0x26A, 42308, 1,
78
+ 0x26B, 0x26B, 10743, 1,
79
+ 0x26C, 0x26C, 42305, 1,
80
+ 0x26F, 0x26F, -211, 1,
81
+ 0x271, 0x271, 10749, 1,
82
+ 0x272, 0x272, -213, 1,
83
+ 0x275, 0x275, -214, 1,
84
+ 0x27D, 0x27D, 10727, 1,
85
+ 0x280, 0x280, -218, 1,
86
+ 0x282, 0x282, 42307, 1,
87
+ 0x283, 0x283, -218, 1,
88
+ 0x287, 0x287, 42282, 1,
89
+ 0x288, 0x288, -218, 1,
90
+ 0x289, 0x289, -69, 1,
91
+ 0x28A, 0x28B, -217, 1,
92
+ 0x28C, 0x28C, -71, 1,
93
+ 0x292, 0x292, -219, 1,
94
+ 0x29D, 0x29D, 42261, 1,
95
+ 0x29E, 0x29E, 42258, 1,
96
+ 0x345, 0x345, 84, 1,
97
+ 0x371, 0x373, -1, 2,
98
+ 0x377, 0x377, -1, 1,
99
+ 0x37B, 0x37D, 130, 1,
100
+ 0x3AC, 0x3AC, -38, 1,
101
+ 0x3AD, 0x3AF, -37, 1,
102
+ 0x3B1, 0x3C1, -32, 1,
103
+ 0x3C2, 0x3C2, -31, 1,
104
+ 0x3C3, 0x3CB, -32, 1,
105
+ 0x3CC, 0x3CC, -64, 1,
106
+ 0x3CD, 0x3CE, -63, 1,
107
+ 0x3D0, 0x3D0, -62, 1,
108
+ 0x3D1, 0x3D1, -57, 1,
109
+ 0x3D5, 0x3D5, -47, 1,
110
+ 0x3D6, 0x3D6, -54, 1,
111
+ 0x3D7, 0x3D7, -8, 1,
112
+ 0x3D9, 0x3EF, -1, 2,
113
+ 0x3F0, 0x3F0, -86, 1,
114
+ 0x3F1, 0x3F1, -80, 1,
115
+ 0x3F2, 0x3F2, 7, 1,
116
+ 0x3F3, 0x3F3, -116, 1,
117
+ 0x3F5, 0x3F5, -96, 1,
118
+ 0x3F8, 0x3F8, -1, 1,
119
+ 0x3FB, 0x3FB, -1, 1,
120
+ 0x430, 0x44F, -32, 1,
121
+ 0x450, 0x45F, -80, 1,
122
+ 0x461, 0x481, -1, 2,
123
+ 0x48B, 0x4BF, -1, 2,
124
+ 0x4C2, 0x4CE, -1, 2,
125
+ 0x4CF, 0x4CF, -15, 1,
126
+ 0x4D1, 0x52F, -1, 2,
127
+ 0x561, 0x586, -48, 1,
128
+ 0x10D0, 0x10FA, 3008, 1,
129
+ 0x10FD, 0x10FF, 3008, 1,
130
+ 0x13F8, 0x13FD, -8, 1,
131
+ 0x1C80, 0x1C80, -6254, 1,
132
+ 0x1C81, 0x1C81, -6253, 1,
133
+ 0x1C82, 0x1C82, -6244, 1,
134
+ 0x1C83, 0x1C84, -6242, 1,
135
+ 0x1C85, 0x1C85, -6243, 1,
136
+ 0x1C86, 0x1C86, -6236, 1,
137
+ 0x1C87, 0x1C87, -6181, 1,
138
+ 0x1C88, 0x1C88, 35266, 1,
139
+ 0x1D79, 0x1D79, 35332, 1,
140
+ 0x1D7D, 0x1D7D, 3814, 1,
141
+ 0x1D8E, 0x1D8E, 35384, 1,
142
+ 0x1E01, 0x1E95, -1, 2,
143
+ 0x1E9B, 0x1E9B, -59, 1,
144
+ 0x1EA1, 0x1EFF, -1, 2,
145
+ 0x1F00, 0x1F07, 8, 1,
146
+ 0x1F10, 0x1F15, 8, 1,
147
+ 0x1F20, 0x1F27, 8, 1,
148
+ 0x1F30, 0x1F37, 8, 1,
149
+ 0x1F40, 0x1F45, 8, 1,
150
+ 0x1F51, 0x1F57, 8, 2,
151
+ 0x1F60, 0x1F67, 8, 1,
152
+ 0x1F70, 0x1F71, 74, 1,
153
+ 0x1F72, 0x1F75, 86, 1,
154
+ 0x1F76, 0x1F77, 100, 1,
155
+ 0x1F78, 0x1F79, 128, 1,
156
+ 0x1F7A, 0x1F7B, 112, 1,
157
+ 0x1F7C, 0x1F7D, 126, 1,
158
+ 0x1F80, 0x1F87, 8, 1,
159
+ 0x1F90, 0x1F97, 8, 1,
160
+ 0x1FA0, 0x1FA7, 8, 1,
161
+ 0x1FB0, 0x1FB1, 8, 1,
162
+ 0x1FB3, 0x1FB3, 9, 1,
163
+ 0x1FBE, 0x1FBE, -7205, 1,
164
+ 0x1FC3, 0x1FC3, 9, 1,
165
+ 0x1FD0, 0x1FD1, 8, 1,
166
+ 0x1FE0, 0x1FE1, 8, 1,
167
+ 0x1FE5, 0x1FE5, 7, 1,
168
+ 0x1FF3, 0x1FF3, 9, 1,
169
+ 0x214E, 0x214E, -28, 1,
170
+ 0x2170, 0x217F, -16, 1,
171
+ 0x2184, 0x2184, -1, 1,
172
+ 0x24D0, 0x24E9, -26, 1,
173
+ 0x2C30, 0x2C5F, -48, 1,
174
+ 0x2C61, 0x2C61, -1, 1,
175
+ 0x2C65, 0x2C65, -10795, 1,
176
+ 0x2C66, 0x2C66, -10792, 1,
177
+ 0x2C68, 0x2C6C, -1, 2,
178
+ 0x2C73, 0x2C73, -1, 1,
179
+ 0x2C76, 0x2C76, -1, 1,
180
+ 0x2C81, 0x2CE3, -1, 2,
181
+ 0x2CEC, 0x2CEE, -1, 2,
182
+ 0x2CF3, 0x2CF3, -1, 1,
183
+ 0x2D00, 0x2D25, -7264, 1,
184
+ 0x2D27, 0x2D27, -7264, 1,
185
+ 0x2D2D, 0x2D2D, -7264, 1,
186
+ 0xA641, 0xA66D, -1, 2,
187
+ 0xA681, 0xA69B, -1, 2,
188
+ 0xA723, 0xA72F, -1, 2,
189
+ 0xA733, 0xA76F, -1, 2,
190
+ 0xA77A, 0xA77C, -1, 2,
191
+ 0xA77F, 0xA787, -1, 2,
192
+ 0xA78C, 0xA78C, -1, 1,
193
+ 0xA791, 0xA793, -1, 2,
194
+ 0xA794, 0xA794, 48, 1,
195
+ 0xA797, 0xA7A9, -1, 2,
196
+ 0xA7B5, 0xA7C3, -1, 2,
197
+ 0xA7C8, 0xA7CA, -1, 2,
198
+ 0xA7D1, 0xA7D1, -1, 1,
199
+ 0xA7D7, 0xA7D9, -1, 2,
200
+ 0xA7F6, 0xA7F6, -1, 1,
201
+ 0xAB53, 0xAB53, -928, 1,
202
+ 0xAB70, 0xABBF, -38864, 1,
203
+ 0xFF41, 0xFF5A, -32, 1,
204
+ 0x10428, 0x1044F, -40, 1,
205
+ 0x104D8, 0x104FB, -40, 1,
206
+ 0x10597, 0x105A1, -39, 1,
207
+ 0x105A3, 0x105B1, -39, 1,
208
+ 0x105B3, 0x105B9, -39, 1,
209
+ 0x105BB, 0x105BC, -39, 1,
210
+ 0x10CC0, 0x10CF2, -64, 1,
211
+ 0x118C0, 0x118DF, -32, 1,
212
+ 0x16E60, 0x16E7F, -32, 1,
213
+ 0x1E922, 0x1E943, -34, 1,
214
+ ];
@@ -1,7 +1,8 @@
1
1
  export { Texts } from './Texts.mjs';
2
2
  export { TextContext, PackageTrees, type TextPackage } from './TextContext.mjs';
3
- export { TextOptions, TextOptionError, TEXT_OPTION_NAMES, type TextOptionsInit, type TextModelView, type TextInclude, type TextFields, type TextBindings, type TextSymbols, type TextMath, type TextTables, type TextMarkupDetail, type TextLayout, } from './TextOptions.mjs';
4
- export { TextResult, TextBlock, TextRun, TextRow, TextCell, TextField, TextNumbering, TextRevision, TextWarning, TextComment, TextImage, ImageDescription, AltTextDescriber, type ImageDescriber, type TextBlockKind, type TextStory, type TextRunKind, type NoteType, type TextRunSource, } from './TextResult.mjs';
3
+ export { TextOptions, TextOptionError, TEXT_OPTION_NAMES, type TextOptionsInit, type TextModelView, type TextInclude, type TextFields, type TextBindings, type TextSymbols, type TextMath, type TextTables, type TextMarkupDetail, type TextLayout, type TextDropCaps, type TextSmallCaps, type TextRepair, type TextProfile, } from './TextOptions.mjs';
4
+ export { TextResult, TextBlock, TextRun, TextRow, TextCell, TextField, TextNumbering, TextRevision, TextWarning, TextComment, TextImage, ImageDescription, AltTextDescriber, type ImageDescriber, type TextBlockKind, type TextStory, type TextRunKind, type NoteType, type TextRunSource, type TextVerticalAlignment, } from './TextResult.mjs';
5
5
  export { PlainText, INDENT_SPACES, LISTED_FORMAT_NOTE } from './PlainText.mjs';
6
+ export { CaseMapping } from './CaseMapping.mjs';
6
7
  export { LinkTargets } from './LinkTargets.mjs';
7
8
  export { MarkdownExporter, MarkdownExportOptions, type MarkdownExportOptionsInit, type MarkdownImage, type MarkdownImageDestination, type MarkdownBlock, type MarkdownBlocks, } from './MarkdownExporter.mjs';
@@ -4,5 +4,6 @@ export { TextContext, PackageTrees } from './TextContext.mjs';
4
4
  export { TextOptions, TextOptionError, TEXT_OPTION_NAMES, } from './TextOptions.mjs';
5
5
  export { TextResult, TextBlock, TextRun, TextRow, TextCell, TextField, TextNumbering, TextRevision, TextWarning, TextComment, TextImage, ImageDescription, AltTextDescriber, } from './TextResult.mjs';
6
6
  export { PlainText, INDENT_SPACES, LISTED_FORMAT_NOTE } from './PlainText.mjs';
7
+ export { CaseMapping } from './CaseMapping.mjs';
7
8
  export { LinkTargets } from './LinkTargets.mjs';
8
9
  export { MarkdownExporter, MarkdownExportOptions, } from './MarkdownExporter.mjs';
@@ -0,0 +1,29 @@
1
+ import { type WordIntegerReading, type WordIntegerStorage } from '@docx4j/generated-objects-ts/helpers/wml';
2
+ /** `[min, max]` in the attribute's own unit: every value in it Word reads as written, and none outside. */
3
+ export type KeptRange = readonly [number, number];
4
+ /** The certain range of an attribute the table has but no round measured: outside it every measured attribute of its type changes. */
5
+ export declare const UNMEASURED_RANGE: KeptRange;
6
+ /** Whether a reading is of an attribute no round measured (`storage` says so), as against one Word reads to no number. */
7
+ export declare const isUnmeasured: (reading: WordIntegerReading) => boolean;
8
+ /**
9
+ * The range Word 365 keeps as written in an attribute of the table (CR-017 E1's `range`; CR-002 section 65.3's bounds):
10
+ * - a signed field `-2^(bits-1)` to `2^(bits-1) - 1`, an unsigned one `0` to `2^bits - 1`;
11
+ * - `w:ind`'s `firstLine` and `hanging`, one signed field, `0` to `32767` and `0` to `32768`;
12
+ * - a line or a row height whose sign is the rule: under `exact` `1` to `32768`, under `atLeast` `0` to `32767`, a line
13
+ * under `auto` the plain signed field; a row height under `hRule="auto"` is ignored, so null;
14
+ * - a frame's height `0` to `32767` (15 bits);
15
+ * - then the clamps (a tab stop, the page size), and a column's width or space, whose negative Word replaces (a
16
+ * computed width; -1, which it also keeps as written, its own sentinel).
17
+ * The rule is the `lineRule` or `hRule` beside the attribute, where it has one. Undefined for an attribute not in the
18
+ * table. 65535 in an attribute Word's save writes as -1 (`w:spacing`'s `before` and `after`, the unsigned page margins)
19
+ * is in the range, and Word reads a -1 there as 65535 too, its own spelling.
20
+ */
21
+ export declare function keptRange(typeName: string, property: string, rule?: string): KeptRange | null | undefined;
22
+ /** `keptRange` from the table's entry; `property` for the shared field, `rule` for a line or a height. */
23
+ export declare function rangeOf(entry: WordIntegerStorage, property: string, rule?: string): KeptRange | null;
24
+ /**
25
+ * Word's reading, for a message: the value, in the shared field's other attribute where the sign moved it (`25536 in
26
+ * w:hanging`), with the rule where the sign carries one (`atLeast 1`, `exact 32768`); `not known` for an unmeasured
27
+ * attribute.
28
+ */
29
+ export declare function describeReading(reading: WordIntegerReading, attribute: string): string;
@@ -0,0 +1,78 @@
1
+ // CR-017: what Word 365 keeps of an integer attribute, from the objects package's table (its CR-016, docx4j CR-066's
2
+ // rounds 5 and 6, run by Jason 2026-10-26). Word stores each attribute in a field of its binary format's width, 16 bits
3
+ // for most, and reads a value past it wrapped, sometimes then clamped, with no error or repair. The table gives the
4
+ // width, the sign and the rules per attribute; this module turns an entry into the range of values Word keeps as
5
+ // written, which the setters' guards (CR-002 section 65.3, `wordRange.mts`) and the out-of-range warnings (CR-017 P2
6
+ // and P3, `XmlPart.valueOutOfRange`) both read, so there is one source for both. A report names its entry (`typeName`,
7
+ // `property`, `storage` and the `rule` beside the value, objects 0.7.0), so `rangeOf` takes it straight.
8
+ import { WORD_INTEGER_STORAGE } from '@docx4j/generated-objects-ts/helpers/wml';
9
+ /** The certain range of an attribute the table has but no round measured: outside it every measured attribute of its type changes. */
10
+ export const UNMEASURED_RANGE = [-32768, 65535];
11
+ /** Whether a reading is of an attribute no round measured (`storage` says so), as against one Word reads to no number. */
12
+ export const isUnmeasured = (reading) => reading.storage.startsWith('unmeasured');
13
+ /**
14
+ * The range Word 365 keeps as written in an attribute of the table (CR-017 E1's `range`; CR-002 section 65.3's bounds):
15
+ * - a signed field `-2^(bits-1)` to `2^(bits-1) - 1`, an unsigned one `0` to `2^bits - 1`;
16
+ * - `w:ind`'s `firstLine` and `hanging`, one signed field, `0` to `32767` and `0` to `32768`;
17
+ * - a line or a row height whose sign is the rule: under `exact` `1` to `32768`, under `atLeast` `0` to `32767`, a line
18
+ * under `auto` the plain signed field; a row height under `hRule="auto"` is ignored, so null;
19
+ * - a frame's height `0` to `32767` (15 bits);
20
+ * - then the clamps (a tab stop, the page size), and a column's width or space, whose negative Word replaces (a
21
+ * computed width; -1, which it also keeps as written, its own sentinel).
22
+ * The rule is the `lineRule` or `hRule` beside the attribute, where it has one. Undefined for an attribute not in the
23
+ * table. 65535 in an attribute Word's save writes as -1 (`w:spacing`'s `before` and `after`, the unsigned page margins)
24
+ * is in the range, and Word reads a -1 there as 65535 too, its own spelling.
25
+ */
26
+ export function keptRange(typeName, property, rule) {
27
+ var _a;
28
+ const entry = (_a = WORD_INTEGER_STORAGE[typeName]) === null || _a === void 0 ? void 0 : _a[property];
29
+ return entry === undefined ? undefined : rangeOf(entry, property, rule);
30
+ }
31
+ /** `keptRange` from the table's entry; `property` for the shared field, `rule` for a line or a height. */
32
+ export function rangeOf(entry, property, rule) {
33
+ if (!entry.measured)
34
+ return UNMEASURED_RANGE;
35
+ const half = 2 ** (entry.bits - 1);
36
+ let min;
37
+ let max;
38
+ if (entry.heightFlag)
39
+ [min, max] = [0, half - 1];
40
+ else if (entry.pair)
41
+ [min, max] = property === entry.pair.negative ? [0, half] : [0, half - 1];
42
+ else if (entry.signRule) {
43
+ const read = rule !== null && rule !== void 0 ? rule : (entry.signRule === 'hRule' ? 'atLeast' : 'auto');
44
+ if (entry.signRule === 'hRule' && read === 'auto')
45
+ return null;
46
+ if (read === 'exact')
47
+ [min, max] = [1, half];
48
+ else if (read === 'atLeast')
49
+ [min, max] = [0, half - 1];
50
+ else
51
+ [min, max] = [-half, half - 1];
52
+ }
53
+ else if (entry.signed)
54
+ [min, max] = [-half, half - 1];
55
+ else
56
+ [min, max] = [0, 2 ** entry.bits - 1];
57
+ if (entry.negative !== undefined)
58
+ min = Math.max(min, 0);
59
+ if (entry.min !== undefined)
60
+ min = Math.max(min, entry.min);
61
+ if (entry.max !== undefined)
62
+ max = Math.min(max, entry.max);
63
+ return [min, max];
64
+ }
65
+ /** Whether a reading's storage string names a rule beside the value (a line's `lineRule`, a height's `hRule`). */
66
+ const dependsOnRule = (storage) => /\brule\b|clearing exact/.test(storage);
67
+ /**
68
+ * Word's reading, for a message: the value, in the shared field's other attribute where the sign moved it (`25536 in
69
+ * w:hanging`), with the rule where the sign carries one (`atLeast 1`, `exact 32768`); `not known` for an unmeasured
70
+ * attribute.
71
+ */
72
+ export function describeReading(reading, attribute) {
73
+ if (reading.value === null)
74
+ return reading.storage.includes('computed') ? 'a width Word computes' : 'not known';
75
+ const where = reading.attribute !== undefined && reading.attribute !== attribute ? ` in w:${reading.attribute}` : '';
76
+ const rule = reading.rule !== undefined && dependsOnRule(reading.storage) ? `${reading.rule} ` : '';
77
+ return `${rule}${reading.value}${where}`;
78
+ }
@@ -15,10 +15,24 @@ function literal(text) {
15
15
  function w3cdtf(date) {
16
16
  return { TYPE_NAME: 'org_docx4j_docProps_core_dc_terms.W3CDTF', content: [date.toISOString().replace(/\.\d{3}Z$/, 'Z')] };
17
17
  }
18
+ /**
19
+ * A `dcterms:created` or `dcterms:modified` value as Word 365 reads it (docx4j CR-067 section 12.2, Jason's probe of
20
+ * 2026-10-28; CR-018 D6): a date alone (`2024-02-03`) and a time with no offset (`2025-06-07T08:09:10`) are UTC, as a `Z`
21
+ * value is (Word showed 11:00 and 18:09 at UTC+11 and UTC+10), so they are read here as UTC fields, where ECMAScript's
22
+ * `Date` would read the offset-free time as local. A `Z` or an offset is honoured as before. The seconds are kept: Word
23
+ * shows the value to the minute, but this reads the stored instant.
24
+ */
18
25
  function dateOf(value) {
19
- const text = literalText(value);
26
+ const text = literalText(value).trim();
20
27
  if (text === '')
21
28
  return undefined;
29
+ const bare = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?)?$/.exec(text);
30
+ if (bare) {
31
+ const [year, month, day, hour, minute, second, fraction] = bare.slice(1);
32
+ const ms = fraction === undefined ? 0 : Math.round(Number(`0.${fraction}`) * 1000);
33
+ const date = new Date(Date.UTC(Number(year), Number(month) - 1, Number(day), Number(hour !== null && hour !== void 0 ? hour : 0), Number(minute !== null && minute !== void 0 ? minute : 0), Number(second !== null && second !== void 0 ? second : 0), ms));
34
+ return Number.isNaN(date.getTime()) ? undefined : date;
35
+ }
22
36
  const date = new Date(text);
23
37
  return Number.isNaN(date.getTime()) ? undefined : date;
24
38
  }
@@ -184,7 +184,7 @@ class Emitter {
184
184
  * the generated document (CR-001 Phase B step 2; the same holds for `runFormat` below).
185
185
  */
186
186
  paragraphProperties(p) {
187
- var _a, _b, _c, _d, _e, _f, _g;
187
+ var _a, _b, _c, _d, _e, _f;
188
188
  const pPr = p.pPr;
189
189
  if (!pPr)
190
190
  return [];
@@ -223,13 +223,14 @@ class Emitter {
223
223
  if (spacing.after !== undefined)
224
224
  out.push(['spaceAfter', num(spacing.after / TWIPS_PER_POINT)]);
225
225
  if (spacing.line !== undefined) {
226
- // Paragraph.lineSpacing writes w:lineRule="exact", so only an exact rule round-trips.
227
- if (spacing.lineRule !== 'exact')
228
- throw new Unexpressible(`w:spacing w:lineRule="${(_c = spacing.lineRule) !== null && _c !== void 0 ? _c : 'auto'}"`);
226
+ // Paragraph.lineSpacing writes w:lineRule="auto", as Word's setter does (CR-002 section 65.9), so only an auto rule,
227
+ // stated or the default, round-trips.
228
+ if (spacing.lineRule !== undefined && spacing.lineRule !== 'auto')
229
+ throw new Unexpressible(`w:spacing w:lineRule="${spacing.lineRule}"`);
229
230
  out.push(['lineSpacing', num(spacing.line / TWIPS_PER_POINT)]);
230
231
  }
231
232
  }
232
- const outlineLvl = (_d = pPr.outlineLvl) === null || _d === void 0 ? void 0 : _d.val;
233
+ const outlineLvl = (_c = pPr.outlineLvl) === null || _c === void 0 ? void 0 : _c.val;
233
234
  if (outlineLvl !== undefined)
234
235
  out.push(['outlineLevel', num(outlineLvl + 1)]);
235
236
  const numPr = pPr.numPr;
@@ -240,10 +241,10 @@ class Emitter {
240
241
  // to know whether the list is a bullet one (CR-002 section 17).
241
242
  if (!within(numPr, NUMPR_KEYS))
242
243
  throw new Unexpressible(`w:numPr (${keysOf(numPr).filter((k) => !NUMPR_KEYS.has(k)).join(', ')})`);
243
- const numId = (_e = numPr.numId) === null || _e === void 0 ? void 0 : _e.val;
244
+ const numId = (_d = numPr.numId) === null || _d === void 0 ? void 0 : _d.val;
244
245
  if (numId === undefined)
245
246
  throw new Unexpressible('w:numPr with no w:numId');
246
- out.push([CALL, numId === 0 ? 'detachFromList()' : `attachToList(${numId}, ${(_g = (_f = numPr.ilvl) === null || _f === void 0 ? void 0 : _f.val) !== null && _g !== void 0 ? _g : 0})`]);
247
+ out.push([CALL, numId === 0 ? 'detachFromList()' : `attachToList(${numId}, ${(_f = (_e = numPr.ilvl) === null || _e === void 0 ? void 0 : _e.val) !== null && _f !== void 0 ? _f : 0})`]);
247
248
  }
248
249
  return out;
249
250
  }
@@ -1,4 +1,4 @@
1
- import type { PartStore, PartSink, PutOptions } from './PartStore.mjs';
1
+ import { type PartStore, type PartSink, type PutOptions } from './PartStore.mjs';
2
2
  /**
3
3
  * A package spread over a directory: `word/document.xml` is the file `<dir>/word/document.xml`,
4
4
  * `[Content_Types].xml` is read from the directory like any other entry, and a part's size comes
@@ -14,7 +14,10 @@ import type { PartStore, PartSink, PutOptions } from './PartStore.mjs';
14
14
  */
15
15
  export declare class DirectoryPartStore implements PartStore {
16
16
  readonly dir: string;
17
- /** Store name (no leading '/') to [absolute file path, size]. */
17
+ /**
18
+ * Store name (no leading '/') to [absolute file path, size], looked up without case; of two files whose names differ only
19
+ * in case (a case-sensitive file system), the first in the walk is read and the rest counted (CR-024).
20
+ */
18
21
  private readonly entries;
19
22
  private constructor();
20
23
  /** Scans a directory and returns a store over it. */
@@ -22,6 +25,7 @@ export declare class DirectoryPartStore implements PartStore {
22
25
  private scan;
23
26
  partNames(): Iterable<string>;
24
27
  has(partName: string): boolean;
28
+ duplicates(): ReadonlyMap<string, number>;
25
29
  load(partName: string): Promise<Uint8Array>;
26
30
  size(partName: string): number | undefined;
27
31
  }
@@ -3,6 +3,7 @@
3
3
  // only, never from `.` or `./opc`, so a browser or add-in bundle never sees them.
4
4
  import { readFile, readdir, stat, mkdir, writeFile } from 'node:fs/promises';
5
5
  import { join, dirname, sep } from 'node:path';
6
+ import { EntryIndex } from './PartStore.mjs';
6
7
  import { CONTENT_TYPES_NAME } from './PartName.mjs';
7
8
  import { Docx4JException } from './exceptions.mjs';
8
9
  /**
@@ -21,8 +22,11 @@ import { Docx4JException } from './exceptions.mjs';
21
22
  export class DirectoryPartStore {
22
23
  constructor(dir) {
23
24
  this.dir = dir;
24
- /** Store name (no leading '/') to [absolute file path, size]. */
25
- this.entries = new Map();
25
+ /**
26
+ * Store name (no leading '/') to [absolute file path, size], looked up without case; of two files whose names differ only
27
+ * in case (a case-sensitive file system), the first in the walk is read and the rest counted (CR-024).
28
+ */
29
+ this.entries = new EntryIndex();
26
30
  }
27
31
  /** Scans a directory and returns a store over it. */
28
32
  static async open(dir) {
@@ -48,15 +52,18 @@ export class DirectoryPartStore {
48
52
  if (info.isDirectory())
49
53
  await this.scan(childRelative);
50
54
  else if (info.isFile())
51
- this.entries.set(childRelative, [childPath, info.size]);
55
+ this.entries.add(childRelative, [childPath, info.size]);
52
56
  }
53
57
  }
54
58
  partNames() {
55
- return this.entries.keys();
59
+ return this.entries.names();
56
60
  }
57
61
  has(partName) {
58
62
  return this.entries.has(normalize(partName));
59
63
  }
64
+ duplicates() {
65
+ return this.entries.duplicates();
66
+ }
60
67
  async load(partName) {
61
68
  const entry = this.entries.get(normalize(partName));
62
69
  if (!entry)
@@ -1,5 +1,5 @@
1
1
  import { type PackageElement } from '@docx4j/generated-objects-ts';
2
- import type { PartStore, PartSink, PutOptions } from './PartStore.mjs';
2
+ import { type PartStore, type PartSink, type PutOptions } from './PartStore.mjs';
3
3
  export declare const PKG_NS = "http://schemas.microsoft.com/office/2006/xmlPackage";
4
4
  /**
5
5
  * A flat OPC package (`pkg:package`, what Office JS `getOoxml()` returns) as a container
@@ -7,10 +7,11 @@ export declare const PKG_NS = "http://schemas.microsoft.com/office/2006/xmlPacka
7
7
  * same job is done by `FlatOpcXmlImporter`). The content types are carried per part, so
8
8
  * `[Content_Types].xml` is synthesised. XML parts are serialised back to bytes on `load`; the
9
9
  * document loaded from them is therefore not byte-identical to what Office would have zipped.
10
+ * Parts are looked up as OPC part names, without case, and of two `pkg:part`s of one name the first
11
+ * is the one read, the rest counted in `duplicates()` (CR-024).
10
12
  */
11
13
  export declare class FlatOpcPartStore implements PartStore {
12
14
  private readonly parts;
13
- private readonly order;
14
15
  private readonly cache;
15
16
  private contentTypesXml?;
16
17
  /** From the `pkg:package` string. */
@@ -22,6 +23,7 @@ export declare class FlatOpcPartStore implements PartStore {
22
23
  contentTypeOf(partName: string): string | undefined;
23
24
  partNames(): Iterable<string>;
24
25
  has(partName: string): boolean;
26
+ duplicates(): ReadonlyMap<string, number>;
25
27
  load(partName: string): Promise<Uint8Array>;
26
28
  private buildContentTypes;
27
29
  }
@@ -1,4 +1,5 @@
1
1
  import { marshalNode } from '@docx4j/generated-objects-ts';
2
+ import { EntryIndex, entryKey } from './PartStore.mjs';
2
3
  import { ContentTypeManager } from './ContentTypeManager.mjs';
3
4
  import { ContentTypes, isXmlContentType } from './ContentTypes.mjs';
4
5
  import { CONTENT_TYPES_NAME } from './PartName.mjs';
@@ -11,18 +12,18 @@ export const PKG_NS = 'http://schemas.microsoft.com/office/2006/xmlPackage';
11
12
  * same job is done by `FlatOpcXmlImporter`). The content types are carried per part, so
12
13
  * `[Content_Types].xml` is synthesised. XML parts are serialised back to bytes on `load`; the
13
14
  * document loaded from them is therefore not byte-identical to what Office would have zipped.
15
+ * Parts are looked up as OPC part names, without case, and of two `pkg:part`s of one name the first
16
+ * is the one read, the rest counted in `duplicates()` (CR-024).
14
17
  */
15
18
  export class FlatOpcPartStore {
16
19
  /** From the `pkg:package` string. */
17
20
  constructor(source) {
18
- this.parts = new Map();
19
- this.order = [];
21
+ this.parts = new EntryIndex();
20
22
  this.cache = new Map();
21
23
  if (typeof source === 'string')
22
24
  this.readString(source);
23
25
  else
24
26
  this.readPackageElement(source);
25
- this.order.unshift(CONTENT_TYPES_NAME);
26
27
  }
27
28
  readString(text) {
28
29
  var _a;
@@ -65,8 +66,7 @@ export class FlatOpcPartStore {
65
66
  }
66
67
  }
67
68
  add(entry) {
68
- this.parts.set(entry.name, entry);
69
- this.order.push(entry.name);
69
+ this.parts.add(entry.name, entry);
70
70
  }
71
71
  /** The content type of a part as carried by the flat package. */
72
72
  contentTypeOf(partName) {
@@ -74,16 +74,19 @@ export class FlatOpcPartStore {
74
74
  return (_a = this.parts.get(partName)) === null || _a === void 0 ? void 0 : _a.contentType;
75
75
  }
76
76
  partNames() {
77
- return this.order;
77
+ return [CONTENT_TYPES_NAME, ...this.parts.names()];
78
78
  }
79
79
  has(partName) {
80
80
  return partName === CONTENT_TYPES_NAME || this.parts.has(partName);
81
81
  }
82
+ duplicates() {
83
+ return this.parts.duplicates();
84
+ }
82
85
  async load(partName) {
83
86
  var _a;
84
87
  if (partName === CONTENT_TYPES_NAME)
85
88
  return ((_a = this.contentTypesXml) !== null && _a !== void 0 ? _a : (this.contentTypesXml = encodeText(this.buildContentTypes().toXml())));
86
- const cached = this.cache.get(partName);
89
+ const cached = this.cache.get(entryKey(partName));
87
90
  if (cached)
88
91
  return cached;
89
92
  const part = this.parts.get(partName);
@@ -100,7 +103,7 @@ export class FlatOpcPartStore {
100
103
  else {
101
104
  bytes = new Uint8Array(0);
102
105
  }
103
- this.cache.set(partName, bytes);
106
+ this.cache.set(entryKey(partName), bytes);
104
107
  return bytes;
105
108
  }
106
109
  buildContentTypes() {
@@ -2,6 +2,14 @@ import type { PartStore } from './PartStore.mjs';
2
2
  import { type DomPreprocessor } from '../parts/XmlPart.mjs';
3
3
  import { PartRegistry } from '../parts/PartRegistry.mjs';
4
4
  import type { OpcPackage } from '../packages/OpcPackage.mjs';
5
+ /**
6
+ * WD REQ-207's option (CR-031): how a load treats a package Word reads only through a repair, or won't open. `'refuse'`, the
7
+ * default, keeps every refusal; `'word'` follows Word's repair where the WD states one, with that repair's warning; `'all'`
8
+ * does that and makes this package's own repairs, each documented and warned (README.md, "Repairs").
9
+ */
10
+ export type RepairMode = 'refuse' | 'word' | 'all';
11
+ /** The values of `LoadOptions.repair`, in the WD's order. */
12
+ export declare const REPAIR_MODES: readonly RepairMode[];
5
13
  export interface LoadOptions {
6
14
  /** Part classes by content type; defaults to docx4j's table. */
7
15
  registry?: PartRegistry;
@@ -16,6 +24,30 @@ export interface LoadOptions {
16
24
  mcePreprocess?: boolean;
17
25
  /** Runs over every XML part's DOM before it is unmarshalled; set by the package from `mcePreprocess` (`mceKeep` or `mcePreprocess`). */
18
26
  preprocessor?: DomPreprocessor;
27
+ /**
28
+ * How a package Word reads only through a repair, or won't open, is loaded (WD REQ-207 and REQ-208; CR-031). It acts at the
29
+ * load, so it holds for every operation on the package. Any other value is refused.
30
+ *
31
+ * - `'refuse'`, the default: every refusal stands. A container holding two entries of one name, OPC part names compared
32
+ * without case, throws `DuplicateEntryException` (REQ-206, CR-024); more than one officeDocument relationship,
33
+ * `MultipleMainPartsException` (CR-024 section 9); a relationships part in another namespace or none,
34
+ * `RelationshipsNamespaceException` (CR-025 section 8); an `External` officeDocument relationship beside an internal
35
+ * one, `ExternalMainPartException` (REQ-206's NOTE).
36
+ * - `'word'`: Word's repair, each with its warning. The first entry of each duplicated name is read, in the container's
37
+ * order (a zip's central directory), the rest ignored, a `DuplicateEntryWarning` each; of several officeDocument
38
+ * relationships the **last** one's target, as a fresh Word reads it, the others dropped, one `MultipleMainPartsWarning`;
39
+ * a relationships part in a wrong namespace read by local name, a `RelationshipsNamespaceWarning`. A save writes the
40
+ * repaired package: one copy of each entry, one main part, the right namespace. `External` beside an internal
41
+ * relationship is still refused, since Word refuses it even through its repair.
42
+ * - `'all'`: `'word'`, and this package's own repairs. One today: `External` beside an internal relationship, the internal
43
+ * target read and every `External` officeDocument relationship dropped, its URL never fetched, an
44
+ * `ExternalMainPartWarning`.
45
+ *
46
+ * At every value an `External` officeDocument relationship with no internal one is refused, as a package with no main
47
+ * document part (REQ-321), and the save's own gate is left alone: `pkg.checkLossOnSave` decides whether a save may lose
48
+ * what a read skipped (CR-031 D6).
49
+ */
50
+ repair?: RepairMode;
19
51
  }
20
52
  /**
21
53
  * Loads a package from a container (docx4j io3.Load3): content types, then the package