@bobfrankston/rmfmail 1.0.665 → 1.0.666
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/TODO.md +8 -5
- package/bin/build-bundles.mjs +96 -0
- package/client/app.bundle.js +8942 -0
- package/client/app.bundle.js.map +7 -0
- package/client/app.js +69 -2
- package/client/app.js.map +1 -1
- package/client/app.ts +69 -2
- package/client/compose/compose.bundle.js +2872 -0
- package/client/compose/compose.bundle.js.map +7 -0
- package/client/compose/compose.html +5 -1
- package/client/index.html +53 -3
- package/package.json +3 -2
package/client/app.js
CHANGED
|
@@ -1024,7 +1024,19 @@ function sanitizeQuotedBody(msg) {
|
|
|
1024
1024
|
body = body.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "");
|
|
1025
1025
|
body = body.replace(/\s+style="[^"]*"/gi, "");
|
|
1026
1026
|
body = body.replace(/\s+class="[^"]*"/gi, "");
|
|
1027
|
-
|
|
1027
|
+
// Strip layout-table attrs only off non-<img> tags. Earlier this regex
|
|
1028
|
+
// ate width/height on <img> too, which is what made App Store / Play
|
|
1029
|
+
// Store buttons render huge in quoted replies (the source ad had
|
|
1030
|
+
// explicit width="120" height="40" on each image). Q138.
|
|
1031
|
+
body = body.replace(/<(?!img\b)([^>]*?)\s+(width|height|align|valign|bgcolor|cellpadding|cellspacing|border)="[^"]*"([^>]*)>/gi, (_m, before, _attr, after) => `<${before}${after}>`);
|
|
1032
|
+
// Loop until no more matches — a single tag with multiple stripped
|
|
1033
|
+
// attrs needs more than one pass since the regex only handles one
|
|
1034
|
+
// attribute per match.
|
|
1035
|
+
let prev = "";
|
|
1036
|
+
while (prev !== body) {
|
|
1037
|
+
prev = body;
|
|
1038
|
+
body = body.replace(/<(?!img\b)([^>]*?)\s+(width|height|align|valign|bgcolor|cellpadding|cellspacing|border)="[^"]*"([^>]*)>/gi, (_m, before, _attr, after) => `<${before}${after}>`);
|
|
1039
|
+
}
|
|
1028
1040
|
body = body.replace(/<table[^>]*>/gi, "<div>").replace(/<\/table>/gi, "</div>");
|
|
1029
1041
|
body = body.replace(/<t[rdh][^>]*>/gi, "").replace(/<\/t[rdh]>/gi, " ");
|
|
1030
1042
|
body = body.replace(/<thead[^>]*>|<\/thead>|<tbody[^>]*>|<\/tbody>/gi, "");
|
|
@@ -4036,8 +4048,29 @@ optEditorTiptap?.addEventListener("change", () => {
|
|
|
4036
4048
|
saveEditorSetting("tiptap");
|
|
4037
4049
|
});
|
|
4038
4050
|
optEditorTinymce?.addEventListener("change", () => {
|
|
4039
|
-
if (optEditorTinymce.checked)
|
|
4051
|
+
if (optEditorTinymce.checked) {
|
|
4040
4052
|
saveEditorSetting("tinymce");
|
|
4053
|
+
// Q133 pre-warm — fire the TinyMCE bundle fetch right now so the
|
|
4054
|
+
// next compose-open finds tinymce.min.js already in WebView2's
|
|
4055
|
+
// HTTP cache. Without this, the first compose after picking
|
|
4056
|
+
// TinyMCE in Settings blocks ~1 s while the bundle downloads.
|
|
4057
|
+
try {
|
|
4058
|
+
// Default points at the locally bundled TinyMCE (build-tinymce.js
|
|
4059
|
+
// copies it from node_modules). Path is relative to index.html
|
|
4060
|
+
// which lives at the client/ root; compose.html (in client/compose/)
|
|
4061
|
+
// uses `../lib/tinymce/...` instead.
|
|
4062
|
+
const cdnUrl = localStorage.getItem("mailx-tinymce-cdn") || "lib/tinymce/tinymce.min.js";
|
|
4063
|
+
// Use <link rel="prefetch"> — fires the request as a hint,
|
|
4064
|
+
// doesn't execute the script (we don't want a stray global
|
|
4065
|
+
// tinymce in the main window; it lives in the compose iframe).
|
|
4066
|
+
const link = document.createElement("link");
|
|
4067
|
+
link.rel = "prefetch";
|
|
4068
|
+
link.as = "script";
|
|
4069
|
+
link.href = cdnUrl;
|
|
4070
|
+
document.head.appendChild(link);
|
|
4071
|
+
}
|
|
4072
|
+
catch { /* prefetch is best-effort */ }
|
|
4073
|
+
}
|
|
4041
4074
|
});
|
|
4042
4075
|
// External editor preference (Edit-in-Word handoff target). Stored under
|
|
4043
4076
|
// settings.externalEditor so the service can read it via loadSettings().
|
|
@@ -4460,4 +4493,38 @@ if (isApp) {
|
|
|
4460
4493
|
window.addEventListener("beforeunload", sendGeometry);
|
|
4461
4494
|
setInterval(sendGeometry, 60_000);
|
|
4462
4495
|
}
|
|
4496
|
+
// Boot-snapshot writer — captures key DOM regions to localStorage so the
|
|
4497
|
+
// next cold start hydrates instantly (see index.html's hydrateFromBootSnapshot).
|
|
4498
|
+
// Saves every 30 s and on beforeunload; pages with no inbox open just save
|
|
4499
|
+
// empty strings, which the loader treats as "skip this region."
|
|
4500
|
+
function saveBootSnapshot() {
|
|
4501
|
+
try {
|
|
4502
|
+
const folderTree = document.getElementById("folder-tree");
|
|
4503
|
+
const messageList = document.getElementById("ml-body");
|
|
4504
|
+
const folderTitle = document.getElementById("ml-folder-title");
|
|
4505
|
+
// Only save when at least one region has content. An in-flight render
|
|
4506
|
+
// (e.g. user clicked a folder, list is empty for a tick) would
|
|
4507
|
+
// otherwise clobber the previous good snapshot.
|
|
4508
|
+
const ftHtml = folderTree?.innerHTML?.trim() || "";
|
|
4509
|
+
const mlHtml = messageList?.innerHTML?.trim() || "";
|
|
4510
|
+
if (!ftHtml && !mlHtml)
|
|
4511
|
+
return;
|
|
4512
|
+
const snap = {
|
|
4513
|
+
folderTree: ftHtml,
|
|
4514
|
+
messageList: mlHtml,
|
|
4515
|
+
folderTitle: folderTitle?.innerHTML?.trim() || "",
|
|
4516
|
+
savedAt: Date.now(),
|
|
4517
|
+
};
|
|
4518
|
+
localStorage.setItem("mailx-boot-snapshot", JSON.stringify(snap));
|
|
4519
|
+
}
|
|
4520
|
+
catch { /* best-effort */ }
|
|
4521
|
+
}
|
|
4522
|
+
window.addEventListener("beforeunload", saveBootSnapshot);
|
|
4523
|
+
// Also save when the user tabs away — a Windows kill of an inactive
|
|
4524
|
+
// app would otherwise lose the snapshot up to 30 s old.
|
|
4525
|
+
document.addEventListener("visibilitychange", () => {
|
|
4526
|
+
if (document.visibilityState === "hidden")
|
|
4527
|
+
saveBootSnapshot();
|
|
4528
|
+
});
|
|
4529
|
+
setInterval(saveBootSnapshot, 30_000);
|
|
4463
4530
|
//# sourceMappingURL=app.js.map
|