@usejunior/odf-core 0.9.1 → 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 (56) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +2 -0
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/compare/emit.d.ts +8 -3
  5. package/dist/compare/emit.d.ts.map +1 -1
  6. package/dist/compare/emit.js +39 -7
  7. package/dist/compare/emit.js.map +1 -1
  8. package/dist/compare/inline_diff.d.ts +5 -0
  9. package/dist/compare/inline_diff.d.ts.map +1 -1
  10. package/dist/compare/inline_diff.js +71 -1
  11. package/dist/compare/inline_diff.js.map +1 -1
  12. package/dist/convert/docx_to_odt.d.ts +20 -0
  13. package/dist/convert/docx_to_odt.d.ts.map +1 -0
  14. package/dist/convert/docx_to_odt.js +199 -0
  15. package/dist/convert/docx_to_odt.js.map +1 -0
  16. package/dist/convert/index.d.ts +3 -0
  17. package/dist/convert/index.d.ts.map +1 -0
  18. package/dist/convert/index.js +2 -0
  19. package/dist/convert/index.js.map +1 -0
  20. package/dist/convert/inline.d.ts +55 -0
  21. package/dist/convert/inline.d.ts.map +1 -0
  22. package/dist/convert/inline.js +274 -0
  23. package/dist/convert/inline.js.map +1 -0
  24. package/dist/convert/lists.d.ts +41 -0
  25. package/dist/convert/lists.d.ts.map +1 -0
  26. package/dist/convert/lists.js +137 -0
  27. package/dist/convert/lists.js.map +1 -0
  28. package/dist/convert/package.d.ts +54 -0
  29. package/dist/convert/package.d.ts.map +1 -0
  30. package/dist/convert/package.js +232 -0
  31. package/dist/convert/package.js.map +1 -0
  32. package/dist/convert/paragraph_styles.d.ts +25 -0
  33. package/dist/convert/paragraph_styles.d.ts.map +1 -0
  34. package/dist/convert/paragraph_styles.js +63 -0
  35. package/dist/convert/paragraph_styles.js.map +1 -0
  36. package/dist/convert/tables.d.ts +44 -0
  37. package/dist/convert/tables.d.ts.map +1 -0
  38. package/dist/convert/tables.js +226 -0
  39. package/dist/convert/tables.js.map +1 -0
  40. package/dist/convert/types.d.ts +27 -0
  41. package/dist/convert/types.d.ts.map +1 -0
  42. package/dist/convert/types.js +25 -0
  43. package/dist/convert/types.js.map +1 -0
  44. package/dist/index.d.ts +1 -0
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +1 -0
  47. package/dist/index.js.map +1 -1
  48. package/dist/shared/odf/OdfArchive.d.ts +16 -0
  49. package/dist/shared/odf/OdfArchive.d.ts.map +1 -1
  50. package/dist/shared/odf/OdfArchive.js +48 -1
  51. package/dist/shared/odf/OdfArchive.js.map +1 -1
  52. package/dist/shared/odf/namespaces.d.ts +4 -0
  53. package/dist/shared/odf/namespaces.d.ts.map +1 -1
  54. package/dist/shared/odf/namespaces.js +8 -0
  55. package/dist/shared/odf/namespaces.js.map +1 -1
  56. package/package.json +5 -4
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Fresh-package scaffolding for the DOCX → ODT converter: XML part templates and the
3
+ * whitespace writer that is the emit-side mirror of `shared/odf/text_segments.ts`.
4
+ *
5
+ * The `office:version="1.3"` attribute on every document root is required — LibreOffice
6
+ * tolerates its absence, but strict ODF validators reject the package without it.
7
+ */
8
+ import { parseXml, extractStyleRunFormatting } from '@usejunior/docx-core';
9
+ import { ODF_NS } from '../shared/odf/namespaces.js';
10
+ /** Quote a font family for `svg:font-family` when it contains non-name characters (spaces). */
11
+ export function quoteFontFamily(face) {
12
+ return /^[A-Za-z0-9-]+$/.test(face) ? face : `'${face.replaceAll("'", '')}'`;
13
+ }
14
+ /** Template heading font sizes (pt) for `Heading_20_1` … `Heading_20_6` (source may override). */
15
+ const HEADING_SIZES_PT = [18, 16, 14, 13, 12, 11];
16
+ const CONTENT_SKELETON = [
17
+ '<?xml version="1.0" encoding="UTF-8"?>',
18
+ '<office:document-content',
19
+ ` xmlns:office="${ODF_NS.OFFICE}"`,
20
+ ` xmlns:text="${ODF_NS.TEXT}"`,
21
+ ` xmlns:table="${ODF_NS.TABLE}"`,
22
+ ` xmlns:style="${ODF_NS.STYLE}"`,
23
+ ` xmlns:fo="${ODF_NS.FO}"`,
24
+ ` xmlns:xlink="${ODF_NS.XLINK}"`,
25
+ ` xmlns:svg="${ODF_NS.SVG}"`,
26
+ ' office:version="1.3">',
27
+ ' <office:font-face-decls/>',
28
+ ' <office:automatic-styles/>',
29
+ ' <office:body><office:text/></office:body>',
30
+ '</office:document-content>',
31
+ ].join('\n');
32
+ /** Parse the empty content.xml skeleton and hand back its insertion points. */
33
+ export function createContentScaffold() {
34
+ const doc = parseXml(CONTENT_SKELETON);
35
+ const fontFaceDecls = doc.getElementsByTagNameNS(ODF_NS.OFFICE, 'font-face-decls')[0];
36
+ const automaticStyles = doc.getElementsByTagNameNS(ODF_NS.OFFICE, 'automatic-styles')[0];
37
+ const body = doc.getElementsByTagNameNS(ODF_NS.OFFICE, 'text')[0];
38
+ return { doc, fontFaceDecls, automaticStyles, body };
39
+ }
40
+ /**
41
+ * Resolve the source styles the converted `styles.xml` is seeded from: `Heading1..6` (matched
42
+ * by styleId or by the canonical `heading N` style name) and `Normal`. Properties a chain
43
+ * never specifies stay `null` so the template defaults survive.
44
+ */
45
+ export function deriveSourceNamedStyles(styles) {
46
+ const headingIdByLevel = new Map();
47
+ let normalId = null;
48
+ for (const [id, def] of styles.byId) {
49
+ const byId = /^Heading([1-6])$/.exec(id);
50
+ const byName = /^heading ([1-6])$/i.exec(def.name);
51
+ const level = byId ? Number(byId[1]) : byName ? Number(byName[1]) : null;
52
+ if (level !== null && !headingIdByLevel.has(level))
53
+ headingIdByLevel.set(level, id);
54
+ if (normalId === null && (id === 'Normal' || /^normal$/i.test(def.name)))
55
+ normalId = id;
56
+ }
57
+ const headings = new Map();
58
+ for (const [level, id] of headingIdByLevel) {
59
+ headings.set(level, extractStyleRunFormatting(styles, id));
60
+ }
61
+ return { headings, normal: normalId ? extractStyleRunFormatting(styles, normalId) : null };
62
+ }
63
+ function escapeXmlAttr(value) {
64
+ return value
65
+ .replace(/&/g, '&amp;')
66
+ .replace(/</g, '&lt;')
67
+ .replace(/>/g, '&gt;')
68
+ .replace(/"/g, '&quot;');
69
+ }
70
+ /**
71
+ * `style:text-properties` attributes for a source-derived named style. Only properties the
72
+ * source chain specifies are emitted; `null` lets the template's own defaults (or the parent
73
+ * style) win. `collectFace` records faces needing a `style:font-face` declaration.
74
+ */
75
+ function textPropertiesAttrs(fmt, collectFace) {
76
+ if (!fmt)
77
+ return [];
78
+ const attrs = [];
79
+ if (fmt.fontSizePt !== null && fmt.fontSizePt > 0)
80
+ attrs.push(`fo:font-size="${fmt.fontSizePt}pt"`);
81
+ if (fmt.bold !== null)
82
+ attrs.push(`fo:font-weight="${fmt.bold ? 'bold' : 'normal'}"`);
83
+ if (fmt.italic !== null)
84
+ attrs.push(`fo:font-style="${fmt.italic ? 'italic' : 'normal'}"`);
85
+ if (fmt.colorHex !== null && /^[0-9A-Fa-f]{6}$/.test(fmt.colorHex)) {
86
+ attrs.push(`fo:color="#${fmt.colorHex.toLowerCase()}"`);
87
+ }
88
+ if (fmt.fontName !== null && fmt.fontName.trim() !== '') {
89
+ collectFace(fmt.fontName);
90
+ attrs.push(`style:font-name="${escapeXmlAttr(fmt.fontName)}"`);
91
+ }
92
+ return attrs;
93
+ }
94
+ /**
95
+ * Seed `styles.xml`: `Standard`, a bold `Heading` base, `Heading_20_1..6` (descending sizes,
96
+ * `style:default-outline-level`), and `Text_20_body`. When `source` carries the document's
97
+ * resolved style-chain formatting, heading sizes/weights/colors/fonts and the `Standard` body
98
+ * font come from the source instead of the fixed template (#406 phase 3); properties the
99
+ * source never specifies keep the template defaults.
100
+ */
101
+ export function buildStylesXml(source) {
102
+ const faces = new Set();
103
+ const collectFace = (face) => { faces.add(face); };
104
+ const headingStyles = HEADING_SIZES_PT.map((templateSize, i) => {
105
+ const level = i + 1;
106
+ const sourceAttrs = textPropertiesAttrs(source?.headings.get(level) ?? null, collectFace);
107
+ const attrs = sourceAttrs.some((a) => a.startsWith('fo:font-size='))
108
+ ? sourceAttrs
109
+ : [`fo:font-size="${templateSize}pt"`, ...sourceAttrs];
110
+ return [
111
+ ` <style:style style:name="Heading_20_${level}" style:display-name="Heading ${level}"`,
112
+ ` style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body"`,
113
+ ` style:default-outline-level="${level}" style:class="text">`,
114
+ ` <style:text-properties ${attrs.join(' ')}/>`,
115
+ ' </style:style>',
116
+ ].join('\n');
117
+ });
118
+ const standardAttrs = textPropertiesAttrs(source?.normal ?? null, collectFace);
119
+ const standardStyle = standardAttrs.length > 0
120
+ ? [
121
+ ' <style:style style:name="Standard" style:family="paragraph" style:class="text">',
122
+ ` <style:text-properties ${standardAttrs.join(' ')}/>`,
123
+ ' </style:style>',
124
+ ].join('\n')
125
+ : ' <style:style style:name="Standard" style:family="paragraph" style:class="text"/>';
126
+ const fontFaceDecls = faces.size > 0
127
+ ? [
128
+ ' <office:font-face-decls>',
129
+ ...Array.from(faces, (face) => ` <style:font-face style:name="${escapeXmlAttr(face)}" svg:font-family="${escapeXmlAttr(quoteFontFamily(face))}"/>`),
130
+ ' </office:font-face-decls>',
131
+ ]
132
+ : [];
133
+ return [
134
+ '<?xml version="1.0" encoding="UTF-8"?>',
135
+ '<office:document-styles',
136
+ ` xmlns:office="${ODF_NS.OFFICE}"`,
137
+ ` xmlns:style="${ODF_NS.STYLE}"`,
138
+ ` xmlns:fo="${ODF_NS.FO}"`,
139
+ ` xmlns:svg="${ODF_NS.SVG}"`,
140
+ ' office:version="1.3">',
141
+ ...fontFaceDecls,
142
+ ' <office:styles>',
143
+ standardStyle,
144
+ ' <style:style style:name="Text_20_body" style:display-name="Text body"',
145
+ ' style:family="paragraph" style:parent-style-name="Standard" style:class="text"/>',
146
+ ' <style:style style:name="Heading" style:family="paragraph"',
147
+ ' style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">',
148
+ ' <style:text-properties fo:font-weight="bold"/>',
149
+ ' </style:style>',
150
+ ...headingStyles,
151
+ ' </office:styles>',
152
+ '</office:document-styles>',
153
+ '',
154
+ ].join('\n');
155
+ }
156
+ function escapeXmlText(value) {
157
+ return value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
158
+ }
159
+ /** Build `meta.xml` carrying the generator string and optional title. */
160
+ export function buildMetaXml(metadata) {
161
+ const generator = metadata?.generator ?? '@usejunior/odf-core convertDocxToOdt';
162
+ const title = metadata?.title;
163
+ return [
164
+ '<?xml version="1.0" encoding="UTF-8"?>',
165
+ '<office:document-meta',
166
+ ` xmlns:office="${ODF_NS.OFFICE}"`,
167
+ ` xmlns:meta="${ODF_NS.META}"`,
168
+ ` xmlns:dc="${ODF_NS.DC}"`,
169
+ ' office:version="1.3">',
170
+ ' <office:meta>',
171
+ ` <meta:generator>${escapeXmlText(generator)}</meta:generator>`,
172
+ ...(title ? [` <dc:title>${escapeXmlText(title)}</dc:title>`] : []),
173
+ ' </office:meta>',
174
+ '</office:document-meta>',
175
+ '',
176
+ ].join('\n');
177
+ }
178
+ /**
179
+ * Append visible text to `parent`, encoding whitespace the way ODF readers decode it
180
+ * (the writer mirror of `buildSegments`): a run of N≥2 spaces becomes one literal space +
181
+ * `<text:s text:c="N-1"/>`, tabs become `text:tab`, newlines become `text:line-break`.
182
+ * A leading space is encoded as `text:s` outright — ODF processors collapse literal
183
+ * leading whitespace.
184
+ */
185
+ export function appendTextWithWhitespace(doc, parent, text) {
186
+ if (text.length === 0)
187
+ return;
188
+ const isAtBlockStart = parent.firstChild === null;
189
+ let i = 0;
190
+ while (i < text.length) {
191
+ const ch = text[i];
192
+ if (ch === '\t') {
193
+ parent.appendChild(doc.createElementNS(ODF_NS.TEXT, 'text:tab'));
194
+ i += 1;
195
+ continue;
196
+ }
197
+ if (ch === '\n') {
198
+ parent.appendChild(doc.createElementNS(ODF_NS.TEXT, 'text:line-break'));
199
+ i += 1;
200
+ continue;
201
+ }
202
+ if (ch === ' ') {
203
+ let n = 1;
204
+ while (text[i + n] === ' ')
205
+ n += 1;
206
+ const leading = isAtBlockStart && i === 0 && parent.firstChild === null;
207
+ if (leading) {
208
+ const s = doc.createElementNS(ODF_NS.TEXT, 'text:s');
209
+ if (n > 1)
210
+ s.setAttributeNS(ODF_NS.TEXT, 'text:c', String(n));
211
+ parent.appendChild(s);
212
+ }
213
+ else {
214
+ parent.appendChild(doc.createTextNode(' '));
215
+ if (n > 1) {
216
+ const s = doc.createElementNS(ODF_NS.TEXT, 'text:s');
217
+ if (n > 2)
218
+ s.setAttributeNS(ODF_NS.TEXT, 'text:c', String(n - 1));
219
+ parent.appendChild(s);
220
+ }
221
+ }
222
+ i += n;
223
+ continue;
224
+ }
225
+ let end = i;
226
+ while (end < text.length && text[end] !== ' ' && text[end] !== '\t' && text[end] !== '\n')
227
+ end += 1;
228
+ parent.appendChild(doc.createTextNode(text.slice(i, end)));
229
+ i = end;
230
+ }
231
+ }
232
+ //# sourceMappingURL=package.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.js","sourceRoot":"","sources":["../../src/convert/package.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Paragraph-level automatic styles for the DOCX → ODT converter: the view's
3
+ * `paragraph_alignment` + `paragraph_indents_pt` → deduped `P<n>` styles carrying
4
+ * `fo:text-align` / `fo:margin-left` / `fo:text-indent` (#406 phase 3).
5
+ *
6
+ * Styles are only created when something deviates from the named parent's defaults
7
+ * (non-LEFT alignment or a non-zero indent); plain paragraphs keep the parent name directly.
8
+ * List items request alignment only — `text:list` nesting already supplies indentation, and
9
+ * re-applying `fo:margin-left` would double-indent.
10
+ */
11
+ import type { DocumentViewNode } from '@usejunior/docx-core';
12
+ export declare class ParagraphStyleRegistry {
13
+ private readonly doc;
14
+ private readonly container;
15
+ private byKey;
16
+ constructor(doc: Document, container: Element);
17
+ /**
18
+ * Style name for a paragraph with `parentStyle` and the node's alignment/indents.
19
+ * Returns `parentStyle` itself when nothing deviates.
20
+ */
21
+ styleFor(parentStyle: string, node: DocumentViewNode, opts?: {
22
+ indents?: boolean;
23
+ }): string;
24
+ }
25
+ //# sourceMappingURL=paragraph_styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paragraph_styles.d.ts","sourceRoot":"","sources":["../../src/convert/paragraph_styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAgB7D,qBAAa,sBAAsB;IAI/B,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO,CAAC,KAAK,CAA6B;gBAGvB,GAAG,EAAE,QAAQ,EACb,SAAS,EAAE,OAAO;IAGrC;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM;CAyB5F"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Paragraph-level automatic styles for the DOCX → ODT converter: the view's
3
+ * `paragraph_alignment` + `paragraph_indents_pt` → deduped `P<n>` styles carrying
4
+ * `fo:text-align` / `fo:margin-left` / `fo:text-indent` (#406 phase 3).
5
+ *
6
+ * Styles are only created when something deviates from the named parent's defaults
7
+ * (non-LEFT alignment or a non-zero indent); plain paragraphs keep the parent name directly.
8
+ * List items request alignment only — `text:list` nesting already supplies indentation, and
9
+ * re-applying `fo:margin-left` would double-indent.
10
+ */
11
+ import { ODF_NS } from '../shared/odf/namespaces.js';
12
+ /** OOXML `ParagraphAlignment` → ODF `fo:text-align`. LEFT is the default and emits nothing. */
13
+ const TEXT_ALIGN_MAP = {
14
+ CENTER: 'center',
15
+ RIGHT: 'end',
16
+ JUSTIFY: 'justify',
17
+ };
18
+ /** Format points for style attributes: round to 2 decimals, trim trailing zeros. */
19
+ function fmtPt(v) {
20
+ return `${Number(v.toFixed(2))}pt`;
21
+ }
22
+ export class ParagraphStyleRegistry {
23
+ doc;
24
+ container;
25
+ byKey = new Map();
26
+ constructor(doc, container) {
27
+ this.doc = doc;
28
+ this.container = container;
29
+ }
30
+ /**
31
+ * Style name for a paragraph with `parentStyle` and the node's alignment/indents.
32
+ * Returns `parentStyle` itself when nothing deviates.
33
+ */
34
+ styleFor(parentStyle, node, opts) {
35
+ const includeIndents = opts?.indents ?? true;
36
+ const align = TEXT_ALIGN_MAP[node.paragraph_alignment] ?? null;
37
+ const left = includeIndents ? node.paragraph_indents_pt.left : 0;
38
+ const firstLine = includeIndents ? node.paragraph_indents_pt.first_line : 0;
39
+ if (align === null && left === 0 && firstLine === 0)
40
+ return parentStyle;
41
+ const key = `${parentStyle}|${align ?? ''}|${left}|${firstLine}`;
42
+ const existing = this.byKey.get(key);
43
+ if (existing)
44
+ return existing;
45
+ const name = `P${this.byKey.size + 1}`;
46
+ const style = this.doc.createElementNS(ODF_NS.STYLE, 'style:style');
47
+ style.setAttributeNS(ODF_NS.STYLE, 'style:name', name);
48
+ style.setAttributeNS(ODF_NS.STYLE, 'style:family', 'paragraph');
49
+ style.setAttributeNS(ODF_NS.STYLE, 'style:parent-style-name', parentStyle);
50
+ const props = this.doc.createElementNS(ODF_NS.STYLE, 'style:paragraph-properties');
51
+ if (align !== null)
52
+ props.setAttributeNS(ODF_NS.FO, 'fo:text-align', align);
53
+ if (left !== 0)
54
+ props.setAttributeNS(ODF_NS.FO, 'fo:margin-left', fmtPt(left));
55
+ if (firstLine !== 0)
56
+ props.setAttributeNS(ODF_NS.FO, 'fo:text-indent', fmtPt(firstLine));
57
+ style.appendChild(props);
58
+ this.container.appendChild(style);
59
+ this.byKey.set(key, name);
60
+ return name;
61
+ }
62
+ }
63
+ //# sourceMappingURL=paragraph_styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paragraph_styles.js","sourceRoot":"","sources":["../../src/convert/paragraph_styles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Table emission for the DOCX → ODT converter: a contiguous run of view nodes sharing one
3
+ * `table_context.table_id` → a complete rectangular `table:table` grid.
4
+ *
5
+ * Lossy by design, mirroring the HTML serializer's `renderTable`: the view model discards
6
+ * `gridSpan`/`vMerge`, so merged cells are indistinguishable from genuinely empty grid
7
+ * positions — gaps are filled with empty cells (recorded as `table-grid-gaps-filled`).
8
+ * Borders and column widths come from the raw source `w:tbl` (#406 phase 3): an explicit
9
+ * `w:tblBorders` is honored uniformly per table (including explicitly borderless tables) and
10
+ * `w:tblGrid` widths become `table:table-column` styles. Tables without explicit borders keep
11
+ * the 0.5pt default (most Word tables are bordered via their table style, whose `w:tblPr`
12
+ * the styles model does not carry). Per-cell `w:tcBorders` overrides are out of scope.
13
+ */
14
+ import { type DocumentViewNode } from '@usejunior/docx-core';
15
+ import type { LossinessCollector } from './types.js';
16
+ /**
17
+ * Resolve the uniform `fo:border` for a table from its explicit `w:tblBorders`, preferring
18
+ * inside edges (what most cells show). Explicitly border-free tables return `'none'`; tables
19
+ * without a `w:tblBorders` at all return the bordered default.
20
+ */
21
+ export declare function resolveTableBorderSpec(tbl: Element | null): string;
22
+ /** Column widths in points from `w:tblGrid/w:gridCol` (`w:w` is twips); empty when absent. */
23
+ export declare function readGridColWidthsPt(tbl: Element | null): number[];
24
+ /**
25
+ * Deduped automatic styles for table emission: one `table-cell` style per distinct border
26
+ * spec and one `table-column` style per distinct width, shared across tables.
27
+ */
28
+ export declare class TableStyleRegistry {
29
+ private readonly doc;
30
+ private readonly container;
31
+ private cellByBorder;
32
+ private columnByWidth;
33
+ constructor(doc: Document, container: Element);
34
+ cellStyleFor(borderSpec: string): string;
35
+ columnStyleFor(widthPt: number): string;
36
+ }
37
+ /**
38
+ * Append the table built from `group` to `body`. Cell paragraph content is delegated to
39
+ * `fillParagraph` (the orchestrator's inline emitter) and cell paragraph styles to
40
+ * `paragraphStyleFor` so this module stays cycle-free. `sourceTbl` is the raw `w:tbl` this
41
+ * group was derived from (null when unavailable — defaults apply).
42
+ */
43
+ export declare function appendTable(doc: Document, body: Element, group: DocumentViewNode[], tableNumber: number, sourceTbl: Element | null, tableStyles: TableStyleRegistry, fillParagraph: (p: Element, node: DocumentViewNode) => void, paragraphStyleFor: (node: DocumentViewNode) => string, lossiness: LossinessCollector): void;
44
+ //# sourceMappingURL=tables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../../src/convert/tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAQ,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA4BrD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,GAAG,MAAM,CAqBlE;AAED,8FAA8F;AAC9F,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,GAAG,MAAM,EAAE,CAYjE;AAED;;;GAGG;AACH,qBAAa,kBAAkB;IAK3B,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAL5B,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,aAAa,CAA6B;gBAG/B,GAAG,EAAE,QAAQ,EACb,SAAS,EAAE,OAAO;IAGrC,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAgBxC,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAexC;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,gBAAgB,EAAE,EACzB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,OAAO,GAAG,IAAI,EACzB,WAAW,EAAE,kBAAkB,EAC/B,aAAa,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,EAC3D,iBAAiB,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,MAAM,EACrD,SAAS,EAAE,kBAAkB,GAC5B,IAAI,CAoFN"}
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Table emission for the DOCX → ODT converter: a contiguous run of view nodes sharing one
3
+ * `table_context.table_id` → a complete rectangular `table:table` grid.
4
+ *
5
+ * Lossy by design, mirroring the HTML serializer's `renderTable`: the view model discards
6
+ * `gridSpan`/`vMerge`, so merged cells are indistinguishable from genuinely empty grid
7
+ * positions — gaps are filled with empty cells (recorded as `table-grid-gaps-filled`).
8
+ * Borders and column widths come from the raw source `w:tbl` (#406 phase 3): an explicit
9
+ * `w:tblBorders` is honored uniformly per table (including explicitly borderless tables) and
10
+ * `w:tblGrid` widths become `table:table-column` styles. Tables without explicit borders keep
11
+ * the 0.5pt default (most Word tables are bordered via their table style, whose `w:tblPr`
12
+ * the styles model does not carry). Per-cell `w:tcBorders` overrides are out of scope.
13
+ */
14
+ import { W_NS } from '@usejunior/docx-core';
15
+ import { ODF_NS } from '../shared/odf/namespaces.js';
16
+ /** The `fo:border` applied when the source declares no explicit `w:tblBorders`. */
17
+ const DEFAULT_BORDER_SPEC = '0.5pt solid #000000';
18
+ /** OOXML `ST_Border` → ODF border line style (anything unmapped degrades to solid). */
19
+ const BORDER_STYLE_MAP = {
20
+ single: 'solid',
21
+ double: 'double',
22
+ dotted: 'dotted',
23
+ dashed: 'dashed',
24
+ };
25
+ function firstChildNS(parent, localName) {
26
+ if (!parent)
27
+ return null;
28
+ for (let i = 0; i < parent.childNodes.length; i++) {
29
+ const child = parent.childNodes[i];
30
+ if (child.nodeType === 1 && child.localName === localName && child.namespaceURI === W_NS) {
31
+ return child;
32
+ }
33
+ }
34
+ return null;
35
+ }
36
+ function wAttr(el, localName) {
37
+ return el.getAttributeNS(W_NS, localName) || el.getAttribute(`w:${localName}`) || null;
38
+ }
39
+ /**
40
+ * Resolve the uniform `fo:border` for a table from its explicit `w:tblBorders`, preferring
41
+ * inside edges (what most cells show). Explicitly border-free tables return `'none'`; tables
42
+ * without a `w:tblBorders` at all return the bordered default.
43
+ */
44
+ export function resolveTableBorderSpec(tbl) {
45
+ const tblPr = firstChildNS(tbl, 'tblPr');
46
+ const borders = firstChildNS(tblPr, 'tblBorders');
47
+ if (!borders)
48
+ return DEFAULT_BORDER_SPEC;
49
+ const candidates = ['insideH', 'insideV', 'top', 'bottom', 'left', 'right']
50
+ .map((edge) => firstChildNS(borders, edge))
51
+ .filter((el) => el !== null);
52
+ if (candidates.length === 0)
53
+ return DEFAULT_BORDER_SPEC;
54
+ for (const edge of candidates) {
55
+ const val = wAttr(edge, 'val') ?? 'none';
56
+ if (val === 'none' || val === 'nil')
57
+ continue;
58
+ // w:sz is eighths of a point; absent → Word's hairline default (≈0.5pt).
59
+ const szRaw = Number(wAttr(edge, 'sz') ?? NaN);
60
+ const widthPt = Number.isFinite(szRaw) && szRaw > 0 ? Number((szRaw / 8).toFixed(2)) : 0.5;
61
+ const colorRaw = wAttr(edge, 'color');
62
+ const color = colorRaw && /^[0-9A-Fa-f]{6}$/.test(colorRaw) ? `#${colorRaw.toLowerCase()}` : '#000000';
63
+ return `${widthPt}pt ${BORDER_STYLE_MAP[val] ?? 'solid'} ${color}`;
64
+ }
65
+ return 'none'; // every declared edge was explicitly none/nil
66
+ }
67
+ /** Column widths in points from `w:tblGrid/w:gridCol` (`w:w` is twips); empty when absent. */
68
+ export function readGridColWidthsPt(tbl) {
69
+ const grid = firstChildNS(tbl, 'tblGrid');
70
+ if (!grid)
71
+ return [];
72
+ const widths = [];
73
+ for (let i = 0; i < grid.childNodes.length; i++) {
74
+ const child = grid.childNodes[i];
75
+ if (child.nodeType !== 1 || child.localName !== 'gridCol')
76
+ continue;
77
+ const w = Number(wAttr(child, 'w') ?? NaN);
78
+ if (!Number.isFinite(w) || w <= 0)
79
+ return []; // a single unusable column invalidates the grid
80
+ widths.push(w / 20);
81
+ }
82
+ return widths;
83
+ }
84
+ /**
85
+ * Deduped automatic styles for table emission: one `table-cell` style per distinct border
86
+ * spec and one `table-column` style per distinct width, shared across tables.
87
+ */
88
+ export class TableStyleRegistry {
89
+ doc;
90
+ container;
91
+ cellByBorder = new Map();
92
+ columnByWidth = new Map();
93
+ constructor(doc, container) {
94
+ this.doc = doc;
95
+ this.container = container;
96
+ }
97
+ cellStyleFor(borderSpec) {
98
+ const existing = this.cellByBorder.get(borderSpec);
99
+ if (existing)
100
+ return existing;
101
+ const name = `ConvCell${this.cellByBorder.size + 1}`;
102
+ const style = this.doc.createElementNS(ODF_NS.STYLE, 'style:style');
103
+ style.setAttributeNS(ODF_NS.STYLE, 'style:name', name);
104
+ style.setAttributeNS(ODF_NS.STYLE, 'style:family', 'table-cell');
105
+ const props = this.doc.createElementNS(ODF_NS.STYLE, 'style:table-cell-properties');
106
+ props.setAttributeNS(ODF_NS.FO, 'fo:border', borderSpec);
107
+ props.setAttributeNS(ODF_NS.FO, 'fo:padding', '0.0382in');
108
+ style.appendChild(props);
109
+ this.container.appendChild(style);
110
+ this.cellByBorder.set(borderSpec, name);
111
+ return name;
112
+ }
113
+ columnStyleFor(widthPt) {
114
+ const key = String(widthPt);
115
+ const existing = this.columnByWidth.get(key);
116
+ if (existing)
117
+ return existing;
118
+ const name = `ConvCol${this.columnByWidth.size + 1}`;
119
+ const style = this.doc.createElementNS(ODF_NS.STYLE, 'style:style');
120
+ style.setAttributeNS(ODF_NS.STYLE, 'style:name', name);
121
+ style.setAttributeNS(ODF_NS.STYLE, 'style:family', 'table-column');
122
+ const props = this.doc.createElementNS(ODF_NS.STYLE, 'style:table-column-properties');
123
+ props.setAttributeNS(ODF_NS.STYLE, 'style:column-width', `${Number(widthPt.toFixed(2))}pt`);
124
+ style.appendChild(props);
125
+ this.container.appendChild(style);
126
+ this.columnByWidth.set(key, name);
127
+ return name;
128
+ }
129
+ }
130
+ /**
131
+ * Append the table built from `group` to `body`. Cell paragraph content is delegated to
132
+ * `fillParagraph` (the orchestrator's inline emitter) and cell paragraph styles to
133
+ * `paragraphStyleFor` so this module stays cycle-free. `sourceTbl` is the raw `w:tbl` this
134
+ * group was derived from (null when unavailable — defaults apply).
135
+ */
136
+ export function appendTable(doc, body, group, tableNumber, sourceTbl, tableStyles, fillParagraph, paragraphStyleFor, lossiness) {
137
+ let totalCols = 0;
138
+ for (const n of group) {
139
+ const tc = n.table_context;
140
+ if (!tc)
141
+ continue;
142
+ totalCols = Math.max(totalCols, tc.total_cols, tc.col_index + 1);
143
+ }
144
+ if (totalCols <= 0)
145
+ return;
146
+ const rows = new Map();
147
+ const rowOrder = [];
148
+ const headerRows = new Set();
149
+ for (const n of group) {
150
+ const tc = n.table_context;
151
+ if (!tc)
152
+ continue;
153
+ if (!rows.has(tc.row_index)) {
154
+ rows.set(tc.row_index, new Map());
155
+ rowOrder.push(tc.row_index);
156
+ }
157
+ const cellMap = rows.get(tc.row_index);
158
+ const cellNodes = cellMap.get(tc.col_index) ?? [];
159
+ cellNodes.push(n);
160
+ cellMap.set(tc.col_index, cellNodes);
161
+ if (tc.is_header_row)
162
+ headerRows.add(tc.row_index);
163
+ }
164
+ rowOrder.sort((a, b) => a - b);
165
+ if (rowOrder.length === 0)
166
+ return;
167
+ const cellStyleName = tableStyles.cellStyleFor(resolveTableBorderSpec(sourceTbl));
168
+ const table = doc.createElementNS(ODF_NS.TABLE, 'table:table');
169
+ table.setAttributeNS(ODF_NS.TABLE, 'table:name', `Table${tableNumber}`);
170
+ // Source grid widths drive per-column styles; a grid that does not match the view's
171
+ // column count (gridSpan merges can desync them) falls back to unstyled repeated columns.
172
+ const gridWidths = readGridColWidthsPt(sourceTbl);
173
+ if (gridWidths.length === totalCols) {
174
+ for (const widthPt of gridWidths) {
175
+ const column = doc.createElementNS(ODF_NS.TABLE, 'table:table-column');
176
+ column.setAttributeNS(ODF_NS.TABLE, 'table:style-name', tableStyles.columnStyleFor(widthPt));
177
+ table.appendChild(column);
178
+ }
179
+ }
180
+ else {
181
+ const columns = doc.createElementNS(ODF_NS.TABLE, 'table:table-column');
182
+ columns.setAttributeNS(ODF_NS.TABLE, 'table:number-columns-repeated', String(totalCols));
183
+ table.appendChild(columns);
184
+ }
185
+ body.appendChild(table);
186
+ const buildRow = (rowIndex) => {
187
+ const row = doc.createElementNS(ODF_NS.TABLE, 'table:table-row');
188
+ const cellMap = rows.get(rowIndex) ?? new Map();
189
+ for (let c = 0; c < totalCols; c++) {
190
+ const cell = doc.createElementNS(ODF_NS.TABLE, 'table:table-cell');
191
+ cell.setAttributeNS(ODF_NS.OFFICE, 'office:value-type', 'string');
192
+ cell.setAttributeNS(ODF_NS.TABLE, 'table:style-name', cellStyleName);
193
+ const cellNodes = cellMap.get(c);
194
+ if (cellNodes && cellNodes.length > 0) {
195
+ for (const node of cellNodes) {
196
+ const p = doc.createElementNS(ODF_NS.TEXT, 'text:p');
197
+ p.setAttributeNS(ODF_NS.TEXT, 'text:style-name', paragraphStyleFor(node));
198
+ cell.appendChild(p);
199
+ fillParagraph(p, node);
200
+ }
201
+ }
202
+ else {
203
+ lossiness.add('table-grid-gaps-filled', `Table${tableNumber} r${rowIndex}c${c}`);
204
+ cell.appendChild(doc.createElementNS(ODF_NS.TEXT, 'text:p'));
205
+ }
206
+ row.appendChild(cell);
207
+ }
208
+ return row;
209
+ };
210
+ // The LEADING run of header-flagged rows goes into `table:table-header-rows` (the ODF
211
+ // analogue of the HTML serializer's `<thead>`). The view model flags `is_header_row` for
212
+ // row 0 of every table — a heuristic, not Word's `w:tblHeader` — so in practice this is
213
+ // the first row.
214
+ let headerEnd = 0;
215
+ while (headerEnd < rowOrder.length && headerRows.has(rowOrder[headerEnd]))
216
+ headerEnd += 1;
217
+ if (headerEnd > 0) {
218
+ const headerContainer = doc.createElementNS(ODF_NS.TABLE, 'table:table-header-rows');
219
+ for (let r = 0; r < headerEnd; r++)
220
+ headerContainer.appendChild(buildRow(rowOrder[r]));
221
+ table.appendChild(headerContainer);
222
+ }
223
+ for (let r = headerEnd; r < rowOrder.length; r++)
224
+ table.appendChild(buildRow(rowOrder[r]));
225
+ }
226
+ //# sourceMappingURL=tables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tables.js","sourceRoot":"","sources":["../../src/convert/tables.ts"],"names":[],"mappings":"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"}