@usejunior/docx-core 0.10.0 → 0.11.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 (232) hide show
  1. package/LICENSE +202 -21
  2. package/NOTICE +2 -0
  3. package/README.md +2 -2
  4. package/dist/.tsbuildinfo +1 -1
  5. package/dist/atomizer.d.ts +13 -7
  6. package/dist/atomizer.d.ts.map +1 -1
  7. package/dist/atomizer.js +59 -24
  8. package/dist/atomizer.js.map +1 -1
  9. package/dist/baselines/atomizer/auxiliaryIdCollision.d.ts +99 -0
  10. package/dist/baselines/atomizer/auxiliaryIdCollision.d.ts.map +1 -0
  11. package/dist/baselines/atomizer/auxiliaryIdCollision.js +415 -0
  12. package/dist/baselines/atomizer/auxiliaryIdCollision.js.map +1 -0
  13. package/dist/baselines/atomizer/documentReconstructor.d.ts.map +1 -1
  14. package/dist/baselines/atomizer/documentReconstructor.js +120 -27
  15. package/dist/baselines/atomizer/documentReconstructor.js.map +1 -1
  16. package/dist/baselines/atomizer/inPlaceModifier-wrappers.d.ts +9 -0
  17. package/dist/baselines/atomizer/inPlaceModifier-wrappers.d.ts.map +1 -1
  18. package/dist/baselines/atomizer/inPlaceModifier-wrappers.js +52 -4
  19. package/dist/baselines/atomizer/inPlaceModifier-wrappers.js.map +1 -1
  20. package/dist/baselines/atomizer/pipeline.d.ts +12 -53
  21. package/dist/baselines/atomizer/pipeline.d.ts.map +1 -1
  22. package/dist/baselines/atomizer/pipeline.js +126 -231
  23. package/dist/baselines/atomizer/pipeline.js.map +1 -1
  24. package/dist/baselines/atomizer/trackChangesAcceptorAst.d.ts.map +1 -1
  25. package/dist/baselines/atomizer/trackChangesAcceptorAst.js +153 -23
  26. package/dist/baselines/atomizer/trackChangesAcceptorAst.js.map +1 -1
  27. package/dist/baselines/wmlcomparer/DotnetCli.d.ts.map +1 -1
  28. package/dist/baselines/wmlcomparer/DotnetCli.js +7 -0
  29. package/dist/baselines/wmlcomparer/DotnetCli.js.map +1 -1
  30. package/dist/cli/compare-two.d.ts.map +1 -1
  31. package/dist/cli/compare-two.js +3 -1
  32. package/dist/cli/compare-two.js.map +1 -1
  33. package/dist/cli/conformance-adapter.d.ts +3 -0
  34. package/dist/cli/conformance-adapter.d.ts.map +1 -0
  35. package/dist/cli/conformance-adapter.js +93 -0
  36. package/dist/cli/conformance-adapter.js.map +1 -0
  37. package/dist/cli/index.d.ts.map +1 -1
  38. package/dist/cli/index.js +5 -1
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/compare-types.d.ts +46 -0
  41. package/dist/compare-types.d.ts.map +1 -1
  42. package/dist/generation/compile.d.ts +21 -0
  43. package/dist/generation/compile.d.ts.map +1 -0
  44. package/dist/generation/compile.js +46 -0
  45. package/dist/generation/compile.js.map +1 -0
  46. package/dist/generation/context.d.ts +42 -0
  47. package/dist/generation/context.d.ts.map +1 -0
  48. package/dist/generation/context.js +65 -0
  49. package/dist/generation/context.js.map +1 -0
  50. package/dist/generation/emit/comments-part.d.ts +36 -0
  51. package/dist/generation/emit/comments-part.d.ts.map +1 -0
  52. package/dist/generation/emit/comments-part.js +116 -0
  53. package/dist/generation/emit/comments-part.js.map +1 -0
  54. package/dist/generation/emit/document-part.d.ts +24 -0
  55. package/dist/generation/emit/document-part.d.ts.map +1 -0
  56. package/dist/generation/emit/document-part.js +60 -0
  57. package/dist/generation/emit/document-part.js.map +1 -0
  58. package/dist/generation/emit/emit-context.d.ts +26 -0
  59. package/dist/generation/emit/emit-context.d.ts.map +1 -0
  60. package/dist/generation/emit/emit-context.js +19 -0
  61. package/dist/generation/emit/emit-context.js.map +1 -0
  62. package/dist/generation/emit/header-footer-part.d.ts +23 -0
  63. package/dist/generation/emit/header-footer-part.d.ts.map +1 -0
  64. package/dist/generation/emit/header-footer-part.js +57 -0
  65. package/dist/generation/emit/header-footer-part.js.map +1 -0
  66. package/dist/generation/emit/numbering-part.d.ts +29 -0
  67. package/dist/generation/emit/numbering-part.d.ts.map +1 -0
  68. package/dist/generation/emit/numbering-part.js +100 -0
  69. package/dist/generation/emit/numbering-part.js.map +1 -0
  70. package/dist/generation/emit/package-parts.d.ts +24 -0
  71. package/dist/generation/emit/package-parts.d.ts.map +1 -0
  72. package/dist/generation/emit/package-parts.js +121 -0
  73. package/dist/generation/emit/package-parts.js.map +1 -0
  74. package/dist/generation/emit/paragraph.d.ts +24 -0
  75. package/dist/generation/emit/paragraph.d.ts.map +1 -0
  76. package/dist/generation/emit/paragraph.js +63 -0
  77. package/dist/generation/emit/paragraph.js.map +1 -0
  78. package/dist/generation/emit/properties.d.ts +34 -0
  79. package/dist/generation/emit/properties.d.ts.map +1 -0
  80. package/dist/generation/emit/properties.js +138 -0
  81. package/dist/generation/emit/properties.js.map +1 -0
  82. package/dist/generation/emit/run.d.ts +15 -0
  83. package/dist/generation/emit/run.d.ts.map +1 -0
  84. package/dist/generation/emit/run.js +71 -0
  85. package/dist/generation/emit/run.js.map +1 -0
  86. package/dist/generation/emit/section.d.ts +29 -0
  87. package/dist/generation/emit/section.d.ts.map +1 -0
  88. package/dist/generation/emit/section.js +117 -0
  89. package/dist/generation/emit/section.js.map +1 -0
  90. package/dist/generation/emit/settings-part.d.ts +13 -0
  91. package/dist/generation/emit/settings-part.d.ts.map +1 -0
  92. package/dist/generation/emit/settings-part.js +24 -0
  93. package/dist/generation/emit/settings-part.js.map +1 -0
  94. package/dist/generation/emit/styles-part.d.ts +16 -0
  95. package/dist/generation/emit/styles-part.d.ts.map +1 -0
  96. package/dist/generation/emit/styles-part.js +80 -0
  97. package/dist/generation/emit/styles-part.js.map +1 -0
  98. package/dist/generation/emit/table.d.ts +26 -0
  99. package/dist/generation/emit/table.d.ts.map +1 -0
  100. package/dist/generation/emit/table.js +196 -0
  101. package/dist/generation/emit/table.js.map +1 -0
  102. package/dist/generation/errors.d.ts +22 -0
  103. package/dist/generation/errors.d.ts.map +1 -0
  104. package/dist/generation/errors.js +29 -0
  105. package/dist/generation/errors.js.map +1 -0
  106. package/dist/generation/index.d.ts +13 -0
  107. package/dist/generation/index.d.ts.map +1 -0
  108. package/dist/generation/index.js +12 -0
  109. package/dist/generation/index.js.map +1 -0
  110. package/dist/generation/ordering.d.ts +46 -0
  111. package/dist/generation/ordering.d.ts.map +1 -0
  112. package/dist/generation/ordering.js +119 -0
  113. package/dist/generation/ordering.js.map +1 -0
  114. package/dist/generation/recipes.d.ts +47 -0
  115. package/dist/generation/recipes.d.ts.map +1 -0
  116. package/dist/generation/recipes.js +84 -0
  117. package/dist/generation/recipes.js.map +1 -0
  118. package/dist/generation/structural-checks.d.ts +24 -0
  119. package/dist/generation/structural-checks.d.ts.map +1 -0
  120. package/dist/generation/structural-checks.js +318 -0
  121. package/dist/generation/structural-checks.js.map +1 -0
  122. package/dist/generation/types.d.ts +217 -0
  123. package/dist/generation/types.d.ts.map +1 -0
  124. package/dist/generation/types.js +16 -0
  125. package/dist/generation/types.js.map +1 -0
  126. package/dist/generation/validate-spec.d.ts +27 -0
  127. package/dist/generation/validate-spec.d.ts.map +1 -0
  128. package/dist/generation/validate-spec.js +307 -0
  129. package/dist/generation/validate-spec.js.map +1 -0
  130. package/dist/index.d.ts +3 -0
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +8 -0
  133. package/dist/index.js.map +1 -1
  134. package/dist/integration/generation-probes.d.ts +15 -0
  135. package/dist/integration/generation-probes.d.ts.map +1 -0
  136. package/dist/integration/generation-probes.js +84 -0
  137. package/dist/integration/generation-probes.js.map +1 -0
  138. package/dist/integration/libreoffice-oracle.d.ts +8 -0
  139. package/dist/integration/libreoffice-oracle.d.ts.map +1 -1
  140. package/dist/integration/libreoffice-oracle.js +14 -6
  141. package/dist/integration/libreoffice-oracle.js.map +1 -1
  142. package/dist/integration/synthetic-docx-fixture.d.ts +72 -0
  143. package/dist/integration/synthetic-docx-fixture.d.ts.map +1 -1
  144. package/dist/integration/synthetic-docx-fixture.js +131 -4
  145. package/dist/integration/synthetic-docx-fixture.js.map +1 -1
  146. package/dist/primitives/accept_changes.d.ts +2 -1
  147. package/dist/primitives/accept_changes.d.ts.map +1 -1
  148. package/dist/primitives/accept_changes.js +153 -12
  149. package/dist/primitives/accept_changes.js.map +1 -1
  150. package/dist/primitives/document.d.ts +38 -0
  151. package/dist/primitives/document.d.ts.map +1 -1
  152. package/dist/primitives/document.js +75 -9
  153. package/dist/primitives/document.js.map +1 -1
  154. package/dist/primitives/document_view-comments.d.ts.map +1 -1
  155. package/dist/primitives/document_view-comments.js +4 -3
  156. package/dist/primitives/document_view-comments.js.map +1 -1
  157. package/dist/primitives/document_view-types.d.ts +15 -0
  158. package/dist/primitives/document_view-types.d.ts.map +1 -1
  159. package/dist/primitives/document_view.d.ts.map +1 -1
  160. package/dist/primitives/document_view.js +21 -13
  161. package/dist/primitives/document_view.js.map +1 -1
  162. package/dist/primitives/formatting_tags.d.ts +1 -0
  163. package/dist/primitives/formatting_tags.d.ts.map +1 -1
  164. package/dist/primitives/formatting_tags.js +16 -10
  165. package/dist/primitives/formatting_tags.js.map +1 -1
  166. package/dist/primitives/index.d.ts +4 -0
  167. package/dist/primitives/index.d.ts.map +1 -1
  168. package/dist/primitives/index.js +4 -0
  169. package/dist/primitives/index.js.map +1 -1
  170. package/dist/primitives/layout.d.ts.map +1 -1
  171. package/dist/primitives/layout.js +13 -0
  172. package/dist/primitives/layout.js.map +1 -1
  173. package/dist/primitives/minimal_save.d.ts +38 -0
  174. package/dist/primitives/minimal_save.d.ts.map +1 -0
  175. package/dist/primitives/minimal_save.js +323 -0
  176. package/dist/primitives/minimal_save.js.map +1 -0
  177. package/dist/primitives/namespaces.d.ts +41 -0
  178. package/dist/primitives/namespaces.d.ts.map +1 -1
  179. package/dist/primitives/namespaces.js +43 -0
  180. package/dist/primitives/namespaces.js.map +1 -1
  181. package/dist/primitives/reject_changes.d.ts +4 -2
  182. package/dist/primitives/reject_changes.d.ts.map +1 -1
  183. package/dist/primitives/reject_changes.js +177 -24
  184. package/dist/primitives/reject_changes.js.map +1 -1
  185. package/dist/primitives/revision-parts.d.ts +7 -0
  186. package/dist/primitives/revision-parts.d.ts.map +1 -0
  187. package/dist/primitives/revision-parts.js +27 -0
  188. package/dist/primitives/revision-parts.js.map +1 -0
  189. package/dist/primitives/revision-vocabulary.d.ts +7 -0
  190. package/dist/primitives/revision-vocabulary.d.ts.map +1 -0
  191. package/dist/primitives/revision-vocabulary.js +39 -0
  192. package/dist/primitives/revision-vocabulary.js.map +1 -0
  193. package/dist/primitives/schema-corpus-capture.d.ts +19 -0
  194. package/dist/primitives/schema-corpus-capture.d.ts.map +1 -0
  195. package/dist/primitives/schema-corpus-capture.js +29 -0
  196. package/dist/primitives/schema-corpus-capture.js.map +1 -0
  197. package/dist/primitives/sectPrAudit.d.ts +19 -0
  198. package/dist/primitives/sectPrAudit.d.ts.map +1 -0
  199. package/dist/primitives/sectPrAudit.js +165 -0
  200. package/dist/primitives/sectPrAudit.js.map +1 -0
  201. package/dist/primitives/semantic_tags.d.ts.map +1 -1
  202. package/dist/primitives/semantic_tags.js +2 -1
  203. package/dist/primitives/semantic_tags.js.map +1 -1
  204. package/dist/primitives/serialize_html.d.ts +1 -0
  205. package/dist/primitives/serialize_html.d.ts.map +1 -1
  206. package/dist/primitives/serialize_html.js +4 -2
  207. package/dist/primitives/serialize_html.js.map +1 -1
  208. package/dist/primitives/styles.d.ts +15 -0
  209. package/dist/primitives/styles.d.ts.map +1 -1
  210. package/dist/primitives/styles.js +11 -0
  211. package/dist/primitives/styles.js.map +1 -1
  212. package/dist/primitives/track-changes-emitter.d.ts +9 -0
  213. package/dist/primitives/track-changes-emitter.d.ts.map +1 -1
  214. package/dist/primitives/track-changes-emitter.js +54 -4
  215. package/dist/primitives/track-changes-emitter.js.map +1 -1
  216. package/dist/primitives/validate_ai_revisions.d.ts +35 -0
  217. package/dist/primitives/validate_ai_revisions.d.ts.map +1 -0
  218. package/dist/primitives/validate_ai_revisions.js +323 -0
  219. package/dist/primitives/validate_ai_revisions.js.map +1 -0
  220. package/dist/primitives/xml.d.ts +5 -0
  221. package/dist/primitives/xml.d.ts.map +1 -1
  222. package/dist/primitives/xml.js +5 -0
  223. package/dist/primitives/xml.js.map +1 -1
  224. package/dist/primitives/zip.d.ts +1 -0
  225. package/dist/primitives/zip.d.ts.map +1 -1
  226. package/dist/primitives/zip.js +21 -3
  227. package/dist/primitives/zip.js.map +1 -1
  228. package/dist/shared/field-structure.d.ts +14 -0
  229. package/dist/shared/field-structure.d.ts.map +1 -0
  230. package/dist/shared/field-structure.js +166 -0
  231. package/dist/shared/field-structure.js.map +1 -0
  232. package/package.json +7 -4
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * docx-platform-tests adapter protocol v1 entrypoint.
4
+ *
5
+ * Invoked by the suite runner as:
6
+ * safe-docx-conformance-adapter --protocol-version 1 \
7
+ * --operation operation.json --input input.docx --output output.docx
8
+ *
9
+ * Exit codes (per the suite's docs/adapter-protocol.md):
10
+ * 0 success, 1 error, 2 unsupported operation, 3 protocol mismatch.
11
+ * Declining with 2 is mandatory for operations outside the implemented
12
+ * set — the suite's design treats honest gaps as data, never approximate.
13
+ */
14
+ import { readFileSync, realpathSync, writeFileSync } from 'node:fs';
15
+ import { pathToFileURL } from 'node:url';
16
+ import { DocxDocument } from '../primitives/document.js';
17
+ import { getParagraphText, replaceParagraphTextRange } from '../primitives/text.js';
18
+ const SUPPORTED_PROTOCOL_VERSION = '1';
19
+ const SUPPORTED_OPERATIONS = new Set([
20
+ 'acceptAllTrackedChanges',
21
+ 'rejectAllTrackedChanges',
22
+ 'replaceFirstTextOccurrence',
23
+ ]);
24
+ function argValue(argv, flag) {
25
+ const idx = argv.indexOf(flag);
26
+ return idx !== -1 ? argv[idx + 1] : undefined;
27
+ }
28
+ export async function runConformanceAdapter(argv) {
29
+ const protocolVersion = argValue(argv, '--protocol-version');
30
+ const operationPath = argValue(argv, '--operation');
31
+ const inputPath = argValue(argv, '--input');
32
+ const outputPath = argValue(argv, '--output');
33
+ if (protocolVersion !== SUPPORTED_PROTOCOL_VERSION) {
34
+ console.log(`safe-docx-conformance-adapter speaks protocol v${SUPPORTED_PROTOCOL_VERSION}, got ${protocolVersion ?? 'none'}`);
35
+ return 3;
36
+ }
37
+ if (!operationPath || !inputPath || !outputPath) {
38
+ console.error('usage: --protocol-version 1 --operation <json> --input <docx> --output <docx>');
39
+ return 1;
40
+ }
41
+ const operation = JSON.parse(readFileSync(operationPath, 'utf8'));
42
+ // Decline before touching the input: unsupported must not depend on the
43
+ // document being readable.
44
+ if (!SUPPORTED_OPERATIONS.has(operation.operationName)) {
45
+ console.log(`safe-docx adapter does not implement operation '${operation.operationName}'`);
46
+ return 2;
47
+ }
48
+ const doc = await DocxDocument.load(readFileSync(inputPath));
49
+ switch (operation.operationName) {
50
+ case 'acceptAllTrackedChanges':
51
+ await doc.acceptChanges();
52
+ break;
53
+ case 'rejectAllTrackedChanges':
54
+ await doc.rejectChanges();
55
+ break;
56
+ case 'replaceFirstTextOccurrence': {
57
+ const { findText, replaceText } = operation;
58
+ if (typeof findText !== 'string' || typeof replaceText !== 'string') {
59
+ console.error('replaceFirstTextOccurrence requires findText and replaceText');
60
+ return 1;
61
+ }
62
+ // DSL 1.0 match scope: first paragraph-local occurrence in document
63
+ // order; the replacement is a plain edit, not a tracked change.
64
+ const paragraph = doc
65
+ .getParagraphs()
66
+ .find((p) => getParagraphText(p).includes(findText));
67
+ if (!paragraph) {
68
+ console.error(`findText not present in any paragraph: ${JSON.stringify(findText)}`);
69
+ return 1;
70
+ }
71
+ const start = getParagraphText(paragraph).indexOf(findText);
72
+ replaceParagraphTextRange(paragraph, start, start + findText.length, replaceText);
73
+ break;
74
+ }
75
+ default:
76
+ // Unreachable: membership was checked above.
77
+ return 2;
78
+ }
79
+ const { buffer } = await doc.toBuffer();
80
+ writeFileSync(outputPath, buffer);
81
+ return 0;
82
+ }
83
+ // realpathSync: when invoked through the node_modules/.bin symlink,
84
+ // process.argv[1] is the symlink while import.meta.url is the real file.
85
+ if (process.argv[1] && pathToFileURL(realpathSync(process.argv[1])).href === import.meta.url) {
86
+ runConformanceAdapter(process.argv.slice(2))
87
+ .then((code) => process.exit(code))
88
+ .catch((err) => {
89
+ console.error(err?.message ?? String(err));
90
+ process.exit(1);
91
+ });
92
+ }
93
+ //# sourceMappingURL=conformance-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformance-adapter.js","sourceRoot":"","sources":["../../src/cli/conformance-adapter.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAIA,wBAAsB,MAAM,CAAC,IAAI,WAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAU/D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAKA,wBAAsB,MAAM,CAAC,IAAI,WAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAU/D"}
package/dist/cli/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { realpathSync } from 'node:fs';
2
3
  import { pathToFileURL } from 'node:url';
3
4
  import { runCompareCli } from './compare-two.js';
4
5
  export async function runCli(argv = process.argv) {
@@ -11,7 +12,10 @@ export async function runCli(argv = process.argv) {
11
12
  // eslint-disable-next-line no-console
12
13
  console.log(JSON.stringify(result));
13
14
  }
14
- if (process.argv[1] && pathToFileURL(process.argv[1]).href === import.meta.url) {
15
+ // npm installs bins as node_modules/.bin symlinks, so argv[1] must be
16
+ // realpath-resolved before comparing against import.meta.url (which node
17
+ // always resolves to the real dist file). See #398.
18
+ if (process.argv[1] && pathToFileURL(realpathSync(process.argv[1])).href === import.meta.url) {
15
19
  runCli(process.argv).catch((err) => {
16
20
  // eslint-disable-next-line no-console
17
21
  console.error(err?.message ?? String(err));
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI;IAC9C,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QACpC,sCAAsC;QACtC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO;IACT,CAAC;IAED,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/E,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACjC,sCAAsC;QACtC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI;IAC9C,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QACpC,sCAAsC;QACtC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO;IACT,CAAC;IAED,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,sEAAsE;AACtE,yEAAyE;AACzE,oDAAoD;AACpD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7F,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACjC,sCAAsC;QACtC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -34,9 +34,35 @@ export interface CompareOptions {
34
34
  engine?: 'wmlcomparer' | 'atomizer' | 'auto';
35
35
  }
36
36
  export interface CompareStats {
37
+ /**
38
+ * Human-facing inserted change ranges. This counts contiguous inserted atom
39
+ * runs, matching the coalesced w:ins regions emitted in OOXML.
40
+ */
37
41
  insertions: number;
42
+ /**
43
+ * Human-facing deleted change ranges. This counts contiguous deleted atom
44
+ * runs, matching the coalesced w:del regions emitted in OOXML.
45
+ */
38
46
  deletions: number;
47
+ /**
48
+ * Paragraphs containing both inserted and deleted content. Format-only
49
+ * changes are reported separately in formatChanges.
50
+ */
39
51
  modifications: number;
52
+ /** Same value as insertions, exposed with explicit range-level semantics. */
53
+ insertedRanges: number;
54
+ /** Same value as deletions, exposed with explicit range-level semantics. */
55
+ deletedRanges: number;
56
+ /** Atom-level inserted units for granular/benchmark consumers. */
57
+ insertedAtoms: number;
58
+ /** Atom-level deleted units for granular/benchmark consumers. */
59
+ deletedAtoms: number;
60
+ /** Same value as modifications, exposed without overloading the term. */
61
+ modifiedParagraphs: number;
62
+ /** Contiguous format-only change ranges. */
63
+ formatChanges: number;
64
+ /** Atom-level format-only units for granular/benchmark consumers. */
65
+ formatChangeAtoms: number;
40
66
  }
41
67
  export type ReconstructionMode = 'rebuild' | 'inplace';
42
68
  export type ReconstructionFallbackReason = 'round_trip_safety_check_failed';
@@ -122,6 +148,20 @@ export interface ReconstructionAttemptDiagnostics {
122
148
  export interface ReconstructionFallbackDiagnostics {
123
149
  attempts: ReconstructionAttemptDiagnostics[];
124
150
  }
151
+ /**
152
+ * Round-trip safety evaluation of rebuild output. Rebuild is the terminal
153
+ * reconstruction strategy — there is no further fallback — so a failed check
154
+ * cannot reroute the pipeline. The document is returned anyway and the
155
+ * failures are surfaced here as a caller-visible warning.
156
+ *
157
+ * @see https://github.com/UseJunior/safe-docx/issues/226
158
+ */
159
+ export interface ReconstructionRebuildSafetyDiagnostics {
160
+ checks: ReconstructionSafetyChecks;
161
+ failedChecks: ReconstructionSafetyCheckName[];
162
+ failureDetails?: ReconstructionSafetyFailureDetails;
163
+ firstDiffSummary?: ReconstructionSafetyFailureSummary;
164
+ }
125
165
  export interface CompareResult {
126
166
  /** The resulting DOCX with track changes */
127
167
  document: Buffer;
@@ -147,5 +187,11 @@ export interface CompareResult {
147
187
  * Present only when atomizer falls back.
148
188
  */
149
189
  fallbackDiagnostics?: ReconstructionFallbackDiagnostics;
190
+ /**
191
+ * Safety-check failures observed on rebuild output — whether rebuild was
192
+ * requested explicitly (the default mode) or reached via inplace fallback.
193
+ * Present only when at least one check failed.
194
+ */
195
+ rebuildSafetyDiagnostics?: ReconstructionRebuildSafetyDiagnostics;
150
196
  }
151
197
  //# sourceMappingURL=compare-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compare-types.d.ts","sourceRoot":"","sources":["../src/compare-types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,aAAa,GAAG,UAAU,GAAG,MAAM,CAAC;CAC9C;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,CAAC;AAEvD,MAAM,MAAM,4BAA4B,GAAG,gCAAgC,CAAC;AAE5E,MAAM,MAAM,6BAA6B,GACrC,YAAY,GACZ,YAAY,GACZ,iBAAiB,GACjB,iBAAiB,GACjB,gBAAgB,CAAC;AAErB,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,iCAAiC;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,4BAA4B,EAAE,MAAM,CAAC;IACrC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,qCAAqC;IACpD,UAAU,EAAE,qBAAqB,CAAC;IAClC,uBAAuB,EAAE,qBAAqB,CAAC;IAC/C,wBAAwB,EAAE,qBAAqB,CAAC;IAChD,QAAQ,EAAE,qBAAqB,CAAC;IAChC,MAAM,EAAE,qBAAqB,CAAC;IAC9B,2BAA2B,EAAE,MAAM,EAAE,CAAC;IACtC,yBAAyB,EAAE,MAAM,EAAE,CAAC;IACpC,yBAAyB,EAAE,MAAM,EAAE,CAAC;IACpC,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,yBAAyB,EAAE,MAAM,EAAE,CAAC;IACpC,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,qBAAqB,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,kCAAkC;IACjD,UAAU,CAAC,EAAE,iCAAiC,CAAC;IAC/C,UAAU,CAAC,EAAE,iCAAiC,CAAC;IAC/C,eAAe,CAAC,EAAE,qCAAqC,CAAC;IACxD,eAAe,CAAC,EAAE,qCAAqC,CAAC;CACzD;AAED,MAAM,WAAW,4BAA4B;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iCAAiC;IAChD,4BAA4B,EAAE,MAAM,CAAC;IACrC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,qCAAqC;IACpD,UAAU,EAAE,4BAA4B,CAAC;IACzC,uBAAuB,EAAE,4BAA4B,CAAC;IACtD,wBAAwB,EAAE,4BAA4B,CAAC;IACvD,QAAQ,EAAE,4BAA4B,CAAC;IACvC,MAAM,EAAE,4BAA4B,CAAC;IACrC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,kCAAkC;IACjD,UAAU,CAAC,EAAE,iCAAiC,CAAC;IAC/C,UAAU,CAAC,EAAE,iCAAiC,CAAC;IAC/C,eAAe,CAAC,EAAE,qCAAqC,CAAC;IACxD,eAAe,CAAC,EAAE,qCAAqC,CAAC;CACzD;AAED,MAAM,WAAW,gCAAgC;IAC/C,IAAI,EACA,oBAAoB,GACpB,mBAAmB,GACnB,8BAA8B,GAC9B,6BAA6B,CAAC;IAClC,MAAM,EAAE,0BAA0B,CAAC;IACnC,YAAY,EAAE,6BAA6B,EAAE,CAAC;IAC9C,cAAc,CAAC,EAAE,kCAAkC,CAAC;IACpD,gBAAgB,CAAC,EAAE,kCAAkC,CAAC;CACvD;AAED,MAAM,WAAW,iCAAiC;IAChD,QAAQ,EAAE,gCAAgC,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,KAAK,EAAE,YAAY,CAAC;IACpB,4BAA4B;IAC5B,MAAM,EAAE,aAAa,GAAG,UAAU,CAAC;IACnC;;OAEG;IACH,2BAA2B,CAAC,EAAE,kBAAkB,CAAC;IACjD;;OAEG;IACH,sBAAsB,CAAC,EAAE,kBAAkB,CAAC;IAC5C;;;OAGG;IACH,cAAc,CAAC,EAAE,4BAA4B,CAAC;IAC9C;;;OAGG;IACH,mBAAmB,CAAC,EAAE,iCAAiC,CAAC;CACzD"}
1
+ {"version":3,"file":"compare-types.d.ts","sourceRoot":"","sources":["../src/compare-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The generation compiler: DocumentSpec → validated spec → per-part emitters
3
+ * → ordered file record → zip buffer.
4
+ *
5
+ * Determinism contract: identical specs compile to byte-identical buffers.
6
+ * No emitter reads the clock or randomness; zip entry dates are pinned to a
7
+ * fixed epoch (document-facing dates come from spec.meta.createdIso).
8
+ *
9
+ * Ordering: header/footer parts are allocated first so their relationship
10
+ * ids exist when the document part binds section references; the package
11
+ * plumbing runs last because [Content_Types].xml is assembled from the part
12
+ * registry.
13
+ */
14
+ import type { DocumentSpec } from './types.js';
15
+ export type GenerateDocxOptions = {
16
+ /** Overrides spec.options.includeDraftingNotes when provided. */
17
+ includeDraftingNotes?: boolean;
18
+ };
19
+ /** Compile a DocumentSpec into a complete DOCX package. */
20
+ export declare function generateDocx(spec: DocumentSpec, opts?: GenerateDocxOptions): Promise<Buffer>;
21
+ //# sourceMappingURL=compile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/generation/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAaH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/C,MAAM,MAAM,mBAAmB,GAAG;IAChC,iEAAiE;IACjE,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF,2DAA2D;AAC3D,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBlG"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The generation compiler: DocumentSpec → validated spec → per-part emitters
3
+ * → ordered file record → zip buffer.
4
+ *
5
+ * Determinism contract: identical specs compile to byte-identical buffers.
6
+ * No emitter reads the clock or randomness; zip entry dates are pinned to a
7
+ * fixed epoch (document-facing dates come from spec.meta.createdIso).
8
+ *
9
+ * Ordering: header/footer parts are allocated first so their relationship
10
+ * ids exist when the document part binds section references; the package
11
+ * plumbing runs last because [Content_Types].xml is assembled from the part
12
+ * registry.
13
+ */
14
+ import { createZipBuffer } from '../primitives/zip.js';
15
+ import { maybeCaptureEmittedDocumentXml } from '../primitives/schema-corpus-capture.js';
16
+ import { CompileContext } from './context.js';
17
+ import { emitCommentsPartsIfNeeded } from './emit/comments-part.js';
18
+ import { DraftingNoteCollector } from './emit/emit-context.js';
19
+ import { emitDocumentPart } from './emit/document-part.js';
20
+ import { emitHeaderFooterParts } from './emit/header-footer-part.js';
21
+ import { emitNumberingPartIfNeeded } from './emit/numbering-part.js';
22
+ import { emitPackageParts } from './emit/package-parts.js';
23
+ import { emitSettingsPartIfNeeded } from './emit/settings-part.js';
24
+ import { emitStylesPart } from './emit/styles-part.js';
25
+ import { validateSpec } from './validate-spec.js';
26
+ /** Fixed zip-entry timestamp (2006-01-01T00:00:00Z, the OOXML vintage). */
27
+ const ZIP_EPOCH = new Date(Date.UTC(2006, 0, 1));
28
+ /** Compile a DocumentSpec into a complete DOCX package. */
29
+ export async function generateDocx(spec, opts) {
30
+ validateSpec(spec);
31
+ const notesEnabled = opts?.includeDraftingNotes ?? spec.options?.includeDraftingNotes ?? true;
32
+ const ctx = new CompileContext();
33
+ const numberingIds = emitNumberingPartIfNeeded(spec, ctx);
34
+ const headerFooterRefs = emitHeaderFooterParts(spec, ctx, { numberingIds });
35
+ const notes = notesEnabled ? new DraftingNoteCollector() : undefined;
36
+ const documentPartXml = emitDocumentPart(spec, headerFooterRefs, { numberingIds, notes });
37
+ maybeCaptureEmittedDocumentXml(documentPartXml);
38
+ ctx.setFileContent('word/document.xml', documentPartXml);
39
+ if (notes)
40
+ emitCommentsPartsIfNeeded(spec, ctx, notes);
41
+ emitStylesPart(spec, ctx);
42
+ emitSettingsPartIfNeeded(spec, ctx);
43
+ emitPackageParts(spec, ctx);
44
+ return createZipBuffer(ctx.toFileRecord(), { fileDate: ZIP_EPOCH });
45
+ }
46
+ //# sourceMappingURL=compile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/generation/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,2EAA2E;AAC3E,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAOjD,2DAA2D;AAC3D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAkB,EAAE,IAA0B;IAC/E,YAAY,CAAC,IAAI,CAAC,CAAC;IAEnB,MAAM,YAAY,GAAG,IAAI,EAAE,oBAAoB,IAAI,IAAI,CAAC,OAAO,EAAE,oBAAoB,IAAI,IAAI,CAAC;IAC9F,MAAM,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;IACjC,MAAM,YAAY,GAAG,yBAAyB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,qBAAqB,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACrE,MAAM,eAAe,GAAG,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1F,8BAA8B,CAAC,eAAe,CAAC,CAAC;IAChD,GAAG,CAAC,cAAc,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;IACzD,IAAI,KAAK;QAAE,yBAAyB,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IACvD,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC1B,wBAAwB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACpC,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE5B,OAAO,eAAe,CAAC,GAAG,CAAC,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;AACtE,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Compile-time state shared by the part emitters.
3
+ *
4
+ * The context owns the part registry (part name → content type + optional
5
+ * document-level relationship), the relationship-id allocator, and the
6
+ * ordered file map handed to the zip assembler. All allocation is
7
+ * deterministic: ids are sequential counters, never random, and no part of
8
+ * the compiler reads the clock.
9
+ */
10
+ export type RegisteredPart = {
11
+ /** Zip path, e.g. 'word/header1.xml'. */
12
+ name: string;
13
+ /** Content type registered as an Override in [Content_Types].xml. */
14
+ contentType: string;
15
+ /** Relationship from word/document.xml, when the part is document-attached. */
16
+ documentRel?: {
17
+ type: string;
18
+ rId: string;
19
+ };
20
+ };
21
+ export declare class CompileContext {
22
+ private readonly partsByName;
23
+ private readonly fileContents;
24
+ private nextRid;
25
+ private nextHeaderIndex;
26
+ private nextFooterIndex;
27
+ /** Register a part that needs a content-type Override (content set separately). */
28
+ registerPart(name: string, contentType: string, documentRelType?: string): RegisteredPart;
29
+ allocateRid(): string;
30
+ allocateHeaderPartName(): string;
31
+ allocateFooterPartName(): string;
32
+ setFileContent(name: string, content: string): void;
33
+ registeredParts(): RegisteredPart[];
34
+ documentRelParts(): RegisteredPart[];
35
+ /**
36
+ * Assemble the final zip-file record. [Content_Types].xml is placed first —
37
+ * createZipBuffer preserves insertion order but does not enforce ordering
38
+ * itself, so the contract lives here.
39
+ */
40
+ toFileRecord(): Record<string, string>;
41
+ }
42
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/generation/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,cAAc,GAAG;IAC3B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C,CAAC;AAEF,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqC;IACjE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAC1D,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,eAAe,CAAK;IAE5B,mFAAmF;IACnF,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,cAAc;IAYzF,WAAW,IAAI,MAAM;IAIrB,sBAAsB,IAAI,MAAM;IAIhC,sBAAsB,IAAI,MAAM;IAIhC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAInD,eAAe,IAAI,cAAc,EAAE;IAInC,gBAAgB,IAAI,cAAc,EAAE;IAIpC;;;;OAIG;IACH,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAYvC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Compile-time state shared by the part emitters.
3
+ *
4
+ * The context owns the part registry (part name → content type + optional
5
+ * document-level relationship), the relationship-id allocator, and the
6
+ * ordered file map handed to the zip assembler. All allocation is
7
+ * deterministic: ids are sequential counters, never random, and no part of
8
+ * the compiler reads the clock.
9
+ */
10
+ export class CompileContext {
11
+ partsByName = new Map();
12
+ fileContents = new Map();
13
+ nextRid = 1;
14
+ nextHeaderIndex = 1;
15
+ nextFooterIndex = 1;
16
+ /** Register a part that needs a content-type Override (content set separately). */
17
+ registerPart(name, contentType, documentRelType) {
18
+ if (this.partsByName.has(name)) {
19
+ return this.partsByName.get(name);
20
+ }
21
+ const part = { name, contentType };
22
+ if (documentRelType) {
23
+ part.documentRel = { type: documentRelType, rId: this.allocateRid() };
24
+ }
25
+ this.partsByName.set(name, part);
26
+ return part;
27
+ }
28
+ allocateRid() {
29
+ return `rId${this.nextRid++}`;
30
+ }
31
+ allocateHeaderPartName() {
32
+ return `word/header${this.nextHeaderIndex++}.xml`;
33
+ }
34
+ allocateFooterPartName() {
35
+ return `word/footer${this.nextFooterIndex++}.xml`;
36
+ }
37
+ setFileContent(name, content) {
38
+ this.fileContents.set(name, content);
39
+ }
40
+ registeredParts() {
41
+ return Array.from(this.partsByName.values());
42
+ }
43
+ documentRelParts() {
44
+ return this.registeredParts().filter((p) => p.documentRel);
45
+ }
46
+ /**
47
+ * Assemble the final zip-file record. [Content_Types].xml is placed first —
48
+ * createZipBuffer preserves insertion order but does not enforce ordering
49
+ * itself, so the contract lives here.
50
+ */
51
+ toFileRecord() {
52
+ const contentTypes = this.fileContents.get('[Content_Types].xml');
53
+ if (contentTypes === undefined) {
54
+ throw new Error('compile bug: [Content_Types].xml was never emitted');
55
+ }
56
+ const record = { '[Content_Types].xml': contentTypes };
57
+ for (const [name, content] of this.fileContents) {
58
+ if (name === '[Content_Types].xml')
59
+ continue;
60
+ record[name] = content;
61
+ }
62
+ return record;
63
+ }
64
+ }
65
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/generation/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,MAAM,OAAO,cAAc;IACR,WAAW,GAAG,IAAI,GAAG,EAA0B,CAAC;IAChD,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClD,OAAO,GAAG,CAAC,CAAC;IACZ,eAAe,GAAG,CAAC,CAAC;IACpB,eAAe,GAAG,CAAC,CAAC;IAE5B,mFAAmF;IACnF,YAAY,CAAC,IAAY,EAAE,WAAmB,EAAE,eAAwB;QACtE,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QACrC,CAAC;QACD,MAAM,IAAI,GAAmB,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QACnD,IAAI,eAAe,EAAE,CAAC;YACpB,IAAI,CAAC,WAAW,GAAG,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACxE,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,WAAW;QACT,OAAO,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;IAChC,CAAC;IAED,sBAAsB;QACpB,OAAO,cAAc,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC;IACpD,CAAC;IAED,sBAAsB;QACpB,OAAO,cAAc,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC;IACpD,CAAC;IAED,cAAc,CAAC,IAAY,EAAE,OAAe;QAC1C,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IAED,eAAe;QACb,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,gBAAgB;QACd,OAAO,IAAI,CAAC,eAAe,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAC7D,CAAC;IAED;;;;OAIG;IACH,YAAY;QACV,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QAClE,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;QACD,MAAM,MAAM,GAA2B,EAAE,qBAAqB,EAAE,YAAY,EAAE,CAAC;QAC/E,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAChD,IAAI,IAAI,KAAK,qBAAqB;gBAAE,SAAS;YAC7C,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;QACzB,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Drafting-note comment parts: word/comments.xml plus the Word-extension
3
+ * ancillary parts word/commentsExtended.xml and word/people.xml.
4
+ *
5
+ * All three are always emitted together when notes are enabled. The
6
+ * ancillary pair is deliberately on by default: plain comments.xml loads in
7
+ * every reader we test, but Word 2013+ writes the trio and its own comment
8
+ * UI degrades (no resolve state, no people presence) without them. Content
9
+ * and relationship types match what Word itself writes — verified against
10
+ * the Open XML SDK's WordprocessingCommentsExPart/WordprocessingPeoplePart
11
+ * constants (the `application/vnd.ms-word.commentsExtended+xml` variant
12
+ * found in some third-party packages is NOT what Word emits). They also
13
+ * match the editing path in primitives/comments.ts, so a generated document
14
+ * is indistinguishable from an edited one to the comment APIs.
15
+ *
16
+ * Determinism: comment ids are allocated in document order by the
17
+ * DraftingNoteCollector; w14:paraId values derive from those ids; dates come
18
+ * only from DraftingNoteSpec.dateIso (falling back to meta.createdIso);
19
+ * authors fall back note.author → meta.author → 'safe-docx'. No clock, no
20
+ * randomness — identical specs produce byte-identical comment parts.
21
+ *
22
+ * @conformance ECMA-376 edition 5, Part 1 § 17.13.4.6
23
+ * @conformance ECMA-376 edition 5, Part 1 § 17.13.4.2
24
+ */
25
+ import type { CompileContext } from '../context.js';
26
+ import type { DocumentSpec } from '../types.js';
27
+ import type { DraftingNoteCollector } from './emit-context.js';
28
+ export declare const COMMENTS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml";
29
+ export declare const COMMENTS_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
30
+ export declare const COMMENTS_EXTENDED_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml";
31
+ export declare const COMMENTS_EXTENDED_REL_TYPE = "http://schemas.microsoft.com/office/2011/relationships/commentsExtended";
32
+ export declare const PEOPLE_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.people+xml";
33
+ export declare const PEOPLE_REL_TYPE = "http://schemas.microsoft.com/office/2011/relationships/people";
34
+ /** Emit the comment trio from the notes collected during body emission. */
35
+ export declare function emitCommentsPartsIfNeeded(spec: DocumentSpec, ctx: CompileContext, collector: DraftingNoteCollector): void;
36
+ //# sourceMappingURL=comments-part.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comments-part.d.ts","sourceRoot":"","sources":["../../../src/generation/emit/comments-part.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE/D,eAAO,MAAM,qBAAqB,gFAAgF,CAAC;AACnH,eAAO,MAAM,iBAAiB,iFAAiF,CAAC;AAChH,eAAO,MAAM,8BAA8B,wFAC4C,CAAC;AACxF,eAAO,MAAM,0BAA0B,4EAA4E,CAAC;AACpH,eAAO,MAAM,mBAAmB,8EAA8E,CAAC;AAC/G,eAAO,MAAM,eAAe,kEAAkE,CAAC;AAyB/F,2EAA2E;AAC3E,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,YAAY,EAClB,GAAG,EAAE,cAAc,EACnB,SAAS,EAAE,qBAAqB,GAC/B,IAAI,CAUN"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Drafting-note comment parts: word/comments.xml plus the Word-extension
3
+ * ancillary parts word/commentsExtended.xml and word/people.xml.
4
+ *
5
+ * All three are always emitted together when notes are enabled. The
6
+ * ancillary pair is deliberately on by default: plain comments.xml loads in
7
+ * every reader we test, but Word 2013+ writes the trio and its own comment
8
+ * UI degrades (no resolve state, no people presence) without them. Content
9
+ * and relationship types match what Word itself writes — verified against
10
+ * the Open XML SDK's WordprocessingCommentsExPart/WordprocessingPeoplePart
11
+ * constants (the `application/vnd.ms-word.commentsExtended+xml` variant
12
+ * found in some third-party packages is NOT what Word emits). They also
13
+ * match the editing path in primitives/comments.ts, so a generated document
14
+ * is indistinguishable from an edited one to the comment APIs.
15
+ *
16
+ * Determinism: comment ids are allocated in document order by the
17
+ * DraftingNoteCollector; w14:paraId values derive from those ids; dates come
18
+ * only from DraftingNoteSpec.dateIso (falling back to meta.createdIso);
19
+ * authors fall back note.author → meta.author → 'safe-docx'. No clock, no
20
+ * randomness — identical specs produce byte-identical comment parts.
21
+ *
22
+ * @conformance ECMA-376 edition 5, Part 1 § 17.13.4.6
23
+ * @conformance ECMA-376 edition 5, Part 1 § 17.13.4.2
24
+ */
25
+ import { createWmlElement, createWmlTextElement } from '../../primitives/dom-helpers.js';
26
+ import { OOXML, W } from '../../primitives/namespaces.js';
27
+ import { parseXml, serializeXml, XML_DECL } from '../../primitives/xml.js';
28
+ export const COMMENTS_CONTENT_TYPE = 'application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml';
29
+ export const COMMENTS_REL_TYPE = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments';
30
+ export const COMMENTS_EXTENDED_CONTENT_TYPE = 'application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml';
31
+ export const COMMENTS_EXTENDED_REL_TYPE = 'http://schemas.microsoft.com/office/2011/relationships/commentsExtended';
32
+ export const PEOPLE_CONTENT_TYPE = 'application/vnd.openxmlformats-officedocument.wordprocessingml.people+xml';
33
+ export const PEOPLE_REL_TYPE = 'http://schemas.microsoft.com/office/2011/relationships/people';
34
+ const COMMENTS_SKELETON = `<w:comments xmlns:w="${OOXML.W_NS}" xmlns:w14="${OOXML.W14_NS}"/>`;
35
+ const DEFAULT_AUTHOR = 'safe-docx';
36
+ /** Deterministic w14:paraId for a comment id: zero-padded uppercase hex. */
37
+ function paraIdFor(id) {
38
+ return id.toString(16).toUpperCase().padStart(8, '0');
39
+ }
40
+ function authorFor(spec, note) {
41
+ return note.author ?? spec.meta?.author ?? DEFAULT_AUTHOR;
42
+ }
43
+ /** Up-to-three-letter initials from the author's words, deterministic. */
44
+ function initialsFor(author) {
45
+ const letters = author
46
+ .split(/\s+/)
47
+ .map((word) => word.replace(/[^\p{L}\p{N}]/gu, '').charAt(0))
48
+ .filter((c) => c.length > 0);
49
+ const initials = letters.slice(0, 3).join('').toUpperCase();
50
+ return initials.length > 0 ? initials : 'SD';
51
+ }
52
+ /** Emit the comment trio from the notes collected during body emission. */
53
+ export function emitCommentsPartsIfNeeded(spec, ctx, collector) {
54
+ if (collector.collected.length === 0)
55
+ return;
56
+ ctx.registerPart('word/comments.xml', COMMENTS_CONTENT_TYPE, COMMENTS_REL_TYPE);
57
+ ctx.registerPart('word/commentsExtended.xml', COMMENTS_EXTENDED_CONTENT_TYPE, COMMENTS_EXTENDED_REL_TYPE);
58
+ ctx.registerPart('word/people.xml', PEOPLE_CONTENT_TYPE, PEOPLE_REL_TYPE);
59
+ ctx.setFileContent('word/comments.xml', emitCommentsXml(spec, collector));
60
+ ctx.setFileContent('word/commentsExtended.xml', emitCommentsExtendedXml(collector));
61
+ ctx.setFileContent('word/people.xml', emitPeopleXml(spec, collector));
62
+ }
63
+ function emitCommentsXml(spec, collector) {
64
+ const doc = parseXml(COMMENTS_SKELETON);
65
+ const root = doc.documentElement;
66
+ for (const { id, note } of collector.collected) {
67
+ const attrs = {
68
+ 'w:id': String(id),
69
+ 'w:author': authorFor(spec, note),
70
+ 'w:initials': initialsFor(authorFor(spec, note)),
71
+ };
72
+ const dateIso = note.dateIso ?? spec.meta?.createdIso;
73
+ if (dateIso !== undefined)
74
+ attrs['w:date'] = dateIso;
75
+ const comment = createWmlElement(doc, W.comment, attrs);
76
+ const p = createWmlElement(doc, W.p);
77
+ p.setAttributeNS(OOXML.W14_NS, 'w14:paraId', paraIdFor(id));
78
+ const run = createWmlElement(doc, W.r);
79
+ run.appendChild(createWmlTextElement(doc, note.text));
80
+ p.appendChild(run);
81
+ comment.appendChild(p);
82
+ root.appendChild(comment);
83
+ }
84
+ return XML_DECL + serializeXml(doc);
85
+ }
86
+ function emitCommentsExtendedXml(collector) {
87
+ const doc = parseXml(`<w15:commentsEx xmlns:w15="${OOXML.W15_NS}"/>`);
88
+ const root = doc.documentElement;
89
+ for (const { id } of collector.collected) {
90
+ const commentEx = doc.createElementNS(OOXML.W15_NS, 'w15:commentEx');
91
+ commentEx.setAttributeNS(OOXML.W15_NS, 'w15:paraId', paraIdFor(id));
92
+ commentEx.setAttributeNS(OOXML.W15_NS, 'w15:done', '0');
93
+ root.appendChild(commentEx);
94
+ }
95
+ return XML_DECL + serializeXml(doc);
96
+ }
97
+ function emitPeopleXml(spec, collector) {
98
+ const doc = parseXml(`<w15:people xmlns:w15="${OOXML.W15_NS}"/>`);
99
+ const root = doc.documentElement;
100
+ const seen = new Set();
101
+ for (const { note } of collector.collected) {
102
+ const author = authorFor(spec, note);
103
+ if (seen.has(author))
104
+ continue;
105
+ seen.add(author);
106
+ const person = doc.createElementNS(OOXML.W15_NS, 'w15:person');
107
+ person.setAttributeNS(OOXML.W15_NS, 'w15:author', author);
108
+ const presence = doc.createElementNS(OOXML.W15_NS, 'w15:presenceInfo');
109
+ presence.setAttributeNS(OOXML.W15_NS, 'w15:providerId', 'None');
110
+ presence.setAttributeNS(OOXML.W15_NS, 'w15:userId', author);
111
+ person.appendChild(presence);
112
+ root.appendChild(person);
113
+ }
114
+ return XML_DECL + serializeXml(doc);
115
+ }
116
+ //# sourceMappingURL=comments-part.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comments-part.js","sourceRoot":"","sources":["../../../src/generation/emit/comments-part.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * word/document.xml emitter.
3
+ *
4
+ * Builds the main document part from a namespace-declaring skeleton: the
5
+ * skeleton string carries every namespace the part uses on the root element,
6
+ * and all children are created through the namespace-safe DOM helpers.
7
+ * xmldom's serializer omits the XML declaration, so it is prepended here;
8
+ * the structural validator asserts every part starts with one.
9
+ */
10
+ import type { DocumentSpec } from '../types.js';
11
+ import type { BlockEmitContext } from './emit-context.js';
12
+ import { type SectionHeaderFooterRefs } from './section.js';
13
+ /**
14
+ * Compile the body: each section's blocks in order. Every non-final section
15
+ * ends with a dedicated break paragraph whose pPr contains only that
16
+ * section's sectPr (what Word itself emits on Insert → Section Break; it
17
+ * also sidesteps the trailing-table case), and the final section's
18
+ * properties bind as the body's last child.
19
+ *
20
+ * @conformance ECMA-376 edition 5, Part 1 § 17.6.18
21
+ * @conformance ECMA-376 edition 5, Part 1 § 17.6.17
22
+ */
23
+ export declare function emitDocumentPart(spec: DocumentSpec, refs?: SectionHeaderFooterRefs[], ctx?: BlockEmitContext): string;
24
+ //# sourceMappingURL=document-part.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-part.d.ts","sourceRoot":"","sources":["../../../src/generation/emit/document-part.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAe,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAOzE;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE,uBAAuB,EAAE,EAAE,GAAG,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAgCrH"}