@bobfrankston/mailx-service 0.1.47
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/ai-usage.d.ts +32 -0
- package/ai-usage.d.ts.map +1 -0
- package/ai-usage.js +98 -0
- package/ai-usage.js.map +1 -0
- package/charset.d.ts +15 -0
- package/charset.d.ts.map +1 -0
- package/charset.js +61 -0
- package/charset.js.map +1 -0
- package/db-worker-client.d.ts +32 -0
- package/db-worker-client.d.ts.map +1 -0
- package/db-worker-client.js +66 -0
- package/db-worker-client.js.map +1 -0
- package/db-worker.d.ts +39 -0
- package/db-worker.d.ts.map +1 -0
- package/db-worker.js +115 -0
- package/db-worker.js.map +1 -0
- package/google-sync.d.ts +151 -0
- package/google-sync.d.ts.map +1 -0
- package/google-sync.js +259 -0
- package/google-sync.js.map +1 -0
- package/html-to-docx.d.ts +1 -0
- package/index.d.ts +1102 -0
- package/index.d.ts.map +1 -0
- package/index.js +5476 -0
- package/index.js.map +1 -0
- package/jsonrpc.d.ts +29 -0
- package/jsonrpc.d.ts.map +1 -0
- package/jsonrpc.js +481 -0
- package/jsonrpc.js.map +1 -0
- package/local-store.d.ts +10 -0
- package/local-store.d.ts.map +1 -0
- package/local-store.js +9 -0
- package/local-store.js.map +1 -0
- package/package.json +53 -0
- package/reconciler.d.ts +90 -0
- package/reconciler.d.ts.map +1 -0
- package/reconciler.js +277 -0
- package/reconciler.js.map +1 -0
- package/sync-queue.d.ts +127 -0
- package/sync-queue.d.ts.map +1 -0
- package/sync-queue.js +271 -0
- package/sync-queue.js.map +1 -0
- package/sync-worker-client.d.ts +33 -0
- package/sync-worker-client.d.ts.map +1 -0
- package/sync-worker-client.js +89 -0
- package/sync-worker-client.js.map +1 -0
- package/sync-worker.d.ts +33 -0
- package/sync-worker.d.ts.map +1 -0
- package/sync-worker.js +143 -0
- package/sync-worker.js.map +1 -0
- package/word-html.d.ts +41 -0
- package/word-html.d.ts.map +1 -0
- package/word-html.js +122 -0
- package/word-html.js.map +1 -0
package/word-html.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Word's own HTML export → a body fragment compose can take.
|
|
3
|
+
*
|
|
4
|
+
* 2026-09-13 20:10 EDT — Claude Code (Fable 5.1), at Bob's direction ("go
|
|
5
|
+
* ahead and build the export fragment route").
|
|
6
|
+
*
|
|
7
|
+
* The Edit-in-Word autosave sidecar calls Word's `Range.ExportFragment(path,
|
|
8
|
+
* wdFormatFilteredHTML)` over COM on every change, which writes Word's
|
|
9
|
+
* filtered-HTML rendering of the document WITHOUT changing the document's
|
|
10
|
+
* own file or format. That HTML keeps colours, fonts, alignment, spacing and
|
|
11
|
+
* paragraph borders as inline styles — the things mammoth's docx→HTML throws
|
|
12
|
+
* away (measured on a real reply 2026-09-13: mammoth returned only <p>, <a>
|
|
13
|
+
* and <br>). This module turns that export into a fragment: body content
|
|
14
|
+
* only, Word's class and comment cruft removed, sidecar image files inlined.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Paragraph formatting that the generated .docx carries as its DOCUMENT
|
|
18
|
+
* DEFAULTS, as Word's export spells it.
|
|
19
|
+
*
|
|
20
|
+
* 2026-09-27 16:45 EDT — Claude Code (Fable 5.1), after Bob's report ("when I
|
|
21
|
+
* roundtrip through word I now see spurious style settings").
|
|
22
|
+
* html-to-docx hardcodes `<w:pPrDefault>` in the styles.xml it writes:
|
|
23
|
+
* `<w:spacing w:after="120" w:line="240" w:lineRule="atLeast"/>` — 6pt after,
|
|
24
|
+
* line height 12pt. Word's export states its own p.MsoNormal in a <style>
|
|
25
|
+
* block and puts the difference on every paragraph inline, so each paragraph
|
|
26
|
+
* came back as `style='margin-bottom:6.0pt;line-height:12.0pt'`. Nobody chose
|
|
27
|
+
* those values, and a fixed 12pt line height cramps any reader whose font is
|
|
28
|
+
* larger. They are the baseline of the document we handed to Word, not an edit.
|
|
29
|
+
*
|
|
30
|
+
* The values belong to html-to-docx (1.8.0), which has no option for them. If
|
|
31
|
+
* the library changes them the declarations reappear in compose; re-measure
|
|
32
|
+
* with tests/word-docx-probe.mjs.
|
|
33
|
+
*/
|
|
34
|
+
export declare const DOCX_BASELINE_PARAGRAPH_STYLE: Record<string, string>;
|
|
35
|
+
/** Remove inline declarations that only restate the generated document's own
|
|
36
|
+
* defaults. A value the user set in Word differs from the baseline and is
|
|
37
|
+
* kept. A style attribute left with nothing in it is removed. */
|
|
38
|
+
export declare function dropBaselineStyles(html: string): string;
|
|
39
|
+
/** Read a Word filtered-HTML export and return body-content HTML for compose. */
|
|
40
|
+
export declare function wordHtmlToFragment(htmPath: string): string;
|
|
41
|
+
//# sourceMappingURL=word-html.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"word-html.d.ts","sourceRoot":"","sources":["word-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA8CH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGhE,CAAC;AAEF;;kEAEkE;AAClE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAcvD;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAiB1D"}
|
package/word-html.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Word's own HTML export → a body fragment compose can take.
|
|
3
|
+
*
|
|
4
|
+
* 2026-09-13 20:10 EDT — Claude Code (Fable 5.1), at Bob's direction ("go
|
|
5
|
+
* ahead and build the export fragment route").
|
|
6
|
+
*
|
|
7
|
+
* The Edit-in-Word autosave sidecar calls Word's `Range.ExportFragment(path,
|
|
8
|
+
* wdFormatFilteredHTML)` over COM on every change, which writes Word's
|
|
9
|
+
* filtered-HTML rendering of the document WITHOUT changing the document's
|
|
10
|
+
* own file or format. That HTML keeps colours, fonts, alignment, spacing and
|
|
11
|
+
* paragraph borders as inline styles — the things mammoth's docx→HTML throws
|
|
12
|
+
* away (measured on a real reply 2026-09-13: mammoth returned only <p>, <a>
|
|
13
|
+
* and <br>). This module turns that export into a fragment: body content
|
|
14
|
+
* only, Word's class and comment cruft removed, sidecar image files inlined.
|
|
15
|
+
*/
|
|
16
|
+
import fs from "node:fs";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
/** Decode Word's export honouring its own charset meta (utf-8 in every
|
|
19
|
+
* export seen so far, but Word has written windows-1252 in the past). */
|
|
20
|
+
function decodeWordHtml(bytes) {
|
|
21
|
+
const probe = bytes.subarray(0, 2048).toString("latin1");
|
|
22
|
+
const m = /charset=["']?([\w-]+)/i.exec(probe);
|
|
23
|
+
const charset = (m?.[1] || "utf-8").toLowerCase();
|
|
24
|
+
try {
|
|
25
|
+
return new TextDecoder(charset).decode(bytes);
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
// An unknown label falls back to utf-8 rather than failing the
|
|
29
|
+
// mirror; the caller logs the fragment length either way.
|
|
30
|
+
console.warn(` [word-edit] unknown charset "${charset}" in Word export — decoding as utf-8 (${e?.message || e})`);
|
|
31
|
+
return bytes.toString("utf-8");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const IMAGE_MIME = {
|
|
35
|
+
".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".gif": "image/gif",
|
|
36
|
+
".bmp": "image/bmp", ".webp": "image/webp", ".svg": "image/svg+xml", ".emf": "image/emf", ".wmf": "image/wmf",
|
|
37
|
+
};
|
|
38
|
+
/** Turn `<img src="x_files/image001.png">` into a data: URI. Word writes
|
|
39
|
+
* images next to the export in a `<name>_files` folder; compose already
|
|
40
|
+
* converts data: images to cid parts on send. A missing file is left as
|
|
41
|
+
* is and logged — the text still mirrors. */
|
|
42
|
+
function inlineImages(html, baseDir) {
|
|
43
|
+
return html.replace(/<img\b[^>]*\bsrc\s*=\s*["']?([^"'\s>]+)["']?[^>]*>/gi, (tag, src) => {
|
|
44
|
+
if (/^(data|https?|cid):/i.test(src))
|
|
45
|
+
return tag;
|
|
46
|
+
const file = path.resolve(baseDir, decodeURIComponent(src));
|
|
47
|
+
const mime = IMAGE_MIME[path.extname(file).toLowerCase()];
|
|
48
|
+
if (!mime)
|
|
49
|
+
return tag;
|
|
50
|
+
try {
|
|
51
|
+
const data = fs.readFileSync(file).toString("base64");
|
|
52
|
+
return tag.replace(src, `data:${mime};base64,${data}`);
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
console.warn(` [word-edit] image ${src} from the Word export could not be read: ${e?.message || e}`);
|
|
56
|
+
return tag;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Paragraph formatting that the generated .docx carries as its DOCUMENT
|
|
62
|
+
* DEFAULTS, as Word's export spells it.
|
|
63
|
+
*
|
|
64
|
+
* 2026-09-27 16:45 EDT — Claude Code (Fable 5.1), after Bob's report ("when I
|
|
65
|
+
* roundtrip through word I now see spurious style settings").
|
|
66
|
+
* html-to-docx hardcodes `<w:pPrDefault>` in the styles.xml it writes:
|
|
67
|
+
* `<w:spacing w:after="120" w:line="240" w:lineRule="atLeast"/>` — 6pt after,
|
|
68
|
+
* line height 12pt. Word's export states its own p.MsoNormal in a <style>
|
|
69
|
+
* block and puts the difference on every paragraph inline, so each paragraph
|
|
70
|
+
* came back as `style='margin-bottom:6.0pt;line-height:12.0pt'`. Nobody chose
|
|
71
|
+
* those values, and a fixed 12pt line height cramps any reader whose font is
|
|
72
|
+
* larger. They are the baseline of the document we handed to Word, not an edit.
|
|
73
|
+
*
|
|
74
|
+
* The values belong to html-to-docx (1.8.0), which has no option for them. If
|
|
75
|
+
* the library changes them the declarations reappear in compose; re-measure
|
|
76
|
+
* with tests/word-docx-probe.mjs.
|
|
77
|
+
*/
|
|
78
|
+
export const DOCX_BASELINE_PARAGRAPH_STYLE = {
|
|
79
|
+
"margin-bottom": "6.0pt",
|
|
80
|
+
"line-height": "12.0pt",
|
|
81
|
+
};
|
|
82
|
+
/** Remove inline declarations that only restate the generated document's own
|
|
83
|
+
* defaults. A value the user set in Word differs from the baseline and is
|
|
84
|
+
* kept. A style attribute left with nothing in it is removed. */
|
|
85
|
+
export function dropBaselineStyles(html) {
|
|
86
|
+
return html.replace(/\sstyle\s*=\s*(["'])([\s\S]*?)\1/gi, (attr, quote, css) => {
|
|
87
|
+
const declarations = css.split(";").map(d => d.trim()).filter(d => d);
|
|
88
|
+
const kept = declarations.filter(d => {
|
|
89
|
+
const colon = d.indexOf(":");
|
|
90
|
+
if (colon < 0)
|
|
91
|
+
return true;
|
|
92
|
+
const property = d.slice(0, colon).trim().toLowerCase();
|
|
93
|
+
const value = d.slice(colon + 1).trim().toLowerCase();
|
|
94
|
+
return DOCX_BASELINE_PARAGRAPH_STYLE[property] !== value;
|
|
95
|
+
});
|
|
96
|
+
if (kept.length === declarations.length)
|
|
97
|
+
return attr;
|
|
98
|
+
if (kept.length === 0)
|
|
99
|
+
return "";
|
|
100
|
+
return ` style=${quote}${kept.join(";")}${quote}`;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/** Read a Word filtered-HTML export and return body-content HTML for compose. */
|
|
104
|
+
export function wordHtmlToFragment(htmPath) {
|
|
105
|
+
const html = decodeWordHtml(fs.readFileSync(htmPath));
|
|
106
|
+
const bodyMatch = html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
|
|
107
|
+
let inner = bodyMatch ? bodyMatch[1] : html;
|
|
108
|
+
inner = inner
|
|
109
|
+
// Conditional comments around fake-list bullets, and any other comment.
|
|
110
|
+
.replace(/<!--[\s\S]*?-->/g, "")
|
|
111
|
+
// Word's paragraph/run classes; their styles live in the export's
|
|
112
|
+
// <style> block, which does not travel with the fragment.
|
|
113
|
+
.replace(/\s+class\s*=\s*["']?Mso[\w-]*["']?/gi, "")
|
|
114
|
+
// Office namespace tags (<o:p></o:p> paragraph marks) and their content-free shells.
|
|
115
|
+
.replace(/<\/?o:[^>]*>/gi, "")
|
|
116
|
+
// Word wraps the whole export in a section div; compose has no use for it.
|
|
117
|
+
.replace(/^\s*<div\s+class\s*=\s*["']?WordSection\d*["']?[^>]*>([\s\S]*)<\/div>\s*$/i, "$1");
|
|
118
|
+
inner = dropBaselineStyles(inner);
|
|
119
|
+
inner = inlineImages(inner, path.dirname(htmPath));
|
|
120
|
+
return inner.trim();
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=word-html.js.map
|
package/word-html.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"word-html.js","sourceRoot":"","sources":["word-html.ts"],"names":[],"mappings":"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"}
|