@wonderwhy-er/desktop-commander 0.2.35 → 0.2.36
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/README.md +2 -0
- package/dist/handlers/filesystem-handlers.js +58 -11
- package/dist/handlers/history-handlers.d.ts +7 -0
- package/dist/handlers/history-handlers.js +33 -1
- package/dist/server.js +30 -4
- package/dist/tools/docx/builders/image.d.ts +14 -0
- package/dist/tools/docx/builders/image.js +84 -0
- package/dist/tools/docx/builders/index.d.ts +9 -3
- package/dist/tools/docx/builders/index.js +9 -3
- package/dist/tools/docx/builders/paragraph.d.ts +12 -0
- package/dist/tools/docx/builders/paragraph.js +29 -0
- package/dist/tools/docx/builders/table.d.ts +8 -0
- package/dist/tools/docx/builders/table.js +94 -0
- package/dist/tools/docx/builders/utils.d.ts +5 -0
- package/dist/tools/docx/builders/utils.js +18 -0
- package/dist/tools/docx/constants.d.ts +28 -32
- package/dist/tools/docx/constants.js +56 -52
- package/dist/tools/docx/create.d.ts +21 -0
- package/dist/tools/docx/create.js +386 -0
- package/dist/tools/docx/dom.d.ts +66 -0
- package/dist/tools/docx/dom.js +228 -0
- package/dist/tools/docx/index.d.ts +8 -12
- package/dist/tools/docx/index.js +8 -14
- package/dist/tools/docx/modify.d.ts +28 -0
- package/dist/tools/docx/modify.js +271 -0
- package/dist/tools/docx/ops/delete-paragraph-at-body-index.d.ts +11 -0
- package/dist/tools/docx/ops/delete-paragraph-at-body-index.js +23 -0
- package/dist/tools/docx/ops/header-replace-text-exact.d.ts +13 -0
- package/dist/tools/docx/ops/header-replace-text-exact.js +55 -0
- package/dist/tools/docx/ops/index.d.ts +17 -0
- package/dist/tools/docx/ops/index.js +67 -0
- package/dist/tools/docx/ops/insert-image-after-text.d.ts +24 -0
- package/dist/tools/docx/ops/insert-image-after-text.js +128 -0
- package/dist/tools/docx/ops/insert-paragraph-after-text.d.ts +12 -0
- package/dist/tools/docx/ops/insert-paragraph-after-text.js +74 -0
- package/dist/tools/docx/ops/insert-table-after-text.d.ts +19 -0
- package/dist/tools/docx/ops/insert-table-after-text.js +57 -0
- package/dist/tools/docx/ops/replace-hyperlink-url.d.ts +12 -0
- package/dist/tools/docx/ops/replace-hyperlink-url.js +37 -0
- package/dist/tools/docx/ops/replace-paragraph-at-body-index.d.ts +9 -0
- package/dist/tools/docx/ops/replace-paragraph-at-body-index.js +25 -0
- package/dist/tools/docx/ops/replace-paragraph-text-exact.d.ts +9 -0
- package/dist/tools/docx/ops/replace-paragraph-text-exact.js +21 -0
- package/dist/tools/docx/ops/set-color-for-paragraph-exact.d.ts +8 -0
- package/dist/tools/docx/ops/set-color-for-paragraph-exact.js +23 -0
- package/dist/tools/docx/ops/set-color-for-style.d.ts +9 -0
- package/dist/tools/docx/ops/set-color-for-style.js +27 -0
- package/dist/tools/docx/ops/set-paragraph-style-at-body-index.d.ts +8 -0
- package/dist/tools/docx/ops/set-paragraph-style-at-body-index.js +57 -0
- package/dist/tools/docx/ops/table-set-cell-text.d.ts +9 -0
- package/dist/tools/docx/ops/table-set-cell-text.js +72 -0
- package/dist/tools/docx/read.d.ts +27 -0
- package/dist/tools/docx/read.js +188 -0
- package/dist/tools/docx/relationships.d.ts +22 -0
- package/dist/tools/docx/relationships.js +76 -0
- package/dist/tools/docx/types.d.ts +174 -104
- package/dist/tools/docx/types.js +2 -5
- package/dist/tools/docx/validate.d.ts +33 -0
- package/dist/tools/docx/validate.js +49 -0
- package/dist/tools/docx/write.d.ts +17 -0
- package/dist/tools/docx/write.js +88 -0
- package/dist/tools/docx/zip.d.ts +21 -0
- package/dist/tools/docx/zip.js +35 -0
- package/dist/tools/schemas.d.ts +13 -0
- package/dist/tools/schemas.js +5 -0
- package/dist/types.d.ts +10 -0
- package/dist/ui/contracts.d.ts +14 -0
- package/dist/ui/contracts.js +18 -0
- package/dist/ui/file-preview/index.html +16 -0
- package/dist/ui/file-preview/preview-runtime.js +13977 -0
- package/dist/ui/file-preview/shared/preview-file-types.d.ts +5 -0
- package/dist/ui/file-preview/shared/preview-file-types.js +57 -0
- package/dist/ui/file-preview/src/app.d.ts +4 -0
- package/dist/ui/file-preview/src/app.js +800 -0
- package/dist/ui/file-preview/src/components/code-viewer.d.ts +6 -0
- package/dist/ui/file-preview/src/components/code-viewer.js +73 -0
- package/dist/ui/file-preview/src/components/highlighting.d.ts +2 -0
- package/dist/ui/file-preview/src/components/highlighting.js +54 -0
- package/dist/ui/file-preview/src/components/html-renderer.d.ts +9 -0
- package/dist/ui/file-preview/src/components/html-renderer.js +63 -0
- package/dist/ui/file-preview/src/components/markdown-renderer.d.ts +1 -0
- package/dist/ui/file-preview/src/components/markdown-renderer.js +21 -0
- package/dist/ui/file-preview/src/components/toolbar.d.ts +6 -0
- package/dist/ui/file-preview/src/components/toolbar.js +75 -0
- package/dist/ui/file-preview/src/image-preview.d.ts +3 -0
- package/dist/ui/file-preview/src/image-preview.js +21 -0
- package/dist/ui/file-preview/src/main.d.ts +1 -0
- package/dist/ui/file-preview/src/main.js +5 -0
- package/dist/ui/file-preview/src/types.d.ts +1 -0
- package/dist/ui/file-preview/src/types.js +1 -0
- package/dist/ui/file-preview/styles.css +764 -0
- package/dist/ui/resources.d.ts +21 -0
- package/dist/ui/resources.js +72 -0
- package/dist/ui/shared/escape-html.d.ts +4 -0
- package/dist/ui/shared/escape-html.js +11 -0
- package/dist/ui/shared/host-lifecycle.d.ts +16 -0
- package/dist/ui/shared/host-lifecycle.js +35 -0
- package/dist/ui/shared/rpc-client.d.ts +14 -0
- package/dist/ui/shared/rpc-client.js +72 -0
- package/dist/ui/shared/theme-adaptation.d.ts +10 -0
- package/dist/ui/shared/theme-adaptation.js +118 -0
- package/dist/ui/shared/tool-header.d.ts +9 -0
- package/dist/ui/shared/tool-header.js +25 -0
- package/dist/ui/shared/tool-shell.d.ts +16 -0
- package/dist/ui/shared/tool-shell.js +65 -0
- package/dist/ui/shared/widget-state.d.ts +28 -0
- package/dist/ui/shared/widget-state.js +60 -0
- package/dist/utils/capture.d.ts +1 -0
- package/dist/utils/capture.js +6 -0
- package/dist/utils/files/docx.d.ts +8 -15
- package/dist/utils/files/docx.js +76 -176
- package/dist/utils/files/text.js +9 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -2
|
@@ -1,57 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* DOCX
|
|
3
|
-
*
|
|
4
|
-
* Centralised constants shared across the DOCX module.
|
|
5
|
-
*
|
|
6
|
-
* @module docx/constants
|
|
2
|
+
* DOCX constants — shared values used across the module.
|
|
7
3
|
*/
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
right: 1440,
|
|
22
|
-
bottom: 1440,
|
|
23
|
-
left: 1440,
|
|
24
|
-
header: 720,
|
|
25
|
-
footer: 720,
|
|
26
|
-
gutter: 0,
|
|
27
|
-
},
|
|
28
|
-
footer: true,
|
|
29
|
-
pageNumber: false,
|
|
4
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
5
|
+
// Image MIME types
|
|
6
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
7
|
+
export const IMAGE_MIME_TYPES = {
|
|
8
|
+
'.png': 'image/png',
|
|
9
|
+
'.jpg': 'image/jpeg',
|
|
10
|
+
'.jpeg': 'image/jpeg',
|
|
11
|
+
'.gif': 'image/gif',
|
|
12
|
+
'.bmp': 'image/bmp',
|
|
13
|
+
'.tiff': 'image/tiff',
|
|
14
|
+
'.tif': 'image/tiff',
|
|
15
|
+
'.svg': 'image/svg+xml',
|
|
16
|
+
'.webp': 'image/webp',
|
|
30
17
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
18
|
+
export function getMimeType(ext) {
|
|
19
|
+
return IMAGE_MIME_TYPES[ext.toLowerCase()] ?? 'application/octet-stream';
|
|
20
|
+
}
|
|
21
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
22
|
+
// EMU conversion (English Metric Units)
|
|
23
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
24
|
+
/**
|
|
25
|
+
* Convert pixels to EMU (English Metric Units).
|
|
26
|
+
* 1 inch = 914400 EMU, 1 px ≈ 9525 EMU (at 96 DPI)
|
|
27
|
+
*/
|
|
28
|
+
export const PX_TO_EMU = 9525;
|
|
29
|
+
export function pixelsToEmu(px) {
|
|
30
|
+
return px * PX_TO_EMU;
|
|
31
|
+
}
|
|
32
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
33
|
+
// XML namespaces
|
|
34
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
35
|
+
export const NAMESPACES = {
|
|
36
|
+
W: 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
|
|
37
|
+
WP: 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing',
|
|
38
|
+
A: 'http://schemas.openxmlformats.org/drawingml/2006/main',
|
|
39
|
+
PIC: 'http://schemas.openxmlformats.org/drawingml/2006/picture',
|
|
40
|
+
R: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
|
|
41
|
+
RELS: 'http://schemas.openxmlformats.org/package/2006/relationships',
|
|
36
42
|
};
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
//
|
|
40
|
-
export const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
44
|
+
// Default values
|
|
45
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
46
|
+
export const DEFAULT_IMAGE_WIDTH = 300;
|
|
47
|
+
export const DEFAULT_IMAGE_HEIGHT = 200;
|
|
48
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
49
|
+
// File paths
|
|
50
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
51
|
+
export const DOCX_PATHS = {
|
|
52
|
+
CONTENT_TYPES: '[Content_Types].xml',
|
|
53
|
+
DOCUMENT_XML: 'word/document.xml',
|
|
54
|
+
DOCUMENT_RELS: 'word/_rels/document.xml.rels',
|
|
55
|
+
ROOT_RELS: '_rels/.rels',
|
|
56
|
+
STYLES_XML: 'word/styles.xml',
|
|
57
|
+
SETTINGS_XML: 'word/settings.xml',
|
|
58
|
+
WEB_SETTINGS_XML: 'word/webSettings.xml',
|
|
59
|
+
FONT_TABLE_XML: 'word/fontTable.xml',
|
|
60
|
+
MEDIA_FOLDER: 'word/media',
|
|
47
61
|
};
|
|
48
|
-
// ─── HTML Wrapper Template ───────────────────────────────────────────────────
|
|
49
|
-
export const HTML_WRAPPER_TEMPLATE = `<!DOCTYPE html>
|
|
50
|
-
<html>
|
|
51
|
-
<head>
|
|
52
|
-
<meta charset="UTF-8">
|
|
53
|
-
</head>
|
|
54
|
-
<body>
|
|
55
|
-
{content}
|
|
56
|
-
</body>
|
|
57
|
-
</html>`;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createDocxNew - Create a brand-new professional DOCX file from scratch.
|
|
3
|
+
*
|
|
4
|
+
* Single Responsibility: Build a complete, professional DOCX structure
|
|
5
|
+
* with proper styles, document defaults, and content from styled DOM structure.
|
|
6
|
+
*
|
|
7
|
+
* This function does NOT read any existing files - it creates everything
|
|
8
|
+
* from scratch with a professional structure.
|
|
9
|
+
*/
|
|
10
|
+
import type { DocxContentStructure, WriteDocxResult } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Create a new professional DOCX file from content structure.
|
|
13
|
+
*
|
|
14
|
+
* This function creates a complete DOCX structure from scratch with:
|
|
15
|
+
* - Professional styles (Normal, Heading1-9, ListParagraph, TableGrid)
|
|
16
|
+
* - Document defaults (Calibri font, proper spacing)
|
|
17
|
+
* - Complete ZIP structure
|
|
18
|
+
*
|
|
19
|
+
* Then builds content from the provided structure.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createDocxNew(outputPath: string, content: DocxContentStructure): Promise<WriteDocxResult>;
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createDocxNew - Create a brand-new professional DOCX file from scratch.
|
|
3
|
+
*
|
|
4
|
+
* Single Responsibility: Build a complete, professional DOCX structure
|
|
5
|
+
* with proper styles, document defaults, and content from styled DOM structure.
|
|
6
|
+
*
|
|
7
|
+
* This function does NOT read any existing files - it creates everything
|
|
8
|
+
* from scratch with a professional structure.
|
|
9
|
+
*/
|
|
10
|
+
import fs from 'fs/promises';
|
|
11
|
+
import PizZip from 'pizzip';
|
|
12
|
+
import { parseXml, serializeXml, getBody } from './dom.js';
|
|
13
|
+
import { buildParagraph, buildTable, buildImageElement } from './builders/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* Create a professional DOCX ZIP structure with:
|
|
16
|
+
* - Complete styles.xml (Normal, Heading1-9, etc.)
|
|
17
|
+
* - Document defaults (fonts, spacing, colors)
|
|
18
|
+
* - Proper relationships
|
|
19
|
+
* - Content types
|
|
20
|
+
* - Empty document body ready for content
|
|
21
|
+
*/
|
|
22
|
+
function createProfessionalDocxZip() {
|
|
23
|
+
const zip = new PizZip();
|
|
24
|
+
// ─── [Content_Types].xml ──────────────────────────────────────────
|
|
25
|
+
zip.file('[Content_Types].xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
26
|
+
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
|
|
27
|
+
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
|
|
28
|
+
<Default Extension="xml" ContentType="application/xml"/>
|
|
29
|
+
<Default Extension="png" ContentType="image/png"/>
|
|
30
|
+
<Default Extension="jpg" ContentType="image/jpeg"/>
|
|
31
|
+
<Default Extension="jpeg" ContentType="image/jpeg"/>
|
|
32
|
+
<Default Extension="gif" ContentType="image/gif"/>
|
|
33
|
+
<Default Extension="bmp" ContentType="image/bmp"/>
|
|
34
|
+
<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
|
|
35
|
+
<Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
|
|
36
|
+
</Types>`);
|
|
37
|
+
// ─── _rels/.rels ──────────────────────────────────────────────────
|
|
38
|
+
zip.folder('_rels')?.file('.rels', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
39
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
40
|
+
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
|
|
41
|
+
</Relationships>`);
|
|
42
|
+
// ─── word/_rels/document.xml.rels ────────────────────────────────
|
|
43
|
+
zip.folder('word')?.folder('_rels')?.file('document.xml.rels', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
44
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
45
|
+
</Relationships>`);
|
|
46
|
+
// ─── word/styles.xml ───────────────────────────────────────────────
|
|
47
|
+
zip.file('word/styles.xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
48
|
+
<w:styles xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
|
49
|
+
<!-- Document Defaults -->
|
|
50
|
+
<w:docDefaults>
|
|
51
|
+
<w:rPrDefault>
|
|
52
|
+
<w:rPr>
|
|
53
|
+
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri" w:eastAsia="Calibri" w:cs="Calibri"/>
|
|
54
|
+
<w:sz w:val="22"/>
|
|
55
|
+
<w:szCs w:val="22"/>
|
|
56
|
+
<w:color w:val="000000"/>
|
|
57
|
+
</w:rPr>
|
|
58
|
+
</w:rPrDefault>
|
|
59
|
+
<w:pPrDefault>
|
|
60
|
+
<w:pPr>
|
|
61
|
+
<w:spacing w:after="200" w:line="276" w:lineRule="auto"/>
|
|
62
|
+
</w:pPr>
|
|
63
|
+
</w:pPrDefault>
|
|
64
|
+
</w:docDefaults>
|
|
65
|
+
|
|
66
|
+
<!-- Normal Style -->
|
|
67
|
+
<w:style w:type="paragraph" w:styleId="Normal">
|
|
68
|
+
<w:name w:val="Normal"/>
|
|
69
|
+
<w:qFormat/>
|
|
70
|
+
<w:pPr>
|
|
71
|
+
<w:spacing w:after="200" w:line="276" w:lineRule="auto"/>
|
|
72
|
+
</w:pPr>
|
|
73
|
+
<w:rPr>
|
|
74
|
+
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri" w:eastAsia="Calibri" w:cs="Calibri"/>
|
|
75
|
+
<w:sz w:val="22"/>
|
|
76
|
+
<w:szCs w:val="22"/>
|
|
77
|
+
<w:color w:val="000000"/>
|
|
78
|
+
</w:rPr>
|
|
79
|
+
</w:style>
|
|
80
|
+
|
|
81
|
+
<!-- Heading Styles -->
|
|
82
|
+
<w:style w:type="paragraph" w:styleId="Heading1">
|
|
83
|
+
<w:name w:val="Heading 1"/>
|
|
84
|
+
<w:basedOn w:val="Normal"/>
|
|
85
|
+
<w:next w:val="Normal"/>
|
|
86
|
+
<w:qFormat/>
|
|
87
|
+
<w:pPr>
|
|
88
|
+
<w:keepNext/>
|
|
89
|
+
<w:spacing w:before="480" w:after="0"/>
|
|
90
|
+
<w:outlineLvl w:val="0"/>
|
|
91
|
+
</w:pPr>
|
|
92
|
+
<w:rPr>
|
|
93
|
+
<w:rFonts w:ascii="Calibri Light" w:hAnsi="Calibri Light" w:eastAsia="Calibri Light" w:cs="Calibri Light"/>
|
|
94
|
+
<w:b/>
|
|
95
|
+
<w:bCs/>
|
|
96
|
+
<w:sz w:val="32"/>
|
|
97
|
+
<w:szCs w:val="32"/>
|
|
98
|
+
<w:color w:val="2F5496"/>
|
|
99
|
+
</w:rPr>
|
|
100
|
+
</w:style>
|
|
101
|
+
|
|
102
|
+
<w:style w:type="paragraph" w:styleId="Heading2">
|
|
103
|
+
<w:name w:val="Heading 2"/>
|
|
104
|
+
<w:basedOn w:val="Normal"/>
|
|
105
|
+
<w:next w:val="Normal"/>
|
|
106
|
+
<w:qFormat/>
|
|
107
|
+
<w:pPr>
|
|
108
|
+
<w:keepNext/>
|
|
109
|
+
<w:spacing w:before="240" w:after="0"/>
|
|
110
|
+
<w:outlineLvl w:val="1"/>
|
|
111
|
+
</w:pPr>
|
|
112
|
+
<w:rPr>
|
|
113
|
+
<w:rFonts w:ascii="Calibri Light" w:hAnsi="Calibri Light" w:eastAsia="Calibri Light" w:cs="Calibri Light"/>
|
|
114
|
+
<w:b/>
|
|
115
|
+
<w:bCs/>
|
|
116
|
+
<w:sz w:val="28"/>
|
|
117
|
+
<w:szCs w:val="28"/>
|
|
118
|
+
<w:color w:val="2F5496"/>
|
|
119
|
+
</w:rPr>
|
|
120
|
+
</w:style>
|
|
121
|
+
|
|
122
|
+
<w:style w:type="paragraph" w:styleId="Heading3">
|
|
123
|
+
<w:name w:val="Heading 3"/>
|
|
124
|
+
<w:basedOn w:val="Normal"/>
|
|
125
|
+
<w:next w:val="Normal"/>
|
|
126
|
+
<w:qFormat/>
|
|
127
|
+
<w:pPr>
|
|
128
|
+
<w:keepNext/>
|
|
129
|
+
<w:spacing w:before="240" w:after="0"/>
|
|
130
|
+
<w:outlineLvl w:val="2"/>
|
|
131
|
+
</w:pPr>
|
|
132
|
+
<w:rPr>
|
|
133
|
+
<w:b/>
|
|
134
|
+
<w:bCs/>
|
|
135
|
+
<w:sz w:val="24"/>
|
|
136
|
+
<w:szCs w:val="24"/>
|
|
137
|
+
<w:color w:val="1F3763"/>
|
|
138
|
+
</w:rPr>
|
|
139
|
+
</w:style>
|
|
140
|
+
|
|
141
|
+
<w:style w:type="paragraph" w:styleId="Heading4">
|
|
142
|
+
<w:name w:val="Heading 4"/>
|
|
143
|
+
<w:basedOn w:val="Normal"/>
|
|
144
|
+
<w:next w:val="Normal"/>
|
|
145
|
+
<w:qFormat/>
|
|
146
|
+
<w:pPr>
|
|
147
|
+
<w:keepNext/>
|
|
148
|
+
<w:spacing w:before="240" w:after="0"/>
|
|
149
|
+
<w:outlineLvl w:val="3"/>
|
|
150
|
+
</w:pPr>
|
|
151
|
+
<w:rPr>
|
|
152
|
+
<w:b/>
|
|
153
|
+
<w:bCs/>
|
|
154
|
+
<w:sz w:val="22"/>
|
|
155
|
+
<w:szCs w:val="22"/>
|
|
156
|
+
<w:color w:val="1F3763"/>
|
|
157
|
+
</w:rPr>
|
|
158
|
+
</w:style>
|
|
159
|
+
|
|
160
|
+
<w:style w:type="paragraph" w:styleId="Heading5">
|
|
161
|
+
<w:name w:val="Heading 5"/>
|
|
162
|
+
<w:basedOn w:val="Normal"/>
|
|
163
|
+
<w:next w:val="Normal"/>
|
|
164
|
+
<w:qFormat/>
|
|
165
|
+
<w:pPr>
|
|
166
|
+
<w:keepNext/>
|
|
167
|
+
<w:spacing w:before="240" w:after="0"/>
|
|
168
|
+
<w:outlineLvl w:val="4"/>
|
|
169
|
+
</w:pPr>
|
|
170
|
+
<w:rPr>
|
|
171
|
+
<w:b/>
|
|
172
|
+
<w:bCs/>
|
|
173
|
+
<w:sz w:val="22"/>
|
|
174
|
+
<w:szCs w:val="22"/>
|
|
175
|
+
<w:color w:val="1F3763"/>
|
|
176
|
+
</w:rPr>
|
|
177
|
+
</w:style>
|
|
178
|
+
|
|
179
|
+
<w:style w:type="paragraph" w:styleId="Heading6">
|
|
180
|
+
<w:name w:val="Heading 6"/>
|
|
181
|
+
<w:basedOn w:val="Normal"/>
|
|
182
|
+
<w:next w:val="Normal"/>
|
|
183
|
+
<w:qFormat/>
|
|
184
|
+
<w:pPr>
|
|
185
|
+
<w:keepNext/>
|
|
186
|
+
<w:spacing w:before="240" w:after="0"/>
|
|
187
|
+
<w:outlineLvl w:val="5"/>
|
|
188
|
+
</w:pPr>
|
|
189
|
+
<w:rPr>
|
|
190
|
+
<w:b/>
|
|
191
|
+
<w:bCs/>
|
|
192
|
+
<w:sz w:val="22"/>
|
|
193
|
+
<w:szCs w:val="22"/>
|
|
194
|
+
<w:color w:val="1F3763"/>
|
|
195
|
+
</w:rPr>
|
|
196
|
+
</w:style>
|
|
197
|
+
|
|
198
|
+
<w:style w:type="paragraph" w:styleId="Heading7">
|
|
199
|
+
<w:name w:val="Heading 7"/>
|
|
200
|
+
<w:basedOn w:val="Normal"/>
|
|
201
|
+
<w:next w:val="Normal"/>
|
|
202
|
+
<w:qFormat/>
|
|
203
|
+
<w:pPr>
|
|
204
|
+
<w:keepNext/>
|
|
205
|
+
<w:spacing w:before="240" w:after="0"/>
|
|
206
|
+
<w:outlineLvl w:val="6"/>
|
|
207
|
+
</w:pPr>
|
|
208
|
+
<w:rPr>
|
|
209
|
+
<w:b/>
|
|
210
|
+
<w:bCs/>
|
|
211
|
+
<w:sz w:val="22"/>
|
|
212
|
+
<w:szCs w:val="22"/>
|
|
213
|
+
<w:color w:val="1F3763"/>
|
|
214
|
+
</w:rPr>
|
|
215
|
+
</w:style>
|
|
216
|
+
|
|
217
|
+
<w:style w:type="paragraph" w:styleId="Heading8">
|
|
218
|
+
<w:name w:val="Heading 8"/>
|
|
219
|
+
<w:basedOn w:val="Normal"/>
|
|
220
|
+
<w:next w:val="Normal"/>
|
|
221
|
+
<w:qFormat/>
|
|
222
|
+
<w:pPr>
|
|
223
|
+
<w:keepNext/>
|
|
224
|
+
<w:spacing w:before="240" w:after="0"/>
|
|
225
|
+
<w:outlineLvl w:val="7"/>
|
|
226
|
+
</w:pPr>
|
|
227
|
+
<w:rPr>
|
|
228
|
+
<w:b/>
|
|
229
|
+
<w:bCs/>
|
|
230
|
+
<w:sz w:val="22"/>
|
|
231
|
+
<w:szCs w:val="22"/>
|
|
232
|
+
<w:color w:val="1F3763"/>
|
|
233
|
+
</w:rPr>
|
|
234
|
+
</w:style>
|
|
235
|
+
|
|
236
|
+
<w:style w:type="paragraph" w:styleId="Heading9">
|
|
237
|
+
<w:name w:val="Heading 9"/>
|
|
238
|
+
<w:basedOn w:val="Normal"/>
|
|
239
|
+
<w:next w:val="Normal"/>
|
|
240
|
+
<w:qFormat/>
|
|
241
|
+
<w:pPr>
|
|
242
|
+
<w:keepNext/>
|
|
243
|
+
<w:spacing w:before="240" w:after="0"/>
|
|
244
|
+
<w:outlineLvl w:val="8"/>
|
|
245
|
+
</w:pPr>
|
|
246
|
+
<w:rPr>
|
|
247
|
+
<w:b/>
|
|
248
|
+
<w:bCs/>
|
|
249
|
+
<w:sz w:val="22"/>
|
|
250
|
+
<w:szCs w:val="22"/>
|
|
251
|
+
<w:color w:val="1F3763"/>
|
|
252
|
+
</w:rPr>
|
|
253
|
+
</w:style>
|
|
254
|
+
|
|
255
|
+
<!-- List Styles -->
|
|
256
|
+
<w:style w:type="paragraph" w:styleId="ListParagraph">
|
|
257
|
+
<w:name w:val="List Paragraph"/>
|
|
258
|
+
<w:basedOn w:val="Normal"/>
|
|
259
|
+
<w:qFormat/>
|
|
260
|
+
<w:pPr>
|
|
261
|
+
<w:ind w:left="720"/>
|
|
262
|
+
</w:pPr>
|
|
263
|
+
</w:style>
|
|
264
|
+
|
|
265
|
+
<!-- Table Styles -->
|
|
266
|
+
<w:style w:type="table" w:styleId="TableGrid">
|
|
267
|
+
<w:name w:val="Table Grid"/>
|
|
268
|
+
<w:basedOn w:val="NormalTable"/>
|
|
269
|
+
<w:qFormat/>
|
|
270
|
+
<w:tblPr>
|
|
271
|
+
<w:tblBorders>
|
|
272
|
+
<w:top w:val="single" w:sz="4" w:space="0" w:color="000000"/>
|
|
273
|
+
<w:left w:val="single" w:sz="4" w:space="0" w:color="000000"/>
|
|
274
|
+
<w:bottom w:val="single" w:sz="4" w:space="0" w:color="000000"/>
|
|
275
|
+
<w:right w:val="single" w:sz="4" w:space="0" w:color="000000"/>
|
|
276
|
+
<w:insideH w:val="single" w:sz="4" w:space="0" w:color="000000"/>
|
|
277
|
+
<w:insideV w:val="single" w:sz="4" w:space="0" w:color="000000"/>
|
|
278
|
+
</w:tblBorders>
|
|
279
|
+
</w:tblPr>
|
|
280
|
+
</w:style>
|
|
281
|
+
</w:styles>`);
|
|
282
|
+
// ─── word/document.xml ─────────────────────────────────────────────
|
|
283
|
+
zip.file('word/document.xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
284
|
+
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
|
285
|
+
<w:body>
|
|
286
|
+
</w:body>
|
|
287
|
+
</w:document>`);
|
|
288
|
+
// ─── word/settings.xml ────────────────────────────────────────────
|
|
289
|
+
zip.file('word/settings.xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
290
|
+
<w:settings xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
|
291
|
+
<w:defaultTabStop w:val="720"/>
|
|
292
|
+
<w:compat>
|
|
293
|
+
<w:compatSetting w:name="compatibilityMode" w:uri="http://schemas.microsoft.com/office/word" w:val="15"/>
|
|
294
|
+
</w:compat>
|
|
295
|
+
</w:settings>`);
|
|
296
|
+
// ─── word/webSettings.xml ────────────────────────────────────────
|
|
297
|
+
zip.file('word/webSettings.xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
298
|
+
<w:webSettings xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
|
299
|
+
<w:optimizeForBrowser/>
|
|
300
|
+
</w:webSettings>`);
|
|
301
|
+
// ─── word/fontTable.xml ───────────────────────────────────────────
|
|
302
|
+
zip.file('word/fontTable.xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
303
|
+
<w:fonts xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
|
304
|
+
<w:font w:name="Calibri">
|
|
305
|
+
<w:panose1 w:val="020F0502020204030204"/>
|
|
306
|
+
<w:charset w:val="00"/>
|
|
307
|
+
<w:family w:val="swiss"/>
|
|
308
|
+
<w:pitch w:val="variable"/>
|
|
309
|
+
<w:sig w:usb0="E00002FF" w:usb1="4000ACFF" w:usb2="00000001" w:usb3="00000000" w:csb0="0000019F" w:csb1="00000000"/>
|
|
310
|
+
</w:font>
|
|
311
|
+
<w:font w:name="Calibri Light">
|
|
312
|
+
<w:panose1 w:val="020F0302020204030204"/>
|
|
313
|
+
<w:charset w:val="00"/>
|
|
314
|
+
<w:family w:val="swiss"/>
|
|
315
|
+
<w:pitch w:val="variable"/>
|
|
316
|
+
<w:sig w:usb0="E00002FF" w:usb1="4000ACFF" w:usb2="00000001" w:usb3="00000000" w:csb0="0000019F" w:csb1="00000000"/>
|
|
317
|
+
</w:font>
|
|
318
|
+
<w:font w:name="Times New Roman">
|
|
319
|
+
<w:panose1 w:val="02020603050405020304"/>
|
|
320
|
+
<w:charset w:val="00"/>
|
|
321
|
+
<w:family w:val="roman"/>
|
|
322
|
+
<w:pitch w:val="variable"/>
|
|
323
|
+
<w:sig w:usb0="E0002AFF" w:usb1="C0007841" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>
|
|
324
|
+
</w:font>
|
|
325
|
+
</w:fonts>`);
|
|
326
|
+
// ─── Create media folder ───────────────────────────────────────────
|
|
327
|
+
zip.folder('word')?.folder('media');
|
|
328
|
+
return zip;
|
|
329
|
+
}
|
|
330
|
+
// ─── Content builders are now in ./builders/index.js ───────────────────
|
|
331
|
+
/**
|
|
332
|
+
* Create a new professional DOCX file from content structure.
|
|
333
|
+
*
|
|
334
|
+
* This function creates a complete DOCX structure from scratch with:
|
|
335
|
+
* - Professional styles (Normal, Heading1-9, ListParagraph, TableGrid)
|
|
336
|
+
* - Document defaults (Calibri font, proper spacing)
|
|
337
|
+
* - Complete ZIP structure
|
|
338
|
+
*
|
|
339
|
+
* Then builds content from the provided structure.
|
|
340
|
+
*/
|
|
341
|
+
export async function createDocxNew(outputPath, content) {
|
|
342
|
+
// 1. Create professional DOCX ZIP structure
|
|
343
|
+
const zip = createProfessionalDocxZip();
|
|
344
|
+
// 2. Parse empty document.xml
|
|
345
|
+
const xmlStr = zip.file('word/document.xml').asText();
|
|
346
|
+
const doc = parseXml(xmlStr);
|
|
347
|
+
const body = getBody(doc);
|
|
348
|
+
// 3. Build content from structure
|
|
349
|
+
let tableCount = 0;
|
|
350
|
+
for (const item of content.items) {
|
|
351
|
+
if (item.type === 'paragraph') {
|
|
352
|
+
const p = buildParagraph(doc, item);
|
|
353
|
+
body.appendChild(p);
|
|
354
|
+
}
|
|
355
|
+
else if (item.type === 'table') {
|
|
356
|
+
const tbl = buildTable(doc, item);
|
|
357
|
+
body.appendChild(tbl);
|
|
358
|
+
tableCount++;
|
|
359
|
+
}
|
|
360
|
+
else if (item.type === 'image') {
|
|
361
|
+
const imgP = await buildImageElement(doc, zip, item);
|
|
362
|
+
body.appendChild(imgP);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// 4. Serialize and save
|
|
366
|
+
const newXml = serializeXml(doc);
|
|
367
|
+
zip.file('word/document.xml', newXml);
|
|
368
|
+
const buf = zip.generate({ type: 'nodebuffer' });
|
|
369
|
+
await fs.writeFile(outputPath, buf);
|
|
370
|
+
// 5. Build stats
|
|
371
|
+
const bodyChildCount = content.items.length;
|
|
372
|
+
const stats = {
|
|
373
|
+
tablesBefore: 0,
|
|
374
|
+
tablesAfter: tableCount,
|
|
375
|
+
bodyChildrenBefore: 0,
|
|
376
|
+
bodyChildrenAfter: bodyChildCount,
|
|
377
|
+
bodySignatureBefore: '',
|
|
378
|
+
bodySignatureAfter: '', // Could compute if needed
|
|
379
|
+
};
|
|
380
|
+
return {
|
|
381
|
+
outputPath,
|
|
382
|
+
results: [], // No ops were applied
|
|
383
|
+
stats,
|
|
384
|
+
warnings: [],
|
|
385
|
+
};
|
|
386
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM utilities for DOCX XML manipulation.
|
|
3
|
+
*
|
|
4
|
+
* Single Responsibility: XML parsing, navigation, and minimal element
|
|
5
|
+
* mutation. No file I/O — every function works on in-memory DOM nodes.
|
|
6
|
+
*
|
|
7
|
+
* Uses @xmldom/xmldom for parsing and serialisation so that the
|
|
8
|
+
* document-order of nodes is always preserved.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseXml(xmlStr: string): Document;
|
|
11
|
+
export declare function serializeXml(doc: Document): string;
|
|
12
|
+
/**
|
|
13
|
+
* Convert any NodeList / HTMLCollection-like object into a real array.
|
|
14
|
+
*/
|
|
15
|
+
export declare function nodeListToArray<T extends Node = Node>(nl: NodeListOf<T> | NodeList | {
|
|
16
|
+
length: number;
|
|
17
|
+
item(index: number): T | null;
|
|
18
|
+
}): T[];
|
|
19
|
+
/** Return the single <w:body> element from a parsed document.xml DOM. */
|
|
20
|
+
export declare function getBody(doc: Document): Element;
|
|
21
|
+
/**
|
|
22
|
+
* Return ALL direct element children of w:body **in document order**.
|
|
23
|
+
* Includes w:p, w:tbl, w:sdt, w:sectPr, etc.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getBodyChildren(body: Element): Element[];
|
|
26
|
+
/**
|
|
27
|
+
* Build a compact signature string from the body children array.
|
|
28
|
+
* Maps each node's qualified name to a short local name:
|
|
29
|
+
* w:p → p, w:tbl → tbl, w:sdt → sdt, w:sectPr → sectPr, …
|
|
30
|
+
* Returns e.g. "p,tbl,p,p,sectPr".
|
|
31
|
+
*/
|
|
32
|
+
export declare function bodySignature(children: Element[]): string;
|
|
33
|
+
/** Concatenate text from every <w:t> descendant of a paragraph. */
|
|
34
|
+
export declare function getParagraphText(p: Element): string;
|
|
35
|
+
/** Read the style id from w:pPr/w:pStyle/@w:val, or null if absent. */
|
|
36
|
+
export declare function getParagraphStyle(p: Element): string | null;
|
|
37
|
+
/**
|
|
38
|
+
* Replace the text of a paragraph with minimal DOM changes.
|
|
39
|
+
* Sets the FIRST w:t to `text`, clears every subsequent w:t.
|
|
40
|
+
* Sets xml:space="preserve" so leading/trailing spaces survive.
|
|
41
|
+
* Does NOT recreate runs or remove paragraph properties.
|
|
42
|
+
*/
|
|
43
|
+
export declare function setParagraphTextMinimal(p: Element, text: string): void;
|
|
44
|
+
/**
|
|
45
|
+
* Ensure a <w:r> element has w:rPr/w:color[@w:val=hex].
|
|
46
|
+
* Creates w:rPr and w:color if they don't exist.
|
|
47
|
+
* Only touches the colour — leaves every other run property intact.
|
|
48
|
+
*/
|
|
49
|
+
export declare function ensureRunColor(run: Element, hex: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* Apply run-level colour to every <w:r> in a paragraph.
|
|
52
|
+
*/
|
|
53
|
+
export declare function colorParagraphRuns(p: Element, color: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* Apply bold / italic / color to every <w:r> in a paragraph.
|
|
56
|
+
* Preserves all existing w:rPr children; only modifies specified props.
|
|
57
|
+
*/
|
|
58
|
+
export declare function styleParagraphRuns(p: Element, style: {
|
|
59
|
+
color?: string;
|
|
60
|
+
bold?: boolean;
|
|
61
|
+
italic?: boolean;
|
|
62
|
+
}): void;
|
|
63
|
+
/** Count direct w:tbl children of body. */
|
|
64
|
+
export declare function countTables(children: Element[]): number;
|
|
65
|
+
/** Count <w:drawing> descendants (rough image count). */
|
|
66
|
+
export declare function countImages(body: Element): number;
|