@bobfrankston/rmfmail 1.2.112 → 1.2.113
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/client/compose/compose.bundle.js +50 -5
- package/client/compose/compose.bundle.js.map +2 -2
- package/client/compose/spellcheck-core.js +59 -3
- package/client/compose/spellcheck-core.js.map +1 -1
- package/client/compose/spellcheck-core.ts +58 -3
- package/client/compose/spellcheck.js +15 -6
- package/client/compose/spellcheck.js.map +1 -1
- package/client/compose/spellcheck.ts +15 -6
- package/package.json +1 -1
|
@@ -1650,8 +1650,11 @@ __export(spellcheck_core_exports, {
|
|
|
1650
1650
|
USER_DICT_KEY: () => USER_DICT_KEY,
|
|
1651
1651
|
addToUserDict: () => addToUserDict,
|
|
1652
1652
|
buildSuggestionList: () => buildSuggestionList,
|
|
1653
|
+
findSkipRanges: () => findSkipRanges,
|
|
1653
1654
|
getSpell: () => getSpell,
|
|
1654
1655
|
getWordAtPoint: () => getWordAtPoint,
|
|
1656
|
+
inSkipRange: () => inSkipRange,
|
|
1657
|
+
isWordCorrect: () => isWordCorrect,
|
|
1655
1658
|
showSuggestionsMenu: () => showSuggestionsMenu
|
|
1656
1659
|
});
|
|
1657
1660
|
async function getSpell() {
|
|
@@ -1714,6 +1717,34 @@ function addToUserDict(word, sp) {
|
|
|
1714
1717
|
sp.add(word);
|
|
1715
1718
|
addUserDictWord(word).catch((e) => console.error("[spell] addUserDictWord:", e));
|
|
1716
1719
|
}
|
|
1720
|
+
function isWordCorrect(word, sp) {
|
|
1721
|
+
let w = word.replace(/['’]+$/u, "");
|
|
1722
|
+
w = w.replace(/['’][sS]$/u, "");
|
|
1723
|
+
if (w.length < MIN_WORD_LEN)
|
|
1724
|
+
return true;
|
|
1725
|
+
return sp.correct(w);
|
|
1726
|
+
}
|
|
1727
|
+
function findSkipRanges(text) {
|
|
1728
|
+
if (!/[.@:]/.test(text))
|
|
1729
|
+
return [];
|
|
1730
|
+
const ranges = [];
|
|
1731
|
+
SKIP_SPAN_RE.lastIndex = 0;
|
|
1732
|
+
let m;
|
|
1733
|
+
while (m = SKIP_SPAN_RE.exec(text)) {
|
|
1734
|
+
let end = m.index + m[0].length;
|
|
1735
|
+
while (end > m.index && /[.,;:!?]/.test(text[end - 1]))
|
|
1736
|
+
end--;
|
|
1737
|
+
if (end > m.index)
|
|
1738
|
+
ranges.push([m.index, end]);
|
|
1739
|
+
}
|
|
1740
|
+
return ranges;
|
|
1741
|
+
}
|
|
1742
|
+
function inSkipRange(ranges, start, end) {
|
|
1743
|
+
for (const [s, e] of ranges)
|
|
1744
|
+
if (start < e && end > s)
|
|
1745
|
+
return true;
|
|
1746
|
+
return false;
|
|
1747
|
+
}
|
|
1717
1748
|
function buildSuggestionList(word, sp) {
|
|
1718
1749
|
const transposed = [];
|
|
1719
1750
|
for (let i = 0; i < word.length - 1; i++) {
|
|
@@ -1840,7 +1871,7 @@ function getWordAtPoint(root, x, y) {
|
|
|
1840
1871
|
const text = node.data;
|
|
1841
1872
|
if (offset > text.length)
|
|
1842
1873
|
offset = text.length;
|
|
1843
|
-
const isWordChar = (c) => /[\p{L}'
|
|
1874
|
+
const isWordChar = (c) => /[\p{L}'’]/u.test(c);
|
|
1844
1875
|
let start = offset;
|
|
1845
1876
|
while (start > 0 && isWordChar(text[start - 1]))
|
|
1846
1877
|
start--;
|
|
@@ -1852,9 +1883,11 @@ function getWordAtPoint(root, x, y) {
|
|
|
1852
1883
|
const word = text.slice(start, end);
|
|
1853
1884
|
if (!/^[\p{L}]/u.test(word))
|
|
1854
1885
|
return null;
|
|
1886
|
+
if (inSkipRange(findSkipRanges(text), start, end))
|
|
1887
|
+
return null;
|
|
1855
1888
|
return { word, node, start, end };
|
|
1856
1889
|
}
|
|
1857
|
-
var import_nspell, USER_DICT_KEY, MARKER_ATTR, MIN_WORD_LEN, SKIP_TAGS, spellPromise;
|
|
1890
|
+
var import_nspell, USER_DICT_KEY, MARKER_ATTR, MIN_WORD_LEN, SKIP_TAGS, spellPromise, URL_BODY, SKIP_SPAN_RE;
|
|
1858
1891
|
var init_spellcheck_core = __esm({
|
|
1859
1892
|
"client/compose/spellcheck-core.js"() {
|
|
1860
1893
|
"use strict";
|
|
@@ -1865,6 +1898,15 @@ var init_spellcheck_core = __esm({
|
|
|
1865
1898
|
MIN_WORD_LEN = 3;
|
|
1866
1899
|
SKIP_TAGS = /* @__PURE__ */ new Set(["BLOCKQUOTE", "CODE", "PRE", "A", "SCRIPT", "STYLE", "KBD", "SAMP", "VAR"]);
|
|
1867
1900
|
spellPromise = null;
|
|
1901
|
+
URL_BODY = String.raw`[\w.\-~:/?#@$&+=%!*]`;
|
|
1902
|
+
SKIP_SPAN_RE = new RegExp(
|
|
1903
|
+
String.raw`(?:(?:[A-Za-z][A-Za-z\d.+-]{1,14}://|mailto:|tel:)${URL_BODY}+` + // scheme'd URL
|
|
1904
|
+
String.raw`|www\.${URL_BODY}+` + // www.…
|
|
1905
|
+
String.raw`|[\w.+\-]+@[\w\-]+(?:\.[\w\-]+)+` + // email
|
|
1906
|
+
String.raw`|[\w\-]+(?:\.[A-Za-z][\w\-]*)+(?:/${URL_BODY}*)?)`,
|
|
1907
|
+
// bare domain [+path]
|
|
1908
|
+
"g"
|
|
1909
|
+
);
|
|
1868
1910
|
}
|
|
1869
1911
|
});
|
|
1870
1912
|
|
|
@@ -2544,18 +2586,21 @@ function wireSpellcheck(editor2) {
|
|
|
2544
2586
|
const sx = body.scrollLeft;
|
|
2545
2587
|
const sy = body.scrollTop;
|
|
2546
2588
|
const frag = doc.createDocumentFragment();
|
|
2547
|
-
const wordRe = /[\p{L}][\p{L}'
|
|
2589
|
+
const wordRe = /[\p{L}][\p{L}'’]*/gu;
|
|
2548
2590
|
for (let n = walker.nextNode(); n; n = walker.nextNode()) {
|
|
2549
2591
|
const text = n.data;
|
|
2550
2592
|
if (!text || text.length < MIN_WORD_LEN)
|
|
2551
2593
|
continue;
|
|
2594
|
+
const skip = findSkipRanges(text);
|
|
2552
2595
|
wordRe.lastIndex = 0;
|
|
2553
2596
|
let m;
|
|
2554
2597
|
while (m = wordRe.exec(text)) {
|
|
2555
2598
|
const w = m[0];
|
|
2556
2599
|
if (w.length < MIN_WORD_LEN)
|
|
2557
2600
|
continue;
|
|
2558
|
-
if (
|
|
2601
|
+
if (inSkipRange(skip, m.index, m.index + w.length))
|
|
2602
|
+
continue;
|
|
2603
|
+
if (isWordCorrect(w, sp))
|
|
2559
2604
|
continue;
|
|
2560
2605
|
const r = doc.createRange();
|
|
2561
2606
|
r.setStart(n, m.index);
|
|
@@ -2626,7 +2671,7 @@ function wireSpellcheck(editor2) {
|
|
|
2626
2671
|
const hit = getWordAtPoint(body, e.clientX, e.clientY);
|
|
2627
2672
|
if (!hit)
|
|
2628
2673
|
return;
|
|
2629
|
-
if (
|
|
2674
|
+
if (isWordCorrect(hit.word, sp))
|
|
2630
2675
|
return;
|
|
2631
2676
|
e.preventDefault();
|
|
2632
2677
|
e.stopPropagation();
|