@bobfrankston/rmfmail 1.2.274 → 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.
Files changed (112) hide show
  1. package/.commitmsg +31 -0
  2. package/bin/build-tinymce.js +27 -0
  3. package/client/android-bootstrap.bundle.js +169 -0
  4. package/client/android-bootstrap.bundle.js.map +2 -2
  5. package/client/app.bundle.js +231 -23
  6. package/client/app.bundle.js.map +4 -4
  7. package/client/app.js +81 -1
  8. package/client/app.js.map +1 -1
  9. package/client/app.ts +75 -1
  10. package/client/components/invite-card.js +107 -0
  11. package/client/components/invite-card.js.map +1 -0
  12. package/client/components/invite-card.ts +119 -0
  13. package/client/components/message-viewer.js +42 -17
  14. package/client/components/message-viewer.js.map +1 -1
  15. package/client/components/message-viewer.ts +42 -16
  16. package/client/compose/compose.bundle.js +90 -2
  17. package/client/compose/compose.bundle.js.map +4 -4
  18. package/client/compose/compose.js +26 -1
  19. package/client/compose/compose.js.map +1 -1
  20. package/client/compose/compose.ts +22 -1
  21. package/client/compose/editor.js +12 -1
  22. package/client/compose/editor.js.map +1 -1
  23. package/client/compose/editor.ts +17 -2
  24. package/client/index.html +1 -0
  25. package/client/lib/rmf-tiny.js +3 -0
  26. package/client/lib/tinymce/langs/ar-SA.js +440 -0
  27. package/client/lib/tinymce/langs/ar.js +441 -0
  28. package/client/lib/tinymce/langs/az.js +440 -0
  29. package/client/lib/tinymce/langs/be.js +440 -0
  30. package/client/lib/tinymce/langs/bg-BG.js +440 -0
  31. package/client/lib/tinymce/langs/bn-BD.js +440 -0
  32. package/client/lib/tinymce/langs/bs.js +440 -0
  33. package/client/lib/tinymce/langs/ca.js +440 -0
  34. package/client/lib/tinymce/langs/cs.js +440 -0
  35. package/client/lib/tinymce/langs/cy.js +440 -0
  36. package/client/lib/tinymce/langs/da.js +440 -0
  37. package/client/lib/tinymce/langs/de.js +440 -0
  38. package/client/lib/tinymce/langs/el.js +440 -0
  39. package/client/lib/tinymce/langs/eo.js +440 -0
  40. package/client/lib/tinymce/langs/es-MX.js +440 -0
  41. package/client/lib/tinymce/langs/es.js +440 -0
  42. package/client/lib/tinymce/langs/et.js +440 -0
  43. package/client/lib/tinymce/langs/eu.js +440 -0
  44. package/client/lib/tinymce/langs/fa.js +441 -0
  45. package/client/lib/tinymce/langs/fi.js +440 -0
  46. package/client/lib/tinymce/langs/fr-FR.js +440 -0
  47. package/client/lib/tinymce/langs/gl.js +440 -0
  48. package/client/lib/tinymce/langs/he-IL.js +440 -0
  49. package/client/lib/tinymce/langs/hr.js +440 -0
  50. package/client/lib/tinymce/langs/hu-HU.js +440 -0
  51. package/client/lib/tinymce/langs/hy.js +440 -0
  52. package/client/lib/tinymce/langs/id.js +440 -0
  53. package/client/lib/tinymce/langs/index.json +63 -0
  54. package/client/lib/tinymce/langs/is-IS.js +440 -0
  55. package/client/lib/tinymce/langs/it.js +440 -0
  56. package/client/lib/tinymce/langs/ja.js +440 -0
  57. package/client/lib/tinymce/langs/ka-GE.js +440 -0
  58. package/client/lib/tinymce/langs/kab.js +440 -0
  59. package/client/lib/tinymce/langs/kk.js +440 -0
  60. package/client/lib/tinymce/langs/ko-KR.js +440 -0
  61. package/client/lib/tinymce/langs/lt.js +440 -0
  62. package/client/lib/tinymce/langs/lv.js +440 -0
  63. package/client/lib/tinymce/langs/nb-NO.js +440 -0
  64. package/client/lib/tinymce/langs/ne.js +440 -0
  65. package/client/lib/tinymce/langs/nl-BE.js +440 -0
  66. package/client/lib/tinymce/langs/nl.js +440 -0
  67. package/client/lib/tinymce/langs/oc.js +440 -0
  68. package/client/lib/tinymce/langs/pl.js +440 -0
  69. package/client/lib/tinymce/langs/pt-BR.js +440 -0
  70. package/client/lib/tinymce/langs/pt-PT.js +440 -0
  71. package/client/lib/tinymce/langs/ro.js +440 -0
  72. package/client/lib/tinymce/langs/ru.js +440 -0
  73. package/client/lib/tinymce/langs/sk.js +440 -0
  74. package/client/lib/tinymce/langs/sl-SI.js +440 -0
  75. package/client/lib/tinymce/langs/sr.js +440 -0
  76. package/client/lib/tinymce/langs/sv-SE.js +440 -0
  77. package/client/lib/tinymce/langs/ta.js +440 -0
  78. package/client/lib/tinymce/langs/tg.js +440 -0
  79. package/client/lib/tinymce/langs/th-TH.js +440 -0
  80. package/client/lib/tinymce/langs/tr.js +440 -0
  81. package/client/lib/tinymce/langs/ug.js +440 -0
  82. package/client/lib/tinymce/langs/uk.js +440 -0
  83. package/client/lib/tinymce/langs/vi.js +440 -0
  84. package/client/lib/tinymce/langs/zh-CN.js +440 -0
  85. package/client/lib/tinymce/langs/zh-HK.js +440 -0
  86. package/client/lib/tinymce/langs/zh-MO.js +440 -0
  87. package/client/lib/tinymce/langs/zh-TW.js +440 -0
  88. package/client/lib/tinymce-langs.js +96 -0
  89. package/client/lib/tinymce-langs.js.map +1 -0
  90. package/client/lib/tinymce-langs.ts +99 -0
  91. package/client/package.json +1 -1
  92. package/client/styles/components.css +48 -0
  93. package/docs/editor.md +29 -3
  94. package/docs/preferences.md +2 -1
  95. package/npmchanges.md +29 -0
  96. package/package.json +18 -15
  97. package/packages/mailx-imap/package-lock.json +2 -2
  98. package/packages/mailx-imap/package.json +2 -2
  99. package/packages/mailx-settings/package.json +1 -1
  100. package/packages/mailx-store/package.json +1 -1
  101. package/packages/mailx-store/store.d.ts +5 -0
  102. package/packages/mailx-store/store.d.ts.map +1 -1
  103. package/packages/mailx-store/store.js +21 -0
  104. package/packages/mailx-store/store.js.map +1 -1
  105. package/packages/mailx-store/store.ts +27 -0
  106. package/packages/mailx-types/index.d.ts +56 -0
  107. package/packages/mailx-types/index.d.ts.map +1 -1
  108. package/packages/mailx-types/index.js +187 -0
  109. package/packages/mailx-types/index.js.map +1 -1
  110. package/packages/mailx-types/index.ts +192 -0
  111. package/packages/mailx-types/package.json +1 -1
  112. /package/packages/mailx-imap/{node_modules.npmglobalize-stash-31304 → node_modules.npmglobalize-stash-48352}/.package-lock.json +0 -0
package/.commitmsg ADDED
@@ -0,0 +1,31 @@
1
+ TinyMCE UI language: 61 packs, auto-detected from the browser
2
+
3
+ The tinymce package ships no langs/ directory at all — the packs are a separate
4
+ community package (tinymce-i18n), one file per language, each a plain
5
+ tinymce.addI18n("de", {...}). build-tinymce.js now copies langs8/ next to
6
+ tinymce.min.js, where TinyMCE's own <baseURL>/langs/<code>.js rule finds it, and
7
+ writes langs/index.json listing what it copied. 61 packs, 1.6 MB; only the
8
+ language in force is ever fetched.
9
+
10
+ TinyMCE has no detection of its own: `language` defaults to "en" and a missing
11
+ langs/<code>.js raises a visible in-editor error notification. So "Auto" is
12
+ ours (client/lib/tinymce-langs.ts): walk navigator.languages and take the first
13
+ hit against the manifest — exact ("pt-BR"), then bare ("de-CH" → "de"), then
14
+ any regional variant ("he" → "he-IL"). English short-circuits, since TinyMCE's
15
+ built-in strings are English. Anything unmatched, and any pinned pack we no
16
+ longer ship, stays English rather than provoking the error. Resolving against
17
+ the manifest rather than a hardcoded list keeps the copied files the single
18
+ source of truth, and follows a mailx-tinymce-cdn override for free because the
19
+ manifest URL is derived from the script URL by the same rule TinyMCE uses.
20
+
21
+ Settings → Editor → Editor language: Auto (naming what it resolves to right
22
+ now), English, then every pack, named via Intl.DisplayNames so no name table is
23
+ maintained here. Stored as ui.editorLanguage; same synchronous-localStorage-
24
+ then-persist shape as the editor type, so the next compose-open is correct.
25
+
26
+ Scope, stated in the menu tooltip and docs/editor.md: these translate the
27
+ editor CHROME only. Message content, the spellcheck dictionary (English) and
28
+ Harper (English only) are untouched, and Quill/tiptap have no localized chrome.
29
+
30
+ tests/tinymce-langs.test.ts pins the resolution against the real manifest.
31
+ Needs rmf-tiny 0.1.52 for the adapter's `language` option.
@@ -10,6 +10,13 @@ import path from "node:path";
10
10
  const root = path.resolve(import.meta.dirname, "..");
11
11
  const src = path.join(root, "node_modules", "tinymce");
12
12
  const dst = path.join(root, "client", "lib", "tinymce");
13
+ // UI translations. The tinymce package itself ships NO langs/ directory —
14
+ // the packs are a separate community package, one file per language, each
15
+ // a plain `tinymce.addI18n("de", {...})` call. TinyMCE resolves them
16
+ // itself as `<baseURL>/langs/<code>.js`, so dropping them beside the
17
+ // script is the whole integration (Claude Code 2026-08-23).
18
+ const langSrc = path.join(root, "node_modules", "tinymce-i18n", "langs8");
19
+ const langDst = path.join(dst, "langs");
13
20
 
14
21
  if (!fs.existsSync(src)) {
15
22
  console.error(`build-tinymce: source not found at ${src} — run npm install first`);
@@ -32,6 +39,26 @@ function copyTree(s, d) {
32
39
  fs.rmSync(dst, { recursive: true, force: true });
33
40
  copyTree(src, dst);
34
41
 
42
+ // Language packs. Only the one language in force is ever fetched at
43
+ // runtime, so shipping every pack costs disk and nothing else. The manifest
44
+ // is what the client resolves "auto" against — the copied files ARE the list
45
+ // of what can be offered, so nothing hardcodes a second copy of it.
46
+ let langs = [];
47
+ if (fs.existsSync(langSrc)) {
48
+ fs.mkdirSync(langDst, { recursive: true });
49
+ for (const name of fs.readdirSync(langSrc)) {
50
+ if (!name.endsWith(".js")) continue;
51
+ fs.copyFileSync(path.join(langSrc, name), path.join(langDst, name));
52
+ langs.push(name.slice(0, -3));
53
+ }
54
+ langs.sort();
55
+ fs.writeFileSync(path.join(langDst, "index.json"), JSON.stringify(langs, null, 2) + "\n");
56
+ console.log(`build-tinymce: copied ${langs.length} language packs → client/lib/tinymce/langs/`);
57
+ } else {
58
+ // Never silently ship an editor whose language menu is empty.
59
+ console.error(`build-tinymce: WARNING no language packs at ${langSrc} — run npm install; the editor will be English-only`);
60
+ }
61
+
35
62
  let count = 0, bytes = 0;
36
63
  function tally(p) {
37
64
  const st = fs.statSync(p);
@@ -2583,10 +2583,12 @@ __export(mailx_types_exports, {
2583
2583
  flaggedOf: () => flaggedOf,
2584
2584
  formatSender: () => formatSender,
2585
2585
  htmlToPlainText: () => htmlToPlainText,
2586
+ inviteHasGoogleRsvp: () => inviteHasGoogleRsvp,
2586
2587
  isAddressToken: () => isAddressToken,
2587
2588
  isJunkPreviewText: () => isJunkPreviewText,
2588
2589
  mergeReminderStates: () => mergeReminderStates,
2589
2590
  normalizeReminderState: () => normalizeReminderState,
2591
+ parseInvite: () => parseInvite,
2590
2592
  parseSearchQuery: () => parseSearchQuery,
2591
2593
  reminderStatesEqual: () => reminderStatesEqual,
2592
2594
  sanitizeHtml: () => sanitizeHtml,
@@ -2887,6 +2889,173 @@ function formatSender(addr) {
2887
2889
  return { text: address, claimed: null };
2888
2890
  return { text: `${name} <${address}>`, claimed: displayNameClaimsOtherAddress(name, address) };
2889
2891
  }
2892
+ function unfoldIcs(text) {
2893
+ const raw = (text || "").replace(/\r\n/g, "\n").split("\n");
2894
+ const out = [];
2895
+ for (const line of raw) {
2896
+ if (/^[ \t]/.test(line) && out.length)
2897
+ out[out.length - 1] += line.slice(1);
2898
+ else
2899
+ out.push(line);
2900
+ }
2901
+ return out;
2902
+ }
2903
+ function unescapeIcs(v) {
2904
+ return (v || "").replace(/\\n/gi, "\n").replace(/\\([;,\\])/g, "$1");
2905
+ }
2906
+ function splitIcsLine(line) {
2907
+ let inQuote = false, colon = -1;
2908
+ for (let i = 0; i < line.length; i++) {
2909
+ const c = line[i];
2910
+ if (c === '"')
2911
+ inQuote = !inQuote;
2912
+ else if (c === ":" && !inQuote) {
2913
+ colon = i;
2914
+ break;
2915
+ }
2916
+ }
2917
+ if (colon < 0)
2918
+ return null;
2919
+ const namePart = line.slice(0, colon);
2920
+ const value = line.slice(colon + 1);
2921
+ const bits = namePart.split(";");
2922
+ const key = (bits.shift() || "").toUpperCase();
2923
+ const params = {};
2924
+ for (const b of bits) {
2925
+ const eq = b.indexOf("=");
2926
+ if (eq < 0)
2927
+ continue;
2928
+ params[b.slice(0, eq).toUpperCase()] = b.slice(eq + 1).replace(/^"|"$/g, "");
2929
+ }
2930
+ return { key, params, value };
2931
+ }
2932
+ function icsDateToIso(v, isUtc) {
2933
+ const m = (v || "").match(/^(\d{4})(\d{2})(\d{2})(?:T(\d{2})(\d{2})(\d{2})(Z)?)?$/);
2934
+ if (!m)
2935
+ return "";
2936
+ const [, y, mo, d, hh, mm, ss, z] = m;
2937
+ if (!hh)
2938
+ return `${y}-${mo}-${d}`;
2939
+ const base = `${y}-${mo}-${d}T${hh}:${mm}:${ss}`;
2940
+ return z || isUtc ? base + "Z" : base;
2941
+ }
2942
+ function parseCalAddress(value, params) {
2943
+ const email = (value || "").replace(/^mailto:/i, "").trim();
2944
+ return { name: (params.CN || "").trim() || email, email };
2945
+ }
2946
+ function parseInvite(ics) {
2947
+ if (!ics || !/BEGIN:VEVENT/i.test(ics))
2948
+ return null;
2949
+ const lines = unfoldIcs(ics);
2950
+ const out = {
2951
+ method: "",
2952
+ uid: "",
2953
+ sequence: 0,
2954
+ summary: "",
2955
+ description: "",
2956
+ location: "",
2957
+ start: "",
2958
+ end: "",
2959
+ tzid: "",
2960
+ allDay: false,
2961
+ organizer: { name: "", email: "" },
2962
+ attendees: [],
2963
+ rrule: "",
2964
+ status: "",
2965
+ fromGoogle: false
2966
+ };
2967
+ let inEvent = false;
2968
+ let depthNonEvent = 0;
2969
+ for (const line of lines) {
2970
+ const up = line.toUpperCase();
2971
+ if (up.startsWith("BEGIN:VEVENT")) {
2972
+ inEvent = true;
2973
+ continue;
2974
+ }
2975
+ if (up.startsWith("END:VEVENT")) {
2976
+ inEvent = false;
2977
+ continue;
2978
+ }
2979
+ if (!inEvent && (up.startsWith("BEGIN:VTIMEZONE") || up.startsWith("BEGIN:VALARM"))) {
2980
+ depthNonEvent++;
2981
+ continue;
2982
+ }
2983
+ if (up.startsWith("END:VTIMEZONE") || up.startsWith("END:VALARM")) {
2984
+ if (depthNonEvent)
2985
+ depthNonEvent--;
2986
+ continue;
2987
+ }
2988
+ if (inEvent && up.startsWith("BEGIN:VALARM")) {
2989
+ depthNonEvent++;
2990
+ continue;
2991
+ }
2992
+ const p = splitIcsLine(line);
2993
+ if (!p)
2994
+ continue;
2995
+ if (!inEvent) {
2996
+ if (p.key === "METHOD")
2997
+ out.method = p.value.trim().toUpperCase();
2998
+ else if (p.key === "PRODID" && /google/i.test(p.value))
2999
+ out.fromGoogle = true;
3000
+ continue;
3001
+ }
3002
+ if (depthNonEvent)
3003
+ continue;
3004
+ switch (p.key) {
3005
+ case "SUMMARY":
3006
+ out.summary = unescapeIcs(p.value);
3007
+ break;
3008
+ case "DESCRIPTION":
3009
+ out.description = unescapeIcs(p.value);
3010
+ break;
3011
+ case "LOCATION":
3012
+ out.location = unescapeIcs(p.value);
3013
+ break;
3014
+ case "UID":
3015
+ out.uid = p.value.trim();
3016
+ break;
3017
+ case "STATUS":
3018
+ out.status = p.value.trim().toUpperCase();
3019
+ break;
3020
+ case "RRULE":
3021
+ out.rrule = p.value.trim();
3022
+ break;
3023
+ case "SEQUENCE":
3024
+ out.sequence = parseInt(p.value, 10) || 0;
3025
+ break;
3026
+ case "DTSTART":
3027
+ out.start = icsDateToIso(p.value.trim(), false);
3028
+ out.tzid = p.params.TZID || out.tzid;
3029
+ out.allDay = (p.params.VALUE || "").toUpperCase() === "DATE" || !/T/.test(p.value);
3030
+ break;
3031
+ case "DTEND":
3032
+ out.end = icsDateToIso(p.value.trim(), false);
3033
+ out.tzid = out.tzid || p.params.TZID || "";
3034
+ break;
3035
+ case "ORGANIZER":
3036
+ out.organizer = parseCalAddress(p.value, p.params);
3037
+ break;
3038
+ case "ATTENDEE": {
3039
+ const a = parseCalAddress(p.value, p.params);
3040
+ out.attendees.push({
3041
+ name: a.name,
3042
+ email: a.email,
3043
+ status: (p.params.PARTSTAT || "NEEDS-ACTION").toUpperCase(),
3044
+ rsvp: (p.params.RSVP || "").toUpperCase() === "TRUE"
3045
+ });
3046
+ break;
3047
+ }
3048
+ }
3049
+ }
3050
+ if (!out.summary && !out.start)
3051
+ return null;
3052
+ return out;
3053
+ }
3054
+ function inviteHasGoogleRsvp(bodyHtml) {
3055
+ if (!bodyHtml)
3056
+ return false;
3057
+ return /calendar\.google\.com\/calendar\/event\?action=RESPOND/i.test(bodyHtml);
3058
+ }
2890
3059
  var _SEEN, _FLAGGED, _ANSWERED, _DRAFT, _DELETED, seenOf, flaggedOf, answeredOf, draftOf, deletedOf, setSeen, setFlagged, setAnswered, setDraft, toggleSeen, toggleFlagged;
2891
3060
  var init_mailx_types = __esm({
2892
3061
  "packages/mailx-types/index.js"() {