@adeu/core 1.6.2 → 1.6.5
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/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +38 -38
- package/src/comments.test.ts +37 -37
- package/src/comments.ts +450 -450
- package/src/diff.test.ts +61 -61
- package/src/diff.ts +250 -250
- package/src/docx/bridge.ts +188 -188
- package/src/docx/dom.ts +53 -53
- package/src/docx/primitives.ts +64 -64
- package/src/domain.ts +10 -10
- package/src/engine.atomic.test.ts +57 -57
- package/src/engine.batch.test.ts +92 -92
- package/src/engine.safety.test.ts +41 -41
- package/src/engine.tables.test.ts +165 -165
- package/src/engine.ts +734 -734
- package/src/index.test.ts +7 -7
- package/src/index.ts +13 -13
- package/src/ingest.test.ts +43 -43
- package/src/ingest.ts +399 -399
- package/src/mapper.test.ts +65 -65
- package/src/mapper.ts +834 -834
- package/src/markup.test.ts +149 -149
- package/src/markup.ts +322 -322
- package/src/models.ts +50 -50
- package/src/outline.ts +376 -376
- package/src/pagination.ts +238 -238
- package/src/test-utils.ts +141 -141
- package/src/utils/docx.ts +477 -477
- package/tsconfig.json +21 -21
- package/tsup.config.ts +9 -9
- package/vitest.config.ts +11 -11
package/src/test-utils.ts
CHANGED
|
@@ -1,142 +1,142 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { resolve, dirname } from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import { DocumentObject } from './docx/bridge.js';
|
|
5
|
-
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
-
const __dirname = dirname(__filename);
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Loads a pristine empty DOCX fixture and clears its body to allow
|
|
11
|
-
* dynamic document construction in tests, mimicking `python-docx`.
|
|
12
|
-
*/
|
|
13
|
-
export async function createTestDocument(): Promise<DocumentObject> {
|
|
14
|
-
const fixturePath = resolve(__dirname, '../../../../shared/fixtures/initial.docx');
|
|
15
|
-
const buf = readFileSync(fixturePath);
|
|
16
|
-
const doc = await DocumentObject.load(buf);
|
|
17
|
-
|
|
18
|
-
// Clear the body completely
|
|
19
|
-
const body = doc.element;
|
|
20
|
-
while (body.firstChild) {
|
|
21
|
-
body.removeChild(body.firstChild);
|
|
22
|
-
}
|
|
23
|
-
return doc;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function addParagraph(doc: DocumentObject, text: string): Element {
|
|
27
|
-
const xmlDoc = doc.element.ownerDocument!;
|
|
28
|
-
const p = xmlDoc.createElement('w:p');
|
|
29
|
-
const r = xmlDoc.createElement('w:r');
|
|
30
|
-
const t = xmlDoc.createElement('w:t');
|
|
31
|
-
|
|
32
|
-
t.textContent = text;
|
|
33
|
-
if (text.includes(' ') || text.includes('\n')) {
|
|
34
|
-
t.setAttribute('xml:space', 'preserve');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
r.appendChild(t);
|
|
38
|
-
p.appendChild(r);
|
|
39
|
-
doc.element.appendChild(p);
|
|
40
|
-
return p;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function addTable(doc: DocumentObject, rows: number, cols: number): Element {
|
|
44
|
-
const xmlDoc = doc.element.ownerDocument!;
|
|
45
|
-
const tbl = xmlDoc.createElement('w:tbl');
|
|
46
|
-
|
|
47
|
-
// Add tblGrid
|
|
48
|
-
const tblGrid = xmlDoc.createElement('w:tblGrid');
|
|
49
|
-
for (let i = 0; i < cols; i++) {
|
|
50
|
-
const gridCol = xmlDoc.createElement('w:gridCol');
|
|
51
|
-
tblGrid.appendChild(gridCol);
|
|
52
|
-
}
|
|
53
|
-
tbl.appendChild(tblGrid);
|
|
54
|
-
|
|
55
|
-
for (let r = 0; r < rows; r++) {
|
|
56
|
-
const tr = xmlDoc.createElement('w:tr');
|
|
57
|
-
for (let c = 0; c < cols; c++) {
|
|
58
|
-
const tc = xmlDoc.createElement('w:tc');
|
|
59
|
-
const p = xmlDoc.createElement('w:p');
|
|
60
|
-
tc.appendChild(p);
|
|
61
|
-
tr.appendChild(tc);
|
|
62
|
-
}
|
|
63
|
-
tbl.appendChild(tr);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
doc.element.appendChild(tbl);
|
|
67
|
-
return tbl;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function setCellText(table: Element, rowIndex: number, colIndex: number, text: string) {
|
|
71
|
-
const rows = Array.from(table.childNodes).filter(n => (n as Element).tagName === 'w:tr') as Element[];
|
|
72
|
-
const row = rows[rowIndex];
|
|
73
|
-
const cells = Array.from(row.childNodes).filter(n => (n as Element).tagName === 'w:tc') as Element[];
|
|
74
|
-
const cell = cells[colIndex];
|
|
75
|
-
|
|
76
|
-
// Clear existing cell content
|
|
77
|
-
while (cell.firstChild) cell.removeChild(cell.firstChild);
|
|
78
|
-
|
|
79
|
-
const xmlDoc = table.ownerDocument!;
|
|
80
|
-
const p = xmlDoc.createElement('w:p');
|
|
81
|
-
const r = xmlDoc.createElement('w:r');
|
|
82
|
-
const t = xmlDoc.createElement('w:t');
|
|
83
|
-
|
|
84
|
-
t.textContent = text;
|
|
85
|
-
if (text.includes(' ')) t.setAttribute('xml:space', 'preserve');
|
|
86
|
-
|
|
87
|
-
r.appendChild(t);
|
|
88
|
-
p.appendChild(r);
|
|
89
|
-
cell.appendChild(p);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export function addNestedTable(cell: Element, rows: number, cols: number): Element {
|
|
93
|
-
const xmlDoc = cell.ownerDocument!;
|
|
94
|
-
const tbl = xmlDoc.createElement('w:tbl');
|
|
95
|
-
|
|
96
|
-
const tblGrid = xmlDoc.createElement('w:tblGrid');
|
|
97
|
-
for (let i = 0; i < cols; i++) {
|
|
98
|
-
tblGrid.appendChild(xmlDoc.createElement('w:gridCol'));
|
|
99
|
-
}
|
|
100
|
-
tbl.appendChild(tblGrid);
|
|
101
|
-
|
|
102
|
-
for (let r = 0; r < rows; r++) {
|
|
103
|
-
const tr = xmlDoc.createElement('w:tr');
|
|
104
|
-
for (let c = 0; c < cols; c++) {
|
|
105
|
-
const tc = xmlDoc.createElement('w:tc');
|
|
106
|
-
const p = xmlDoc.createElement('w:p');
|
|
107
|
-
tc.appendChild(p);
|
|
108
|
-
tr.appendChild(tc);
|
|
109
|
-
}
|
|
110
|
-
tbl.appendChild(tr);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// A table inside a cell must be followed by an empty paragraph in OOXML
|
|
114
|
-
cell.appendChild(tbl);
|
|
115
|
-
cell.appendChild(xmlDoc.createElement('w:p'));
|
|
116
|
-
|
|
117
|
-
return tbl;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function mergeCells(table: Element, rowIndex: number, colIndex1: number, colIndex2: number) {
|
|
121
|
-
const rows = Array.from(table.childNodes).filter(n => (n as Element).tagName === 'w:tr') as Element[];
|
|
122
|
-
const row = rows[rowIndex];
|
|
123
|
-
const cells = Array.from(row.childNodes).filter(n => (n as Element).tagName === 'w:tc') as Element[];
|
|
124
|
-
|
|
125
|
-
const xmlDoc = table.ownerDocument!;
|
|
126
|
-
const tc1 = cells[colIndex1];
|
|
127
|
-
|
|
128
|
-
let tcPr1 = Array.from(tc1.childNodes).find(n => (n as Element).tagName === 'w:tcPr') as Element;
|
|
129
|
-
if (!tcPr1) {
|
|
130
|
-
tcPr1 = xmlDoc.createElement('w:tcPr');
|
|
131
|
-
tc1.insertBefore(tcPr1, tc1.firstChild);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const gridSpan = xmlDoc.createElement('w:gridSpan');
|
|
135
|
-
gridSpan.setAttribute('w:val', (colIndex2 - colIndex1 + 1).toString());
|
|
136
|
-
tcPr1.appendChild(gridSpan);
|
|
137
|
-
|
|
138
|
-
// Physically remove the absorbed cells (this is how raw OOXML handles gridSpans)
|
|
139
|
-
for (let i = colIndex1 + 1; i <= colIndex2; i++) {
|
|
140
|
-
row.removeChild(cells[i]);
|
|
141
|
-
}
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { DocumentObject } from './docx/bridge.js';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Loads a pristine empty DOCX fixture and clears its body to allow
|
|
11
|
+
* dynamic document construction in tests, mimicking `python-docx`.
|
|
12
|
+
*/
|
|
13
|
+
export async function createTestDocument(): Promise<DocumentObject> {
|
|
14
|
+
const fixturePath = resolve(__dirname, '../../../../shared/fixtures/initial.docx');
|
|
15
|
+
const buf = readFileSync(fixturePath);
|
|
16
|
+
const doc = await DocumentObject.load(buf);
|
|
17
|
+
|
|
18
|
+
// Clear the body completely
|
|
19
|
+
const body = doc.element;
|
|
20
|
+
while (body.firstChild) {
|
|
21
|
+
body.removeChild(body.firstChild);
|
|
22
|
+
}
|
|
23
|
+
return doc;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function addParagraph(doc: DocumentObject, text: string): Element {
|
|
27
|
+
const xmlDoc = doc.element.ownerDocument!;
|
|
28
|
+
const p = xmlDoc.createElement('w:p');
|
|
29
|
+
const r = xmlDoc.createElement('w:r');
|
|
30
|
+
const t = xmlDoc.createElement('w:t');
|
|
31
|
+
|
|
32
|
+
t.textContent = text;
|
|
33
|
+
if (text.includes(' ') || text.includes('\n')) {
|
|
34
|
+
t.setAttribute('xml:space', 'preserve');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
r.appendChild(t);
|
|
38
|
+
p.appendChild(r);
|
|
39
|
+
doc.element.appendChild(p);
|
|
40
|
+
return p;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function addTable(doc: DocumentObject, rows: number, cols: number): Element {
|
|
44
|
+
const xmlDoc = doc.element.ownerDocument!;
|
|
45
|
+
const tbl = xmlDoc.createElement('w:tbl');
|
|
46
|
+
|
|
47
|
+
// Add tblGrid
|
|
48
|
+
const tblGrid = xmlDoc.createElement('w:tblGrid');
|
|
49
|
+
for (let i = 0; i < cols; i++) {
|
|
50
|
+
const gridCol = xmlDoc.createElement('w:gridCol');
|
|
51
|
+
tblGrid.appendChild(gridCol);
|
|
52
|
+
}
|
|
53
|
+
tbl.appendChild(tblGrid);
|
|
54
|
+
|
|
55
|
+
for (let r = 0; r < rows; r++) {
|
|
56
|
+
const tr = xmlDoc.createElement('w:tr');
|
|
57
|
+
for (let c = 0; c < cols; c++) {
|
|
58
|
+
const tc = xmlDoc.createElement('w:tc');
|
|
59
|
+
const p = xmlDoc.createElement('w:p');
|
|
60
|
+
tc.appendChild(p);
|
|
61
|
+
tr.appendChild(tc);
|
|
62
|
+
}
|
|
63
|
+
tbl.appendChild(tr);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
doc.element.appendChild(tbl);
|
|
67
|
+
return tbl;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function setCellText(table: Element, rowIndex: number, colIndex: number, text: string) {
|
|
71
|
+
const rows = Array.from(table.childNodes).filter(n => (n as Element).tagName === 'w:tr') as Element[];
|
|
72
|
+
const row = rows[rowIndex];
|
|
73
|
+
const cells = Array.from(row.childNodes).filter(n => (n as Element).tagName === 'w:tc') as Element[];
|
|
74
|
+
const cell = cells[colIndex];
|
|
75
|
+
|
|
76
|
+
// Clear existing cell content
|
|
77
|
+
while (cell.firstChild) cell.removeChild(cell.firstChild);
|
|
78
|
+
|
|
79
|
+
const xmlDoc = table.ownerDocument!;
|
|
80
|
+
const p = xmlDoc.createElement('w:p');
|
|
81
|
+
const r = xmlDoc.createElement('w:r');
|
|
82
|
+
const t = xmlDoc.createElement('w:t');
|
|
83
|
+
|
|
84
|
+
t.textContent = text;
|
|
85
|
+
if (text.includes(' ')) t.setAttribute('xml:space', 'preserve');
|
|
86
|
+
|
|
87
|
+
r.appendChild(t);
|
|
88
|
+
p.appendChild(r);
|
|
89
|
+
cell.appendChild(p);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function addNestedTable(cell: Element, rows: number, cols: number): Element {
|
|
93
|
+
const xmlDoc = cell.ownerDocument!;
|
|
94
|
+
const tbl = xmlDoc.createElement('w:tbl');
|
|
95
|
+
|
|
96
|
+
const tblGrid = xmlDoc.createElement('w:tblGrid');
|
|
97
|
+
for (let i = 0; i < cols; i++) {
|
|
98
|
+
tblGrid.appendChild(xmlDoc.createElement('w:gridCol'));
|
|
99
|
+
}
|
|
100
|
+
tbl.appendChild(tblGrid);
|
|
101
|
+
|
|
102
|
+
for (let r = 0; r < rows; r++) {
|
|
103
|
+
const tr = xmlDoc.createElement('w:tr');
|
|
104
|
+
for (let c = 0; c < cols; c++) {
|
|
105
|
+
const tc = xmlDoc.createElement('w:tc');
|
|
106
|
+
const p = xmlDoc.createElement('w:p');
|
|
107
|
+
tc.appendChild(p);
|
|
108
|
+
tr.appendChild(tc);
|
|
109
|
+
}
|
|
110
|
+
tbl.appendChild(tr);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// A table inside a cell must be followed by an empty paragraph in OOXML
|
|
114
|
+
cell.appendChild(tbl);
|
|
115
|
+
cell.appendChild(xmlDoc.createElement('w:p'));
|
|
116
|
+
|
|
117
|
+
return tbl;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function mergeCells(table: Element, rowIndex: number, colIndex1: number, colIndex2: number) {
|
|
121
|
+
const rows = Array.from(table.childNodes).filter(n => (n as Element).tagName === 'w:tr') as Element[];
|
|
122
|
+
const row = rows[rowIndex];
|
|
123
|
+
const cells = Array.from(row.childNodes).filter(n => (n as Element).tagName === 'w:tc') as Element[];
|
|
124
|
+
|
|
125
|
+
const xmlDoc = table.ownerDocument!;
|
|
126
|
+
const tc1 = cells[colIndex1];
|
|
127
|
+
|
|
128
|
+
let tcPr1 = Array.from(tc1.childNodes).find(n => (n as Element).tagName === 'w:tcPr') as Element;
|
|
129
|
+
if (!tcPr1) {
|
|
130
|
+
tcPr1 = xmlDoc.createElement('w:tcPr');
|
|
131
|
+
tc1.insertBefore(tcPr1, tc1.firstChild);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const gridSpan = xmlDoc.createElement('w:gridSpan');
|
|
135
|
+
gridSpan.setAttribute('w:val', (colIndex2 - colIndex1 + 1).toString());
|
|
136
|
+
tcPr1.appendChild(gridSpan);
|
|
137
|
+
|
|
138
|
+
// Physically remove the absorbed cells (this is how raw OOXML handles gridSpans)
|
|
139
|
+
for (let i = colIndex1 + 1; i <= colIndex2; i++) {
|
|
140
|
+
row.removeChild(cells[i]);
|
|
141
|
+
}
|
|
142
142
|
}
|