@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.
- package/LICENSE +202 -0
- package/NOTICE +2 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/compare/emit.d.ts +8 -3
- package/dist/compare/emit.d.ts.map +1 -1
- package/dist/compare/emit.js +39 -7
- package/dist/compare/emit.js.map +1 -1
- package/dist/compare/inline_diff.d.ts +5 -0
- package/dist/compare/inline_diff.d.ts.map +1 -1
- package/dist/compare/inline_diff.js +71 -1
- package/dist/compare/inline_diff.js.map +1 -1
- package/dist/convert/docx_to_odt.d.ts +20 -0
- package/dist/convert/docx_to_odt.d.ts.map +1 -0
- package/dist/convert/docx_to_odt.js +199 -0
- package/dist/convert/docx_to_odt.js.map +1 -0
- package/dist/convert/index.d.ts +3 -0
- package/dist/convert/index.d.ts.map +1 -0
- package/dist/convert/index.js +2 -0
- package/dist/convert/index.js.map +1 -0
- package/dist/convert/inline.d.ts +55 -0
- package/dist/convert/inline.d.ts.map +1 -0
- package/dist/convert/inline.js +274 -0
- package/dist/convert/inline.js.map +1 -0
- package/dist/convert/lists.d.ts +41 -0
- package/dist/convert/lists.d.ts.map +1 -0
- package/dist/convert/lists.js +137 -0
- package/dist/convert/lists.js.map +1 -0
- package/dist/convert/package.d.ts +54 -0
- package/dist/convert/package.d.ts.map +1 -0
- package/dist/convert/package.js +232 -0
- package/dist/convert/package.js.map +1 -0
- package/dist/convert/paragraph_styles.d.ts +25 -0
- package/dist/convert/paragraph_styles.d.ts.map +1 -0
- package/dist/convert/paragraph_styles.js +63 -0
- package/dist/convert/paragraph_styles.js.map +1 -0
- package/dist/convert/tables.d.ts +44 -0
- package/dist/convert/tables.d.ts.map +1 -0
- package/dist/convert/tables.js +226 -0
- package/dist/convert/tables.js.map +1 -0
- package/dist/convert/types.d.ts +27 -0
- package/dist/convert/types.d.ts.map +1 -0
- package/dist/convert/types.js +25 -0
- package/dist/convert/types.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/shared/odf/OdfArchive.d.ts +16 -0
- package/dist/shared/odf/OdfArchive.d.ts.map +1 -1
- package/dist/shared/odf/OdfArchive.js +48 -1
- package/dist/shared/odf/OdfArchive.js.map +1 -1
- package/dist/shared/odf/namespaces.d.ts +4 -0
- package/dist/shared/odf/namespaces.d.ts.map +1 -1
- package/dist/shared/odf/namespaces.js +8 -0
- package/dist/shared/odf/namespaces.js.map +1 -1
- 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, '&')
|
|
66
|
+
.replace(/</g, '<')
|
|
67
|
+
.replace(/>/g, '>')
|
|
68
|
+
.replace(/"/g, '"');
|
|
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, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
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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"}
|