@bendyline/squisq-formats 1.0.1 → 1.1.1
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 +23 -10
- package/dist/__tests__/container.test.d.ts +8 -0
- package/dist/__tests__/container.test.d.ts.map +1 -0
- package/dist/__tests__/container.test.js +147 -0
- package/dist/__tests__/container.test.js.map +1 -0
- package/dist/{chunk-MQHCXI56.js → chunk-6OVREALI.js} +31 -13
- package/dist/chunk-6OVREALI.js.map +1 -0
- package/dist/{chunk-ULLIPBEJ.js → chunk-743COJWQ.js} +6 -2
- package/dist/chunk-743COJWQ.js.map +1 -0
- package/dist/{chunk-KAK4V57E.js → chunk-BHHEDPRB.js} +16 -112
- package/dist/chunk-BHHEDPRB.js.map +1 -0
- package/dist/chunk-FIFCQN3W.js +630 -0
- package/dist/chunk-FIFCQN3W.js.map +1 -0
- package/dist/chunk-KJ4NS4DX.js +120 -0
- package/dist/chunk-KJ4NS4DX.js.map +1 -0
- package/dist/{chunk-TBPD5PCU.js → chunk-PP5N46YD.js} +33 -11
- package/dist/chunk-PP5N46YD.js.map +1 -0
- package/dist/container/index.d.ts +36 -0
- package/dist/container/index.d.ts.map +1 -0
- package/dist/container/index.js +74 -0
- package/dist/container/index.js.map +1 -0
- package/dist/docx/export.d.ts +6 -0
- package/dist/docx/export.d.ts.map +1 -1
- package/dist/docx/export.js +24 -7
- package/dist/docx/export.js.map +1 -1
- package/dist/html/htmlTemplate.d.ts +6 -0
- package/dist/html/htmlTemplate.d.ts.map +1 -1
- package/dist/html/htmlTemplate.js +5 -1
- package/dist/html/htmlTemplate.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/ooxml/index.d.ts +1 -1
- package/dist/ooxml/index.d.ts.map +1 -1
- package/dist/ooxml/index.js +1 -1
- package/dist/ooxml/index.js.map +1 -1
- package/dist/ooxml/namespaces.d.ts +10 -0
- package/dist/ooxml/namespaces.d.ts.map +1 -1
- package/dist/ooxml/namespaces.js +10 -0
- package/dist/ooxml/namespaces.js.map +1 -1
- package/dist/pdf/export.d.ts +6 -0
- package/dist/pdf/export.d.ts.map +1 -1
- package/dist/pdf/export.js +37 -9
- package/dist/pdf/export.js.map +1 -1
- package/dist/pptx/export.d.ts +75 -0
- package/dist/pptx/export.d.ts.map +1 -0
- package/dist/pptx/export.js +722 -0
- package/dist/pptx/export.js.map +1 -0
- package/dist/pptx/index.d.ts +12 -27
- package/dist/pptx/index.d.ts.map +1 -1
- package/dist/pptx/index.js +12 -22
- package/dist/pptx/index.js.map +1 -1
- package/dist/pptx/styles.d.ts +54 -0
- package/dist/pptx/styles.d.ts.map +1 -0
- package/dist/pptx/styles.js +73 -0
- package/dist/pptx/styles.js.map +1 -0
- package/dist/pptx/templates.d.ts +24 -0
- package/dist/pptx/templates.d.ts.map +1 -0
- package/dist/pptx/templates.js +158 -0
- package/dist/pptx/templates.js.map +1 -0
- package/package.json +7 -2
- package/src/__tests__/container.test.ts +189 -0
- package/src/container/index.ts +89 -0
- package/src/docx/export.ts +36 -8
- package/src/html/htmlTemplate.ts +13 -0
- package/src/index.ts +2 -2
- package/src/ooxml/index.ts +7 -0
- package/src/ooxml/namespaces.ts +23 -0
- package/src/pdf/export.ts +57 -9
- package/src/pptx/export.ts +1041 -0
- package/src/pptx/index.ts +15 -37
- package/src/pptx/styles.ts +96 -0
- package/src/pptx/templates.ts +187 -0
- package/dist/chunk-532L4D5D.js +0 -21
- package/dist/chunk-532L4D5D.js.map +0 -1
- package/dist/chunk-KAK4V57E.js.map +0 -1
- package/dist/chunk-MQHCXI56.js.map +0 -1
- package/dist/chunk-TBPD5PCU.js.map +0 -1
- package/dist/chunk-ULLIPBEJ.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @bendyline/squisq-formats
|
|
2
2
|
|
|
3
|
-
Document format converters for Squisq. Import and export between Squisq's Markdown-based document model and common file formats — DOCX, PDF, and HTML. All converters run entirely in the browser with no server or native binaries required.
|
|
3
|
+
Document format converters for Squisq. Import and export between Squisq's Markdown-based document model and common file formats — DOCX, PPTX, PDF, and HTML. All converters run entirely in the browser with no server or native binaries required.
|
|
4
4
|
|
|
5
5
|
Part of the [Squisq](https://github.com/bendyline/squisq) monorepo.
|
|
6
6
|
|
|
@@ -15,13 +15,15 @@ npm install @bendyline/squisq-formats @bendyline/squisq
|
|
|
15
15
|
|
|
16
16
|
## Supported Formats
|
|
17
17
|
|
|
18
|
-
| Format | Import | Export | Subpath |
|
|
19
|
-
| --------------------- | ------- | ------- | -------------------------------- |
|
|
20
|
-
| **DOCX** (Word) | ✅ | ✅ | `@bendyline/squisq-formats/docx` |
|
|
21
|
-
| **PDF** | ✅ | ✅ | `@bendyline/squisq-formats/pdf` |
|
|
22
|
-
| **HTML** | — | ✅ | `@bendyline/squisq-formats/html` |
|
|
23
|
-
| **PPTX** (PowerPoint) | planned |
|
|
24
|
-
| **XLSX** (Excel) | planned | planned | `@bendyline/squisq-formats/xlsx` |
|
|
18
|
+
| Format | Import | Export | Theme | Subpath |
|
|
19
|
+
| --------------------- | ------- | ------- | ----- | -------------------------------- |
|
|
20
|
+
| **DOCX** (Word) | ✅ | ✅ | ✅ | `@bendyline/squisq-formats/docx` |
|
|
21
|
+
| **PDF** | ✅ | ✅ | ✅ | `@bendyline/squisq-formats/pdf` |
|
|
22
|
+
| **HTML** | — | ✅ | ✅ | `@bendyline/squisq-formats/html` |
|
|
23
|
+
| **PPTX** (PowerPoint) | planned | ✅ | ✅ | `@bendyline/squisq-formats/pptx` |
|
|
24
|
+
| **XLSX** (Excel) | planned | planned | — | `@bendyline/squisq-formats/xlsx` |
|
|
25
|
+
|
|
26
|
+
All export formats accept an optional `themeId` to apply Squisq theme colors and typography.
|
|
25
27
|
|
|
26
28
|
## Quick Examples
|
|
27
29
|
|
|
@@ -68,6 +70,16 @@ const html = docToHtml(doc);
|
|
|
68
70
|
const zipBytes = await docToHtmlZip(doc);
|
|
69
71
|
```
|
|
70
72
|
|
|
73
|
+
### PPTX
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { markdownDocToPptx } from '@bendyline/squisq-formats/pptx';
|
|
77
|
+
|
|
78
|
+
// Export: MarkdownDocument → PPTX (ArrayBuffer)
|
|
79
|
+
// Each H1/H2 heading starts a new slide
|
|
80
|
+
const pptxBytes = await markdownDocToPptx(markdownDoc);
|
|
81
|
+
```
|
|
82
|
+
|
|
71
83
|
### Doc-level Convenience Functions
|
|
72
84
|
|
|
73
85
|
Each format also exports `Doc`-level wrappers that handle the Markdown↔Doc conversion internally:
|
|
@@ -75,6 +87,7 @@ Each format also exports `Doc`-level wrappers that handle the Markdown↔Doc con
|
|
|
75
87
|
```ts
|
|
76
88
|
import { docToDocx, docxToDoc } from '@bendyline/squisq-formats/docx';
|
|
77
89
|
import { docToPdf, pdfToDoc } from '@bendyline/squisq-formats/pdf';
|
|
90
|
+
import { docToPptx } from '@bendyline/squisq-formats/pptx';
|
|
78
91
|
```
|
|
79
92
|
|
|
80
93
|
## Subpath Exports
|
|
@@ -85,12 +98,12 @@ import { docToPdf, pdfToDoc } from '@bendyline/squisq-formats/pdf';
|
|
|
85
98
|
| `@bendyline/squisq-formats/pdf` | PDF import/export + worker config |
|
|
86
99
|
| `@bendyline/squisq-formats/html` | HTML export |
|
|
87
100
|
| `@bendyline/squisq-formats/ooxml` | Shared OOXML infrastructure (ZIP reader/writer, XML utilities) |
|
|
88
|
-
| `@bendyline/squisq-formats/pptx` | PPTX
|
|
101
|
+
| `@bendyline/squisq-formats/pptx` | PPTX export (import planned) |
|
|
89
102
|
| `@bendyline/squisq-formats/xlsx` | XLSX stubs (not yet implemented) |
|
|
90
103
|
|
|
91
104
|
## Architecture
|
|
92
105
|
|
|
93
|
-
All converters use Squisq's `MarkdownDocument` AST as the pivot format. Importing a file parses it into a `MarkdownDocument`; exporting serializes from one. The OOXML subpath provides shared infrastructure for reading and writing Office Open XML packages (used by DOCX, and eventually
|
|
106
|
+
All converters use Squisq's `MarkdownDocument` AST as the pivot format. Importing a file parses it into a `MarkdownDocument`; exporting serializes from one. The OOXML subpath provides shared infrastructure for reading and writing Office Open XML packages (used by DOCX and PPTX, and eventually XLSX).
|
|
94
107
|
|
|
95
108
|
## Related Packages
|
|
96
109
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for container ZIP serialization: containerToZip, zipToContainer.
|
|
3
|
+
*
|
|
4
|
+
* Verifies round-trip fidelity: write files to a container, serialize to ZIP,
|
|
5
|
+
* deserialize back, and confirm all files are intact.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=container.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/container.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for container ZIP serialization: containerToZip, zipToContainer.
|
|
3
|
+
*
|
|
4
|
+
* Verifies round-trip fidelity: write files to a container, serialize to ZIP,
|
|
5
|
+
* deserialize back, and confirm all files are intact.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, expect } from 'vitest';
|
|
8
|
+
import JSZip from 'jszip';
|
|
9
|
+
import { MemoryContentContainer } from '@bendyline/squisq/storage';
|
|
10
|
+
import { containerToZip, zipToContainer } from '../container/index';
|
|
11
|
+
// ============================================
|
|
12
|
+
// Helpers
|
|
13
|
+
// ============================================
|
|
14
|
+
/** Helper to read a Blob as ArrayBuffer (works in jsdom) */
|
|
15
|
+
async function blobToArrayBuffer(blob) {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const reader = new FileReader();
|
|
18
|
+
reader.onload = () => resolve(reader.result);
|
|
19
|
+
reader.onerror = () => reject(reader.error);
|
|
20
|
+
reader.readAsArrayBuffer(blob);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// ============================================
|
|
24
|
+
// containerToZip
|
|
25
|
+
// ============================================
|
|
26
|
+
describe('containerToZip', () => {
|
|
27
|
+
it('creates a valid ZIP from an empty container', async () => {
|
|
28
|
+
const container = new MemoryContentContainer();
|
|
29
|
+
const blob = await containerToZip(container);
|
|
30
|
+
expect(blob).toBeInstanceOf(Blob);
|
|
31
|
+
expect(blob.size).toBeGreaterThan(0);
|
|
32
|
+
// Should be parseable as a ZIP with no files
|
|
33
|
+
const zip = await JSZip.loadAsync(await blobToArrayBuffer(blob));
|
|
34
|
+
expect(Object.keys(zip.files)).toHaveLength(0);
|
|
35
|
+
});
|
|
36
|
+
it('includes all files from the container', async () => {
|
|
37
|
+
const container = new MemoryContentContainer();
|
|
38
|
+
await container.writeDocument('# Hello World');
|
|
39
|
+
await container.writeFile('images/hero.jpg', new Uint8Array([0xff, 0xd8, 0xff]), 'image/jpeg');
|
|
40
|
+
await container.writeFile('timing.json', new TextEncoder().encode('{"duration":10}'));
|
|
41
|
+
const blob = await containerToZip(container);
|
|
42
|
+
const zip = await JSZip.loadAsync(await blobToArrayBuffer(blob));
|
|
43
|
+
const filenames = Object.keys(zip.files)
|
|
44
|
+
.filter((f) => !zip.files[f].dir)
|
|
45
|
+
.sort();
|
|
46
|
+
expect(filenames).toEqual(['images/hero.jpg', 'index.md', 'timing.json']);
|
|
47
|
+
});
|
|
48
|
+
it('preserves file content', async () => {
|
|
49
|
+
const container = new MemoryContentContainer();
|
|
50
|
+
const markdown = '# Test Document\n\nSome content.';
|
|
51
|
+
await container.writeDocument(markdown);
|
|
52
|
+
const blob = await containerToZip(container);
|
|
53
|
+
const zip = await JSZip.loadAsync(await blobToArrayBuffer(blob));
|
|
54
|
+
const content = await zip.file('index.md').async('string');
|
|
55
|
+
expect(content).toBe(markdown);
|
|
56
|
+
});
|
|
57
|
+
it('preserves binary content', async () => {
|
|
58
|
+
const container = new MemoryContentContainer();
|
|
59
|
+
const binaryData = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
60
|
+
await container.writeFile('image.png', binaryData, 'image/png');
|
|
61
|
+
const blob = await containerToZip(container);
|
|
62
|
+
const zip = await JSZip.loadAsync(await blobToArrayBuffer(blob));
|
|
63
|
+
const data = await zip.file('image.png').async('uint8array');
|
|
64
|
+
expect(data).toEqual(binaryData);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
// ============================================
|
|
68
|
+
// zipToContainer
|
|
69
|
+
// ============================================
|
|
70
|
+
describe('zipToContainer', () => {
|
|
71
|
+
it('loads files from a ZIP', async () => {
|
|
72
|
+
const zip = new JSZip();
|
|
73
|
+
zip.file('index.md', '# Hello');
|
|
74
|
+
zip.file('images/photo.jpg', new Uint8Array([0xff, 0xd8]));
|
|
75
|
+
const zipBlob = await zip.generateAsync({ type: 'blob' });
|
|
76
|
+
const container = await zipToContainer(zipBlob);
|
|
77
|
+
const entries = await container.listFiles();
|
|
78
|
+
expect(entries.map((e) => e.path).sort()).toEqual(['images/photo.jpg', 'index.md']);
|
|
79
|
+
});
|
|
80
|
+
it('preserves text content', async () => {
|
|
81
|
+
const zip = new JSZip();
|
|
82
|
+
zip.file('index.md', '# My Document\n\nParagraph.');
|
|
83
|
+
const zipBlob = await zip.generateAsync({ type: 'blob' });
|
|
84
|
+
const container = await zipToContainer(zipBlob);
|
|
85
|
+
expect(await container.readDocument()).toBe('# My Document\n\nParagraph.');
|
|
86
|
+
});
|
|
87
|
+
it('preserves binary content', async () => {
|
|
88
|
+
const original = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
|
|
89
|
+
const zip = new JSZip();
|
|
90
|
+
zip.file('data.bin', original);
|
|
91
|
+
const zipBlob = await zip.generateAsync({ type: 'blob' });
|
|
92
|
+
const container = await zipToContainer(zipBlob);
|
|
93
|
+
const data = await container.readFile('data.bin');
|
|
94
|
+
expect(new Uint8Array(data)).toEqual(original);
|
|
95
|
+
});
|
|
96
|
+
it('skips directory entries', async () => {
|
|
97
|
+
const zip = new JSZip();
|
|
98
|
+
zip.folder('images');
|
|
99
|
+
zip.file('images/photo.jpg', new Uint8Array([0xff]));
|
|
100
|
+
const zipBlob = await zip.generateAsync({ type: 'blob' });
|
|
101
|
+
const container = await zipToContainer(zipBlob);
|
|
102
|
+
const entries = await container.listFiles();
|
|
103
|
+
// Only the file, not the directory
|
|
104
|
+
expect(entries).toHaveLength(1);
|
|
105
|
+
expect(entries[0].path).toBe('images/photo.jpg');
|
|
106
|
+
});
|
|
107
|
+
it('works with ArrayBuffer input', async () => {
|
|
108
|
+
const zip = new JSZip();
|
|
109
|
+
zip.file('readme.md', '# Read me');
|
|
110
|
+
const ab = await zip.generateAsync({ type: 'arraybuffer' });
|
|
111
|
+
const container = await zipToContainer(ab);
|
|
112
|
+
expect(await container.readDocument()).toBe('# Read me');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
// ============================================
|
|
116
|
+
// Round-trip
|
|
117
|
+
// ============================================
|
|
118
|
+
describe('containerToZip / zipToContainer round-trip', () => {
|
|
119
|
+
it('round-trips a container with markdown and media', async () => {
|
|
120
|
+
// Create original container
|
|
121
|
+
const original = new MemoryContentContainer();
|
|
122
|
+
const markdown = '# Round Trip Test\n\n\n\nSome text.';
|
|
123
|
+
await original.writeDocument(markdown);
|
|
124
|
+
await original.writeFile('images/hero.jpg', new Uint8Array([0xff, 0xd8, 0xff, 0xe0]), 'image/jpeg');
|
|
125
|
+
await original.writeFile('audio/narration.mp3', new Uint8Array([0x49, 0x44, 0x33]), 'audio/mpeg');
|
|
126
|
+
await original.writeFile('timing.json', new TextEncoder().encode('{"segments":[]}'));
|
|
127
|
+
// Serialize to ZIP
|
|
128
|
+
const zipBlob = await containerToZip(original);
|
|
129
|
+
// Deserialize back
|
|
130
|
+
const restored = await zipToContainer(zipBlob);
|
|
131
|
+
// Verify document
|
|
132
|
+
expect(await restored.readDocument()).toBe(markdown);
|
|
133
|
+
expect(await restored.getDocumentPath()).toBe('index.md');
|
|
134
|
+
// Verify all files present
|
|
135
|
+
const entries = (await restored.listFiles()).map((e) => e.path).sort();
|
|
136
|
+
expect(entries).toEqual(['audio/narration.mp3', 'images/hero.jpg', 'index.md', 'timing.json']);
|
|
137
|
+
// Verify binary content
|
|
138
|
+
const heroData = new Uint8Array((await restored.readFile('images/hero.jpg')));
|
|
139
|
+
expect(heroData).toEqual(new Uint8Array([0xff, 0xd8, 0xff, 0xe0]));
|
|
140
|
+
const audioData = new Uint8Array((await restored.readFile('audio/narration.mp3')));
|
|
141
|
+
expect(audioData).toEqual(new Uint8Array([0x49, 0x44, 0x33]));
|
|
142
|
+
// Verify JSON sidecar
|
|
143
|
+
const timingData = new TextDecoder().decode((await restored.readFile('timing.json')));
|
|
144
|
+
expect(timingData).toBe('{"segments":[]}');
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
//# sourceMappingURL=container.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container.test.js","sourceRoot":"","sources":["../../src/__tests__/container.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getPartRelationships,
|
|
3
|
+
getPartXml,
|
|
4
|
+
openPackage
|
|
5
|
+
} from "./chunk-KJ4NS4DX.js";
|
|
1
6
|
import {
|
|
2
7
|
CONTENT_TYPE_DOCX_DOCUMENT,
|
|
3
8
|
CONTENT_TYPE_DOCX_FONT_TABLE,
|
|
@@ -17,13 +22,11 @@ import {
|
|
|
17
22
|
REL_STYLES,
|
|
18
23
|
createPackage,
|
|
19
24
|
escapeXml,
|
|
20
|
-
getPartRelationships,
|
|
21
|
-
getPartXml,
|
|
22
|
-
openPackage,
|
|
23
25
|
xmlDeclaration
|
|
24
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-BHHEDPRB.js";
|
|
25
27
|
|
|
26
28
|
// src/docx/export.ts
|
|
29
|
+
import { resolveTheme } from "@bendyline/squisq/schemas";
|
|
27
30
|
import { docToMarkdown } from "@bendyline/squisq/doc";
|
|
28
31
|
|
|
29
32
|
// src/docx/styles.ts
|
|
@@ -110,8 +113,22 @@ var ExportContext = class {
|
|
|
110
113
|
this.hasLists = false;
|
|
111
114
|
/** Whether we have any footnotes */
|
|
112
115
|
this.hasFootnotes = false;
|
|
113
|
-
|
|
116
|
+
let themeFont;
|
|
117
|
+
let themeTitleFont;
|
|
118
|
+
let themeHeadingColor;
|
|
119
|
+
if (options.themeId) {
|
|
120
|
+
const theme = resolveTheme(options.themeId);
|
|
121
|
+
themeFont = theme.typography?.bodyFontFamily;
|
|
122
|
+
themeTitleFont = theme.typography?.titleFontFamily;
|
|
123
|
+
if (theme.colors?.primary) {
|
|
124
|
+
const c = theme.colors.primary;
|
|
125
|
+
themeHeadingColor = c.startsWith("#") ? c.slice(1) : c;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
this.font = options.defaultFont ?? themeFont ?? DEFAULT_FONT;
|
|
129
|
+
this.headingFont = themeTitleFont ?? this.font;
|
|
114
130
|
this.fontSize = options.defaultFontSize ? options.defaultFontSize * 2 : DEFAULT_FONT_SIZE_HALF_POINTS;
|
|
131
|
+
this.headingColor = themeHeadingColor;
|
|
115
132
|
}
|
|
116
133
|
/** Allocate a new relationship ID */
|
|
117
134
|
allocRelId() {
|
|
@@ -382,7 +399,7 @@ async function buildDocxPackage(bodyXml, ctx, options) {
|
|
|
382
399
|
const footnotesRelId = `rId${relCounter++}`;
|
|
383
400
|
const documentXml = buildDocumentXml(bodyXml);
|
|
384
401
|
pkg.addPart("word/document.xml", documentXml, CONTENT_TYPE_DOCX_DOCUMENT);
|
|
385
|
-
const stylesXml = buildStylesXml(options);
|
|
402
|
+
const stylesXml = buildStylesXml(options, ctx);
|
|
386
403
|
pkg.addPart("word/styles.xml", stylesXml, CONTENT_TYPE_DOCX_STYLES);
|
|
387
404
|
const settingsXml = buildSettingsXml();
|
|
388
405
|
pkg.addPart("word/settings.xml", settingsXml, CONTENT_TYPE_DOCX_SETTINGS);
|
|
@@ -455,19 +472,20 @@ async function buildDocxPackage(bodyXml, ctx, options) {
|
|
|
455
472
|
function buildDocumentXml(bodyXml) {
|
|
456
473
|
return xmlDeclaration() + `<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="${NS_MC}" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="${NS_R}" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="${NS_WML}" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"><w:body>` + bodyXml + `<w:sectPr><w:pgSz w:w="12240" w:h="15840"/><w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720" w:footer="720" w:gutter="0"/><w:cols w:space="720"/></w:sectPr></w:body></w:document>`;
|
|
457
474
|
}
|
|
458
|
-
function buildStylesXml(options) {
|
|
459
|
-
const font =
|
|
460
|
-
const headingFont =
|
|
475
|
+
function buildStylesXml(options, ctx) {
|
|
476
|
+
const font = ctx.font;
|
|
477
|
+
const headingFont = ctx.headingFont;
|
|
461
478
|
return xmlDeclaration() + `<w:styles xmlns:w="${NS_WML}"><w:docDefaults><w:rPrDefault><w:rPr><w:rFonts w:ascii="${escapeXml(font)}" w:hAnsi="${escapeXml(font)}" w:eastAsia="${escapeXml(font)}" w:cs="${escapeXml(font)}"/><w:sz w:val="${DEFAULT_FONT_SIZE_HALF_POINTS}"/><w:szCs w:val="${DEFAULT_FONT_SIZE_HALF_POINTS}"/></w:rPr></w:rPrDefault><w:pPrDefault/></w:docDefaults><w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/><w:qFormat/></w:style>` + // Heading styles
|
|
462
|
-
buildHeadingStyles(headingFont) + // Quote style
|
|
479
|
+
buildHeadingStyles(headingFont, ctx.headingColor) + // Quote style
|
|
463
480
|
`<w:style w:type="paragraph" w:styleId="Quote"><w:name w:val="Quote"/><w:basedOn w:val="Normal"/><w:pPr><w:ind w:left="720"/></w:pPr><w:rPr><w:i/><w:color w:val="404040"/></w:rPr></w:style><w:style w:type="paragraph" w:styleId="Code"><w:name w:val="Code"/><w:basedOn w:val="Normal"/><w:rPr><w:rFonts w:ascii="${DEFAULT_CODE_FONT}" w:hAnsi="${DEFAULT_CODE_FONT}"/><w:sz w:val="${DEFAULT_CODE_FONT_SIZE}"/></w:rPr></w:style><w:style w:type="paragraph" w:styleId="ListParagraph"><w:name w:val="List Paragraph"/><w:basedOn w:val="Normal"/><w:pPr><w:ind w:left="720"/></w:pPr></w:style><w:style w:type="character" w:styleId="Hyperlink"><w:name w:val="Hyperlink"/><w:rPr><w:color w:val="${HYPERLINK_COLOR}"/><w:u w:val="single"/></w:rPr></w:style><w:style w:type="character" w:styleId="FootnoteReference"><w:name w:val="footnote reference"/><w:rPr><w:vertAlign w:val="superscript"/></w:rPr></w:style><w:style w:type="table" w:styleId="TableGrid"><w:name w:val="Table Grid"/><w:tblPr><w:tblBorders><w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:left w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:insideH w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:insideV w:val="single" w:sz="4" w:space="0" w:color="auto"/></w:tblBorders></w:tblPr></w:style></w:styles>`;
|
|
464
481
|
}
|
|
465
|
-
function buildHeadingStyles(headingFont) {
|
|
482
|
+
function buildHeadingStyles(headingFont, headingColor) {
|
|
466
483
|
let result = "";
|
|
467
484
|
for (let depth = 1; depth <= 6; depth++) {
|
|
468
485
|
const styleId = DEPTH_TO_STYLE_ID[depth];
|
|
469
486
|
const fontSize = HEADING_FONT_SIZES[depth] ?? 22;
|
|
470
|
-
|
|
487
|
+
const colorXml = headingColor ? `<w:color w:val="${headingColor}"/>` : "";
|
|
488
|
+
result += `<w:style w:type="paragraph" w:styleId="${styleId}"><w:name w:val="heading ${depth}"/><w:basedOn w:val="Normal"/><w:next w:val="Normal"/><w:qFormat/><w:pPr><w:outlineLvl w:val="${depth - 1}"/><w:spacing w:before="240" w:after="60"/></w:pPr><w:rPr><w:rFonts w:ascii="${escapeXml(headingFont)}" w:hAnsi="${escapeXml(headingFont)}"/><w:b/>` + colorXml + `<w:sz w:val="${fontSize}"/><w:szCs w:val="${fontSize}"/></w:rPr></w:style>`;
|
|
471
489
|
}
|
|
472
490
|
return result;
|
|
473
491
|
}
|
|
@@ -1032,4 +1050,4 @@ export {
|
|
|
1032
1050
|
docxToMarkdownDoc,
|
|
1033
1051
|
docxToDoc
|
|
1034
1052
|
};
|
|
1035
|
-
//# sourceMappingURL=chunk-
|
|
1053
|
+
//# sourceMappingURL=chunk-6OVREALI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/docx/export.ts","../src/docx/styles.ts","../src/docx/import.ts"],"sourcesContent":["/**\n * DOCX Export\n *\n * Converts a squisq MarkdownDocument (or Doc) into a .docx file\n * by generating WordprocessingML XML and assembling the OOXML package.\n *\n * No third-party docx library — all XML is generated directly using\n * the shared ooxml/ infrastructure of this package.\n *\n * @example\n * ```ts\n * import { parseMarkdown } from '@bendyline/squisq/markdown';\n * import { markdownDocToDocx } from '@bendyline/squisq-formats/docx';\n *\n * const md = parseMarkdown('# Hello\\n\\nWorld **bold** text');\n * const blob = await markdownDocToDocx(md);\n * ```\n */\n\nimport type { Doc, Theme } from '@bendyline/squisq/schemas';\nimport { resolveTheme } from '@bendyline/squisq/schemas';\nimport { docToMarkdown } from '@bendyline/squisq/doc';\nimport type {\n MarkdownDocument,\n MarkdownBlockNode,\n MarkdownInlineNode,\n MarkdownHeading,\n MarkdownParagraph,\n MarkdownBlockquote,\n MarkdownList,\n MarkdownListItem,\n MarkdownCodeBlock,\n MarkdownTable,\n MarkdownTableRow,\n MarkdownTableCell,\n MarkdownHtmlBlock,\n MarkdownMathBlock,\n MarkdownFootnoteDefinition,\n MarkdownLink,\n MarkdownImage,\n MarkdownFootnoteReference,\n} from '@bendyline/squisq/markdown';\n\nimport { createPackage } from '../ooxml/writer.js';\nimport { xmlDeclaration, escapeXml } from '../ooxml/xmlUtils.js';\nimport {\n NS_WML,\n NS_R,\n NS_MC,\n REL_OFFICE_DOCUMENT,\n REL_STYLES,\n REL_NUMBERING,\n REL_SETTINGS,\n REL_FONT_TABLE,\n REL_HYPERLINK,\n REL_FOOTNOTES,\n CONTENT_TYPE_DOCX_DOCUMENT,\n CONTENT_TYPE_DOCX_STYLES,\n CONTENT_TYPE_DOCX_NUMBERING,\n CONTENT_TYPE_DOCX_SETTINGS,\n CONTENT_TYPE_DOCX_FONT_TABLE,\n CONTENT_TYPE_DOCX_FOOTNOTES,\n} from '../ooxml/namespaces.js';\nimport {\n DEPTH_TO_STYLE_ID,\n HEADING_FONT_SIZES,\n DEFAULT_FONT,\n DEFAULT_HEADING_FONT,\n DEFAULT_FONT_SIZE_HALF_POINTS,\n DEFAULT_CODE_FONT,\n DEFAULT_CODE_FONT_SIZE,\n HYPERLINK_COLOR,\n pointsToTwips,\n} from './styles.js';\n\n// ============================================\n// Public API\n// ============================================\n\n/**\n * Options for DOCX export.\n */\nexport interface DocxExportOptions {\n /** Document title (appears in core properties) */\n title?: string;\n /** Document author */\n author?: string;\n /** Document description */\n description?: string;\n /** Default body font family. Default: \"Calibri\" */\n defaultFont?: string;\n /** Default body font size in points. Default: 11 */\n defaultFontSize?: number;\n /**\n * Squisq theme ID to apply (e.g., 'documentary', 'cinematic').\n * When set, overrides fonts with the theme's typography and applies\n * the theme's primary color to headings.\n */\n themeId?: string;\n}\n\n/**\n * Convert a MarkdownDocument to a .docx Blob.\n *\n * @param doc - The parsed markdown document\n * @param options - Export options\n * @returns An ArrayBuffer containing the .docx file\n */\nexport async function markdownDocToDocx(\n doc: MarkdownDocument,\n options: DocxExportOptions = {},\n): Promise<ArrayBuffer> {\n const ctx = new ExportContext(options);\n const bodyXml = convertBlocks(doc.children, ctx);\n return buildDocxPackage(bodyXml, ctx, options);\n}\n\n/**\n * Convert a squisq Doc to a .docx Blob.\n *\n * Convenience wrapper that converts Doc → MarkdownDocument → DOCX.\n *\n * @param doc - The squisq Doc\n * @param options - Export options\n * @returns An ArrayBuffer containing the .docx file\n */\nexport async function docToDocx(doc: Doc, options: DocxExportOptions = {}): Promise<ArrayBuffer> {\n const markdownDoc = docToMarkdown(doc);\n return markdownDocToDocx(markdownDoc, options);\n}\n\n// ============================================\n// Export Context\n// ============================================\n\n/**\n * Tracks state during export: relationship IDs, numbering definitions,\n * footnote bodies, and embedded images.\n */\nclass ExportContext {\n private nextRelId = 1;\n private nextNumId = 1;\n private nextFootnoteId = 1; // 0 is separator, start user footnotes at 1\n\n /** Relationships for word/_rels/document.xml.rels */\n readonly relationships: Array<{\n id: string;\n type: string;\n target: string;\n targetMode?: 'External';\n }> = [];\n\n /** Numbering definitions (abstract + num) */\n readonly numberingDefs: NumberingDef[] = [];\n\n /** Footnote XML bodies (keyed by footnote id) */\n readonly footnotes = new Map<number, string>();\n\n /** Footnote identifier → numeric id mapping */\n readonly footnoteIdMap = new Map<string, number>();\n\n /** Embedded images: rId → { path, data, contentType } */\n readonly images: Array<{\n relId: string;\n path: string;\n data: ArrayBuffer | Uint8Array;\n contentType: string;\n }> = [];\n\n /** Whether we have any lists (determines if numbering.xml is needed) */\n hasLists = false;\n\n /** Whether we have any footnotes */\n hasFootnotes = false;\n\n readonly font: string;\n readonly headingFont: string;\n readonly fontSize: number;\n /** Heading text color (hex without #), or undefined for default */\n readonly headingColor: string | undefined;\n\n constructor(options: DocxExportOptions) {\n let themeFont: string | undefined;\n let themeTitleFont: string | undefined;\n let themeHeadingColor: string | undefined;\n\n if (options.themeId) {\n const theme: Theme = resolveTheme(options.themeId);\n themeFont = theme.typography?.bodyFontFamily;\n themeTitleFont = theme.typography?.titleFontFamily;\n if (theme.colors?.primary) {\n const c = theme.colors.primary;\n themeHeadingColor = c.startsWith('#') ? c.slice(1) : c;\n }\n }\n\n this.font = options.defaultFont ?? themeFont ?? DEFAULT_FONT;\n this.headingFont = themeTitleFont ?? this.font;\n this.fontSize = options.defaultFontSize\n ? options.defaultFontSize * 2\n : DEFAULT_FONT_SIZE_HALF_POINTS;\n this.headingColor = themeHeadingColor;\n }\n\n /** Allocate a new relationship ID */\n allocRelId(): string {\n return `rId${this.nextRelId++}`;\n }\n\n /** Add a hyperlink relationship and return the rId */\n addHyperlink(url: string): string {\n const id = this.allocRelId();\n this.relationships.push({\n id,\n type: REL_HYPERLINK,\n target: url,\n targetMode: 'External',\n });\n return id;\n }\n\n /** Allocate a numbering definition for a list */\n allocNumbering(ordered: boolean): number {\n const numId = this.nextNumId++;\n this.numberingDefs.push({ numId, ordered });\n this.hasLists = true;\n return numId;\n }\n\n /** Register or look up a footnote by its string identifier */\n getFootnoteId(identifier: string): number {\n let id = this.footnoteIdMap.get(identifier);\n if (id === undefined) {\n id = this.nextFootnoteId++;\n this.footnoteIdMap.set(identifier, id);\n this.hasFootnotes = true;\n }\n return id;\n }\n}\n\ninterface NumberingDef {\n numId: number;\n ordered: boolean;\n}\n\n// ============================================\n// Block Conversion\n// ============================================\n\nfunction convertBlocks(nodes: MarkdownBlockNode[], ctx: ExportContext): string {\n const parts: string[] = [];\n for (const node of nodes) {\n parts.push(convertBlock(node, ctx, 0));\n }\n return parts.join('');\n}\n\nfunction convertBlock(node: MarkdownBlockNode, ctx: ExportContext, listDepth: number): string {\n switch (node.type) {\n case 'heading':\n return convertHeading(node, ctx);\n case 'paragraph':\n return convertParagraph(node, ctx);\n case 'blockquote':\n return convertBlockquote(node, ctx);\n case 'list':\n return convertList(node, ctx, listDepth);\n case 'code':\n return convertCodeBlock(node);\n case 'table':\n return convertTable(node, ctx);\n case 'thematicBreak':\n return convertThematicBreak();\n case 'htmlBlock':\n return convertHtmlBlock(node);\n case 'math':\n return convertMathBlock(node);\n case 'footnoteDefinition':\n return convertFootnoteDefinition(node, ctx);\n default:\n // Definition lists, directives, link definitions — skip or emit as plain text\n return '';\n }\n}\n\nfunction convertHeading(node: MarkdownHeading, ctx: ExportContext): string {\n const styleId = DEPTH_TO_STYLE_ID[node.depth] ?? 'Heading1';\n const runs = convertInlines(node.children, ctx);\n return `<w:p>` + `<w:pPr><w:pStyle w:val=\"${styleId}\"/></w:pPr>` + runs + `</w:p>`;\n}\n\nfunction convertParagraph(node: MarkdownParagraph, ctx: ExportContext): string {\n const runs = convertInlines(node.children, ctx);\n return `<w:p>${runs}</w:p>`;\n}\n\nfunction convertBlockquote(node: MarkdownBlockquote, ctx: ExportContext): string {\n // Render each child block as a paragraph with Quote style\n const parts: string[] = [];\n for (const child of node.children) {\n if (child.type === 'paragraph') {\n const runs = convertInlines(child.children, ctx);\n parts.push(\n `<w:p>` +\n `<w:pPr><w:pStyle w:val=\"Quote\"/>` +\n `<w:ind w:left=\"${pointsToTwips(36)}\"/>` +\n `<w:pBdr><w:left w:val=\"single\" w:sz=\"12\" w:space=\"4\" w:color=\"CCCCCC\"/></w:pBdr>` +\n `</w:pPr>` +\n runs +\n `</w:p>`,\n );\n } else {\n // Nested non-paragraph (e.g., nested blockquote, list) — recurse\n parts.push(convertBlock(child, ctx, 0));\n }\n }\n return parts.join('');\n}\n\nfunction convertList(node: MarkdownList, ctx: ExportContext, depth: number): string {\n const numId = ctx.allocNumbering(node.ordered ?? false);\n const parts: string[] = [];\n for (const item of node.children) {\n parts.push(convertListItem(item, ctx, numId, depth));\n }\n return parts.join('');\n}\n\nfunction convertListItem(\n item: MarkdownListItem,\n ctx: ExportContext,\n numId: number,\n depth: number,\n): string {\n const parts: string[] = [];\n for (const child of item.children) {\n if (child.type === 'paragraph') {\n const runs = convertInlines(child.children, ctx);\n parts.push(\n `<w:p>` +\n `<w:pPr>` +\n `<w:pStyle w:val=\"ListParagraph\"/>` +\n `<w:numPr><w:ilvl w:val=\"${depth}\"/><w:numId w:val=\"${numId}\"/></w:numPr>` +\n `</w:pPr>` +\n runs +\n `</w:p>`,\n );\n } else if (child.type === 'list') {\n // Nested list — increase depth\n parts.push(convertList(child, ctx, depth + 1));\n } else {\n parts.push(convertBlock(child, ctx, depth));\n }\n }\n return parts.join('');\n}\n\nfunction convertCodeBlock(node: MarkdownCodeBlock): string {\n // Emit each line as a separate paragraph with code styling\n const lines = node.value.split('\\n');\n const parts: string[] = [];\n for (const line of lines) {\n parts.push(\n `<w:p>` +\n `<w:pPr>` +\n `<w:pStyle w:val=\"Code\"/>` +\n `<w:pBdr>` +\n `<w:top w:val=\"single\" w:sz=\"4\" w:space=\"1\" w:color=\"CCCCCC\"/>` +\n `<w:left w:val=\"single\" w:sz=\"4\" w:space=\"4\" w:color=\"CCCCCC\"/>` +\n `<w:bottom w:val=\"single\" w:sz=\"4\" w:space=\"1\" w:color=\"CCCCCC\"/>` +\n `<w:right w:val=\"single\" w:sz=\"4\" w:space=\"4\" w:color=\"CCCCCC\"/>` +\n `</w:pBdr>` +\n `<w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"F5F5F5\"/>` +\n `</w:pPr>` +\n `<w:r>` +\n `<w:rPr><w:rFonts w:ascii=\"${DEFAULT_CODE_FONT}\" w:hAnsi=\"${DEFAULT_CODE_FONT}\"/>` +\n `<w:sz w:val=\"${DEFAULT_CODE_FONT_SIZE}\"/></w:rPr>` +\n `<w:t xml:space=\"preserve\">${escapeXml(line)}</w:t>` +\n `</w:r>` +\n `</w:p>`,\n );\n }\n return parts.join('');\n}\n\nfunction convertTable(node: MarkdownTable, ctx: ExportContext): string {\n const rows: string[] = [];\n for (let ri = 0; ri < node.children.length; ri++) {\n const row = node.children[ri];\n rows.push(convertTableRow(row, ctx, ri === 0, node.align));\n }\n\n return (\n `<w:tbl>` +\n `<w:tblPr>` +\n `<w:tblStyle w:val=\"TableGrid\"/>` +\n `<w:tblW w:w=\"0\" w:type=\"auto\"/>` +\n `<w:tblBorders>` +\n `<w:top w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:left w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:bottom w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:right w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:insideH w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:insideV w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `</w:tblBorders>` +\n `</w:tblPr>` +\n `<w:tblGrid/>` +\n rows.join('') +\n `</w:tbl>`\n );\n}\n\nfunction convertTableRow(\n row: MarkdownTableRow,\n ctx: ExportContext,\n isHeader: boolean,\n align?: (('left' | 'right' | 'center') | null)[],\n): string {\n const cells: string[] = [];\n for (let ci = 0; ci < row.children.length; ci++) {\n const cell = row.children[ci];\n const cellAlign = align?.[ci] ?? null;\n cells.push(convertTableCell(cell, ctx, isHeader, cellAlign));\n }\n const trPr = isHeader ? '<w:trPr><w:tblHeader/></w:trPr>' : '';\n return `<w:tr>${trPr}${cells.join('')}</w:tr>`;\n}\n\nfunction convertTableCell(\n cell: MarkdownTableCell,\n ctx: ExportContext,\n isHeader: boolean,\n align: 'left' | 'right' | 'center' | null,\n): string {\n const runs = convertInlines(cell.children, ctx);\n const rPr = isHeader ? '<w:rPr><w:b/></w:rPr>' : '';\n const jcMap = { left: 'left', center: 'center', right: 'right' };\n const jc = align ? `<w:jc w:val=\"${jcMap[align]}\"/>` : '';\n const pPr = rPr || jc ? `<w:pPr>${jc}</w:pPr>` : '';\n return `<w:tc><w:p>${pPr}${runs}</w:p></w:tc>`;\n}\n\nfunction convertThematicBreak(): string {\n return (\n `<w:p>` +\n `<w:pPr>` +\n `<w:pBdr><w:bottom w:val=\"single\" w:sz=\"6\" w:space=\"1\" w:color=\"auto\"/></w:pBdr>` +\n `</w:pPr>` +\n `</w:p>`\n );\n}\n\nfunction convertHtmlBlock(node: MarkdownHtmlBlock): string {\n // Best-effort: extract text content from the HTML\n const text = stripHtmlTags(node.rawHtml);\n if (!text.trim()) return '';\n return `<w:p><w:r><w:t xml:space=\"preserve\">${escapeXml(text)}</w:t></w:r></w:p>`;\n}\n\nfunction convertMathBlock(node: MarkdownMathBlock): string {\n // Emit as a styled paragraph with the raw LaTeX\n return (\n `<w:p>` +\n `<w:pPr><w:jc w:val=\"center\"/></w:pPr>` +\n `<w:r>` +\n `<w:rPr><w:rFonts w:ascii=\"Cambria Math\" w:hAnsi=\"Cambria Math\"/><w:i/></w:rPr>` +\n `<w:t xml:space=\"preserve\">${escapeXml(node.value)}</w:t>` +\n `</w:r>` +\n `</w:p>`\n );\n}\n\nfunction convertFootnoteDefinition(node: MarkdownFootnoteDefinition, ctx: ExportContext): string {\n const fnId = ctx.getFootnoteId(node.identifier);\n\n // Build the footnote body XML\n const bodyParts: string[] = [];\n for (const child of node.children) {\n if (child.type === 'paragraph') {\n const runs = convertInlines(child.children, ctx);\n bodyParts.push(`<w:p>${runs}</w:p>`);\n }\n }\n\n const footnoteXml =\n `<w:footnote w:id=\"${fnId}\">` +\n (bodyParts.length > 0 ? bodyParts.join('') : `<w:p/>`) +\n `</w:footnote>`;\n\n ctx.footnotes.set(fnId, footnoteXml);\n\n // Don't emit anything in the main body for the definition\n return '';\n}\n\n// ============================================\n// Inline Conversion\n// ============================================\n\n/**\n * Formatting state passed down through nested inline elements.\n */\ninterface InlineFormat {\n bold?: boolean;\n italic?: boolean;\n strike?: boolean;\n code?: boolean;\n}\n\nfunction convertInlines(\n nodes: MarkdownInlineNode[],\n ctx: ExportContext,\n format: InlineFormat = {},\n): string {\n const parts: string[] = [];\n for (const node of nodes) {\n parts.push(convertInline(node, ctx, format));\n }\n return parts.join('');\n}\n\nfunction convertInline(node: MarkdownInlineNode, ctx: ExportContext, format: InlineFormat): string {\n switch (node.type) {\n case 'text':\n return makeRun(node.value, format);\n case 'strong':\n return convertInlines(node.children, ctx, { ...format, bold: true });\n case 'emphasis':\n return convertInlines(node.children, ctx, { ...format, italic: true });\n case 'delete':\n return convertInlines(node.children, ctx, { ...format, strike: true });\n case 'inlineCode':\n return makeRun(node.value, { ...format, code: true });\n case 'link':\n return convertLink(node, ctx, format);\n case 'image':\n return convertImage(node);\n case 'break':\n return `<w:r><w:br/></w:r>`;\n case 'htmlInline':\n return makeRun(stripHtmlTags(node.rawHtml), format);\n case 'inlineMath':\n return makeRun(node.value, { ...format, code: true });\n case 'footnoteReference':\n return convertFootnoteRef(node, ctx);\n default:\n // linkReference, imageReference, textDirective — skip or emit plain\n return '';\n }\n}\n\nfunction makeRun(text: string, format: InlineFormat): string {\n if (!text) return '';\n\n const rPrParts: string[] = [];\n if (format.bold) rPrParts.push('<w:b/>');\n if (format.italic) rPrParts.push('<w:i/>');\n if (format.strike) rPrParts.push('<w:strike/>');\n if (format.code) {\n rPrParts.push(\n `<w:rFonts w:ascii=\"${DEFAULT_CODE_FONT}\" w:hAnsi=\"${DEFAULT_CODE_FONT}\"/>`,\n `<w:sz w:val=\"${DEFAULT_CODE_FONT_SIZE}\"/>`,\n );\n }\n\n const rPr = rPrParts.length > 0 ? `<w:rPr>${rPrParts.join('')}</w:rPr>` : '';\n\n // Use xml:space=\"preserve\" to keep leading/trailing whitespace\n return `<w:r>${rPr}<w:t xml:space=\"preserve\">${escapeXml(text)}</w:t></w:r>`;\n}\n\nfunction convertLink(node: MarkdownLink, ctx: ExportContext, format: InlineFormat): string {\n const rId = ctx.addHyperlink(node.url);\n const _runs = convertInlines(node.children, ctx, { ...format });\n\n // Wrap each run's rPr with hyperlink styling\n // For simplicity, emit inline runs with hyperlink color + underline\n const styledRuns = convertInlinesWithHyperlinkStyle(node.children, ctx, format);\n\n return `<w:hyperlink r:id=\"${rId}\">${styledRuns}</w:hyperlink>`;\n}\n\nfunction convertInlinesWithHyperlinkStyle(\n nodes: MarkdownInlineNode[],\n ctx: ExportContext,\n format: InlineFormat,\n): string {\n const parts: string[] = [];\n for (const node of nodes) {\n if (node.type === 'text') {\n parts.push(makeHyperlinkRun(node.value, format));\n } else {\n // For nested formatting inside links, add hyperlink style\n parts.push(convertInline(node, ctx, format));\n }\n }\n return parts.join('');\n}\n\nfunction makeHyperlinkRun(text: string, format: InlineFormat): string {\n if (!text) return '';\n\n const rPrParts: string[] = [\n '<w:rStyle w:val=\"Hyperlink\"/>',\n `<w:color w:val=\"${HYPERLINK_COLOR}\"/>`,\n '<w:u w:val=\"single\"/>',\n ];\n if (format.bold) rPrParts.push('<w:b/>');\n if (format.italic) rPrParts.push('<w:i/>');\n\n return (\n `<w:r><w:rPr>${rPrParts.join('')}</w:rPr>` +\n `<w:t xml:space=\"preserve\">${escapeXml(text)}</w:t></w:r>`\n );\n}\n\nfunction convertImage(_node: MarkdownImage): string {\n // Image embedding requires fetching the image data and packing it as\n // a binary part. For now, emit a placeholder text run.\n // Full image support can be added by fetching the URL and creating\n // a DrawingML inline + binary media part.\n const alt = _node.alt || _node.url;\n return makeRun(`[Image: ${alt}]`, { italic: true });\n}\n\nfunction convertFootnoteRef(node: MarkdownFootnoteReference, ctx: ExportContext): string {\n const fnId = ctx.getFootnoteId(node.identifier);\n return (\n `<w:r>` +\n `<w:rPr><w:rStyle w:val=\"FootnoteReference\"/><w:vertAlign w:val=\"superscript\"/></w:rPr>` +\n `<w:footnoteReference w:id=\"${fnId}\"/>` +\n `</w:r>`\n );\n}\n\n// ============================================\n// Package Assembly\n// ============================================\n\nasync function buildDocxPackage(\n bodyXml: string,\n ctx: ExportContext,\n options: DocxExportOptions,\n): Promise<ArrayBuffer> {\n const pkg = createPackage();\n\n // --- Register fixed relationships ---\n let relCounter = 100; // Start high to avoid collisions with dynamic rels\n const stylesRelId = `rId${relCounter++}`;\n const numberingRelId = `rId${relCounter++}`;\n const settingsRelId = `rId${relCounter++}`;\n const fontTableRelId = `rId${relCounter++}`;\n const footnotesRelId = `rId${relCounter++}`;\n\n // --- word/document.xml ---\n const documentXml = buildDocumentXml(bodyXml);\n pkg.addPart('word/document.xml', documentXml, CONTENT_TYPE_DOCX_DOCUMENT);\n\n // --- word/styles.xml ---\n const stylesXml = buildStylesXml(options, ctx);\n pkg.addPart('word/styles.xml', stylesXml, CONTENT_TYPE_DOCX_STYLES);\n\n // --- word/settings.xml ---\n const settingsXml = buildSettingsXml();\n pkg.addPart('word/settings.xml', settingsXml, CONTENT_TYPE_DOCX_SETTINGS);\n\n // --- word/fontTable.xml ---\n const fontTableXml = buildFontTableXml(options);\n pkg.addPart('word/fontTable.xml', fontTableXml, CONTENT_TYPE_DOCX_FONT_TABLE);\n\n // --- word/numbering.xml (only if lists present) ---\n if (ctx.hasLists) {\n const numberingXml = buildNumberingXml(ctx);\n pkg.addPart('word/numbering.xml', numberingXml, CONTENT_TYPE_DOCX_NUMBERING);\n }\n\n // --- word/footnotes.xml (only if footnotes present) ---\n if (ctx.hasFootnotes) {\n const footnotesXml = buildFootnotesXml(ctx);\n pkg.addPart('word/footnotes.xml', footnotesXml, CONTENT_TYPE_DOCX_FOOTNOTES);\n }\n\n // --- Root relationship: this package contains a word document ---\n pkg.addRelationship('', {\n id: 'rId1',\n type: REL_OFFICE_DOCUMENT,\n target: 'word/document.xml',\n });\n\n // --- Document relationships ---\n pkg.addRelationship('word/document.xml', {\n id: stylesRelId,\n type: REL_STYLES,\n target: 'styles.xml',\n });\n pkg.addRelationship('word/document.xml', {\n id: settingsRelId,\n type: REL_SETTINGS,\n target: 'settings.xml',\n });\n pkg.addRelationship('word/document.xml', {\n id: fontTableRelId,\n type: REL_FONT_TABLE,\n target: 'fontTable.xml',\n });\n\n if (ctx.hasLists) {\n pkg.addRelationship('word/document.xml', {\n id: numberingRelId,\n type: REL_NUMBERING,\n target: 'numbering.xml',\n });\n }\n\n if (ctx.hasFootnotes) {\n pkg.addRelationship('word/document.xml', {\n id: footnotesRelId,\n type: REL_FOOTNOTES,\n target: 'footnotes.xml',\n });\n }\n\n // --- Dynamic relationships (hyperlinks, images) ---\n for (const rel of ctx.relationships) {\n pkg.addRelationship('word/document.xml', {\n id: rel.id,\n type: rel.type,\n target: rel.target,\n ...(rel.targetMode ? { targetMode: rel.targetMode } : {}),\n });\n }\n\n // --- Embedded images ---\n for (const img of ctx.images) {\n pkg.addBinaryPart(img.path, img.data, img.contentType);\n }\n\n // --- Core properties ---\n if (options.title || options.author || options.description) {\n pkg.setCoreProperties({\n title: options.title,\n creator: options.author,\n description: options.description,\n created: new Date().toISOString(),\n modified: new Date().toISOString(),\n });\n }\n\n return pkg.toArrayBuffer();\n}\n\n// ============================================\n// XML Part Generators\n// ============================================\n\nfunction buildDocumentXml(bodyXml: string): string {\n return (\n xmlDeclaration() +\n `<w:document` +\n ` xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\"` +\n ` xmlns:mc=\"${NS_MC}\"` +\n ` xmlns:o=\"urn:schemas-microsoft-com:office:office\"` +\n ` xmlns:r=\"${NS_R}\"` +\n ` xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\"` +\n ` xmlns:v=\"urn:schemas-microsoft-com:vml\"` +\n ` xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\"` +\n ` xmlns:w10=\"urn:schemas-microsoft-com:office:word\"` +\n ` xmlns:w=\"${NS_WML}\"` +\n ` xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\">` +\n `<w:body>` +\n bodyXml +\n `<w:sectPr>` +\n `<w:pgSz w:w=\"12240\" w:h=\"15840\"/>` +\n `<w:pgMar w:top=\"1440\" w:right=\"1440\" w:bottom=\"1440\" w:left=\"1440\" w:header=\"720\" w:footer=\"720\" w:gutter=\"0\"/>` +\n `<w:cols w:space=\"720\"/>` +\n `</w:sectPr>` +\n `</w:body>` +\n `</w:document>`\n );\n}\n\nfunction buildStylesXml(options: DocxExportOptions, ctx: ExportContext): string {\n const font = ctx.font;\n const headingFont = ctx.headingFont;\n\n return (\n xmlDeclaration() +\n `<w:styles xmlns:w=\"${NS_WML}\">` +\n // Default run properties\n `<w:docDefaults>` +\n `<w:rPrDefault><w:rPr>` +\n `<w:rFonts w:ascii=\"${escapeXml(font)}\" w:hAnsi=\"${escapeXml(font)}\" w:eastAsia=\"${escapeXml(font)}\" w:cs=\"${escapeXml(font)}\"/>` +\n `<w:sz w:val=\"${DEFAULT_FONT_SIZE_HALF_POINTS}\"/>` +\n `<w:szCs w:val=\"${DEFAULT_FONT_SIZE_HALF_POINTS}\"/>` +\n `</w:rPr></w:rPrDefault>` +\n `<w:pPrDefault/>` +\n `</w:docDefaults>` +\n // Normal style\n `<w:style w:type=\"paragraph\" w:default=\"1\" w:styleId=\"Normal\">` +\n `<w:name w:val=\"Normal\"/>` +\n `<w:qFormat/>` +\n `</w:style>` +\n // Heading styles\n buildHeadingStyles(headingFont, ctx.headingColor) +\n // Quote style\n `<w:style w:type=\"paragraph\" w:styleId=\"Quote\">` +\n `<w:name w:val=\"Quote\"/>` +\n `<w:basedOn w:val=\"Normal\"/>` +\n `<w:pPr><w:ind w:left=\"720\"/></w:pPr>` +\n `<w:rPr><w:i/><w:color w:val=\"404040\"/></w:rPr>` +\n `</w:style>` +\n // Code style\n `<w:style w:type=\"paragraph\" w:styleId=\"Code\">` +\n `<w:name w:val=\"Code\"/>` +\n `<w:basedOn w:val=\"Normal\"/>` +\n `<w:rPr>` +\n `<w:rFonts w:ascii=\"${DEFAULT_CODE_FONT}\" w:hAnsi=\"${DEFAULT_CODE_FONT}\"/>` +\n `<w:sz w:val=\"${DEFAULT_CODE_FONT_SIZE}\"/>` +\n `</w:rPr>` +\n `</w:style>` +\n // ListParagraph style\n `<w:style w:type=\"paragraph\" w:styleId=\"ListParagraph\">` +\n `<w:name w:val=\"List Paragraph\"/>` +\n `<w:basedOn w:val=\"Normal\"/>` +\n `<w:pPr><w:ind w:left=\"720\"/></w:pPr>` +\n `</w:style>` +\n // Hyperlink character style\n `<w:style w:type=\"character\" w:styleId=\"Hyperlink\">` +\n `<w:name w:val=\"Hyperlink\"/>` +\n `<w:rPr><w:color w:val=\"${HYPERLINK_COLOR}\"/><w:u w:val=\"single\"/></w:rPr>` +\n `</w:style>` +\n // FootnoteReference character style\n `<w:style w:type=\"character\" w:styleId=\"FootnoteReference\">` +\n `<w:name w:val=\"footnote reference\"/>` +\n `<w:rPr><w:vertAlign w:val=\"superscript\"/></w:rPr>` +\n `</w:style>` +\n // Table Grid style\n `<w:style w:type=\"table\" w:styleId=\"TableGrid\">` +\n `<w:name w:val=\"Table Grid\"/>` +\n `<w:tblPr>` +\n `<w:tblBorders>` +\n `<w:top w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:left w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:bottom w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:right w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:insideH w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:insideV w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `</w:tblBorders>` +\n `</w:tblPr>` +\n `</w:style>` +\n `</w:styles>`\n );\n}\n\nfunction buildHeadingStyles(headingFont: string, headingColor?: string): string {\n let result = '';\n for (let depth = 1; depth <= 6; depth++) {\n const styleId = DEPTH_TO_STYLE_ID[depth];\n const fontSize = HEADING_FONT_SIZES[depth] ?? 22;\n const colorXml = headingColor ? `<w:color w:val=\"${headingColor}\"/>` : '';\n result +=\n `<w:style w:type=\"paragraph\" w:styleId=\"${styleId}\">` +\n `<w:name w:val=\"heading ${depth}\"/>` +\n `<w:basedOn w:val=\"Normal\"/>` +\n `<w:next w:val=\"Normal\"/>` +\n `<w:qFormat/>` +\n `<w:pPr><w:outlineLvl w:val=\"${depth - 1}\"/><w:spacing w:before=\"240\" w:after=\"60\"/></w:pPr>` +\n `<w:rPr>` +\n `<w:rFonts w:ascii=\"${escapeXml(headingFont)}\" w:hAnsi=\"${escapeXml(headingFont)}\"/>` +\n `<w:b/>` +\n colorXml +\n `<w:sz w:val=\"${fontSize}\"/>` +\n `<w:szCs w:val=\"${fontSize}\"/>` +\n `</w:rPr>` +\n `</w:style>`;\n }\n return result;\n}\n\nfunction buildSettingsXml(): string {\n return (\n xmlDeclaration() +\n `<w:settings xmlns:w=\"${NS_WML}\">` +\n `<w:defaultTabStop w:val=\"720\"/>` +\n `<w:characterSpacingControl w:val=\"doNotCompress\"/>` +\n `</w:settings>`\n );\n}\n\nfunction buildFontTableXml(options: DocxExportOptions): string {\n const font = options.defaultFont ?? DEFAULT_FONT;\n return (\n xmlDeclaration() +\n `<w:fonts xmlns:w=\"${NS_WML}\">` +\n `<w:font w:name=\"${escapeXml(font)}\">` +\n `<w:panose1 w:val=\"020F0502020204030204\"/>` +\n `<w:charset w:val=\"00\"/>` +\n `<w:family w:val=\"swiss\"/>` +\n `<w:pitch w:val=\"variable\"/>` +\n `</w:font>` +\n `<w:font w:name=\"${DEFAULT_HEADING_FONT}\">` +\n `<w:panose1 w:val=\"020F0302020204030204\"/>` +\n `<w:charset w:val=\"00\"/>` +\n `<w:family w:val=\"swiss\"/>` +\n `<w:pitch w:val=\"variable\"/>` +\n `</w:font>` +\n `<w:font w:name=\"${DEFAULT_CODE_FONT}\">` +\n `<w:charset w:val=\"00\"/>` +\n `<w:family w:val=\"modern\"/>` +\n `<w:pitch w:val=\"fixed\"/>` +\n `</w:font>` +\n `</w:fonts>`\n );\n}\n\nfunction buildNumberingXml(ctx: ExportContext): string {\n const abstract: string[] = [];\n const concrete: string[] = [];\n\n for (const def of ctx.numberingDefs) {\n const absId = def.numId;\n const levels: string[] = [];\n\n for (let lvl = 0; lvl < 9; lvl++) {\n if (def.ordered) {\n levels.push(\n `<w:lvl w:ilvl=\"${lvl}\">` +\n `<w:start w:val=\"1\"/>` +\n `<w:numFmt w:val=\"decimal\"/>` +\n `<w:lvlText w:val=\"%${lvl + 1}.\"/>` +\n `<w:lvlJc w:val=\"left\"/>` +\n `<w:pPr><w:ind w:left=\"${720 * (lvl + 1)}\" w:hanging=\"360\"/></w:pPr>` +\n `</w:lvl>`,\n );\n } else {\n const bullets = ['\\u2022', '\\u25E6', '\\u25AA']; // •, ◦, ▪\n const bullet = bullets[lvl % bullets.length];\n levels.push(\n `<w:lvl w:ilvl=\"${lvl}\">` +\n `<w:start w:val=\"1\"/>` +\n `<w:numFmt w:val=\"bullet\"/>` +\n `<w:lvlText w:val=\"${bullet}\"/>` +\n `<w:lvlJc w:val=\"left\"/>` +\n `<w:pPr><w:ind w:left=\"${720 * (lvl + 1)}\" w:hanging=\"360\"/></w:pPr>` +\n `<w:rPr><w:rFonts w:ascii=\"Symbol\" w:hAnsi=\"Symbol\"/></w:rPr>` +\n `</w:lvl>`,\n );\n }\n }\n\n abstract.push(\n `<w:abstractNum w:abstractNumId=\"${absId}\">` + levels.join('') + `</w:abstractNum>`,\n );\n concrete.push(\n `<w:num w:numId=\"${def.numId}\">` + `<w:abstractNumId w:val=\"${absId}\"/>` + `</w:num>`,\n );\n }\n\n return (\n xmlDeclaration() +\n `<w:numbering xmlns:w=\"${NS_WML}\">` +\n abstract.join('') +\n concrete.join('') +\n `</w:numbering>`\n );\n}\n\nfunction buildFootnotesXml(ctx: ExportContext): string {\n const footnotes: string[] = [];\n\n // Separator and continuation separator (required by Word)\n footnotes.push(\n `<w:footnote w:type=\"separator\" w:id=\"-1\">` +\n `<w:p><w:r><w:separator/></w:r></w:p>` +\n `</w:footnote>`,\n );\n footnotes.push(\n `<w:footnote w:type=\"continuationSeparator\" w:id=\"0\">` +\n `<w:p><w:r><w:continuationSeparator/></w:r></w:p>` +\n `</w:footnote>`,\n );\n\n // User footnotes\n for (const [_id, xml] of ctx.footnotes) {\n footnotes.push(xml);\n }\n\n return (\n xmlDeclaration() +\n `<w:footnotes xmlns:w=\"${NS_WML}\" xmlns:r=\"${NS_R}\">` +\n footnotes.join('') +\n `</w:footnotes>`\n );\n}\n\n// ============================================\n// Helpers\n// ============================================\n\n/**\n * Strip HTML tags from a string, keeping only text content.\n */\nfunction stripHtmlTags(html: string): string {\n return html.replace(/<[^>]*>/g, '');\n}\n","/**\n * DOCX Constants & Style Definitions\n *\n * Shared constants for DOCX import and export: built-in style IDs,\n * numbering format mappings, content type strings, and default\n * formatting values.\n */\n\n// ============================================\n// Built-in Style IDs\n// ============================================\n\n/**\n * Word built-in paragraph style IDs → heading depth.\n * These are the default style IDs in Word's Normal.dotm template.\n * Import uses these to detect heading levels from pStyle values.\n */\nexport const HEADING_STYLE_MAP: Record<string, number> = {\n Heading1: 1,\n Heading2: 2,\n Heading3: 3,\n Heading4: 4,\n Heading5: 5,\n Heading6: 6,\n heading1: 1,\n heading2: 2,\n heading3: 3,\n heading4: 4,\n heading5: 5,\n heading6: 6,\n // Some localized/legacy variants\n Title: 1,\n Subtitle: 2,\n};\n\n/**\n * Heading depth → Word style ID mapping (for export).\n */\nexport const DEPTH_TO_STYLE_ID: Record<number, string> = {\n 1: 'Heading1',\n 2: 'Heading2',\n 3: 'Heading3',\n 4: 'Heading4',\n 5: 'Heading5',\n 6: 'Heading6',\n};\n\n/**\n * Paragraph style IDs that map to blockquotes on import.\n */\nexport const QUOTE_STYLE_IDS = new Set(['Quote', 'IntenseQuote', 'quote', 'BlockQuote']);\n\n/**\n * Paragraph style ID for code blocks.\n */\nexport const CODE_STYLE_IDS = new Set(['Code', 'CodeBlock', 'HTMLCode', 'PlainText']);\n\n/**\n * Character style IDs that indicate inline code.\n */\nexport const INLINE_CODE_STYLE_IDS = new Set(['CodeChar', 'HTMLCodeChar', 'VerbatimChar']);\n\n// ============================================\n// Numbering Formats\n// ============================================\n\n/**\n * Word numbering format values that indicate an unordered (bullet) list.\n */\nexport const BULLET_NUM_FORMATS = new Set(['bullet', 'none']);\n\n/**\n * Word numbering format values that indicate an ordered (numbered) list.\n */\nexport const ORDERED_NUM_FORMATS = new Set([\n 'decimal',\n 'upperRoman',\n 'lowerRoman',\n 'upperLetter',\n 'lowerLetter',\n 'ordinal',\n 'cardinalText',\n 'ordinalText',\n]);\n\n// ============================================\n// Default Formatting\n// ============================================\n\n/** Default font family for document body text */\nexport const DEFAULT_FONT = 'Calibri';\n\n/** Default font family for headings */\nexport const DEFAULT_HEADING_FONT = 'Calibri Light';\n\n/** Default font size in half-points (22 = 11pt) */\nexport const DEFAULT_FONT_SIZE_HALF_POINTS = 22;\n\n/** Default code font */\nexport const DEFAULT_CODE_FONT = 'Consolas';\n\n/** Default code font size in half-points (20 = 10pt) */\nexport const DEFAULT_CODE_FONT_SIZE = 20;\n\n/**\n * Heading font sizes in half-points (Word default sizes).\n */\nexport const HEADING_FONT_SIZES: Record<number, number> = {\n 1: 32, // 16pt\n 2: 26, // 13pt\n 3: 24, // 12pt\n 4: 22, // 11pt\n 5: 22, // 11pt\n 6: 22, // 11pt\n};\n\n/** Hyperlink color (standard Word blue) */\nexport const HYPERLINK_COLOR = '0563C1';\n\n// ============================================\n// EMU (English Metric Units) Helpers\n// ============================================\n\n/**\n * Convert inches to EMUs (English Metric Units).\n * 1 inch = 914400 EMUs.\n */\nexport function inchesToEmu(inches: number): number {\n return Math.round(inches * 914400);\n}\n\n/**\n * Convert points to half-points (Word's internal unit for font sizes).\n */\nexport function pointsToHalfPoints(points: number): number {\n return Math.round(points * 2);\n}\n\n/**\n * Convert points to twentieths of a point (twips), used for spacing/margins.\n * 1 point = 20 twips.\n */\nexport function pointsToTwips(points: number): number {\n return Math.round(points * 20);\n}\n","/**\n * DOCX Import\n *\n * Parses a .docx file (Office Open XML WordprocessingML) and converts\n * its content into a squisq MarkdownDocument (or Doc).\n *\n * Uses JSZip + DOMParser to read the archive and parse the XML — no\n * third-party docx library. Handles headings, paragraphs, inline\n * formatting (bold, italic, strikethrough), hyperlinks, lists, tables,\n * blockquotes, code blocks, images, and footnotes.\n *\n * @example\n * ```ts\n * import { docxToMarkdownDoc } from '@bendyline/squisq-formats/docx';\n *\n * const response = await fetch('document.docx');\n * const data = await response.arrayBuffer();\n * const doc = await docxToMarkdownDoc(data);\n * ```\n */\n\nimport type { Doc } from '@bendyline/squisq/schemas';\nimport { markdownToDoc } from '@bendyline/squisq/doc';\nimport type {\n MarkdownDocument,\n MarkdownBlockNode,\n MarkdownInlineNode,\n MarkdownHeading,\n MarkdownParagraph,\n MarkdownBlockquote,\n MarkdownList,\n MarkdownListItem,\n MarkdownCodeBlock,\n MarkdownTable,\n MarkdownTableRow,\n MarkdownTableCell,\n MarkdownText,\n MarkdownEmphasis,\n MarkdownStrong,\n MarkdownStrikethrough,\n MarkdownInlineCode,\n MarkdownLink,\n MarkdownImage,\n MarkdownBreak,\n MarkdownFootnoteReference,\n MarkdownFootnoteDefinition,\n} from '@bendyline/squisq/markdown';\n\nimport { openPackage, getPartXml, getPartRelationships } from '../ooxml/reader.js';\nimport type { OoxmlPackage, Relationship } from '../ooxml/types.js';\nimport { NS_WML, NS_R } from '../ooxml/namespaces.js';\nimport {\n HEADING_STYLE_MAP,\n QUOTE_STYLE_IDS,\n CODE_STYLE_IDS,\n INLINE_CODE_STYLE_IDS,\n BULLET_NUM_FORMATS,\n} from './styles.js';\n\n// ============================================\n// Public API\n// ============================================\n\n/**\n * Options for DOCX import.\n */\nexport interface DocxImportOptions {\n /**\n * Whether to extract embedded images as base64 data URIs.\n * When false, images are represented as `[Image]` placeholders.\n * Default: false\n */\n extractImages?: boolean;\n}\n\n/**\n * Convert a .docx file to a MarkdownDocument.\n *\n * @param data - The raw .docx file as ArrayBuffer or Blob\n * @param options - Import options\n * @returns A MarkdownDocument representing the document content\n */\nexport async function docxToMarkdownDoc(\n data: ArrayBuffer | Blob,\n options: DocxImportOptions = {},\n): Promise<MarkdownDocument> {\n const pkg = await openPackage(data);\n const ctx = await buildImportContext(pkg, options);\n\n const documentXml = await getPartXml(pkg, 'word/document.xml');\n if (!documentXml) {\n return { type: 'document', children: [] };\n }\n\n const body = getFirstElement(documentXml, 'body');\n if (!body) {\n return { type: 'document', children: [] };\n }\n\n const blocks = await convertBody(body, ctx);\n\n return { type: 'document', children: blocks };\n}\n\n/**\n * Convert a .docx file to a squisq Doc.\n *\n * Convenience wrapper: DOCX → MarkdownDocument → Doc.\n *\n * @param data - The raw .docx file as ArrayBuffer or Blob\n * @param options - Import options\n * @returns A squisq Doc\n */\nexport async function docxToDoc(\n data: ArrayBuffer | Blob,\n options: DocxImportOptions = {},\n): Promise<Doc> {\n const markdownDoc = await docxToMarkdownDoc(data, options);\n return markdownToDoc(markdownDoc);\n}\n\n// ============================================\n// Import Context\n// ============================================\n\ninterface ImportContext {\n /** Style ID → heading depth mapping (from styles.xml) */\n headingStyles: Map<string, number>;\n /** Style IDs that represent blockquotes */\n quoteStyles: Set<string>;\n /** Style IDs that represent code blocks */\n codeStyles: Set<string>;\n /** Character style IDs that represent inline code */\n inlineCodeStyles: Set<string>;\n /** Document relationship map: rId → Relationship */\n documentRels: Map<string, Relationship>;\n /** Numbering definitions: numId → { levels: Map<ilvl, isOrdered> } */\n numbering: Map<string, NumberingInfo>;\n /** Footnote bodies: footnoteId → Element */\n footnotes: Map<string, Element>;\n /** Reference to the OOXML package (for extracting images) */\n pkg: OoxmlPackage;\n /** Import options */\n options: DocxImportOptions;\n}\n\ninterface NumberingInfo {\n levels: Map<number, boolean>; // ilvl → isOrdered\n}\n\nasync function buildImportContext(\n pkg: OoxmlPackage,\n options: DocxImportOptions,\n): Promise<ImportContext> {\n const ctx: ImportContext = {\n headingStyles: new Map(),\n quoteStyles: new Set(),\n codeStyles: new Set(),\n inlineCodeStyles: new Set(),\n documentRels: new Map(),\n numbering: new Map(),\n footnotes: new Map(),\n pkg,\n options,\n };\n\n // Initialize with built-in defaults\n for (const [id, depth] of Object.entries(HEADING_STYLE_MAP)) {\n ctx.headingStyles.set(id, depth);\n }\n for (const id of QUOTE_STYLE_IDS) {\n ctx.quoteStyles.add(id);\n }\n for (const id of CODE_STYLE_IDS) {\n ctx.codeStyles.add(id);\n }\n for (const id of INLINE_CODE_STYLE_IDS) {\n ctx.inlineCodeStyles.add(id);\n }\n\n // Parse styles.xml for custom heading/quote/code mappings\n await parseStyles(pkg, ctx);\n\n // Parse document relationships\n const rels = await getPartRelationships(pkg, 'word/document.xml');\n for (const rel of rels) {\n ctx.documentRels.set(rel.id, rel);\n }\n\n // Parse numbering.xml\n await parseNumbering(pkg, ctx);\n\n // Parse footnotes.xml\n await parseFootnotes(pkg, ctx);\n\n return ctx;\n}\n\n// ============================================\n// Styles Parsing\n// ============================================\n\nasync function parseStyles(pkg: OoxmlPackage, ctx: ImportContext): Promise<void> {\n const doc = await getPartXml(pkg, 'word/styles.xml');\n if (!doc) return;\n\n const styles = doc.getElementsByTagNameNS(NS_WML, 'style');\n // Fallback for documents that don't use namespace prefixes properly\n const stylesList = styles.length > 0 ? styles : doc.getElementsByTagName('style');\n\n for (let i = 0; i < stylesList.length; i++) {\n const style = stylesList[i];\n const styleId = style.getAttributeNS(NS_WML, 'styleId') ?? style.getAttribute('w:styleId');\n if (!styleId) continue;\n\n const nameEl = getFirstChildElement(style, 'name');\n const styleName = nameEl?.getAttributeNS(NS_WML, 'val') ?? nameEl?.getAttribute('w:val') ?? '';\n\n // Check if this is a heading style by name\n const headingMatch = styleName.match(/^heading\\s+(\\d+)$/i);\n if (headingMatch) {\n const depth = parseInt(headingMatch[1], 10);\n if (depth >= 1 && depth <= 6) {\n ctx.headingStyles.set(styleId, depth);\n }\n }\n\n // Check pPr > outlineLvl for heading detection\n const pPr = getFirstChildElement(style, 'pPr');\n if (pPr) {\n const outlineLvl = getFirstChildElement(pPr, 'outlineLvl');\n if (outlineLvl) {\n const val = outlineLvl.getAttributeNS(NS_WML, 'val') ?? outlineLvl.getAttribute('w:val');\n if (val !== null) {\n const depth = parseInt(val, 10) + 1;\n if (depth >= 1 && depth <= 6) {\n ctx.headingStyles.set(styleId, depth);\n }\n }\n }\n }\n }\n}\n\n// ============================================\n// Numbering Parsing\n// ============================================\n\nasync function parseNumbering(pkg: OoxmlPackage, ctx: ImportContext): Promise<void> {\n const doc = await getPartXml(pkg, 'word/numbering.xml');\n if (!doc) return;\n\n // Parse abstract numbering definitions\n const abstractNums = new Map<string, Map<number, boolean>>(); // abstractNumId → levels(ilvl → isOrdered)\n\n const abstractNumEls = getAllElements(doc, 'abstractNum');\n for (const absNum of abstractNumEls) {\n const absId = getAttr(absNum, 'abstractNumId');\n if (!absId) continue;\n\n const levels = new Map<number, boolean>();\n const lvlEls = getAllChildElements(absNum, 'lvl');\n for (const lvl of lvlEls) {\n const ilvlStr = getAttr(lvl, 'ilvl');\n if (ilvlStr === null) continue;\n const ilvl = parseInt(ilvlStr, 10);\n\n const numFmtEl = getFirstChildElement(lvl, 'numFmt');\n const numFmt = numFmtEl ? getAttr(numFmtEl, 'val') : null;\n\n const isOrdered = numFmt !== null && !BULLET_NUM_FORMATS.has(numFmt);\n levels.set(ilvl, isOrdered);\n }\n\n abstractNums.set(absId, levels);\n }\n\n // Parse concrete num → abstractNum mappings\n const numEls = getAllElements(doc, 'num');\n for (const num of numEls) {\n const numId = getAttr(num, 'numId');\n if (!numId) continue;\n\n const abstractNumIdEl = getFirstChildElement(num, 'abstractNumId');\n const absId = abstractNumIdEl ? getAttr(abstractNumIdEl, 'val') : null;\n if (!absId) continue;\n\n const levels = abstractNums.get(absId);\n if (levels) {\n ctx.numbering.set(numId, { levels });\n }\n }\n}\n\n// ============================================\n// Footnotes Parsing\n// ============================================\n\nasync function parseFootnotes(pkg: OoxmlPackage, ctx: ImportContext): Promise<void> {\n const doc = await getPartXml(pkg, 'word/footnotes.xml');\n if (!doc) return;\n\n const footnoteEls = getAllElements(doc, 'footnote');\n for (const fn of footnoteEls) {\n const id = getAttr(fn, 'id');\n const type = getAttr(fn, 'type');\n // Skip separator and continuation separator footnotes\n if (!id || type === 'separator' || type === 'continuationSeparator') continue;\n ctx.footnotes.set(id, fn);\n }\n}\n\n// ============================================\n// Body Conversion\n// ============================================\n\nasync function convertBody(body: Element, ctx: ImportContext): Promise<MarkdownBlockNode[]> {\n const result: MarkdownBlockNode[] = [];\n const children = Array.from(body.children);\n\n let i = 0;\n while (i < children.length) {\n const el = children[i];\n const localName = el.localName;\n\n if (localName === 'p') {\n // Check if this is part of a list\n const numPr = getNumPr(el);\n if (numPr) {\n // Collect consecutive list paragraphs\n const { node, consumed } = await collectList(children, i, ctx);\n result.push(node);\n i += consumed;\n continue;\n }\n\n const block = await convertParagraph(el, ctx);\n if (block) {\n result.push(block);\n }\n i++;\n } else if (localName === 'tbl') {\n const table = await convertTable(el, ctx);\n if (table) result.push(table);\n i++;\n } else {\n // Skip unknown elements (sectPr, bookmarkStart, etc.)\n i++;\n }\n }\n\n // Append footnote definitions at the end\n const footnoteNodes = await convertFootnoteDefinitions(ctx);\n result.push(...footnoteNodes);\n\n return result;\n}\n\n// ============================================\n// Paragraph Conversion\n// ============================================\n\nasync function convertParagraph(\n el: Element,\n ctx: ImportContext,\n): Promise<MarkdownBlockNode | null> {\n const pPr = getFirstChildElement(el, 'pPr');\n const styleId = getParagraphStyleId(pPr);\n\n // Check for heading\n if (styleId && ctx.headingStyles.has(styleId)) {\n const depth = ctx.headingStyles.get(styleId)!;\n const inlines = await convertRuns(el, ctx);\n if (inlines.length === 0) return null;\n return {\n type: 'heading',\n depth: Math.min(Math.max(depth, 1), 6) as 1 | 2 | 3 | 4 | 5 | 6,\n children: inlines,\n } satisfies MarkdownHeading;\n }\n\n // Check for blockquote\n if (styleId && ctx.quoteStyles.has(styleId)) {\n const inlines = await convertRuns(el, ctx);\n if (inlines.length === 0) return null;\n const paragraph: MarkdownParagraph = { type: 'paragraph', children: inlines };\n return { type: 'blockquote', children: [paragraph] } satisfies MarkdownBlockquote;\n }\n\n // Check for code block\n if (styleId && ctx.codeStyles.has(styleId)) {\n const text = getElementTextContent(el);\n return { type: 'code', value: text } satisfies MarkdownCodeBlock;\n }\n\n // Regular paragraph\n const inlines = await convertRuns(el, ctx);\n if (inlines.length === 0) return null;\n return { type: 'paragraph', children: inlines } satisfies MarkdownParagraph;\n}\n\n// ============================================\n// Run (Inline) Conversion\n// ============================================\n\nasync function convertRuns(\n paragraphEl: Element,\n ctx: ImportContext,\n): Promise<MarkdownInlineNode[]> {\n const result: MarkdownInlineNode[] = [];\n const children = Array.from(paragraphEl.children);\n\n for (const child of children) {\n const localName = child.localName;\n\n if (localName === 'r') {\n const inlines = await convertRun(child, ctx);\n result.push(...inlines);\n } else if (localName === 'hyperlink') {\n const link = await convertHyperlink(child, ctx);\n if (link) result.push(link);\n }\n // Skip pPr, bookmarkStart, bookmarkEnd, etc.\n }\n\n return mergeAdjacentText(result);\n}\n\nasync function convertRun(runEl: Element, ctx: ImportContext): Promise<MarkdownInlineNode[]> {\n const result: MarkdownInlineNode[] = [];\n const rPr = getFirstChildElement(runEl, 'rPr');\n const format = parseRunFormat(rPr, ctx);\n\n for (const child of Array.from(runEl.children)) {\n const localName = child.localName;\n\n if (localName === 't') {\n const text = child.textContent ?? '';\n if (!text) continue;\n\n if (format.code) {\n result.push({ type: 'inlineCode', value: text } satisfies MarkdownInlineCode);\n } else {\n let node: MarkdownInlineNode = { type: 'text', value: text } satisfies MarkdownText;\n if (format.strike) {\n node = { type: 'delete', children: [node] } satisfies MarkdownStrikethrough;\n }\n if (format.italic) {\n node = { type: 'emphasis', children: [node] } satisfies MarkdownEmphasis;\n }\n if (format.bold) {\n node = { type: 'strong', children: [node] } satisfies MarkdownStrong;\n }\n result.push(node);\n }\n } else if (localName === 'br') {\n result.push({ type: 'break' } satisfies MarkdownBreak);\n } else if (localName === 'footnoteReference') {\n const fnId = getAttr(child, 'id');\n if (fnId && fnId !== '0' && fnId !== '-1') {\n result.push({\n type: 'footnoteReference',\n identifier: `fn${fnId}`,\n } satisfies MarkdownFootnoteReference);\n }\n } else if (localName === 'drawing' || localName === 'pict') {\n const img = await extractImage(child, ctx);\n if (img) result.push(img);\n }\n }\n\n return result;\n}\n\ninterface RunFormat {\n bold: boolean;\n italic: boolean;\n strike: boolean;\n code: boolean;\n}\n\nfunction parseRunFormat(rPr: Element | null, ctx: ImportContext): RunFormat {\n if (!rPr) return { bold: false, italic: false, strike: false, code: false };\n\n const bold = hasChildElement(rPr, 'b') && !isFalseToggle(getFirstChildElement(rPr, 'b')!);\n const italic = hasChildElement(rPr, 'i') && !isFalseToggle(getFirstChildElement(rPr, 'i')!);\n const strike =\n hasChildElement(rPr, 'strike') && !isFalseToggle(getFirstChildElement(rPr, 'strike')!);\n\n // Check for inline code via character style\n const rStyle = getFirstChildElement(rPr, 'rStyle');\n const charStyleId = rStyle ? getAttr(rStyle, 'val') : null;\n const isCodeStyle = charStyleId ? ctx.inlineCodeStyles.has(charStyleId) : false;\n\n // Check for monospace font as a code indicator\n const rFonts = getFirstChildElement(rPr, 'rFonts');\n const fontName = rFonts ? (getAttr(rFonts, 'ascii') ?? getAttr(rFonts, 'hAnsi') ?? '') : '';\n const isMonospace = /consolas|courier|mono/i.test(fontName);\n\n return { bold, italic, strike, code: isCodeStyle || isMonospace };\n}\n\nfunction isFalseToggle(el: Element): boolean {\n const val = getAttr(el, 'val');\n return val === '0' || val === 'false';\n}\n\n// ============================================\n// Hyperlink Conversion\n// ============================================\n\nasync function convertHyperlink(el: Element, ctx: ImportContext): Promise<MarkdownLink | null> {\n const rId = el.getAttributeNS(NS_R, 'id') ?? el.getAttribute('r:id');\n\n let url = '';\n if (rId) {\n const rel = ctx.documentRels.get(rId);\n if (rel) url = rel.target;\n }\n\n // Also check for w:anchor (internal bookmarks)\n if (!url) {\n const anchor = el.getAttributeNS(NS_WML, 'anchor') ?? el.getAttribute('w:anchor');\n if (anchor) url = `#${anchor}`;\n }\n\n const inlines: MarkdownInlineNode[] = [];\n for (const child of Array.from(el.children)) {\n if (child.localName === 'r') {\n inlines.push(...(await convertRun(child, ctx)));\n }\n }\n\n if (inlines.length === 0) return null;\n\n return {\n type: 'link',\n url,\n children: mergeAdjacentText(inlines),\n };\n}\n\n// ============================================\n// Image Extraction\n// ============================================\n\nasync function extractImage(_el: Element, _ctx: ImportContext): Promise<MarkdownImage | null> {\n // Image extraction is complex (DrawingML with blip references).\n // For v1, emit a placeholder. Full implementation requires:\n // 1. Find <a:blip r:embed=\"rId_\"/> in the drawing tree\n // 2. Resolve the rId to a media path\n // 3. Extract the binary data and encode as data URI\n // This is planned for a future enhancement.\n return {\n type: 'image',\n url: '',\n alt: 'Image',\n };\n}\n\n// ============================================\n// List Collection\n// ============================================\n\ninterface ListResult {\n node: MarkdownList;\n consumed: number;\n}\n\ninterface NumPrInfo {\n numId: string;\n ilvl: number;\n}\n\nasync function collectList(\n elements: Element[],\n startIdx: number,\n ctx: ImportContext,\n): Promise<ListResult> {\n const firstNumPr = getNumPr(elements[startIdx])!;\n const { numId } = firstNumPr;\n\n // Determine if ordered from numbering definition\n const numInfo = ctx.numbering.get(numId);\n const isOrdered = numInfo?.levels.get(0) ?? false;\n\n const items: MarkdownListItem[] = [];\n let consumed = 0;\n\n let i = startIdx;\n while (i < elements.length) {\n const el = elements[i];\n if (el.localName !== 'p') break;\n\n const numPr = getNumPr(el);\n if (!numPr || numPr.numId !== numId) break;\n\n // Convert this paragraph's inline content\n const inlines = await convertRuns(el, ctx);\n if (inlines.length > 0) {\n const paragraph: MarkdownParagraph = { type: 'paragraph', children: inlines };\n\n // Check if this is a nested list item\n if (numPr.ilvl > firstNumPr.ilvl) {\n // Collect nested list items\n const nested = await collectNestedList(elements, i, ctx, firstNumPr.ilvl);\n if (items.length > 0) {\n // Attach nested list to the last item\n const lastItem = items[items.length - 1];\n const nestedIsOrdered = numInfo?.levels.get(numPr.ilvl) ?? false;\n const nestedList: MarkdownList = {\n type: 'list',\n ordered: nestedIsOrdered,\n children: nested.items,\n };\n lastItem.children.push(nestedList);\n }\n i += nested.consumed;\n consumed += nested.consumed;\n continue;\n }\n\n items.push({\n type: 'listItem',\n children: [paragraph],\n });\n }\n\n i++;\n consumed++;\n }\n\n return {\n node: {\n type: 'list',\n ordered: isOrdered,\n children: items,\n },\n consumed,\n };\n}\n\ninterface NestedListResult {\n items: MarkdownListItem[];\n consumed: number;\n}\n\nasync function collectNestedList(\n elements: Element[],\n startIdx: number,\n ctx: ImportContext,\n parentIlvl: number,\n): Promise<NestedListResult> {\n const items: MarkdownListItem[] = [];\n let consumed = 0;\n\n let i = startIdx;\n while (i < elements.length) {\n const el = elements[i];\n if (el.localName !== 'p') break;\n\n const numPr = getNumPr(el);\n if (!numPr) break;\n if (numPr.ilvl <= parentIlvl) break;\n\n const inlines = await convertRuns(el, ctx);\n if (inlines.length > 0) {\n const paragraph: MarkdownParagraph = { type: 'paragraph', children: inlines };\n items.push({ type: 'listItem', children: [paragraph] });\n }\n\n i++;\n consumed++;\n }\n\n return { items, consumed };\n}\n\nfunction getNumPr(el: Element): NumPrInfo | null {\n const pPr = getFirstChildElement(el, 'pPr');\n if (!pPr) return null;\n\n const numPr = getFirstChildElement(pPr, 'numPr');\n if (!numPr) return null;\n\n const ilvlEl = getFirstChildElement(numPr, 'ilvl');\n const numIdEl = getFirstChildElement(numPr, 'numId');\n\n const ilvlVal = ilvlEl ? getAttr(ilvlEl, 'val') : null;\n const numIdVal = numIdEl ? getAttr(numIdEl, 'val') : null;\n\n if (!numIdVal || numIdVal === '0') return null; // numId 0 means \"no list\"\n\n return {\n numId: numIdVal,\n ilvl: ilvlVal ? parseInt(ilvlVal, 10) : 0,\n };\n}\n\n// ============================================\n// Table Conversion\n// ============================================\n\nasync function convertTable(tblEl: Element, ctx: ImportContext): Promise<MarkdownTable | null> {\n const rows: MarkdownTableRow[] = [];\n\n const trEls = getAllChildElements(tblEl, 'tr');\n for (let ri = 0; ri < trEls.length; ri++) {\n const row = await convertTableRow(trEls[ri], ctx, ri === 0);\n rows.push(row);\n }\n\n if (rows.length === 0) return null;\n\n // If first row isn't explicitly a header, treat it as one anyway\n // (Markdown tables require a header row)\n return {\n type: 'table',\n children: rows,\n };\n}\n\nasync function convertTableRow(\n trEl: Element,\n ctx: ImportContext,\n isHeader: boolean,\n): Promise<MarkdownTableRow> {\n const cells: MarkdownTableCell[] = [];\n const tcEls = getAllChildElements(trEl, 'tc');\n\n for (const tc of tcEls) {\n const cell = await convertTableCell(tc, ctx, isHeader);\n cells.push(cell);\n }\n\n return { type: 'tableRow', children: cells };\n}\n\nasync function convertTableCell(\n tcEl: Element,\n ctx: ImportContext,\n isHeader: boolean,\n): Promise<MarkdownTableCell> {\n const inlines: MarkdownInlineNode[] = [];\n\n // A cell can contain multiple paragraphs; flatten them with breaks\n const paragraphs = getAllChildElements(tcEl, 'p');\n for (let pi = 0; pi < paragraphs.length; pi++) {\n if (pi > 0) {\n inlines.push({ type: 'break' } as MarkdownBreak);\n }\n const runs = await convertRuns(paragraphs[pi], ctx);\n inlines.push(...runs);\n }\n\n return {\n type: 'tableCell',\n isHeader,\n children: mergeAdjacentText(inlines),\n };\n}\n\n// ============================================\n// Footnote Definition Conversion\n// ============================================\n\nasync function convertFootnoteDefinitions(\n ctx: ImportContext,\n): Promise<MarkdownFootnoteDefinition[]> {\n const results: MarkdownFootnoteDefinition[] = [];\n\n for (const [id, el] of ctx.footnotes) {\n const children: MarkdownBlockNode[] = [];\n const paragraphs = getAllChildElements(el, 'p');\n\n for (const p of paragraphs) {\n const inlines = await convertRuns(p, ctx);\n if (inlines.length > 0) {\n children.push({\n type: 'paragraph',\n children: inlines,\n } satisfies MarkdownParagraph);\n }\n }\n\n if (children.length > 0) {\n results.push({\n type: 'footnoteDefinition',\n identifier: `fn${id}`,\n children,\n });\n }\n }\n\n return results;\n}\n\n// ============================================\n// XML Helper Utilities\n// ============================================\n\n/**\n * Get the first element child with a given local name.\n * Handles both namespaced and non-namespaced elements.\n */\nfunction getFirstChildElement(parent: Element | Document, localName: string): Element | null {\n for (const child of Array.from(parent.children ?? [])) {\n if (child.localName === localName) return child;\n }\n return null;\n}\n\n/**\n * Get all direct child elements with a given local name.\n */\nfunction getAllChildElements(parent: Element, localName: string): Element[] {\n const result: Element[] = [];\n for (const child of Array.from(parent.children)) {\n if (child.localName === localName) result.push(child);\n }\n return result;\n}\n\n/**\n * Get all elements with a given local name in the document.\n */\nfunction getAllElements(doc: Document | Element, localName: string): Element[] {\n // Try namespace-aware first\n const nsEls =\n 'getElementsByTagNameNS' in doc ? doc.getElementsByTagNameNS(NS_WML, localName) : null;\n if (nsEls && nsEls.length > 0) return Array.from(nsEls);\n\n // Fallback: try with w: prefix\n const prefixed = doc.getElementsByTagName(`w:${localName}`);\n if (prefixed.length > 0) return Array.from(prefixed);\n\n // Final fallback: bare name\n return Array.from(doc.getElementsByTagName(localName));\n}\n\n/**\n * Get the first element with given local name in the document or subtree.\n */\nfunction getFirstElement(doc: Document | Element, localName: string): Element | null {\n const els = getAllElements(doc, localName);\n return els.length > 0 ? els[0] : null;\n}\n\n/**\n * Get a w:-prefixed attribute, trying namespace-aware first then fallback.\n */\nfunction getAttr(el: Element, localName: string): string | null {\n return el.getAttributeNS(NS_WML, localName) || el.getAttribute(`w:${localName}`) || null;\n}\n\n/**\n * Check if an element has a direct child with the given local name.\n */\nfunction hasChildElement(parent: Element, localName: string): boolean {\n return getFirstChildElement(parent, localName) !== null;\n}\n\n/**\n * Get the paragraph style ID from a pPr element.\n */\nfunction getParagraphStyleId(pPr: Element | null): string | null {\n if (!pPr) return null;\n const pStyle = getFirstChildElement(pPr, 'pStyle');\n if (!pStyle) return null;\n return getAttr(pStyle, 'val');\n}\n\n/**\n * Get all text content from an element (concatenating all w:t descendants).\n */\nfunction getElementTextContent(el: Element): string {\n const parts: string[] = [];\n\n function walk(node: Element): void {\n if (node.localName === 't') {\n parts.push(node.textContent ?? '');\n }\n for (const child of Array.from(node.children)) {\n walk(child);\n }\n }\n\n walk(el);\n return parts.join('');\n}\n\n/**\n * Merge adjacent MarkdownText nodes to reduce fragmentation.\n */\nfunction mergeAdjacentText(nodes: MarkdownInlineNode[]): MarkdownInlineNode[] {\n if (nodes.length <= 1) return nodes;\n\n const result: MarkdownInlineNode[] = [];\n for (const node of nodes) {\n const prev = result[result.length - 1];\n if (node.type === 'text' && prev?.type === 'text') {\n // Merge into previous text node\n (prev as MarkdownText).value += (node as MarkdownText).value;\n } else {\n result.push(node);\n }\n }\n return result;\n}\n"],"mappings":"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","names":["convertParagraph","convertTable","inlines","convertTableRow","convertTableCell"]}
|
|
@@ -126,8 +126,12 @@ function generateInlineHtml(doc, options) {
|
|
|
126
126
|
images,
|
|
127
127
|
mode = "slideshow",
|
|
128
128
|
title = "Squisq Document",
|
|
129
|
-
autoPlay = false
|
|
129
|
+
autoPlay = false,
|
|
130
|
+
themeId
|
|
130
131
|
} = options;
|
|
132
|
+
if (themeId) {
|
|
133
|
+
doc = { ...doc, themeId };
|
|
134
|
+
}
|
|
131
135
|
const imageMap = {};
|
|
132
136
|
if (images) {
|
|
133
137
|
for (const [path, buffer] of images.entries()) {
|
|
@@ -268,4 +272,4 @@ export {
|
|
|
268
272
|
docToHtml,
|
|
269
273
|
docToHtmlZip
|
|
270
274
|
};
|
|
271
|
-
//# sourceMappingURL=chunk-
|
|
275
|
+
//# sourceMappingURL=chunk-743COJWQ.js.map
|