@wonderwhy-er/desktop-commander 0.2.34 → 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.
Files changed (179) hide show
  1. package/README.md +2 -0
  2. package/dist/handlers/filesystem-handlers.js +58 -11
  3. package/dist/handlers/history-handlers.d.ts +7 -0
  4. package/dist/handlers/history-handlers.js +33 -1
  5. package/dist/server.js +30 -4
  6. package/dist/tools/docx/builders/html-builder.d.ts +17 -0
  7. package/dist/tools/docx/builders/html-builder.js +92 -0
  8. package/dist/tools/docx/builders/image.d.ts +14 -0
  9. package/dist/tools/docx/builders/image.js +84 -0
  10. package/dist/tools/docx/builders/index.d.ts +11 -0
  11. package/dist/tools/docx/builders/index.js +11 -0
  12. package/dist/tools/docx/builders/markdown-builder.d.ts +2 -0
  13. package/dist/tools/docx/builders/markdown-builder.js +260 -0
  14. package/dist/tools/docx/builders/paragraph.d.ts +12 -0
  15. package/dist/tools/docx/builders/paragraph.js +29 -0
  16. package/dist/tools/docx/builders/table.d.ts +8 -0
  17. package/dist/tools/docx/builders/table.js +94 -0
  18. package/dist/tools/docx/builders/utils.d.ts +5 -0
  19. package/dist/tools/docx/builders/utils.js +18 -0
  20. package/dist/tools/docx/constants.d.ts +32 -0
  21. package/dist/tools/docx/constants.js +61 -0
  22. package/dist/tools/docx/converters/markdown-to-html.d.ts +17 -0
  23. package/dist/tools/docx/converters/markdown-to-html.js +111 -0
  24. package/dist/tools/docx/create.d.ts +21 -0
  25. package/dist/tools/docx/create.js +386 -0
  26. package/dist/tools/docx/dom.d.ts +66 -0
  27. package/dist/tools/docx/dom.js +228 -0
  28. package/dist/tools/docx/errors.d.ts +28 -0
  29. package/dist/tools/docx/errors.js +48 -0
  30. package/dist/tools/docx/extractors/images.d.ts +14 -0
  31. package/dist/tools/docx/extractors/images.js +40 -0
  32. package/dist/tools/docx/extractors/metadata.d.ts +14 -0
  33. package/dist/tools/docx/extractors/metadata.js +64 -0
  34. package/dist/tools/docx/extractors/sections.d.ts +14 -0
  35. package/dist/tools/docx/extractors/sections.js +61 -0
  36. package/dist/tools/docx/html.d.ts +17 -0
  37. package/dist/tools/docx/html.js +111 -0
  38. package/dist/tools/docx/index.d.ts +10 -0
  39. package/dist/tools/docx/index.js +10 -0
  40. package/dist/tools/docx/markdown.d.ts +84 -0
  41. package/dist/tools/docx/markdown.js +507 -0
  42. package/dist/tools/docx/modify.d.ts +28 -0
  43. package/dist/tools/docx/modify.js +271 -0
  44. package/dist/tools/docx/operations/handlers/index.d.ts +39 -0
  45. package/dist/tools/docx/operations/handlers/index.js +152 -0
  46. package/dist/tools/docx/operations/html-manipulator.d.ts +24 -0
  47. package/dist/tools/docx/operations/html-manipulator.js +352 -0
  48. package/dist/tools/docx/operations/index.d.ts +14 -0
  49. package/dist/tools/docx/operations/index.js +61 -0
  50. package/dist/tools/docx/operations/operation-handlers.d.ts +3 -0
  51. package/dist/tools/docx/operations/operation-handlers.js +67 -0
  52. package/dist/tools/docx/operations/preprocessor.d.ts +14 -0
  53. package/dist/tools/docx/operations/preprocessor.js +44 -0
  54. package/dist/tools/docx/operations/xml-replacer.d.ts +9 -0
  55. package/dist/tools/docx/operations/xml-replacer.js +35 -0
  56. package/dist/tools/docx/operations.d.ts +13 -0
  57. package/dist/tools/docx/operations.js +13 -0
  58. package/dist/tools/docx/ops/delete-paragraph-at-body-index.d.ts +11 -0
  59. package/dist/tools/docx/ops/delete-paragraph-at-body-index.js +23 -0
  60. package/dist/tools/docx/ops/header-replace-text-exact.d.ts +13 -0
  61. package/dist/tools/docx/ops/header-replace-text-exact.js +55 -0
  62. package/dist/tools/docx/ops/index.d.ts +17 -0
  63. package/dist/tools/docx/ops/index.js +67 -0
  64. package/dist/tools/docx/ops/insert-image-after-text.d.ts +24 -0
  65. package/dist/tools/docx/ops/insert-image-after-text.js +128 -0
  66. package/dist/tools/docx/ops/insert-paragraph-after-text.d.ts +12 -0
  67. package/dist/tools/docx/ops/insert-paragraph-after-text.js +74 -0
  68. package/dist/tools/docx/ops/insert-table-after-text.d.ts +19 -0
  69. package/dist/tools/docx/ops/insert-table-after-text.js +57 -0
  70. package/dist/tools/docx/ops/replace-hyperlink-url.d.ts +12 -0
  71. package/dist/tools/docx/ops/replace-hyperlink-url.js +37 -0
  72. package/dist/tools/docx/ops/replace-paragraph-at-body-index.d.ts +9 -0
  73. package/dist/tools/docx/ops/replace-paragraph-at-body-index.js +25 -0
  74. package/dist/tools/docx/ops/replace-paragraph-text-exact.d.ts +9 -0
  75. package/dist/tools/docx/ops/replace-paragraph-text-exact.js +21 -0
  76. package/dist/tools/docx/ops/set-color-for-paragraph-exact.d.ts +8 -0
  77. package/dist/tools/docx/ops/set-color-for-paragraph-exact.js +23 -0
  78. package/dist/tools/docx/ops/set-color-for-style.d.ts +9 -0
  79. package/dist/tools/docx/ops/set-color-for-style.js +27 -0
  80. package/dist/tools/docx/ops/set-paragraph-style-at-body-index.d.ts +8 -0
  81. package/dist/tools/docx/ops/set-paragraph-style-at-body-index.js +57 -0
  82. package/dist/tools/docx/ops/table-set-cell-text.d.ts +9 -0
  83. package/dist/tools/docx/ops/table-set-cell-text.js +72 -0
  84. package/dist/tools/docx/parsers/image-extractor.d.ts +18 -0
  85. package/dist/tools/docx/parsers/image-extractor.js +61 -0
  86. package/dist/tools/docx/parsers/index.d.ts +9 -0
  87. package/dist/tools/docx/parsers/index.js +9 -0
  88. package/dist/tools/docx/parsers/paragraph-parser.d.ts +2 -0
  89. package/dist/tools/docx/parsers/paragraph-parser.js +88 -0
  90. package/dist/tools/docx/parsers/table-parser.d.ts +9 -0
  91. package/dist/tools/docx/parsers/table-parser.js +72 -0
  92. package/dist/tools/docx/parsers/xml-parser.d.ts +25 -0
  93. package/dist/tools/docx/parsers/xml-parser.js +71 -0
  94. package/dist/tools/docx/parsers/zip-reader.d.ts +23 -0
  95. package/dist/tools/docx/parsers/zip-reader.js +52 -0
  96. package/dist/tools/docx/read.d.ts +27 -0
  97. package/dist/tools/docx/read.js +188 -0
  98. package/dist/tools/docx/relationships.d.ts +22 -0
  99. package/dist/tools/docx/relationships.js +76 -0
  100. package/dist/tools/docx/structure.d.ts +25 -0
  101. package/dist/tools/docx/structure.js +102 -0
  102. package/dist/tools/docx/styled-html-parser.d.ts +23 -0
  103. package/dist/tools/docx/styled-html-parser.js +1262 -0
  104. package/dist/tools/docx/types.d.ts +184 -0
  105. package/dist/tools/docx/types.js +5 -0
  106. package/dist/tools/docx/utils/escaping.d.ts +13 -0
  107. package/dist/tools/docx/utils/escaping.js +26 -0
  108. package/dist/tools/docx/utils/images.d.ts +9 -0
  109. package/dist/tools/docx/utils/images.js +26 -0
  110. package/dist/tools/docx/utils/index.d.ts +12 -0
  111. package/dist/tools/docx/utils/index.js +17 -0
  112. package/dist/tools/docx/utils/markdown.d.ts +13 -0
  113. package/dist/tools/docx/utils/markdown.js +32 -0
  114. package/dist/tools/docx/utils/paths.d.ts +15 -0
  115. package/dist/tools/docx/utils/paths.js +27 -0
  116. package/dist/tools/docx/utils/versioning.d.ts +25 -0
  117. package/dist/tools/docx/utils/versioning.js +55 -0
  118. package/dist/tools/docx/utils.d.ts +101 -0
  119. package/dist/tools/docx/utils.js +299 -0
  120. package/dist/tools/docx/validate.d.ts +33 -0
  121. package/dist/tools/docx/validate.js +49 -0
  122. package/dist/tools/docx/validators.d.ts +13 -0
  123. package/dist/tools/docx/validators.js +40 -0
  124. package/dist/tools/docx/write.d.ts +17 -0
  125. package/dist/tools/docx/write.js +88 -0
  126. package/dist/tools/docx/zip.d.ts +21 -0
  127. package/dist/tools/docx/zip.js +35 -0
  128. package/dist/tools/schemas.d.ts +13 -0
  129. package/dist/tools/schemas.js +5 -0
  130. package/dist/types.d.ts +10 -0
  131. package/dist/ui/contracts.d.ts +14 -0
  132. package/dist/ui/contracts.js +18 -0
  133. package/dist/ui/file-preview/index.html +16 -0
  134. package/dist/ui/file-preview/preview-runtime.js +13977 -0
  135. package/dist/ui/file-preview/shared/preview-file-types.d.ts +5 -0
  136. package/dist/ui/file-preview/shared/preview-file-types.js +57 -0
  137. package/dist/ui/file-preview/src/app.d.ts +4 -0
  138. package/dist/ui/file-preview/src/app.js +800 -0
  139. package/dist/ui/file-preview/src/components/code-viewer.d.ts +6 -0
  140. package/dist/ui/file-preview/src/components/code-viewer.js +73 -0
  141. package/dist/ui/file-preview/src/components/highlighting.d.ts +2 -0
  142. package/dist/ui/file-preview/src/components/highlighting.js +54 -0
  143. package/dist/ui/file-preview/src/components/html-renderer.d.ts +9 -0
  144. package/dist/ui/file-preview/src/components/html-renderer.js +63 -0
  145. package/dist/ui/file-preview/src/components/markdown-renderer.d.ts +1 -0
  146. package/dist/ui/file-preview/src/components/markdown-renderer.js +21 -0
  147. package/dist/ui/file-preview/src/components/toolbar.d.ts +6 -0
  148. package/dist/ui/file-preview/src/components/toolbar.js +75 -0
  149. package/dist/ui/file-preview/src/image-preview.d.ts +3 -0
  150. package/dist/ui/file-preview/src/image-preview.js +21 -0
  151. package/dist/ui/file-preview/src/main.d.ts +1 -0
  152. package/dist/ui/file-preview/src/main.js +5 -0
  153. package/dist/ui/file-preview/src/types.d.ts +1 -0
  154. package/dist/ui/file-preview/src/types.js +1 -0
  155. package/dist/ui/file-preview/styles.css +764 -0
  156. package/dist/ui/resources.d.ts +21 -0
  157. package/dist/ui/resources.js +72 -0
  158. package/dist/ui/shared/escape-html.d.ts +4 -0
  159. package/dist/ui/shared/escape-html.js +11 -0
  160. package/dist/ui/shared/host-lifecycle.d.ts +16 -0
  161. package/dist/ui/shared/host-lifecycle.js +35 -0
  162. package/dist/ui/shared/rpc-client.d.ts +14 -0
  163. package/dist/ui/shared/rpc-client.js +72 -0
  164. package/dist/ui/shared/theme-adaptation.d.ts +10 -0
  165. package/dist/ui/shared/theme-adaptation.js +118 -0
  166. package/dist/ui/shared/tool-header.d.ts +9 -0
  167. package/dist/ui/shared/tool-header.js +25 -0
  168. package/dist/ui/shared/tool-shell.d.ts +16 -0
  169. package/dist/ui/shared/tool-shell.js +65 -0
  170. package/dist/ui/shared/widget-state.d.ts +28 -0
  171. package/dist/ui/shared/widget-state.js +60 -0
  172. package/dist/utils/capture.d.ts +1 -0
  173. package/dist/utils/capture.js +10 -4
  174. package/dist/utils/files/docx.d.ts +34 -0
  175. package/dist/utils/files/docx.js +145 -0
  176. package/dist/utils/files/text.js +9 -1
  177. package/dist/version.d.ts +1 -1
  178. package/dist/version.js +1 -1
  179. package/package.json +5 -2
@@ -0,0 +1,260 @@
1
+ import { createRequire } from 'module';
2
+ const require = createRequire(import.meta.url);
3
+ // @ts-ignore
4
+ import * as docx from 'docx';
5
+ const { AlignmentType, Document, HeadingLevel, Paragraph, Table, TableCell, TableRow, TextRun, WidthType, Packer, } = docx;
6
+ import { DocxErrorCode, withErrorContext } from '../errors.js';
7
+ import { normalizeLineEndings, prepareImageForDocx, createImageRun, } from '../utils.js';
8
+ export async function createDocxFromMarkdown(markdown, options = {}) {
9
+ return withErrorContext(async () => {
10
+ const children = [];
11
+ const baseDir = options.baseDir;
12
+ const lines = normalizeLineEndings(markdown).split('\n');
13
+ let i = 0;
14
+ while (i < lines.length) {
15
+ const rawLine = lines[i];
16
+ const line = rawLine.trimEnd();
17
+ // Skip empty lines
18
+ if (!line.trim()) {
19
+ i++;
20
+ continue;
21
+ }
22
+ // 1) Markdown table detection
23
+ const isHeader = isTableHeaderLine(line);
24
+ const hasSeparator = i + 1 < lines.length && isTableSeparatorLine(lines[i + 1]);
25
+ if (isHeader && hasSeparator) {
26
+ const tableLines = [line];
27
+ i++;
28
+ tableLines.push(lines[i]); // Add separator line
29
+ i++;
30
+ // Collect all subsequent table rows
31
+ while (i < lines.length) {
32
+ const nextLine = lines[i].trim();
33
+ if (!nextLine || !isTableRowLine(nextLine)) {
34
+ break;
35
+ }
36
+ tableLines.push(nextLine);
37
+ i++;
38
+ }
39
+ try {
40
+ const table = createTableFromMarkdown(tableLines);
41
+ children.push(table);
42
+ }
43
+ catch (error) {
44
+ console.error('[DOCX Build] Failed to create table:', error);
45
+ // Fallback: add table lines as plain text
46
+ for (const tableLine of tableLines) {
47
+ children.push(new Paragraph({ text: tableLine }));
48
+ }
49
+ }
50
+ continue;
51
+ }
52
+ // 2) Images
53
+ const imageMatch = line.match(/!\[([^\]]*)\]\(([^)]+)\)/);
54
+ if (imageMatch) {
55
+ const altText = imageMatch[1] || '';
56
+ const src = imageMatch[2];
57
+ try {
58
+ const imageData = await prepareImageForDocx(src, altText, baseDir);
59
+ const imageRun = createImageRun(imageData);
60
+ const paragraph = new Paragraph({
61
+ children: [imageRun],
62
+ alignment: AlignmentType.CENTER,
63
+ });
64
+ children.push(paragraph);
65
+ }
66
+ catch (error) {
67
+ console.warn(`Failed to embed image ${src}:`, error);
68
+ children.push(new Paragraph({
69
+ text: `[Image: ${altText || src}]`,
70
+ }));
71
+ }
72
+ i++;
73
+ continue;
74
+ }
75
+ // 3) Headings
76
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
77
+ if (headingMatch) {
78
+ const level = headingMatch[1].length;
79
+ const text = headingMatch[2].trim();
80
+ const textRuns = parseInlineFormatting(text);
81
+ const heading = new Paragraph({
82
+ children: textRuns,
83
+ heading: getHeadingLevel(level),
84
+ });
85
+ children.push(heading);
86
+ i++;
87
+ continue;
88
+ }
89
+ // 4) Regular paragraphs
90
+ const textRuns = parseInlineFormatting(rawLine);
91
+ const paragraph = new Paragraph({
92
+ children: textRuns,
93
+ });
94
+ children.push(paragraph);
95
+ i++;
96
+ }
97
+ const doc = new Document({
98
+ sections: [{
99
+ properties: {},
100
+ children: children,
101
+ }],
102
+ });
103
+ return await Packer.toBuffer(doc);
104
+ }, DocxErrorCode.DOCX_CREATE_FAILED, { markdownLength: markdown.length });
105
+ }
106
+ // ============================================================================
107
+ // Helper Functions
108
+ // ============================================================================
109
+ function isTableHeaderLine(line) {
110
+ const trimmed = line.trim();
111
+ if (!trimmed.includes('|'))
112
+ return false;
113
+ const startsWithPipe = trimmed.startsWith('|');
114
+ const endsWithPipe = trimmed.endsWith('|');
115
+ const pipeCount = (trimmed.match(/\|/g) || []).length;
116
+ if (startsWithPipe && endsWithPipe) {
117
+ return pipeCount >= 2;
118
+ }
119
+ return pipeCount >= 1;
120
+ }
121
+ function isTableSeparatorLine(line) {
122
+ const trimmed = line.trim();
123
+ if (!trimmed.includes('|'))
124
+ return false;
125
+ let content = trimmed;
126
+ if (content.startsWith('|'))
127
+ content = content.substring(1);
128
+ if (content.endsWith('|'))
129
+ content = content.substring(0, content.length - 1);
130
+ const parts = content.split('|');
131
+ let validParts = 0;
132
+ for (const part of parts) {
133
+ const cleaned = part.trim();
134
+ if (cleaned.length === 0)
135
+ continue;
136
+ if (/^:?-+:?$/.test(cleaned)) {
137
+ validParts++;
138
+ }
139
+ else {
140
+ return false;
141
+ }
142
+ }
143
+ return validParts > 0;
144
+ }
145
+ function isTableRowLine(line) {
146
+ const trimmed = line.trim();
147
+ if (!trimmed.includes('|'))
148
+ return false;
149
+ if (isTableSeparatorLine(trimmed))
150
+ return false;
151
+ const pipeCount = (trimmed.match(/\|/g) || []).length;
152
+ return pipeCount >= 1;
153
+ }
154
+ function splitTableRow(line) {
155
+ const trimmed = line.trim();
156
+ let withoutBorders = trimmed;
157
+ if (withoutBorders.startsWith('|')) {
158
+ withoutBorders = withoutBorders.substring(1);
159
+ }
160
+ if (withoutBorders.endsWith('|')) {
161
+ withoutBorders = withoutBorders.substring(0, withoutBorders.length - 1);
162
+ }
163
+ return withoutBorders.split('|').map(cell => cell.trim());
164
+ }
165
+ function createTableFromMarkdown(lines) {
166
+ if (lines.length < 2) {
167
+ return new Table({ rows: [] });
168
+ }
169
+ const headerCells = splitTableRow(lines[0]);
170
+ const rows = [];
171
+ // Header row
172
+ rows.push(new TableRow({
173
+ children: headerCells.map((cell) => {
174
+ const textRuns = parseInlineFormatting(cell.trim());
175
+ textRuns.forEach(run => {
176
+ run.bold = true;
177
+ });
178
+ return new TableCell({
179
+ children: [
180
+ new Paragraph({
181
+ children: textRuns,
182
+ alignment: AlignmentType.CENTER,
183
+ }),
184
+ ],
185
+ });
186
+ }),
187
+ }));
188
+ // Data rows (skip separator at index 1)
189
+ for (let i = 2; i < lines.length; i++) {
190
+ const cells = splitTableRow(lines[i]);
191
+ rows.push(new TableRow({
192
+ children: cells.map((cell) => {
193
+ const textRuns = parseInlineFormatting(cell.trim());
194
+ return new TableCell({
195
+ children: [
196
+ new Paragraph({
197
+ children: textRuns,
198
+ }),
199
+ ],
200
+ });
201
+ }),
202
+ }));
203
+ }
204
+ return new Table({
205
+ width: { size: 100, type: WidthType.PERCENTAGE },
206
+ rows,
207
+ });
208
+ }
209
+ function parseInlineFormatting(text) {
210
+ const runs = [];
211
+ let currentText = '';
212
+ let i = 0;
213
+ while (i < text.length) {
214
+ // Check for **bold**
215
+ if (text.substring(i, i + 2) === '**') {
216
+ if (currentText) {
217
+ runs.push(new TextRun({ text: currentText }));
218
+ currentText = '';
219
+ }
220
+ const closeIndex = text.indexOf('**', i + 2);
221
+ if (closeIndex !== -1) {
222
+ const boldText = text.substring(i + 2, closeIndex);
223
+ runs.push(new TextRun({ text: boldText, bold: true }));
224
+ i = closeIndex + 2;
225
+ continue;
226
+ }
227
+ }
228
+ // Check for *italic*
229
+ if (text[i] === '*' && text[i + 1] !== '*') {
230
+ if (currentText) {
231
+ runs.push(new TextRun({ text: currentText }));
232
+ currentText = '';
233
+ }
234
+ const closeIndex = text.indexOf('*', i + 1);
235
+ if (closeIndex !== -1) {
236
+ const italicText = text.substring(i + 1, closeIndex);
237
+ runs.push(new TextRun({ text: italicText, italics: true }));
238
+ i = closeIndex + 1;
239
+ continue;
240
+ }
241
+ }
242
+ currentText += text[i];
243
+ i++;
244
+ }
245
+ if (currentText) {
246
+ runs.push(new TextRun({ text: currentText }));
247
+ }
248
+ return runs.length > 0 ? runs : [new TextRun({ text: text })];
249
+ }
250
+ function getHeadingLevel(level) {
251
+ const levelMap = {
252
+ 1: HeadingLevel.HEADING_1,
253
+ 2: HeadingLevel.HEADING_2,
254
+ 3: HeadingLevel.HEADING_3,
255
+ 4: HeadingLevel.HEADING_4,
256
+ 5: HeadingLevel.HEADING_5,
257
+ 6: HeadingLevel.HEADING_6,
258
+ };
259
+ return levelMap[level] ?? HeadingLevel.HEADING_1;
260
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Paragraph builder — creates w:p elements with optional styles.
3
+ */
4
+ import type { DocxContentParagraph } from '../types.js';
5
+ /**
6
+ * Build a paragraph element from content structure.
7
+ *
8
+ * @param doc The XML document
9
+ * @param item The paragraph content item
10
+ * @returns A w:p element
11
+ */
12
+ export declare function buildParagraph(doc: Document, item: DocxContentParagraph): Element;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Paragraph builder — creates w:p elements with optional styles.
3
+ */
4
+ /**
5
+ * Build a paragraph element from content structure.
6
+ *
7
+ * @param doc The XML document
8
+ * @param item The paragraph content item
9
+ * @returns A w:p element
10
+ */
11
+ export function buildParagraph(doc, item) {
12
+ const p = doc.createElement('w:p');
13
+ // Set style if provided
14
+ if (item.style) {
15
+ const pPr = doc.createElement('w:pPr');
16
+ const pStyle = doc.createElement('w:pStyle');
17
+ pStyle.setAttribute('w:val', item.style);
18
+ pPr.appendChild(pStyle);
19
+ p.appendChild(pPr);
20
+ }
21
+ // Add text run
22
+ const r = doc.createElement('w:r');
23
+ const t = doc.createElement('w:t');
24
+ t.setAttribute('xml:space', 'preserve');
25
+ t.textContent = item.text;
26
+ r.appendChild(t);
27
+ p.appendChild(r);
28
+ return p;
29
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Table builder — creates w:tbl elements with headers, rows, and styling.
3
+ */
4
+ import type { DocxContentTable, InsertTableOp } from '../types.js';
5
+ /**
6
+ * Build a table element from content structure or operation.
7
+ */
8
+ export declare function buildTable(doc: Document, spec: DocxContentTable | InsertTableOp): Element;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Table builder — creates w:tbl elements with headers, rows, and styling.
3
+ */
4
+ /**
5
+ * Build a table element from content structure or operation.
6
+ */
7
+ export function buildTable(doc, spec) {
8
+ const tbl = doc.createElement('w:tbl');
9
+ // Table properties
10
+ const tblPr = doc.createElement('w:tblPr');
11
+ if (spec.style) {
12
+ const tblStyle = doc.createElement('w:tblStyle');
13
+ tblStyle.setAttribute('w:val', spec.style);
14
+ tblPr.appendChild(tblStyle);
15
+ }
16
+ const tblW = doc.createElement('w:tblW');
17
+ tblW.setAttribute('w:w', '0');
18
+ tblW.setAttribute('w:type', 'auto');
19
+ tblPr.appendChild(tblW);
20
+ // Table borders
21
+ const tblBorders = doc.createElement('w:tblBorders');
22
+ for (const side of ['top', 'left', 'bottom', 'right', 'insideH', 'insideV']) {
23
+ const border = doc.createElement(`w:${side}`);
24
+ border.setAttribute('w:val', 'single');
25
+ border.setAttribute('w:sz', '4');
26
+ border.setAttribute('w:space', '0');
27
+ border.setAttribute('w:color', '000000');
28
+ tblBorders.appendChild(border);
29
+ }
30
+ tblPr.appendChild(tblBorders);
31
+ tbl.appendChild(tblPr);
32
+ // Table grid
33
+ const colCount = spec.headers
34
+ ? spec.headers.length
35
+ : spec.rows.length > 0
36
+ ? spec.rows[0].length
37
+ : 0;
38
+ if (colCount > 0) {
39
+ const tblGrid = doc.createElement('w:tblGrid');
40
+ for (let c = 0; c < colCount; c++) {
41
+ const gridCol = doc.createElement('w:gridCol');
42
+ const w = spec.colWidths?.[c] ?? Math.floor(9000 / colCount);
43
+ gridCol.setAttribute('w:w', String(w));
44
+ tblGrid.appendChild(gridCol);
45
+ }
46
+ tbl.appendChild(tblGrid);
47
+ }
48
+ // Helper to build a cell
49
+ const buildCell = (text, isHeader, widthTwips) => {
50
+ const tc = doc.createElement('w:tc');
51
+ if (widthTwips) {
52
+ const tcPr = doc.createElement('w:tcPr');
53
+ const tcW = doc.createElement('w:tcW');
54
+ tcW.setAttribute('w:w', String(widthTwips));
55
+ tcW.setAttribute('w:type', 'dxa');
56
+ tcPr.appendChild(tcW);
57
+ tc.appendChild(tcPr);
58
+ }
59
+ const p = doc.createElement('w:p');
60
+ const r = doc.createElement('w:r');
61
+ if (isHeader) {
62
+ const rPr = doc.createElement('w:rPr');
63
+ const b = doc.createElement('w:b');
64
+ rPr.appendChild(b);
65
+ r.appendChild(rPr);
66
+ }
67
+ const t = doc.createElement('w:t');
68
+ t.setAttribute('xml:space', 'preserve');
69
+ t.textContent = text;
70
+ r.appendChild(t);
71
+ p.appendChild(r);
72
+ tc.appendChild(p);
73
+ return tc;
74
+ };
75
+ // Header row
76
+ if (spec.headers && spec.headers.length > 0) {
77
+ const tr = doc.createElement('w:tr');
78
+ for (let i = 0; i < spec.headers.length; i++) {
79
+ const width = spec.colWidths?.[i];
80
+ tr.appendChild(buildCell(spec.headers[i], true, width));
81
+ }
82
+ tbl.appendChild(tr);
83
+ }
84
+ // Data rows
85
+ for (const row of spec.rows) {
86
+ const tr = doc.createElement('w:tr');
87
+ for (let i = 0; i < row.length; i++) {
88
+ const width = spec.colWidths?.[i];
89
+ tr.appendChild(buildCell(row[i], false, width));
90
+ }
91
+ tbl.appendChild(tr);
92
+ }
93
+ return tbl;
94
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * XML escaping utilities.
3
+ */
4
+ export declare function escapeXml(s: string): string;
5
+ export declare function escapeXmlAttr(s: string): string;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * XML escaping utilities.
3
+ */
4
+ export function escapeXml(s) {
5
+ return s
6
+ .replace(/&/g, '&amp;')
7
+ .replace(/</g, '&lt;')
8
+ .replace(/>/g, '&gt;')
9
+ .replace(/"/g, '&quot;')
10
+ .replace(/'/g, '&apos;');
11
+ }
12
+ export function escapeXmlAttr(s) {
13
+ return s
14
+ .replace(/&/g, '&amp;')
15
+ .replace(/"/g, '&quot;')
16
+ .replace(/</g, '&lt;')
17
+ .replace(/>/g, '&gt;');
18
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * DOCX constants — shared values used across the module.
3
+ */
4
+ export declare const IMAGE_MIME_TYPES: Record<string, string>;
5
+ export declare function getMimeType(ext: string): string;
6
+ /**
7
+ * Convert pixels to EMU (English Metric Units).
8
+ * 1 inch = 914400 EMU, 1 px ≈ 9525 EMU (at 96 DPI)
9
+ */
10
+ export declare const PX_TO_EMU = 9525;
11
+ export declare function pixelsToEmu(px: number): number;
12
+ export declare const NAMESPACES: {
13
+ readonly W: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
14
+ readonly WP: "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing";
15
+ readonly A: "http://schemas.openxmlformats.org/drawingml/2006/main";
16
+ readonly PIC: "http://schemas.openxmlformats.org/drawingml/2006/picture";
17
+ readonly R: "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
18
+ readonly RELS: "http://schemas.openxmlformats.org/package/2006/relationships";
19
+ };
20
+ export declare const DEFAULT_IMAGE_WIDTH = 300;
21
+ export declare const DEFAULT_IMAGE_HEIGHT = 200;
22
+ export declare const DOCX_PATHS: {
23
+ readonly CONTENT_TYPES: "[Content_Types].xml";
24
+ readonly DOCUMENT_XML: "word/document.xml";
25
+ readonly DOCUMENT_RELS: "word/_rels/document.xml.rels";
26
+ readonly ROOT_RELS: "_rels/.rels";
27
+ readonly STYLES_XML: "word/styles.xml";
28
+ readonly SETTINGS_XML: "word/settings.xml";
29
+ readonly WEB_SETTINGS_XML: "word/webSettings.xml";
30
+ readonly FONT_TABLE_XML: "word/fontTable.xml";
31
+ readonly MEDIA_FOLDER: "word/media";
32
+ };
@@ -0,0 +1,61 @@
1
+ /**
2
+ * DOCX constants — shared values used across the module.
3
+ */
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',
17
+ };
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',
42
+ };
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',
61
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Markdown → HTML Converter
3
+ *
4
+ * Provides markdown-to-HTML conversion for DOCX content operations
5
+ * (appendMarkdown, insertTable with markdown input, etc.).
6
+ *
7
+ * @module docx/converters/markdown-to-html
8
+ */
9
+ /** Convert basic markdown text to HTML. */
10
+ export declare function markdownToHtml(markdown: string): string;
11
+ /**
12
+ * Convert a markdown table to an HTML `<table>` with inline CSS borders.
13
+ * html-to-docx needs explicit border styles — without them, tables are invisible in Word.
14
+ */
15
+ export declare function markdownTableToHtml(markdown: string): string;
16
+ /** Build a markdown table string from a 2-D rows array (first row = header). */
17
+ export declare function buildMarkdownTableFromRows(rows: string[][]): string;
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Markdown → HTML Converter
3
+ *
4
+ * Provides markdown-to-HTML conversion for DOCX content operations
5
+ * (appendMarkdown, insertTable with markdown input, etc.).
6
+ *
7
+ * @module docx/converters/markdown-to-html
8
+ */
9
+ import { escapeHtml } from '../utils/escaping.js';
10
+ // ─── Markdown → HTML ─────────────────────────────────────────────────────────
11
+ /** Convert basic markdown text to HTML. */
12
+ export function markdownToHtml(markdown) {
13
+ if (!markdown?.trim())
14
+ return '';
15
+ let html = markdown.trim();
16
+ // Headings (h6 → h1 to avoid partial matches)
17
+ html = html.replace(/^######\s+(.+)$/gm, '<h6>$1</h6>');
18
+ html = html.replace(/^#####\s+(.+)$/gm, '<h5>$1</h5>');
19
+ html = html.replace(/^####\s+(.+)$/gm, '<h4>$1</h4>');
20
+ html = html.replace(/^###\s+(.+)$/gm, '<h3>$1</h3>');
21
+ html = html.replace(/^##\s+(.+)$/gm, '<h2>$1</h2>');
22
+ html = html.replace(/^#\s+(.+)$/gm, '<h1>$1</h1>');
23
+ // Bold (before italic to avoid conflicts)
24
+ html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
25
+ html = html.replace(/__(.+?)__/g, '<strong>$1</strong>');
26
+ // Italic
27
+ html = html.replace(/\*(.+?)\*/g, '<em>$1</em>');
28
+ html = html.replace(/_(.+?)_/g, '<em>$1</em>');
29
+ // Images & links
30
+ html = html.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1" />');
31
+ html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
32
+ // Inline code
33
+ html = html.replace(/`([^`]+)`/g, '<code>$1</code>');
34
+ // Paragraphs (double-newline separated)
35
+ return html
36
+ .split(/\n\n+/)
37
+ .map((p) => p.trim())
38
+ .filter(Boolean)
39
+ .map((p) => {
40
+ // Don't wrap blocks that are already complete HTML elements
41
+ if (p.startsWith('<') && p.endsWith('>'))
42
+ return p.replace(/\n/g, '<br>');
43
+ return `<p>${p.replace(/\n/g, '<br>')}</p>`;
44
+ })
45
+ .join('\n');
46
+ }
47
+ // ─── Markdown Table → HTML ───────────────────────────────────────────────────
48
+ /** Parse a single markdown table row into cell values. */
49
+ function parseTableRow(row) {
50
+ return row.replace(/^\|/, '').replace(/\|$/, '').split('|').map((c) => c.trim());
51
+ }
52
+ /**
53
+ * Convert a markdown table to an HTML `<table>` with inline CSS borders.
54
+ * html-to-docx needs explicit border styles — without them, tables are invisible in Word.
55
+ */
56
+ export function markdownTableToHtml(markdown) {
57
+ if (!markdown?.trim())
58
+ return '';
59
+ const lines = markdown
60
+ .trim()
61
+ .split('\n')
62
+ .map((l) => l.trim())
63
+ .filter(Boolean);
64
+ if (lines.length < 2)
65
+ return '';
66
+ const headerCells = parseTableRow(lines[0]);
67
+ if (headerCells.length === 0)
68
+ return '';
69
+ const dataRows = lines.slice(2).map(parseTableRow);
70
+ const BORDER = 'border:1px solid #000;';
71
+ const CELL = `${BORDER} padding:6px 10px;`;
72
+ const HEADER = `${CELL} background-color:#f2f2f2; font-weight:bold;`;
73
+ let html = `<table style="border-collapse:collapse; width:100%; ${BORDER}">\n`;
74
+ html += ' <thead>\n <tr>\n';
75
+ for (const cell of headerCells) {
76
+ html += ` <th style="${HEADER}">${escapeHtml(cell)}</th>\n`;
77
+ }
78
+ html += ' </tr>\n </thead>\n';
79
+ if (dataRows.length > 0) {
80
+ html += ' <tbody>\n';
81
+ for (const row of dataRows) {
82
+ html += ' <tr>\n';
83
+ for (const cell of row) {
84
+ html += ` <td style="${CELL}">${escapeHtml(cell)}</td>\n`;
85
+ }
86
+ html += ' </tr>\n';
87
+ }
88
+ html += ' </tbody>\n';
89
+ }
90
+ return html + '</table>';
91
+ }
92
+ // ─── Rows Array → Markdown Table ─────────────────────────────────────────────
93
+ /** Build a markdown table string from a 2-D rows array (first row = header). */
94
+ export function buildMarkdownTableFromRows(rows) {
95
+ if (!rows?.length)
96
+ return '';
97
+ const header = rows[0];
98
+ if (!header?.length)
99
+ return '';
100
+ const lines = [
101
+ `| ${header.join(' | ')} |`,
102
+ `| ${header.map(() => '---').join(' | ')} |`,
103
+ ];
104
+ for (const row of rows.slice(1)) {
105
+ const padded = [...row];
106
+ while (padded.length < header.length)
107
+ padded.push('');
108
+ lines.push(`| ${padded.slice(0, header.length).join(' | ')} |`);
109
+ }
110
+ return lines.join('\n');
111
+ }