@aster-editor/word 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/README.md +204 -81
  2. package/dist/docx/compare/align.d.ts +24 -0
  3. package/dist/docx/compare/align.d.ts.map +1 -0
  4. package/dist/docx/compare/align.js +217 -0
  5. package/dist/docx/compare/align.js.map +1 -0
  6. package/dist/docx/compare/compare-blocks.d.ts +29 -0
  7. package/dist/docx/compare/compare-blocks.d.ts.map +1 -0
  8. package/dist/docx/compare/compare-blocks.js +234 -0
  9. package/dist/docx/compare/compare-blocks.js.map +1 -0
  10. package/dist/docx/compare/compare-context.d.ts +25 -0
  11. package/dist/docx/compare/compare-context.d.ts.map +1 -0
  12. package/dist/docx/compare/compare-context.js +31 -0
  13. package/dist/docx/compare/compare-context.js.map +1 -0
  14. package/dist/docx/compare/compare-docx.d.ts +4 -0
  15. package/dist/docx/compare/compare-docx.d.ts.map +1 -0
  16. package/dist/docx/compare/compare-docx.js +173 -0
  17. package/dist/docx/compare/compare-docx.js.map +1 -0
  18. package/dist/docx/compare/compare-tables.d.ts +13 -0
  19. package/dist/docx/compare/compare-tables.d.ts.map +1 -0
  20. package/dist/docx/compare/compare-tables.js +47 -0
  21. package/dist/docx/compare/compare-tables.js.map +1 -0
  22. package/dist/docx/compare/model-borders.d.ts +27 -0
  23. package/dist/docx/compare/model-borders.d.ts.map +1 -0
  24. package/dist/docx/compare/model-borders.js +41 -0
  25. package/dist/docx/compare/model-borders.js.map +1 -0
  26. package/dist/docx/compare/model-paragraph.d.ts +25 -0
  27. package/dist/docx/compare/model-paragraph.d.ts.map +1 -0
  28. package/dist/docx/compare/model-paragraph.js +309 -0
  29. package/dist/docx/compare/model-paragraph.js.map +1 -0
  30. package/dist/docx/compare/model-sections.d.ts +11 -0
  31. package/dist/docx/compare/model-sections.d.ts.map +1 -0
  32. package/dist/docx/compare/model-sections.js +97 -0
  33. package/dist/docx/compare/model-sections.js.map +1 -0
  34. package/dist/docx/compare/model.d.ts +113 -0
  35. package/dist/docx/compare/model.d.ts.map +1 -0
  36. package/dist/docx/compare/model.js +214 -0
  37. package/dist/docx/compare/model.js.map +1 -0
  38. package/dist/docx/compare/parts.d.ts +40 -0
  39. package/dist/docx/compare/parts.d.ts.map +1 -0
  40. package/dist/docx/compare/parts.js +113 -0
  41. package/dist/docx/compare/parts.js.map +1 -0
  42. package/dist/docx/compare/tally.d.ts +23 -0
  43. package/dist/docx/compare/tally.d.ts.map +1 -0
  44. package/dist/docx/compare/tally.js +94 -0
  45. package/dist/docx/compare/tally.js.map +1 -0
  46. package/dist/docx/compare/types.d.ts +55 -0
  47. package/dist/docx/compare/types.d.ts.map +1 -0
  48. package/dist/docx/compare/types.js +2 -0
  49. package/dist/docx/compare/types.js.map +1 -0
  50. package/dist/docx/compare/values.d.ts +13 -0
  51. package/dist/docx/compare/values.d.ts.map +1 -0
  52. package/dist/docx/compare/values.js +44 -0
  53. package/dist/docx/compare/values.js.map +1 -0
  54. package/dist/docx/import-docx.d.ts.map +1 -1
  55. package/dist/docx/import-docx.js +65 -6
  56. package/dist/docx/import-docx.js.map +1 -1
  57. package/dist/docx/postprocess/strip-empty-paragraphs.d.ts +3 -0
  58. package/dist/docx/postprocess/strip-empty-paragraphs.d.ts.map +1 -1
  59. package/dist/docx/postprocess/strip-empty-paragraphs.js +7 -1
  60. package/dist/docx/postprocess/strip-empty-paragraphs.js.map +1 -1
  61. package/dist/docx/postprocess/types.d.ts +1 -1
  62. package/dist/docx/postprocess/types.d.ts.map +1 -1
  63. package/dist/docx/preprocess/variables.d.ts.map +1 -1
  64. package/dist/docx/preprocess/variables.js +2 -2
  65. package/dist/docx/preprocess/variables.js.map +1 -1
  66. package/dist/docx/preprocess/xml-utils.d.ts +7 -0
  67. package/dist/docx/preprocess/xml-utils.d.ts.map +1 -1
  68. package/dist/docx/preprocess/xml-utils.js +9 -0
  69. package/dist/docx/preprocess/xml-utils.js.map +1 -1
  70. package/dist/docx/reader/headers.d.ts +17 -0
  71. package/dist/docx/reader/headers.d.ts.map +1 -0
  72. package/dist/docx/reader/headers.js +64 -0
  73. package/dist/docx/reader/headers.js.map +1 -0
  74. package/dist/docx/reader/html.d.ts +12 -0
  75. package/dist/docx/reader/html.d.ts.map +1 -0
  76. package/dist/docx/reader/html.js +27 -0
  77. package/dist/docx/reader/html.js.map +1 -0
  78. package/dist/docx/reader/images.d.ts +27 -0
  79. package/dist/docx/reader/images.d.ts.map +1 -0
  80. package/dist/docx/reader/images.js +288 -0
  81. package/dist/docx/reader/images.js.map +1 -0
  82. package/dist/docx/reader/index.d.ts +10 -0
  83. package/dist/docx/reader/index.d.ts.map +1 -0
  84. package/dist/docx/reader/index.js +177 -0
  85. package/dist/docx/reader/index.js.map +1 -0
  86. package/dist/docx/reader/lists.d.ts +44 -0
  87. package/dist/docx/reader/lists.d.ts.map +1 -0
  88. package/dist/docx/reader/lists.js +360 -0
  89. package/dist/docx/reader/lists.js.map +1 -0
  90. package/dist/docx/reader/lost.d.ts +30 -0
  91. package/dist/docx/reader/lost.d.ts.map +1 -0
  92. package/dist/docx/reader/lost.js +215 -0
  93. package/dist/docx/reader/lost.js.map +1 -0
  94. package/dist/docx/reader/notes.d.ts +4 -0
  95. package/dist/docx/reader/notes.d.ts.map +1 -0
  96. package/dist/docx/reader/notes.js +112 -0
  97. package/dist/docx/reader/notes.js.map +1 -0
  98. package/dist/docx/reader/package.d.ts +16 -0
  99. package/dist/docx/reader/package.d.ts.map +1 -0
  100. package/dist/docx/reader/package.js +138 -0
  101. package/dist/docx/reader/package.js.map +1 -0
  102. package/dist/docx/reader/paragraphs.d.ts +15 -0
  103. package/dist/docx/reader/paragraphs.d.ts.map +1 -0
  104. package/dist/docx/reader/paragraphs.js +162 -0
  105. package/dist/docx/reader/paragraphs.js.map +1 -0
  106. package/dist/docx/reader/properties.d.ts +90 -0
  107. package/dist/docx/reader/properties.d.ts.map +1 -0
  108. package/dist/docx/reader/properties.js +402 -0
  109. package/dist/docx/reader/properties.js.map +1 -0
  110. package/dist/docx/reader/runs.d.ts +49 -0
  111. package/dist/docx/reader/runs.d.ts.map +1 -0
  112. package/dist/docx/reader/runs.js +442 -0
  113. package/dist/docx/reader/runs.js.map +1 -0
  114. package/dist/docx/reader/sections.d.ts +36 -0
  115. package/dist/docx/reader/sections.d.ts.map +1 -0
  116. package/dist/docx/reader/sections.js +158 -0
  117. package/dist/docx/reader/sections.js.map +1 -0
  118. package/dist/docx/reader/styles.d.ts +24 -0
  119. package/dist/docx/reader/styles.d.ts.map +1 -0
  120. package/dist/docx/reader/styles.js +383 -0
  121. package/dist/docx/reader/styles.js.map +1 -0
  122. package/dist/docx/reader/tables.d.ts +6 -0
  123. package/dist/docx/reader/tables.d.ts.map +1 -0
  124. package/dist/docx/reader/tables.js +175 -0
  125. package/dist/docx/reader/tables.js.map +1 -0
  126. package/dist/docx/reader/test-support.d.ts +25 -0
  127. package/dist/docx/reader/test-support.d.ts.map +1 -0
  128. package/dist/docx/reader/test-support.js +135 -0
  129. package/dist/docx/reader/test-support.js.map +1 -0
  130. package/dist/docx/reader/testing-blocks.d.ts +50 -0
  131. package/dist/docx/reader/testing-blocks.d.ts.map +1 -0
  132. package/dist/docx/reader/testing-blocks.js +302 -0
  133. package/dist/docx/reader/testing-blocks.js.map +1 -0
  134. package/dist/docx/reader/types.d.ts +181 -0
  135. package/dist/docx/reader/types.d.ts.map +1 -0
  136. package/dist/docx/reader/types.js +2 -0
  137. package/dist/docx/reader/types.js.map +1 -0
  138. package/dist/docx/reader/units-blocks.d.ts +75 -0
  139. package/dist/docx/reader/units-blocks.d.ts.map +1 -0
  140. package/dist/docx/reader/units-blocks.js +254 -0
  141. package/dist/docx/reader/units-blocks.js.map +1 -0
  142. package/dist/docx/reader/units.d.ts +72 -0
  143. package/dist/docx/reader/units.d.ts.map +1 -0
  144. package/dist/docx/reader/units.js +177 -0
  145. package/dist/docx/reader/units.js.map +1 -0
  146. package/dist/docx/types.d.ts +47 -2
  147. package/dist/docx/types.d.ts.map +1 -1
  148. package/dist/docx/writer/content-types.d.ts +30 -0
  149. package/dist/docx/writer/content-types.d.ts.map +1 -0
  150. package/dist/docx/writer/content-types.js +81 -0
  151. package/dist/docx/writer/content-types.js.map +1 -0
  152. package/dist/docx/writer/core-properties.d.ts +16 -0
  153. package/dist/docx/writer/core-properties.d.ts.map +1 -0
  154. package/dist/docx/writer/core-properties.js +64 -0
  155. package/dist/docx/writer/core-properties.js.map +1 -0
  156. package/dist/docx/writer/footnotes-merge.d.ts +30 -0
  157. package/dist/docx/writer/footnotes-merge.d.ts.map +1 -0
  158. package/dist/docx/writer/footnotes-merge.js +71 -0
  159. package/dist/docx/writer/footnotes-merge.js.map +1 -0
  160. package/dist/docx/writer/graft.d.ts +41 -0
  161. package/dist/docx/writer/graft.d.ts.map +1 -0
  162. package/dist/docx/writer/graft.js +277 -0
  163. package/dist/docx/writer/graft.js.map +1 -0
  164. package/dist/docx/writer/header-footer-graft.d.ts +34 -0
  165. package/dist/docx/writer/header-footer-graft.d.ts.map +1 -0
  166. package/dist/docx/writer/header-footer-graft.js +155 -0
  167. package/dist/docx/writer/header-footer-graft.js.map +1 -0
  168. package/dist/docx/writer/header-footer-variables.d.ts +25 -0
  169. package/dist/docx/writer/header-footer-variables.d.ts.map +1 -0
  170. package/dist/docx/writer/header-footer-variables.js +101 -0
  171. package/dist/docx/writer/header-footer-variables.js.map +1 -0
  172. package/dist/docx/writer/media.d.ts +32 -0
  173. package/dist/docx/writer/media.d.ts.map +1 -0
  174. package/dist/docx/writer/media.js +88 -0
  175. package/dist/docx/writer/media.js.map +1 -0
  176. package/dist/docx/writer/numbering-merge.d.ts +37 -0
  177. package/dist/docx/writer/numbering-merge.d.ts.map +1 -0
  178. package/dist/docx/writer/numbering-merge.js +140 -0
  179. package/dist/docx/writer/numbering-merge.js.map +1 -0
  180. package/dist/docx/writer/relationships.d.ts +63 -0
  181. package/dist/docx/writer/relationships.d.ts.map +1 -0
  182. package/dist/docx/writer/relationships.js +127 -0
  183. package/dist/docx/writer/relationships.js.map +1 -0
  184. package/dist/docx/writer/settings-merge.d.ts +21 -0
  185. package/dist/docx/writer/settings-merge.d.ts.map +1 -0
  186. package/dist/docx/writer/settings-merge.js +165 -0
  187. package/dist/docx/writer/settings-merge.js.map +1 -0
  188. package/dist/docx/writer/style-reconcile.d.ts +29 -0
  189. package/dist/docx/writer/style-reconcile.d.ts.map +1 -0
  190. package/dist/docx/writer/style-reconcile.js +319 -0
  191. package/dist/docx/writer/style-reconcile.js.map +1 -0
  192. package/dist/docx/writer/style-strip.d.ts +33 -0
  193. package/dist/docx/writer/style-strip.d.ts.map +1 -0
  194. package/dist/docx/writer/style-strip.js +267 -0
  195. package/dist/docx/writer/style-strip.js.map +1 -0
  196. package/dist/docx/writer/styles-merge.d.ts +57 -0
  197. package/dist/docx/writer/styles-merge.d.ts.map +1 -0
  198. package/dist/docx/writer/styles-merge.js +184 -0
  199. package/dist/docx/writer/styles-merge.js.map +1 -0
  200. package/dist/docx/writer/template.d.ts +48 -0
  201. package/dist/docx/writer/template.d.ts.map +1 -0
  202. package/dist/docx/writer/template.js +280 -0
  203. package/dist/docx/writer/template.js.map +1 -0
  204. package/dist/docx/writer/testing.d.ts +52 -0
  205. package/dist/docx/writer/testing.d.ts.map +1 -0
  206. package/dist/docx/writer/testing.js +318 -0
  207. package/dist/docx/writer/testing.js.map +1 -0
  208. package/dist/docx/writer/xml-io.d.ts +90 -0
  209. package/dist/docx/writer/xml-io.d.ts.map +1 -0
  210. package/dist/docx/writer/xml-io.js +215 -0
  211. package/dist/docx/writer/xml-io.js.map +1 -0
  212. package/dist/export/blocks.d.ts.map +1 -1
  213. package/dist/export/blocks.js +149 -12
  214. package/dist/export/blocks.js.map +1 -1
  215. package/dist/export/context.d.ts +34 -2
  216. package/dist/export/context.d.ts.map +1 -1
  217. package/dist/export/context.js +28 -2
  218. package/dist/export/context.js.map +1 -1
  219. package/dist/export/css.d.ts +58 -0
  220. package/dist/export/css.d.ts.map +1 -1
  221. package/dist/export/css.js +194 -0
  222. package/dist/export/css.js.map +1 -1
  223. package/dist/export/dom.d.ts +2 -0
  224. package/dist/export/dom.d.ts.map +1 -1
  225. package/dist/export/dom.js +2 -0
  226. package/dist/export/dom.js.map +1 -1
  227. package/dist/export/export-docx.d.ts +4 -0
  228. package/dist/export/export-docx.d.ts.map +1 -1
  229. package/dist/export/export-docx.js +57 -4
  230. package/dist/export/export-docx.js.map +1 -1
  231. package/dist/export/header-footer.d.ts +15 -1
  232. package/dist/export/header-footer.d.ts.map +1 -1
  233. package/dist/export/header-footer.js +37 -0
  234. package/dist/export/header-footer.js.map +1 -1
  235. package/dist/export/html-to-docx.d.ts +20 -2
  236. package/dist/export/html-to-docx.d.ts.map +1 -1
  237. package/dist/export/html-to-docx.js +40 -14
  238. package/dist/export/html-to-docx.js.map +1 -1
  239. package/dist/export/inline.d.ts +25 -3
  240. package/dist/export/inline.d.ts.map +1 -1
  241. package/dist/export/inline.js +91 -34
  242. package/dist/export/inline.js.map +1 -1
  243. package/dist/export/styles.d.ts +51 -7
  244. package/dist/export/styles.d.ts.map +1 -1
  245. package/dist/export/styles.js +121 -16
  246. package/dist/export/styles.js.map +1 -1
  247. package/dist/export/tables.d.ts.map +1 -1
  248. package/dist/export/tables.js +140 -12
  249. package/dist/export/tables.js.map +1 -1
  250. package/dist/export/types.d.ts +44 -5
  251. package/dist/export/types.d.ts.map +1 -1
  252. package/dist/index.d.ts +5 -2
  253. package/dist/index.d.ts.map +1 -1
  254. package/dist/index.js +1 -0
  255. package/dist/index.js.map +1 -1
  256. package/package.json +2 -2
@@ -0,0 +1,214 @@
1
+ import { childNamed, childrenNamed, textOf, wordAttribute } from '../preprocess/xml-utils';
2
+ import { readDocumentLang } from '../reader/sections';
3
+ import { twipsToPt } from '../reader/units';
4
+ import { numericAttribute, readBorders, shadingColor, } from '../reader/units-blocks';
5
+ import { effectiveCellBorders, effectiveTableBorders, nonEmptyBorders, } from './model-borders';
6
+ import { isBlankParagraph, readParagraphs } from './model-paragraph';
7
+ import { readSections } from './model-sections';
8
+ const VERTICAL_ALIGNS = new Map([
9
+ ['top', 'top'],
10
+ ['center', 'middle'],
11
+ ['bottom', 'bottom'],
12
+ ]);
13
+ /** Notes d'une partie (`footnotes` / `endnotes`) : `kind:id` → texte brut. */
14
+ async function readNotes(pkg) {
15
+ const notes = new Map();
16
+ for (const kind of ['footnote', 'endnote']) {
17
+ const path = await pkg.related(pkg.mainPart, `/${kind}s`);
18
+ const doc = path ? await pkg.part(path) : null;
19
+ if (!doc)
20
+ continue;
21
+ for (const note of childrenNamed(doc.documentElement, kind)) {
22
+ const id = wordAttribute(note, 'id');
23
+ if (id)
24
+ notes.set(`${kind}:${id}`, textOf(note).trim());
25
+ }
26
+ }
27
+ return notes;
28
+ }
29
+ function tableWidth(tblW) {
30
+ if (!tblW)
31
+ return undefined;
32
+ const type = wordAttribute(tblW, 'type');
33
+ const raw = wordAttribute(tblW, 'w');
34
+ if (raw === '' || type === 'auto' || type === 'nil')
35
+ return undefined;
36
+ if (type === 'pct' || raw.endsWith('%')) {
37
+ const value = raw.endsWith('%') ? Number(raw.slice(0, -1)) : Number(raw) / 50;
38
+ return Number.isFinite(value) ? `${String(Math.round(value * 100) / 100)}%` : undefined;
39
+ }
40
+ const value = Number(raw);
41
+ return Number.isFinite(value) ? `${String(twipsToPt(value))}pt` : undefined;
42
+ }
43
+ /**
44
+ * Largeur effective d'une cellule : `w:tcW` en twips quand il est posé, sinon les colonnes
45
+ * de grille qu'elle couvre (ce que Word rend). `pct` et `auto` sans grille : inconnue.
46
+ */
47
+ function cellWidthPt(tcW, colspan, cell) {
48
+ const type = tcW ? wordAttribute(tcW, 'type') : '';
49
+ const twips = numericAttribute(tcW, 'w');
50
+ if (twips !== undefined && twips > 0 && type !== 'pct' && type !== 'auto') {
51
+ return twipsToPt(twips);
52
+ }
53
+ if (type === 'pct')
54
+ return undefined;
55
+ const columns = cell.gridTwips.slice(cell.gridStart, cell.gridStart + colspan);
56
+ if (columns.length === 0)
57
+ return undefined;
58
+ return twipsToPt(columns.reduce((sum, width) => sum + width, 0));
59
+ }
60
+ function readCell(tc, ctx, cell) {
61
+ const tcPr = childNamed(tc, 'tcPr');
62
+ const vMergeElement = tcPr ? childNamed(tcPr, 'vMerge') : null;
63
+ const vMergeValue = vMergeElement ? wordAttribute(vMergeElement, 'val') : null;
64
+ const colspan = Math.max(1, numericAttribute(tcPr ? childNamed(tcPr, 'gridSpan') : null, 'val') ?? 1);
65
+ const widthPt = cellWidthPt(tcPr ? childNamed(tcPr, 'tcW') : null, colspan, cell);
66
+ const tcBorders = readBorders(tcPr ? childNamed(tcPr, 'tcBorders') : null);
67
+ const borders = nonEmptyBorders(effectiveCellBorders(cell.style, cell.tblBorders, tcBorders, cell.edges));
68
+ const vAlign = tcPr ? childNamed(tcPr, 'vAlign') : null;
69
+ const verticalAlign = vAlign ? VERTICAL_ALIGNS.get(wordAttribute(vAlign, 'val')) : undefined;
70
+ const shading = shadingColor(tcPr ? childNamed(tcPr, 'shd') : null) ?? cell.style?.cellShading;
71
+ return {
72
+ colspan,
73
+ ...(vMergeElement ? { vMerge: vMergeValue === 'restart' ? 'restart' : 'continue' } : {}),
74
+ ...(widthPt !== undefined ? { widthPt } : {}),
75
+ ...(borders ? { borders } : {}),
76
+ ...(shading ? { shading } : {}),
77
+ ...(verticalAlign ? { verticalAlign } : {}),
78
+ blocks: readBlocks(tc, ctx),
79
+ };
80
+ }
81
+ /**
82
+ * Enfants nommés d'un conteneur de tableau, `w:sdt`/`w:sdtContent` et `w:customXml`
83
+ * aplatis (R30-08) : une ligne ou une cellule sous un contrôle de contenu (section
84
+ * répétée, cellule contrôlée) est une ligne ou une cellule comme les autres pour Word.
85
+ */
86
+ function tableChildren(parent, name) {
87
+ const out = [];
88
+ for (const child of Array.from(parent.children)) {
89
+ if (child.localName === name)
90
+ out.push(child);
91
+ else if (child.localName === 'sdt') {
92
+ const content = childNamed(child, 'sdtContent');
93
+ if (content)
94
+ out.push(...tableChildren(content, name));
95
+ }
96
+ else if (child.localName === 'customXml')
97
+ out.push(...tableChildren(child, name));
98
+ }
99
+ return out;
100
+ }
101
+ /** Nombre de colonnes de grille d'une ligne : somme des `gridSpan`. */
102
+ function rowSpan(tr) {
103
+ return tableChildren(tr, 'tc').reduce((sum, tc) => {
104
+ const tcPr = childNamed(tc, 'tcPr');
105
+ return (sum + Math.max(1, numericAttribute(tcPr ? childNamed(tcPr, 'gridSpan') : null, 'val') ?? 1));
106
+ }, 0);
107
+ }
108
+ function readTable(tbl, ctx) {
109
+ const tblPr = childNamed(tbl, 'tblPr');
110
+ const tblStyle = tblPr ? childNamed(tblPr, 'tblStyle') : null;
111
+ const styleId = tblStyle ? wordAttribute(tblStyle, 'val') : '';
112
+ const jc = tblPr ? childNamed(tblPr, 'jc') : null;
113
+ const align = jc ? wordAttribute(jc, 'val') : '';
114
+ const tblBorders = readBorders(tblPr ? childNamed(tblPr, 'tblBorders') : null);
115
+ const style = ctx.styles.tableStyle(styleId || null);
116
+ const borders = nonEmptyBorders(effectiveTableBorders(style, tblBorders));
117
+ const grid = childNamed(tbl, 'tblGrid');
118
+ const gridTwips = grid
119
+ ? childrenNamed(grid, 'gridCol')
120
+ .map((col) => numericAttribute(col, 'w'))
121
+ .filter((w) => w !== undefined)
122
+ : [];
123
+ const trs = tableChildren(tbl, 'tr');
124
+ // Boucle plutôt que `Math.max(...spread)` : au-delà de ≈ 125 000 lignes, la pile d'appels débordait (R30-07).
125
+ const columns = trs.reduce((max, tr) => Math.max(max, rowSpan(tr)), gridTwips.length);
126
+ const rows = trs.map((tr, r) => {
127
+ let gridStart = 0;
128
+ return tableChildren(tr, 'tc').map((tc) => {
129
+ const tcPr = childNamed(tc, 'tcPr');
130
+ const colspan = Math.max(1, numericAttribute(tcPr ? childNamed(tcPr, 'gridSpan') : null, 'val') ?? 1);
131
+ const edges = {
132
+ top: r === 0,
133
+ bottom: r === trs.length - 1,
134
+ left: gridStart === 0,
135
+ right: gridStart + colspan >= columns,
136
+ };
137
+ const model = readCell(tc, ctx, { style, tblBorders, gridTwips, gridStart, edges });
138
+ gridStart += colspan;
139
+ return model;
140
+ });
141
+ });
142
+ const rowsText = (pick) => rows.map((row) => row.map((cell) => cell.blocks.map(pick).join('\n')).join('\t')).join('\n');
143
+ const width = tableWidth(tblPr ? childNamed(tblPr, 'tblW') : null);
144
+ return {
145
+ kind: 'table',
146
+ text: rowsText((block) => block.text),
147
+ placeholderText: rowsText((block) => block.placeholderText),
148
+ ...(styleId ? { styleId } : {}),
149
+ ...(width ? { width } : {}),
150
+ ...(align ? { align } : {}),
151
+ ...(borders ? { borders } : {}),
152
+ columnWidthsPt: gridTwips.map(twipsToPt),
153
+ rows,
154
+ };
155
+ }
156
+ /** Texte brut d'une suite de blocs, paragraphes séparés par des sauts de ligne. */
157
+ export function blocksText(blocks) {
158
+ return blocks.map((block) => block.text).join('\n');
159
+ }
160
+ /**
161
+ * Ajoute un paragraphe ; un paragraphe vide qui ne porte qu'un saut de page (`<w:p><w:br
162
+ * w:type="page"/></w:p>`) se replie sur le paragraphe précédent, dont il marque la fin.
163
+ */
164
+ function pushParagraph(blocks, paragraph) {
165
+ const previous = blocks[blocks.length - 1];
166
+ if (paragraph.pageBreakAfter &&
167
+ isBlankParagraph(paragraph) &&
168
+ previous?.kind === 'paragraph' &&
169
+ !previous.pageBreakAfter) {
170
+ blocks[blocks.length - 1] = { ...previous, pageBreakAfter: true };
171
+ return;
172
+ }
173
+ blocks.push(paragraph);
174
+ }
175
+ /** Blocs d'un conteneur (`w:body`, `w:tc`, `w:hdr`…), `w:sdt` aplatis, le reste ignoré. */
176
+ function readBlocks(container, ctx) {
177
+ const blocks = [];
178
+ for (const child of Array.from(container.children)) {
179
+ if (child.localName === 'p') {
180
+ for (const paragraph of readParagraphs(child, ctx))
181
+ pushParagraph(blocks, paragraph);
182
+ }
183
+ else if (child.localName === 'tbl')
184
+ blocks.push(readTable(child, ctx));
185
+ else if (child.localName === 'sdt') {
186
+ const content = childNamed(child, 'sdtContent');
187
+ if (content)
188
+ blocks.push(...readBlocks(content, ctx));
189
+ }
190
+ else if (child.localName === 'customXml') {
191
+ // Bloc `w:customXml` : conteneur transparent, comme pour le lecteur (R25-05).
192
+ blocks.push(...readBlocks(child, ctx));
193
+ }
194
+ }
195
+ return blocks;
196
+ }
197
+ /** Lit le modèle comparable d'un paquet ouvert. Lève si la partie principale est illisible. */
198
+ export async function readDocumentModel(pkg, styles, numbering) {
199
+ const main = await pkg.part(pkg.mainPart);
200
+ const body = main ? childNamed(main.documentElement, 'body') : null;
201
+ if (!body)
202
+ throw new Error(`compareDocx : partie principale ${pkg.mainPart} illisible`);
203
+ const ctx = {
204
+ pkg,
205
+ part: pkg.mainPart,
206
+ styles,
207
+ numbering,
208
+ notes: await readNotes(pkg),
209
+ };
210
+ const sections = await readSections(body, ctx, readBlocks);
211
+ const lang = await readDocumentLang(pkg);
212
+ return { blocks: readBlocks(body, ctx), sections, ...(lang ? { lang } : {}) };
213
+ }
214
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/docx/compare/model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { XmlParse } from '../reader/types';
2
+ /**
3
+ * Comparaison à l'octet des parties du paquet (styles, numérotation, thème, polices,
4
+ * en-têtes, pieds, images…). Le corps (`word/document.xml`), ses relations et les
5
+ * propriétés datées (`docProps/core.xml`, `docProps/app.xml`) sont toujours exclus : ils
6
+ * sont régénérés par construction et comparés propriété par propriété ailleurs.
7
+ */
8
+ export interface PartsComparison {
9
+ readonly identical: string[];
10
+ readonly changed: {
11
+ readonly path: string;
12
+ readonly summary: string;
13
+ }[];
14
+ /** Parties comparées (présentes dans l'original), conservées ou non, pour le score. */
15
+ readonly compared: {
16
+ readonly path: string;
17
+ readonly kept: boolean;
18
+ readonly summary: string;
19
+ }[];
20
+ }
21
+ export interface PartsOptions {
22
+ /** Préfixes de chemin retenus ; tout par défaut. */
23
+ readonly prefixes?: readonly string[];
24
+ /** Parties jamais comparées (corps, relations du corps, propriétés datées). */
25
+ readonly excluded: ReadonlySet<string>;
26
+ readonly ignoreRevisionIds: boolean;
27
+ readonly parseXml: XmlParse;
28
+ }
29
+ /** Tous les fichiers (pas les dossiers) d'une archive, triés. */
30
+ export declare function listParts(buffer: ArrayBuffer): Promise<Map<string, Uint8Array>>;
31
+ /** Retire les identifiants de révision et les marques sans effet visuel d'un XML Word. */
32
+ export declare function stripRevisionIds(xml: string): string;
33
+ /**
34
+ * Compare les parties de l'original à celles du résultat. Une partie de l'original absente
35
+ * du résultat est « supprimée », une partie nouvelle est « ajoutée » (listée, pas comptée).
36
+ * Avec `ignoreRevisionIds`, une partie XML égale hors `w:rsid*` compte comme conservée
37
+ * tout en restant listée comme changée.
38
+ */
39
+ export declare function compareParts(original: ReadonlyMap<string, Uint8Array>, result: ReadonlyMap<string, Uint8Array>, options: PartsOptions): PartsComparison;
40
+ //# sourceMappingURL=parts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parts.d.ts","sourceRoot":"","sources":["../../../src/docx/compare/parts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACxE,uFAAuF;IACvF,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAClG;AAED,MAAM,WAAW,YAAY;IAC3B,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AAID,iEAAiE;AACjE,wBAAsB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAWrF;AAgBD,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAiCD;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,EACzC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,EACvC,OAAO,EAAE,YAAY,GACpB,eAAe,CA4CjB"}
@@ -0,0 +1,113 @@
1
+ import JSZip from 'jszip';
2
+ const SNIPPET_LENGTH = 80;
3
+ /** Tous les fichiers (pas les dossiers) d'une archive, triés. */
4
+ export async function listParts(buffer) {
5
+ const zip = await JSZip.loadAsync(buffer);
6
+ const parts = new Map();
7
+ const names = Object.keys(zip.files)
8
+ .filter((name) => !zip.files[name]?.dir)
9
+ .sort();
10
+ for (const name of names) {
11
+ const file = zip.file(name);
12
+ if (file)
13
+ parts.set(name, await file.async('uint8array'));
14
+ }
15
+ return parts;
16
+ }
17
+ function sameBytes(a, b) {
18
+ if (a.byteLength !== b.byteLength)
19
+ return false;
20
+ for (let i = 0; i < a.byteLength; i += 1)
21
+ if (a[i] !== b[i])
22
+ return false;
23
+ return true;
24
+ }
25
+ function isXmlPath(path) {
26
+ return path.endsWith('.xml') || path.endsWith('.rels');
27
+ }
28
+ const REVISION_ATTRIBUTES = /\s+w:rsid[A-Za-z]*="[^"]*"/g;
29
+ const REVISION_ELEMENTS = /<w:(?:lastRenderedPageBreak|proofErr|bookmarkStart|bookmarkEnd)\b[^>]*\/>|<w:rsids>[\s\S]*?<\/w:rsids>/g;
30
+ /** Retire les identifiants de révision et les marques sans effet visuel d'un XML Word. */
31
+ export function stripRevisionIds(xml) {
32
+ return xml.replace(REVISION_ELEMENTS, '').replace(REVISION_ATTRIBUTES, '');
33
+ }
34
+ function xmlLines(xml) {
35
+ return xml.replace(/>\s*</g, '>\n<').split('\n');
36
+ }
37
+ function snippet(line) {
38
+ if (line === undefined)
39
+ return '(fin)';
40
+ return line.length > SNIPPET_LENGTH ? `${line.slice(0, SNIPPET_LENGTH)}…` : line;
41
+ }
42
+ function isParsable(xml, parseXml) {
43
+ try {
44
+ const doc = parseXml(xml);
45
+ return doc.documentElement !== null && doc.documentElement.localName !== 'parsererror';
46
+ }
47
+ catch {
48
+ return false;
49
+ }
50
+ }
51
+ /** Résumé d'une partie XML qui diffère : tailles et première ligne différente. */
52
+ function xmlSummary(a, b, sizes) {
53
+ const linesA = xmlLines(a);
54
+ const linesB = xmlLines(b);
55
+ const count = Math.max(linesA.length, linesB.length);
56
+ for (let i = 0; i < count; i += 1) {
57
+ if (linesA[i] !== linesB[i]) {
58
+ return `${sizes} ; ligne ${String(i + 1)} : « ${snippet(linesA[i])} » → « ${snippet(linesB[i])} »`;
59
+ }
60
+ }
61
+ return sizes;
62
+ }
63
+ /**
64
+ * Compare les parties de l'original à celles du résultat. Une partie de l'original absente
65
+ * du résultat est « supprimée », une partie nouvelle est « ajoutée » (listée, pas comptée).
66
+ * Avec `ignoreRevisionIds`, une partie XML égale hors `w:rsid*` compte comme conservée
67
+ * tout en restant listée comme changée.
68
+ */
69
+ export function compareParts(original, result, options) {
70
+ const decoder = new TextDecoder();
71
+ const identical = [];
72
+ const changed = [];
73
+ const compared = [];
74
+ const inScope = (path) => !options.excluded.has(path) &&
75
+ (options.prefixes === undefined || options.prefixes.some((p) => path.startsWith(p)));
76
+ const differs = (path, summary, kept = false) => {
77
+ changed.push({ path, summary });
78
+ compared.push({ path, kept, summary });
79
+ };
80
+ for (const [path, bytes] of original) {
81
+ if (!inScope(path))
82
+ continue;
83
+ const other = result.get(path);
84
+ if (!other) {
85
+ differs(path, 'supprimée');
86
+ continue;
87
+ }
88
+ if (sameBytes(bytes, other)) {
89
+ identical.push(path);
90
+ compared.push({ path, kept: true, summary: 'identique' });
91
+ continue;
92
+ }
93
+ const sizes = `taille ${String(bytes.byteLength)} → ${String(other.byteLength)} octets`;
94
+ if (!isXmlPath(path)) {
95
+ differs(path, sizes);
96
+ continue;
97
+ }
98
+ const a = decoder.decode(bytes);
99
+ const b = decoder.decode(other);
100
+ if (options.ignoreRevisionIds && stripRevisionIds(a) === stripRevisionIds(b)) {
101
+ differs(path, 'identique hors identifiants de révision', true);
102
+ continue;
103
+ }
104
+ const parsable = isParsable(a, options.parseXml) && isParsable(b, options.parseXml);
105
+ differs(path, parsable ? xmlSummary(a, b, sizes) : `${sizes} (XML illisible)`);
106
+ }
107
+ for (const path of result.keys()) {
108
+ if (inScope(path) && !original.has(path))
109
+ changed.push({ path, summary: 'ajoutée' });
110
+ }
111
+ return { identical, changed, compared };
112
+ }
113
+ //# sourceMappingURL=parts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parts.js","sourceRoot":"","sources":["../../../src/docx/compare/parts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { FidelityProperty, FidelityPropertyGroup } from './types';
2
+ /**
3
+ * Comptage des propriétés comparées et calcul du score pondéré. Chaque appel à `record`
4
+ * est une occurrence : conservée si les deux chaînes canoniques sont égales, perdue sinon
5
+ * (les cinq premières pertes servent d'exemples). Le score est la moyenne pondérée des
6
+ * taux `kept / total` par groupe ; un groupe sans occurrence ne compte pas.
7
+ */
8
+ /** Poids des groupes, figés par le brief L28. */
9
+ export declare const GROUP_WEIGHTS: Readonly<Record<FidelityPropertyGroup, number>>;
10
+ export declare class Tally {
11
+ private readonly counters;
12
+ /** Une occurrence de `name` : conservée si `expected === actual`. */
13
+ record(group: FidelityPropertyGroup, name: string, where: string, expected: string, actual: string): boolean;
14
+ /** Propriétés dans l'ordre des groupes puis des noms, prêtes pour le rapport. */
15
+ properties(): FidelityProperty[];
16
+ }
17
+ /**
18
+ * Score pondéré : pour chaque groupe ayant au moins une occurrence, taux `kept / total`
19
+ * agrégé sur ses propriétés, pondéré par `GROUP_WEIGHTS`. Arrondi à trois décimales ;
20
+ * `1` quand rien n'a été comparé.
21
+ */
22
+ export declare function computeScore(properties: readonly FidelityProperty[]): number;
23
+ //# sourceMappingURL=tally.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tally.d.ts","sourceRoot":"","sources":["../../../src/docx/compare/tally.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAExF;;;;;GAKG;AAEH,iDAAiD;AACjD,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAYzE,CAAC;AAyBF,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IAEvD,qEAAqE;IACrE,MAAM,CACJ,KAAK,EAAE,qBAAqB,EAC5B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO;IAeV,iFAAiF;IACjF,UAAU,IAAI,gBAAgB,EAAE;CAgBjC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,CAkB5E"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Comptage des propriétés comparées et calcul du score pondéré. Chaque appel à `record`
3
+ * est une occurrence : conservée si les deux chaînes canoniques sont égales, perdue sinon
4
+ * (les cinq premières pertes servent d'exemples). Le score est la moyenne pondérée des
5
+ * taux `kept / total` par groupe ; un groupe sans occurrence ne compte pas.
6
+ */
7
+ /** Poids des groupes, figés par le brief L28. */
8
+ export const GROUP_WEIGHTS = {
9
+ text: 3,
10
+ 'paragraph-style': 2,
11
+ 'paragraph-format': 2,
12
+ 'run-format': 2,
13
+ list: 1,
14
+ table: 2,
15
+ image: 1,
16
+ note: 1,
17
+ 'header-footer': 2,
18
+ section: 2,
19
+ 'package-part': 2,
20
+ };
21
+ const GROUP_ORDER = [
22
+ 'text',
23
+ 'paragraph-style',
24
+ 'paragraph-format',
25
+ 'run-format',
26
+ 'list',
27
+ 'table',
28
+ 'image',
29
+ 'note',
30
+ 'header-footer',
31
+ 'section',
32
+ 'package-part',
33
+ ];
34
+ const MAX_EXAMPLES = 5;
35
+ export class Tally {
36
+ counters = new Map();
37
+ /** Une occurrence de `name` : conservée si `expected === actual`. */
38
+ record(group, name, where, expected, actual) {
39
+ let counter = this.counters.get(name);
40
+ if (!counter) {
41
+ counter = { group, total: 0, kept: 0, examples: [] };
42
+ this.counters.set(name, counter);
43
+ }
44
+ counter.total += 1;
45
+ const kept = expected === actual;
46
+ if (kept)
47
+ counter.kept += 1;
48
+ else if (counter.examples.length < MAX_EXAMPLES) {
49
+ counter.examples.push({ where, expected, actual });
50
+ }
51
+ return kept;
52
+ }
53
+ /** Propriétés dans l'ordre des groupes puis des noms, prêtes pour le rapport. */
54
+ properties() {
55
+ return Array.from(this.counters.entries())
56
+ .map(([name, counter]) => ({
57
+ name,
58
+ group: counter.group,
59
+ total: counter.total,
60
+ kept: counter.kept,
61
+ lost: counter.total - counter.kept,
62
+ examples: counter.examples,
63
+ }))
64
+ .sort((a, b) => GROUP_ORDER.indexOf(a.group) - GROUP_ORDER.indexOf(b.group) ||
65
+ a.name.localeCompare(b.name));
66
+ }
67
+ }
68
+ /**
69
+ * Score pondéré : pour chaque groupe ayant au moins une occurrence, taux `kept / total`
70
+ * agrégé sur ses propriétés, pondéré par `GROUP_WEIGHTS`. Arrondi à trois décimales ;
71
+ * `1` quand rien n'a été comparé.
72
+ */
73
+ export function computeScore(properties) {
74
+ const totals = new Map();
75
+ for (const property of properties) {
76
+ const entry = totals.get(property.group) ?? { total: 0, kept: 0 };
77
+ entry.total += property.total;
78
+ entry.kept += property.kept;
79
+ totals.set(property.group, entry);
80
+ }
81
+ let weightSum = 0;
82
+ let weighted = 0;
83
+ for (const [group, { total, kept }] of totals) {
84
+ if (total === 0)
85
+ continue;
86
+ const weight = GROUP_WEIGHTS[group];
87
+ weightSum += weight;
88
+ weighted += (weight * kept) / total;
89
+ }
90
+ if (weightSum === 0)
91
+ return 1;
92
+ return Math.round((weighted / weightSum) * 1000) / 1000;
93
+ }
94
+ //# sourceMappingURL=tally.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tally.js","sourceRoot":"","sources":["../../../src/docx/compare/tally.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import type { DocxInput, DocxLostObject } from '../types';
2
+ /**
3
+ * Contrat du rapport de fidélité (session 3, figé en phase 0, implémenté par L28).
4
+ * Compare un `.docx` d'origine et le `.docx` produit après import, édition éventuelle et
5
+ * export dans le gabarit : propriété par propriété, pas à l'octet.
6
+ */
7
+ /** Famille de propriétés comparées, pour agréger le score. */
8
+ export type FidelityPropertyGroup = 'text' | 'paragraph-style' | 'paragraph-format' | 'run-format' | 'list' | 'table' | 'image' | 'note' | 'header-footer' | 'section' | 'package-part';
9
+ export interface FidelityProperty {
10
+ /** Nom lisible, ex. `paragraph.lineHeight`, `run.fontFamily`, `part:word/styles.xml`. */
11
+ readonly name: string;
12
+ readonly group: FidelityPropertyGroup;
13
+ /** Occurrences dans l'original. */
14
+ readonly total: number;
15
+ /** Occurrences retrouvées à l'identique dans le résultat. */
16
+ readonly kept: number;
17
+ /** `total - kept`. */
18
+ readonly lost: number;
19
+ /** Jusqu'à cinq exemples de pertes : où (index de paragraphe, chemin de partie) et quoi. */
20
+ readonly examples: readonly FidelityExample[];
21
+ }
22
+ export interface FidelityExample {
23
+ /** Localisation lisible, ex. `paragraphe 12`, `tableau 2 cellule (1,3)`, `word/header1.xml`. */
24
+ readonly where: string;
25
+ readonly expected: string;
26
+ readonly actual: string;
27
+ }
28
+ export interface FidelityReport {
29
+ /** Score pondéré entre 0 et 1 (1 = rien de perdu sur les propriétés comparées). */
30
+ readonly score: number;
31
+ readonly properties: readonly FidelityProperty[];
32
+ /** Parties du paquet identiques à l'octet (styles, numérotation, thème, en-têtes…). */
33
+ readonly identicalParts: readonly string[];
34
+ /** Parties qui diffèrent, avec un résumé de la différence. */
35
+ readonly changedParts: readonly {
36
+ readonly path: string;
37
+ readonly summary: string;
38
+ }[];
39
+ /** Objets non représentables signalés par l'import du résultat ou de l'original. */
40
+ readonly lost: readonly DocxLostObject[];
41
+ /** Remarques libres (propriétés non comparées, approximations). */
42
+ readonly notes: readonly string[];
43
+ }
44
+ export interface CompareDocxOptions {
45
+ /**
46
+ * Parties du paquet à comparer à l'octet, par préfixe de chemin. Par défaut tout sauf
47
+ * `word/document.xml`, `docProps/core.xml` (dates) et les `.rels` du corps.
48
+ */
49
+ readonly binaryParts?: readonly string[];
50
+ /** Ignorer les `w:rsid*` et autres identifiants de révision, vrai par défaut. */
51
+ readonly ignoreRevisionIds?: boolean;
52
+ }
53
+ /** Signature de `compareDocx` (L28) : original, résultat, options. */
54
+ export type CompareDocx = (original: DocxInput, result: DocxInput, options?: CompareDocxOptions) => Promise<FidelityReport>;
55
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/docx/compare/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1D;;;;GAIG;AAEH,8DAA8D;AAC9D,MAAM,MAAM,qBAAqB,GAC7B,MAAM,GACN,iBAAiB,GACjB,kBAAkB,GAClB,YAAY,GACZ,MAAM,GACN,OAAO,GACP,OAAO,GACP,MAAM,GACN,eAAe,GACf,SAAS,GACT,cAAc,CAAC;AAEnB,MAAM,WAAW,gBAAgB;IAC/B,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;IACtC,mCAAmC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sBAAsB;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;CAC/C;AAED,MAAM,WAAW,eAAe;IAC9B,gGAAgG;IAChG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,mFAAmF;IACnF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACjD,uFAAuF;IACvF,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,8DAA8D;IAC9D,QAAQ,CAAC,YAAY,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtF,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,CAAC;IACzC,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,iFAAiF;IACjF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,sEAAsE;AACtE,MAAM,MAAM,WAAW,GAAG,CACxB,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,SAAS,EACjB,OAAO,CAAC,EAAE,kBAAkB,KACzB,OAAO,CAAC,cAAc,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/docx/compare/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Normalisation des valeurs comparées par le rapport de fidélité : tout passe par une
3
+ * chaîne canonique (nombres arrondis à deux décimales, couleurs en minuscules, clés
4
+ * d'objet triées, `undefined` rendu `(absent)`) pour que l'égalité soit une égalité de
5
+ * chaînes et que les exemples du rapport soient lisibles.
6
+ */
7
+ /** Valeur absente d'un côté, affichée telle quelle dans les exemples. */
8
+ export declare const ABSENT = "(absent)";
9
+ /** Chaîne canonique d'une valeur quelconque, `(absent)` pour `undefined` et `null`. */
10
+ export declare function fmt(value: unknown): string;
11
+ /** Vrai si les deux valeurs ont la même chaîne canonique. */
12
+ export declare function same(a: unknown, b: unknown): boolean;
13
+ //# sourceMappingURL=values.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../../src/docx/compare/values.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,yEAAyE;AACzE,eAAO,MAAM,MAAM,aAAa,CAAC;AAmBjC,uFAAuF;AACvF,wBAAgB,GAAG,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAM1C;AAED,6DAA6D;AAC7D,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAEpD"}