@bobfrankston/rmfmail 1.2.276 → 1.2.277
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/.commitmsg +28 -23
- package/bin/build-tinymce.js +27 -0
- package/client/app.bundle.js +108 -0
- package/client/app.bundle.js.map +4 -4
- package/client/app.js +65 -0
- package/client/app.js.map +1 -1
- package/client/app.ts +59 -0
- package/client/compose/compose.bundle.js +90 -2
- package/client/compose/compose.bundle.js.map +4 -4
- package/client/compose/compose.js +26 -1
- package/client/compose/compose.js.map +1 -1
- package/client/compose/compose.ts +22 -1
- package/client/compose/editor.js +12 -1
- package/client/compose/editor.js.map +1 -1
- package/client/compose/editor.ts +17 -2
- package/client/index.html +1 -0
- package/client/lib/rmf-tiny.js +3 -0
- package/client/lib/tinymce/langs/ar-SA.js +440 -0
- package/client/lib/tinymce/langs/ar.js +441 -0
- package/client/lib/tinymce/langs/az.js +440 -0
- package/client/lib/tinymce/langs/be.js +440 -0
- package/client/lib/tinymce/langs/bg-BG.js +440 -0
- package/client/lib/tinymce/langs/bn-BD.js +440 -0
- package/client/lib/tinymce/langs/bs.js +440 -0
- package/client/lib/tinymce/langs/ca.js +440 -0
- package/client/lib/tinymce/langs/cs.js +440 -0
- package/client/lib/tinymce/langs/cy.js +440 -0
- package/client/lib/tinymce/langs/da.js +440 -0
- package/client/lib/tinymce/langs/de.js +440 -0
- package/client/lib/tinymce/langs/el.js +440 -0
- package/client/lib/tinymce/langs/eo.js +440 -0
- package/client/lib/tinymce/langs/es-MX.js +440 -0
- package/client/lib/tinymce/langs/es.js +440 -0
- package/client/lib/tinymce/langs/et.js +440 -0
- package/client/lib/tinymce/langs/eu.js +440 -0
- package/client/lib/tinymce/langs/fa.js +441 -0
- package/client/lib/tinymce/langs/fi.js +440 -0
- package/client/lib/tinymce/langs/fr-FR.js +440 -0
- package/client/lib/tinymce/langs/gl.js +440 -0
- package/client/lib/tinymce/langs/he-IL.js +440 -0
- package/client/lib/tinymce/langs/hr.js +440 -0
- package/client/lib/tinymce/langs/hu-HU.js +440 -0
- package/client/lib/tinymce/langs/hy.js +440 -0
- package/client/lib/tinymce/langs/id.js +440 -0
- package/client/lib/tinymce/langs/index.json +63 -0
- package/client/lib/tinymce/langs/is-IS.js +440 -0
- package/client/lib/tinymce/langs/it.js +440 -0
- package/client/lib/tinymce/langs/ja.js +440 -0
- package/client/lib/tinymce/langs/ka-GE.js +440 -0
- package/client/lib/tinymce/langs/kab.js +440 -0
- package/client/lib/tinymce/langs/kk.js +440 -0
- package/client/lib/tinymce/langs/ko-KR.js +440 -0
- package/client/lib/tinymce/langs/lt.js +440 -0
- package/client/lib/tinymce/langs/lv.js +440 -0
- package/client/lib/tinymce/langs/nb-NO.js +440 -0
- package/client/lib/tinymce/langs/ne.js +440 -0
- package/client/lib/tinymce/langs/nl-BE.js +440 -0
- package/client/lib/tinymce/langs/nl.js +440 -0
- package/client/lib/tinymce/langs/oc.js +440 -0
- package/client/lib/tinymce/langs/pl.js +440 -0
- package/client/lib/tinymce/langs/pt-BR.js +440 -0
- package/client/lib/tinymce/langs/pt-PT.js +440 -0
- package/client/lib/tinymce/langs/ro.js +440 -0
- package/client/lib/tinymce/langs/ru.js +440 -0
- package/client/lib/tinymce/langs/sk.js +440 -0
- package/client/lib/tinymce/langs/sl-SI.js +440 -0
- package/client/lib/tinymce/langs/sr.js +440 -0
- package/client/lib/tinymce/langs/sv-SE.js +440 -0
- package/client/lib/tinymce/langs/ta.js +440 -0
- package/client/lib/tinymce/langs/tg.js +440 -0
- package/client/lib/tinymce/langs/th-TH.js +440 -0
- package/client/lib/tinymce/langs/tr.js +440 -0
- package/client/lib/tinymce/langs/ug.js +440 -0
- package/client/lib/tinymce/langs/uk.js +440 -0
- package/client/lib/tinymce/langs/vi.js +440 -0
- package/client/lib/tinymce/langs/zh-CN.js +440 -0
- package/client/lib/tinymce/langs/zh-HK.js +440 -0
- package/client/lib/tinymce/langs/zh-MO.js +440 -0
- package/client/lib/tinymce/langs/zh-TW.js +440 -0
- package/client/lib/tinymce-langs.js +96 -0
- package/client/lib/tinymce-langs.js.map +1 -0
- package/client/lib/tinymce-langs.ts +99 -0
- package/docs/editor.md +29 -3
- package/docs/preferences.md +2 -1
- package/npmchanges.md +29 -0
- package/package.json +11 -8
- /package/packages/mailx-imap/{node_modules.npmglobalize-stash-59216 → node_modules.npmglobalize-stash-48352}/.package-lock.json +0 -0
package/client/app.ts
CHANGED
|
@@ -5670,6 +5670,65 @@ document.getElementById("opt-compose-font-size")?.addEventListener("change", (e)
|
|
|
5670
5670
|
}).catch(() => {});
|
|
5671
5671
|
});
|
|
5672
5672
|
|
|
5673
|
+
// TinyMCE UI-language picker. The options are whatever language packs
|
|
5674
|
+
// build-tinymce.js actually copied next to the script (langs/index.json), so
|
|
5675
|
+
// the menu can never offer a pack that would 404 at editor init — TinyMCE
|
|
5676
|
+
// raises a visible error notification for a missing langs/<code>.js.
|
|
5677
|
+
//
|
|
5678
|
+
// These translate the editor CHROME only. Content, the spellcheck dictionary
|
|
5679
|
+
// and Harper are untouched and stay English, which is why the control sits
|
|
5680
|
+
// under Editor rather than anywhere that reads as a global language setting.
|
|
5681
|
+
//
|
|
5682
|
+
// TinyMCE itself has no detection — "Auto" is ours, resolving the browser's
|
|
5683
|
+
// ordered language list against the shipped packs. The Auto row names what it
|
|
5684
|
+
// currently resolves to so the choice is not a guess. (Claude Code 2026-08-23)
|
|
5685
|
+
const optEditorLanguage = document.getElementById("opt-editor-language") as HTMLSelectElement;
|
|
5686
|
+
if (optEditorLanguage) {
|
|
5687
|
+
(async () => {
|
|
5688
|
+
const scriptUrl = localStorage.getItem("mailx-tinymce-cdn") || "lib/tinymce/tinymce.min.js";
|
|
5689
|
+
const { availableLanguages, resolveLanguage, languageLabel, LANGUAGE_AUTO, LANGUAGE_ENGLISH } =
|
|
5690
|
+
await import("./lib/tinymce-langs.js");
|
|
5691
|
+
const available = await availableLanguages(scriptUrl);
|
|
5692
|
+
const autoPick = resolveLanguage(LANGUAGE_AUTO, available);
|
|
5693
|
+
const add = (value: string, text: string) => {
|
|
5694
|
+
const o = document.createElement("option");
|
|
5695
|
+
o.value = value;
|
|
5696
|
+
o.textContent = text;
|
|
5697
|
+
optEditorLanguage.appendChild(o);
|
|
5698
|
+
};
|
|
5699
|
+
add(LANGUAGE_AUTO, `Auto — ${languageLabel(autoPick)}`);
|
|
5700
|
+
add(LANGUAGE_ENGLISH, languageLabel(LANGUAGE_ENGLISH));
|
|
5701
|
+
for (const code of [...available].sort((a, b) => languageLabel(a).localeCompare(languageLabel(b)))) {
|
|
5702
|
+
add(code, `${languageLabel(code)} (${code})`);
|
|
5703
|
+
}
|
|
5704
|
+
if (!available.length) {
|
|
5705
|
+
optEditorLanguage.disabled = true;
|
|
5706
|
+
optEditorLanguage.title = "No language packs found next to tinymce.min.js — English only";
|
|
5707
|
+
}
|
|
5708
|
+
let current = LANGUAGE_AUTO;
|
|
5709
|
+
try { current = localStorage.getItem("mailx-editor-language") || LANGUAGE_AUTO; } catch { /* */ }
|
|
5710
|
+
try {
|
|
5711
|
+
const settings: any = await getSettings();
|
|
5712
|
+
if (typeof settings?.ui?.editorLanguage === "string" && settings.ui.editorLanguage) current = settings.ui.editorLanguage;
|
|
5713
|
+
} catch { /* cache value stands */ }
|
|
5714
|
+
optEditorLanguage.value = current;
|
|
5715
|
+
// A pinned pack that is no longer shipped would leave the select on
|
|
5716
|
+
// nothing at all; say so rather than showing a blank control.
|
|
5717
|
+
if (!optEditorLanguage.value) optEditorLanguage.value = LANGUAGE_AUTO;
|
|
5718
|
+
})().catch((e: any) => console.error("[settings] editor-language menu failed:", e?.message || e));
|
|
5719
|
+
|
|
5720
|
+
optEditorLanguage.addEventListener("change", () => {
|
|
5721
|
+
const value = optEditorLanguage.value;
|
|
5722
|
+
// Synchronous cache write for the same reason as saveEditorSetting:
|
|
5723
|
+
// compose reads it at module load, so the next compose-open is right.
|
|
5724
|
+
try { localStorage.setItem("mailx-editor-language", value); } catch { /* private mode */ }
|
|
5725
|
+
getSettings().then((settings: any) => {
|
|
5726
|
+
settings.ui = { ...settings.ui, editorLanguage: value };
|
|
5727
|
+
saveSettings(settings);
|
|
5728
|
+
}).catch((e: any) => console.error("[settings] editor language save failed:", e?.message || e));
|
|
5729
|
+
});
|
|
5730
|
+
}
|
|
5731
|
+
|
|
5673
5732
|
// Save editor choice to server settings
|
|
5674
5733
|
function saveEditorSetting(editor: string): void {
|
|
5675
5734
|
// Update the localStorage cache SYNCHRONOUSLY. compose.ts reads
|
|
@@ -2714,6 +2714,9 @@ async function createTinyMceEditor(container2, opts = {}) {
|
|
|
2714
2714
|
// Adding Text first so it's the default; rest are the modern
|
|
2715
2715
|
// languages we actually paste.
|
|
2716
2716
|
codesample_languages: CODE_LANGS,
|
|
2717
|
+
// UI language. Left unset (TinyMCE default "en") when the host
|
|
2718
|
+
// passes nothing, which also skips the langs/ fetch entirely.
|
|
2719
|
+
...opts.language && opts.language !== "en" ? { language: opts.language } : {},
|
|
2717
2720
|
// WebView's native spell-check (red underlines, right-click
|
|
2718
2721
|
// "Add to dictionary"). Free; same UX as Quill's spellcheck=true.
|
|
2719
2722
|
// Premium tinymcespellchecker plugin would replace this with a
|
|
@@ -3428,6 +3431,67 @@ var init_rmf_tiny = __esm({
|
|
|
3428
3431
|
}
|
|
3429
3432
|
});
|
|
3430
3433
|
|
|
3434
|
+
// client/lib/tinymce-langs.js
|
|
3435
|
+
var tinymce_langs_exports = {};
|
|
3436
|
+
__export(tinymce_langs_exports, {
|
|
3437
|
+
LANGUAGE_AUTO: () => LANGUAGE_AUTO,
|
|
3438
|
+
LANGUAGE_ENGLISH: () => LANGUAGE_ENGLISH,
|
|
3439
|
+
availableLanguages: () => availableLanguages,
|
|
3440
|
+
langManifestUrl: () => langManifestUrl,
|
|
3441
|
+
languageLabel: () => languageLabel,
|
|
3442
|
+
resolveLanguage: () => resolveLanguage
|
|
3443
|
+
});
|
|
3444
|
+
function langManifestUrl(tinymceScriptUrl) {
|
|
3445
|
+
return new URL("langs/index.json", new URL(tinymceScriptUrl, location.href)).href;
|
|
3446
|
+
}
|
|
3447
|
+
async function availableLanguages(tinymceScriptUrl) {
|
|
3448
|
+
try {
|
|
3449
|
+
const r = await fetch(langManifestUrl(tinymceScriptUrl));
|
|
3450
|
+
if (!r.ok)
|
|
3451
|
+
return [];
|
|
3452
|
+
const list = await r.json();
|
|
3453
|
+
return Array.isArray(list) ? list.filter((x) => typeof x === "string") : [];
|
|
3454
|
+
} catch {
|
|
3455
|
+
return [];
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
function resolveLanguage(setting, available, preferred = navigator.languages || [navigator.language]) {
|
|
3459
|
+
const byLower = new Map(available.map((code) => [code.toLowerCase(), code]));
|
|
3460
|
+
if (setting && setting !== LANGUAGE_AUTO) {
|
|
3461
|
+
if (setting === LANGUAGE_ENGLISH)
|
|
3462
|
+
return LANGUAGE_ENGLISH;
|
|
3463
|
+
return byLower.get(setting.toLowerCase()) || LANGUAGE_ENGLISH;
|
|
3464
|
+
}
|
|
3465
|
+
for (const tag of preferred) {
|
|
3466
|
+
if (!tag)
|
|
3467
|
+
continue;
|
|
3468
|
+
const lower = tag.toLowerCase();
|
|
3469
|
+
const base = lower.split("-")[0];
|
|
3470
|
+
if (base === LANGUAGE_ENGLISH)
|
|
3471
|
+
return LANGUAGE_ENGLISH;
|
|
3472
|
+
const hit = byLower.get(lower) || byLower.get(base) || available.find((code) => code.toLowerCase().split("-")[0] === base);
|
|
3473
|
+
if (hit)
|
|
3474
|
+
return hit;
|
|
3475
|
+
}
|
|
3476
|
+
return LANGUAGE_ENGLISH;
|
|
3477
|
+
}
|
|
3478
|
+
function languageLabel(code) {
|
|
3479
|
+
try {
|
|
3480
|
+
const names = new Intl.DisplayNames(navigator.languages || void 0, { type: "language" });
|
|
3481
|
+
return names.of(code) || code;
|
|
3482
|
+
} catch {
|
|
3483
|
+
return code;
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
var LANGUAGE_AUTO, LANGUAGE_ENGLISH;
|
|
3487
|
+
var init_tinymce_langs = __esm({
|
|
3488
|
+
"client/lib/tinymce-langs.js"() {
|
|
3489
|
+
"use strict";
|
|
3490
|
+
LANGUAGE_AUTO = "auto";
|
|
3491
|
+
LANGUAGE_ENGLISH = "en";
|
|
3492
|
+
}
|
|
3493
|
+
});
|
|
3494
|
+
|
|
3431
3495
|
// client/compose/spellcheck.js
|
|
3432
3496
|
var spellcheck_exports = {};
|
|
3433
3497
|
__export(spellcheck_exports, {
|
|
@@ -5074,7 +5138,15 @@ async function createTinyMceEditor2(container2, opts = {}) {
|
|
|
5074
5138
|
}
|
|
5075
5139
|
const m = await Promise.resolve().then(() => (init_rmf_tiny(), rmf_tiny_exports));
|
|
5076
5140
|
const cssPx = parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--compose-font-size"));
|
|
5077
|
-
|
|
5141
|
+
let language;
|
|
5142
|
+
try {
|
|
5143
|
+
const { availableLanguages: availableLanguages2, resolveLanguage: resolveLanguage2, LANGUAGE_ENGLISH: LANGUAGE_ENGLISH2 } = await Promise.resolve().then(() => (init_tinymce_langs(), tinymce_langs_exports));
|
|
5144
|
+
const resolved = resolveLanguage2(opts.language || "auto", await availableLanguages2(cdnUrl));
|
|
5145
|
+
if (resolved !== LANGUAGE_ENGLISH2)
|
|
5146
|
+
language = resolved;
|
|
5147
|
+
} catch {
|
|
5148
|
+
}
|
|
5149
|
+
const ed = await m.createTinyMceEditor(container2, { cdnUrl, apiKey, onFiles: opts.onFiles, fontSizePx: Number.isFinite(cssPx) ? cssPx : void 0, language });
|
|
5078
5150
|
try {
|
|
5079
5151
|
const native = ed.nativeEditor;
|
|
5080
5152
|
const body = native?.getBody?.();
|
|
@@ -5161,6 +5233,15 @@ if (__bootUi?.editor === "tiptap" || __bootUi?.editor === "quill" || __bootUi?.e
|
|
|
5161
5233
|
} catch {
|
|
5162
5234
|
}
|
|
5163
5235
|
}
|
|
5236
|
+
var editorLanguage = "auto";
|
|
5237
|
+
if (typeof __bootUi?.editorLanguage === "string" && __bootUi.editorLanguage) {
|
|
5238
|
+
editorLanguage = __bootUi.editorLanguage;
|
|
5239
|
+
} else {
|
|
5240
|
+
try {
|
|
5241
|
+
editorLanguage = localStorage.getItem("mailx-editor-language") || "auto";
|
|
5242
|
+
} catch {
|
|
5243
|
+
}
|
|
5244
|
+
}
|
|
5164
5245
|
var COMPOSE_FONT_MIN_PX = 8;
|
|
5165
5246
|
var COMPOSE_FONT_MAX_PX = 32;
|
|
5166
5247
|
var COMPOSE_FONT_DEFAULT_PX = 20;
|
|
@@ -5183,6 +5264,13 @@ try {
|
|
|
5183
5264
|
localStorage.setItem("mailx-editor-type", next);
|
|
5184
5265
|
} catch {
|
|
5185
5266
|
}
|
|
5267
|
+
const lang = appSettings?.ui?.editorLanguage;
|
|
5268
|
+
if (typeof lang === "string" && lang) {
|
|
5269
|
+
try {
|
|
5270
|
+
localStorage.setItem("mailx-editor-language", lang);
|
|
5271
|
+
} catch {
|
|
5272
|
+
}
|
|
5273
|
+
}
|
|
5186
5274
|
const fontPx = Number(appSettings?.ui?.composeFontSize);
|
|
5187
5275
|
if (Number.isFinite(fontPx) && fontPx >= COMPOSE_FONT_MIN_PX && fontPx <= COMPOSE_FONT_MAX_PX) {
|
|
5188
5276
|
try {
|
|
@@ -5243,7 +5331,7 @@ async function tryEditor(type) {
|
|
|
5243
5331
|
try {
|
|
5244
5332
|
const ed = await createEditor(container, type, { onFiles: (files) => {
|
|
5245
5333
|
void ingestFiles(files);
|
|
5246
|
-
} });
|
|
5334
|
+
}, language: editorLanguage });
|
|
5247
5335
|
if (type === "tinymce" && ed && ed.nativeEditor) {
|
|
5248
5336
|
const native = ed.nativeEditor;
|
|
5249
5337
|
const attach = () => {
|