fable-editor 1.2.5 → 1.2.7
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/dist/angular/core/editor.d.ts +7 -2
- package/dist/angular/esm2022/core/editor.mjs +61 -3
- package/dist/angular/fesm2022/fable-editor.mjs +60 -2
- package/dist/angular/fesm2022/fable-editor.mjs.map +1 -1
- package/dist/core/editor.css +1 -1
- package/dist/core/editor.d.ts +7 -2
- package/dist/core/editor.d.ts.map +1 -1
- package/dist/core/index.cjs +3 -3
- package/dist/core/index.mjs +136 -103
- package/dist/react/index.cjs +9 -9
- package/dist/react/index.mjs +173 -140
- package/package.json +1 -1
- package/style.css +1 -1
|
@@ -1771,6 +1771,45 @@ function installTooltips() {
|
|
|
1771
1771
|
document.addEventListener('mousedown', hideTip, true);
|
|
1772
1772
|
addEventListener('scroll', hideTip, true);
|
|
1773
1773
|
}
|
|
1774
|
+
/* ---------------------------------------------------------- email-export direction
|
|
1775
|
+
detection — used only by getContentForEmail(). Content pasted from Word/Outlook
|
|
1776
|
+
usually carries explicit dir="rtl"/"ltr" per paragraph, but plain-text paste
|
|
1777
|
+
(normalizeTextPaste's dir="auto") and some other sources carry no reliable
|
|
1778
|
+
explicit direction at all. For those blocks we fall back to a first-strong-
|
|
1779
|
+
character scan (the same idea as HTML5's dir="auto") instead of the app's
|
|
1780
|
+
configured UI language, which has nothing to do with what the pasted text
|
|
1781
|
+
actually is. */
|
|
1782
|
+
const EMAIL_RTL_CHAR = /[\u0590-\u05FF\u0600-\u06FF\u0750-\u077F\u0780-\u07BF\u08A0-\u08FF\uFB1D-\uFB4F\uFB50-\uFDFF\uFE70-\uFEFF]/;
|
|
1783
|
+
const EMAIL_STRONG_CHAR = /\p{L}/u;
|
|
1784
|
+
const EMAIL_BLOCK_SELECTOR = 'p,div,li,td,th,blockquote,h1,h2,h3,h4,h5,h6,pre,figcaption';
|
|
1785
|
+
function firstStrongDir(text) {
|
|
1786
|
+
for (const ch of text) {
|
|
1787
|
+
if (EMAIL_RTL_CHAR.test(ch))
|
|
1788
|
+
return 'rtl';
|
|
1789
|
+
if (EMAIL_STRONG_CHAR.test(ch))
|
|
1790
|
+
return 'ltr';
|
|
1791
|
+
}
|
|
1792
|
+
return null;
|
|
1793
|
+
}
|
|
1794
|
+
/* Text belonging to el itself, skipping subtrees rooted at a descendant that
|
|
1795
|
+
already carries its own explicit rtl/ltr dir — that subtree's direction is
|
|
1796
|
+
already independently decided and shouldn't sway el's own detection. */
|
|
1797
|
+
function ownText(el) {
|
|
1798
|
+
let text = '';
|
|
1799
|
+
el.childNodes.forEach((node) => {
|
|
1800
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
1801
|
+
text += node.nodeValue || '';
|
|
1802
|
+
}
|
|
1803
|
+
else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
1804
|
+
const child = node;
|
|
1805
|
+
const d = (child.getAttribute('dir') || '').toLowerCase();
|
|
1806
|
+
if (d === 'rtl' || d === 'ltr')
|
|
1807
|
+
return;
|
|
1808
|
+
text += ownText(child);
|
|
1809
|
+
}
|
|
1810
|
+
});
|
|
1811
|
+
return text;
|
|
1812
|
+
}
|
|
1774
1813
|
class FableEditor {
|
|
1775
1814
|
static instanceCounter = 0;
|
|
1776
1815
|
options;
|
|
@@ -2137,6 +2176,7 @@ class FableEditor {
|
|
|
2137
2176
|
this.positionCodeCtx();
|
|
2138
2177
|
});
|
|
2139
2178
|
this.onWin('scroll', () => {
|
|
2179
|
+
this.closePop();
|
|
2140
2180
|
this.positionTableHandles();
|
|
2141
2181
|
this.positionImageHandles();
|
|
2142
2182
|
this.positionImgPhCtx();
|
|
@@ -2254,8 +2294,13 @@ class FableEditor {
|
|
|
2254
2294
|
* descendant that has no `text-align` of its own — even one with its own
|
|
2255
2295
|
* dir="rtl". Elements that already carry their own dir (preserved as-is by
|
|
2256
2296
|
* the paste engine) each get their own matching text-align only if they
|
|
2257
|
-
* don't already have one
|
|
2258
|
-
*
|
|
2297
|
+
* don't already have one. Blocks with no reliable explicit dir (missing, or
|
|
2298
|
+
* dir="auto" from plain-text paste) get their direction from a first-strong-
|
|
2299
|
+
* character scan of their own text instead of silently inheriting the
|
|
2300
|
+
* editor's configured UI language — mixed-direction content and any
|
|
2301
|
+
* alignment the user explicitly set are left untouched either way. Only
|
|
2302
|
+
* content with no strongly-directional character anywhere falls back to the
|
|
2303
|
+
* editor's current direction. */
|
|
2259
2304
|
getContentForEmail() {
|
|
2260
2305
|
const setStyle = (el, decl) => {
|
|
2261
2306
|
const cur = (el.getAttribute('style') || '').trim();
|
|
@@ -2274,6 +2319,19 @@ class FableEditor {
|
|
|
2274
2319
|
if (!/text-align\s*:/i.test(el.getAttribute('style') || ''))
|
|
2275
2320
|
setStyle(el, `text-align:${d === 'rtl' ? 'right' : 'left'}`);
|
|
2276
2321
|
});
|
|
2322
|
+
box.querySelectorAll(EMAIL_BLOCK_SELECTOR).forEach((el) => {
|
|
2323
|
+
const raw = (el.getAttribute('dir') || '').toLowerCase();
|
|
2324
|
+
if (raw === 'rtl' || raw === 'ltr')
|
|
2325
|
+
return;
|
|
2326
|
+
const d = firstStrongDir(ownText(el));
|
|
2327
|
+
if (!d)
|
|
2328
|
+
return;
|
|
2329
|
+
if (!found)
|
|
2330
|
+
found = d;
|
|
2331
|
+
el.setAttribute('dir', d);
|
|
2332
|
+
const hasAlign = /text-align\s*:/i.test(el.getAttribute('style') || '');
|
|
2333
|
+
setStyle(el, hasAlign ? `direction:${d}` : `direction:${d};text-align:${d === 'rtl' ? 'right' : 'left'}`);
|
|
2334
|
+
});
|
|
2277
2335
|
const dir = found || this.ed.getAttribute('dir') || this.dir();
|
|
2278
2336
|
box.querySelectorAll('table:not([dir])').forEach((tbl) => {
|
|
2279
2337
|
tbl.setAttribute('dir', dir);
|