@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.
@@ -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}'’\-]/u.test(c);
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}'’-]*/gu;
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 (sp.correct(w))
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 (sp.correct(hit.word))
2674
+ if (isWordCorrect(hit.word, sp))
2630
2675
  return;
2631
2676
  e.preventDefault();
2632
2677
  e.stopPropagation();