@chayns-components/emoji-input 5.3.2 → 5.3.6
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/lib/cjs/components/emoji-input/EmojiInput.js +61 -1
- package/lib/cjs/components/emoji-input/EmojiInput.js.map +1 -1
- package/lib/cjs/constants/emoji.js +6 -5
- package/lib/cjs/constants/emoji.js.map +1 -1
- package/lib/cjs/constants/regex.js +2 -1
- package/lib/cjs/constants/regex.js.map +1 -1
- package/lib/cjs/utils/emoji.js +9 -2
- package/lib/cjs/utils/emoji.js.map +1 -1
- package/lib/cjs/utils/insert.js +86 -1
- package/lib/cjs/utils/insert.js.map +1 -1
- package/lib/cjs/utils/text.js +5 -0
- package/lib/cjs/utils/text.js.map +1 -1
- package/lib/esm/components/emoji-input/EmojiInput.js +62 -2
- package/lib/esm/components/emoji-input/EmojiInput.js.map +1 -1
- package/lib/esm/constants/emoji.js +6 -5
- package/lib/esm/constants/emoji.js.map +1 -1
- package/lib/esm/constants/regex.js +1 -0
- package/lib/esm/constants/regex.js.map +1 -1
- package/lib/esm/utils/emoji.js +9 -2
- package/lib/esm/utils/emoji.js.map +1 -1
- package/lib/esm/utils/insert.js +83 -0
- package/lib/esm/utils/insert.js.map +1 -1
- package/lib/esm/utils/text.js +6 -1
- package/lib/esm/utils/text.js.map +1 -1
- package/lib/types/constants/regex.d.ts +1 -0
- package/lib/types/utils/emoji.d.ts +11 -1
- package/lib/types/utils/insert.d.ts +11 -0
- package/package.json +3 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export const asciiList = {
|
|
2
|
+
// Active entries (>= 3 characters)
|
|
2
3
|
'*\\0/*': '1f646',
|
|
3
4
|
'*\\O/*': '1f646',
|
|
4
5
|
'-___-': '1f611',
|
|
@@ -65,7 +66,6 @@ export const asciiList = {
|
|
|
65
66
|
':-/': '1f615',
|
|
66
67
|
':-.': '1f615',
|
|
67
68
|
':-P': '1f61b',
|
|
68
|
-
':Þ': '1f61b',
|
|
69
69
|
':-b': '1f61b',
|
|
70
70
|
':-O': '1f62e',
|
|
71
71
|
O_O: '1f62e',
|
|
@@ -74,8 +74,9 @@ export const asciiList = {
|
|
|
74
74
|
':-#': '1f636',
|
|
75
75
|
':-)': '1f642',
|
|
76
76
|
'(y)': '1f44d',
|
|
77
|
-
'<3': '2764-fe0f',
|
|
78
77
|
'=D': '1f603',
|
|
78
|
+
'<3': '2764-fe0f',
|
|
79
|
+
':Þ': '1f61b',
|
|
79
80
|
';)': '1f609',
|
|
80
81
|
'*)': '1f609',
|
|
81
82
|
';]': '1f609',
|
|
@@ -92,9 +93,9 @@ export const asciiList = {
|
|
|
92
93
|
'=$': '1f633',
|
|
93
94
|
'#)': '1f635',
|
|
94
95
|
'%)': '1f635',
|
|
95
|
-
'X)': '1f635',
|
|
96
|
-
'B)': '1f60e',
|
|
97
|
-
'8)': '1f60e',
|
|
96
|
+
// 'X)': '1f635',
|
|
97
|
+
// 'B)': '1f60e',
|
|
98
|
+
// '8)': '1f60e',
|
|
98
99
|
':/': '1f615',
|
|
99
100
|
':\\': '1f615',
|
|
100
101
|
'=/': '1f615',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emoji.js","names":["asciiList","O_O","asciiRegexp","regAscii","RegExp"],"sources":["../../../src/constants/emoji.ts"],"sourcesContent":["export const asciiList: { [key: string]: string } = {\n '*\\\\0/*': '1f646',\n '*\\\\O/*': '1f646',\n '-___-': '1f611',\n \":'-)\": '1f602',\n \"':-)\": '1f605',\n \"':-D\": '1f605',\n '>:-)': '1f606',\n \"':-(\": '1f613',\n '>:-(': '1f620',\n \":'-(\": '1f622',\n 'O:-)': '1f607',\n '0:-3': '1f607',\n '0:-)': '1f607',\n '0;^)': '1f607',\n 'O;-)': '1f607',\n '0;-)': '1f607',\n 'O:-3': '1f607',\n '-__-': '1f611',\n ':-Þ': '1f61b',\n '</3': '1f494',\n \":')\": '1f602',\n ':-D': '1f603',\n \"':)\": '1f605',\n \"'=)\": '1f605',\n \"':D\": '1f605',\n \"'=D\": '1f605',\n '>:)': '1f606',\n '>;)': '1f606',\n '>=)': '1f606',\n ';-)': '1f609',\n '*-)': '1f609',\n ';-]': '1f609',\n ';^)': '1f609',\n \"':(\": '1f613',\n \"'=(\": '1f613',\n ':-*': '1f618',\n ':^*': '1f618',\n '>:P': '1f61c',\n 'X-P': '1f61c',\n '>:[': '1f61e',\n ':-(': '1f61e',\n ':-[': '1f61e',\n '>:(': '1f620',\n \":'(\": '1f622',\n ';-(': '1f622',\n '>.<': '1f623',\n '#-)': '1f635',\n '%-)': '1f635',\n 'X-)': '1f635',\n '\\\\0/': '1f646',\n '\\\\O/': '1f646',\n '0:3': '1f607',\n '0:)': '1f607',\n 'O:)': '1f607',\n 'O=)': '1f607',\n 'O:3': '1f607',\n 'B-)': '1f60e',\n '8-)': '1f60e',\n 'B-D': '1f60e',\n '8-D': '1f60e',\n '-_-': '1f611',\n '>:\\\\': '1f615',\n '>:/': '1f615',\n ':-/': '1f615',\n ':-.': '1f615',\n ':-P': '1f61b',\n '
|
|
1
|
+
{"version":3,"file":"emoji.js","names":["asciiList","O_O","asciiRegexp","regAscii","RegExp"],"sources":["../../../src/constants/emoji.ts"],"sourcesContent":["export const asciiList: { [key: string]: string } = {\n // Active entries (>= 3 characters)\n '*\\\\0/*': '1f646',\n '*\\\\O/*': '1f646',\n '-___-': '1f611',\n \":'-)\": '1f602',\n \"':-)\": '1f605',\n \"':-D\": '1f605',\n '>:-)': '1f606',\n \"':-(\": '1f613',\n '>:-(': '1f620',\n \":'-(\": '1f622',\n 'O:-)': '1f607',\n '0:-3': '1f607',\n '0:-)': '1f607',\n '0;^)': '1f607',\n 'O;-)': '1f607',\n '0;-)': '1f607',\n 'O:-3': '1f607',\n '-__-': '1f611',\n ':-Þ': '1f61b',\n '</3': '1f494',\n \":')\": '1f602',\n ':-D': '1f603',\n \"':)\": '1f605',\n \"'=)\": '1f605',\n \"':D\": '1f605',\n \"'=D\": '1f605',\n '>:)': '1f606',\n '>;)': '1f606',\n '>=)': '1f606',\n ';-)': '1f609',\n '*-)': '1f609',\n ';-]': '1f609',\n ';^)': '1f609',\n \"':(\": '1f613',\n \"'=(\": '1f613',\n ':-*': '1f618',\n ':^*': '1f618',\n '>:P': '1f61c',\n 'X-P': '1f61c',\n '>:[': '1f61e',\n ':-(': '1f61e',\n ':-[': '1f61e',\n '>:(': '1f620',\n \":'(\": '1f622',\n ';-(': '1f622',\n '>.<': '1f623',\n '#-)': '1f635',\n '%-)': '1f635',\n 'X-)': '1f635',\n '\\\\0/': '1f646',\n '\\\\O/': '1f646',\n '0:3': '1f607',\n '0:)': '1f607',\n 'O:)': '1f607',\n 'O=)': '1f607',\n 'O:3': '1f607',\n 'B-)': '1f60e',\n '8-)': '1f60e',\n 'B-D': '1f60e',\n '8-D': '1f60e',\n '-_-': '1f611',\n '>:\\\\': '1f615',\n '>:/': '1f615',\n ':-/': '1f615',\n ':-.': '1f615',\n ':-P': '1f61b',\n ':-b': '1f61b',\n ':-O': '1f62e',\n O_O: '1f62e',\n '>:O': '1f62e',\n ':-X': '1f636',\n ':-#': '1f636',\n ':-)': '1f642',\n '(y)': '1f44d',\n '=D': '1f603',\n '<3': '2764-fe0f',\n ':Þ': '1f61b',\n ';)': '1f609',\n '*)': '1f609',\n ';]': '1f609',\n ';D': '1f609',\n ':*': '1f618',\n '=*': '1f618',\n ':(': '1f61e',\n ':[': '1f61e',\n '=(': '1f61e',\n ':@': '1f620',\n ';(': '1f622',\n 'D:': '1f628',\n ':$': '1f633',\n '=$': '1f633',\n '#)': '1f635',\n '%)': '1f635',\n // 'X)': '1f635',\n // 'B)': '1f60e',\n // '8)': '1f60e',\n ':/': '1f615',\n ':\\\\': '1f615',\n '=/': '1f615',\n '=\\\\': '1f615',\n ':L': '1f615',\n '=L': '1f615',\n ':P': '1f61b',\n '=P': '1f61b',\n ':b': '1f61b',\n ':O': '1f62e',\n ':X': '1f636',\n ':#': '1f636',\n '=X': '1f636',\n '=#': '1f636',\n ':)': '1f642',\n '=]': '1f642',\n '=)': '1f642',\n ':]': '1f642',\n ':D': '1f604',\n};\n\nconst asciiRegexp =\n \"(\\\\*\\\\\\\\0\\\\/\\\\*|\\\\*\\\\\\\\O\\\\/\\\\*|\\\\-___\\\\-|\\\\:'\\\\-\\\\)|'\\\\:\\\\-\\\\)|'\\\\:\\\\-D|\\\\>\\\\:\\\\-\\\\)|>\\\\:\\\\-\\\\)|'\\\\:\\\\-\\\\(|\\\\>\\\\:\\\\-\\\\(|>\\\\:\\\\-\\\\(|\\\\:'\\\\-\\\\(|O\\\\:\\\\-\\\\)|0\\\\:\\\\-3|0\\\\:\\\\-\\\\)|0;\\\\^\\\\)|O;\\\\-\\\\)|0;\\\\-\\\\)|O\\\\:\\\\-3|\\\\-__\\\\-|\\\\:\\\\-Þ|\\\\:\\\\-Þ|\\\\<\\\\/3|<\\\\/3|\\\\:'\\\\)|\\\\:\\\\-D|'\\\\:\\\\)|'\\\\=\\\\)|'\\\\:D|'\\\\=D|\\\\>\\\\:\\\\)|>\\\\:\\\\)|\\\\>;\\\\)|>;\\\\)|\\\\>\\\\=\\\\)|>\\\\=\\\\)|;\\\\-\\\\)|\\\\*\\\\-\\\\)|;\\\\-\\\\]|;\\\\^\\\\)|'\\\\:\\\\(|'\\\\=\\\\(|\\\\:\\\\-\\\\*|\\\\:\\\\^\\\\*|\\\\>\\\\:P|>\\\\:P|X\\\\-P|\\\\>\\\\:\\\\[|>\\\\:\\\\[|\\\\:\\\\-\\\\(|\\\\:\\\\-\\\\[|\\\\>\\\\:\\\\(|>\\\\:\\\\(|\\\\:'\\\\(|;\\\\-\\\\(|\\\\>\\\\.\\\\<|>\\\\.<|#\\\\-\\\\)|%\\\\-\\\\)|X\\\\-\\\\)|\\\\\\\\0\\\\/|\\\\\\\\O\\\\/|0\\\\:3|0\\\\:\\\\)|O\\\\:\\\\)|O\\\\=\\\\)|O\\\\:3|B\\\\-\\\\)|8\\\\-\\\\)|B\\\\-D|8\\\\-D|\\\\-_\\\\-|\\\\>\\\\:\\\\\\\\|>\\\\:\\\\\\\\|\\\\>\\\\:\\\\/|>\\\\:\\\\/|\\\\:\\\\-\\\\/|\\\\:\\\\-\\\\.|\\\\:\\\\-P|\\\\:Þ|\\\\:Þ|\\\\:\\\\-b|\\\\:\\\\-O|O_O|\\\\>\\\\:O|>\\\\:O|\\\\:\\\\-X|\\\\:\\\\-#|\\\\:\\\\-\\\\)|\\\\(y\\\\)|\\\\<3|<3|\\\\=D|;\\\\)|\\\\*\\\\)|;\\\\]|;D|\\\\:\\\\*|\\\\=\\\\*|\\\\:\\\\(|\\\\:\\\\[|\\\\=\\\\(|\\\\:@|;\\\\(|D\\\\:|\\\\:\\\\$|\\\\=\\\\$|#\\\\)|%\\\\)|X\\\\)|B\\\\)|8\\\\)|\\\\:\\\\/|\\\\:\\\\\\\\|\\\\=\\\\/|\\\\=\\\\\\\\|\\\\:L|\\\\=L|\\\\:P|\\\\=P|\\\\:b|\\\\:O|\\\\:X|\\\\:#|\\\\=X|\\\\=#|\\\\:\\\\)|\\\\=\\\\]|\\\\=\\\\)|\\\\:\\\\]|\\\\:D)\";\n\nexport const regAscii = new RegExp(\n `<object[^>]*>.*?</object>|<span[^>]*>.*?</span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|((\\\\s|^)${asciiRegexp}(?=\\\\s|$|[!,.?]))`,\n 'gi',\n);\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -6,4 +6,5 @@ export const HTML_NER_IGNORE_REGEX = /<nerIgnore>(.+?)<\/nerIgnore>/g;
|
|
|
6
6
|
export const HTML_NER_REPLACE_REGEX = /<nerReplace\s*(?:prefix="(.*?)")?\s*type="(.*?)"\s*value="(.*?)">(.*?)<\/nerReplace>/gi;
|
|
7
7
|
export const HTML_BOLD_REGEX = /<b>(.+?)<\/b>/g;
|
|
8
8
|
export const HTML_A_TAG_REGEX = /(?:<|<)a\b[^>]*?(?:>|>)(.*?)(?:<|<)\/a(?:>|>)/g;
|
|
9
|
+
export const HTML_NO_EMOJI_REGEX = /<span class="no-emoji-convert">([\s\S]*?)<\/span>/g;
|
|
9
10
|
//# sourceMappingURL=regex.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"regex.js","names":["BB_LC_MENTION_REGEX","BB_NER_IGNORE_REGEX","BB_NER_REPLACE_REGEX","HTML_LC_MENTION_REGEX","HTML_NER_IGNORE_REGEX","HTML_NER_REPLACE_REGEX","HTML_BOLD_REGEX","HTML_A_TAG_REGEX"],"sources":["../../../src/constants/regex.ts"],"sourcesContent":["export const BB_LC_MENTION_REGEX = /\\[lc_mention.+?id=\"([^\"]+?)\"](.+?)\\[\\/lc_mention]/g;\nexport const BB_NER_IGNORE_REGEX = /\\[nerIgnore](.+?)\\[\\/nerIgnore]/g;\nexport const BB_NER_REPLACE_REGEX =\n /\\[nerReplace\\s*(?:prefix=\"(.*?)\")?\\s*type=\"(.*?)\"\\s*value=\"(.*?)\"](.*?)\\[\\/nerReplace]/gi;\n\nexport const HTML_LC_MENTION_REGEX =\n /<lc_mention.+?id=\"([^\"]+?)\">(?:<span.*?<\\/span>)*(.+?)<\\/lc_mention>/g;\nexport const HTML_NER_IGNORE_REGEX = /<nerIgnore>(.+?)<\\/nerIgnore>/g;\nexport const HTML_NER_REPLACE_REGEX =\n /<nerReplace\\s*(?:prefix=\"(.*?)\")?\\s*type=\"(.*?)\"\\s*value=\"(.*?)\">(.*?)<\\/nerReplace>/gi;\nexport const HTML_BOLD_REGEX = /<b>(.+?)<\\/b>/g;\nexport const HTML_A_TAG_REGEX = /(?:<|<)a\\b[^>]*?(?:>|>)(.*?)(?:<|<)\\/a(?:>|>)/g;\n"],"mappings":"AAAA,OAAO,MAAMA,mBAAmB,GAAG,oDAAoD;AACvF,OAAO,MAAMC,mBAAmB,GAAG,kCAAkC;AACrE,OAAO,MAAMC,oBAAoB,GAC7B,0FAA0F;AAE9F,OAAO,MAAMC,qBAAqB,GAC9B,uEAAuE;AAC3E,OAAO,MAAMC,qBAAqB,GAAG,gCAAgC;AACrE,OAAO,MAAMC,sBAAsB,GAC/B,wFAAwF;AAC5F,OAAO,MAAMC,eAAe,GAAG,gBAAgB;AAC/C,OAAO,MAAMC,gBAAgB,GAAG,4DAA4D","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"regex.js","names":["BB_LC_MENTION_REGEX","BB_NER_IGNORE_REGEX","BB_NER_REPLACE_REGEX","HTML_LC_MENTION_REGEX","HTML_NER_IGNORE_REGEX","HTML_NER_REPLACE_REGEX","HTML_BOLD_REGEX","HTML_A_TAG_REGEX","HTML_NO_EMOJI_REGEX"],"sources":["../../../src/constants/regex.ts"],"sourcesContent":["export const BB_LC_MENTION_REGEX = /\\[lc_mention.+?id=\"([^\"]+?)\"](.+?)\\[\\/lc_mention]/g;\nexport const BB_NER_IGNORE_REGEX = /\\[nerIgnore](.+?)\\[\\/nerIgnore]/g;\nexport const BB_NER_REPLACE_REGEX =\n /\\[nerReplace\\s*(?:prefix=\"(.*?)\")?\\s*type=\"(.*?)\"\\s*value=\"(.*?)\"](.*?)\\[\\/nerReplace]/gi;\n\nexport const HTML_LC_MENTION_REGEX =\n /<lc_mention.+?id=\"([^\"]+?)\">(?:<span.*?<\\/span>)*(.+?)<\\/lc_mention>/g;\nexport const HTML_NER_IGNORE_REGEX = /<nerIgnore>(.+?)<\\/nerIgnore>/g;\nexport const HTML_NER_REPLACE_REGEX =\n /<nerReplace\\s*(?:prefix=\"(.*?)\")?\\s*type=\"(.*?)\"\\s*value=\"(.*?)\">(.*?)<\\/nerReplace>/gi;\nexport const HTML_BOLD_REGEX = /<b>(.+?)<\\/b>/g;\nexport const HTML_A_TAG_REGEX = /(?:<|<)a\\b[^>]*?(?:>|>)(.*?)(?:<|<)\\/a(?:>|>)/g;\n\nexport const HTML_NO_EMOJI_REGEX = /<span class=\"no-emoji-convert\">([\\s\\S]*?)<\\/span>/g;\n"],"mappings":"AAAA,OAAO,MAAMA,mBAAmB,GAAG,oDAAoD;AACvF,OAAO,MAAMC,mBAAmB,GAAG,kCAAkC;AACrE,OAAO,MAAMC,oBAAoB,GAC7B,0FAA0F;AAE9F,OAAO,MAAMC,qBAAqB,GAC9B,uEAAuE;AAC3E,OAAO,MAAMC,qBAAqB,GAAG,gCAAgC;AACrE,OAAO,MAAMC,sBAAsB,GAC/B,wFAAwF;AAC5F,OAAO,MAAMC,eAAe,GAAG,gBAAgB;AAC/C,OAAO,MAAMC,gBAAgB,GAAG,4DAA4D;AAE5F,OAAO,MAAMC,mBAAmB,GAAG,oDAAoD","ignoreList":[]}
|
package/lib/esm/utils/emoji.js
CHANGED
|
@@ -54,7 +54,7 @@ export const escapeHTML = text => {
|
|
|
54
54
|
};
|
|
55
55
|
return text.replace(/[&<>"']/g, match => escaped[match] ?? match);
|
|
56
56
|
};
|
|
57
|
-
export const convertEmojisToUnicode = (text, regShortnames, shortNameList) => {
|
|
57
|
+
export const convertEmojisToUnicode = (text, regShortnames, shortNameList, options) => {
|
|
58
58
|
let result = text;
|
|
59
59
|
result = result.replace(/https?:\/\/.*?(?=$|\s)/gi, fullMatch => fullMatch.replace(/:/g, '%3A'));
|
|
60
60
|
result = result.replace(regShortnames, shortname => {
|
|
@@ -71,7 +71,14 @@ export const convertEmojisToUnicode = (text, regShortnames, shortNameList) => {
|
|
|
71
71
|
if (typeof m3 === 'string' && m3 !== '') {
|
|
72
72
|
const unicode = asciiList[unescapeHTML(m3)];
|
|
73
73
|
if (unicode) {
|
|
74
|
-
|
|
74
|
+
const emoji = convert(unicode.toUpperCase());
|
|
75
|
+
if (typeof options?.onAsciiConversion === 'function') {
|
|
76
|
+
options.onAsciiConversion({
|
|
77
|
+
original: m3,
|
|
78
|
+
emoji
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return m2 + emoji;
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
return fullMatch;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emoji.js","names":["asciiList","regAscii","convert","unicode","indexOf","parts","s","split","i","length","part","parseInt","hi","Math","floor","lo","String","fromCharCode","push","join","unescapeHTML","text","unescaped","replace","match","escapeHTML","escaped","convertEmojisToUnicode","regShortnames","shortNameList","result","fullMatch","shortname","toUpperCase","m1","m2","m3","
|
|
1
|
+
{"version":3,"file":"emoji.js","names":["asciiList","regAscii","convert","unicode","indexOf","parts","s","split","i","length","part","parseInt","hi","Math","floor","lo","String","fromCharCode","push","join","unescapeHTML","text","unescaped","replace","match","escapeHTML","escaped","convertEmojisToUnicode","regShortnames","shortNameList","options","result","fullMatch","shortname","toUpperCase","m1","m2","m3","emoji","onAsciiConversion","original","addSkinToneToEmoji","emojiList","skinTone","map","rawEmoji","skin_tone_support"],"sources":["../../../src/utils/emoji.ts"],"sourcesContent":["import { asciiList, regAscii } from '../constants/emoji';\n\nconst convert = (unicode: string) => {\n if (unicode.indexOf('-') > -1) {\n const parts = [];\n\n const s = unicode.split('-');\n\n for (let i = 0; i < s.length; i++) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n let part: number | string = parseInt(s[i]!, 16);\n\n if (part >= 0x10000 && part <= 0x10ffff) {\n const hi = Math.floor((part - 0x10000) / 0x400) + 0xd800;\n const lo = ((part - 0x10000) % 0x400) + 0xdc00;\n\n part = String.fromCharCode(hi) + String.fromCharCode(lo);\n } else {\n part = String.fromCharCode(part);\n }\n\n parts.push(part);\n }\n\n return parts.join('');\n }\n\n const s = parseInt(unicode, 16);\n\n if (s >= 0x10000 && s <= 0x10ffff) {\n const hi = Math.floor((s - 0x10000) / 0x400) + 0xd800;\n const lo = ((s - 0x10000) % 0x400) + 0xdc00;\n\n return String.fromCharCode(hi) + String.fromCharCode(lo);\n }\n\n return String.fromCharCode(s);\n};\n\nexport const unescapeHTML = (text: string) => {\n const unescaped: { [key: string]: string } = {\n '&': '&',\n '&': '&',\n '&': '&',\n '<': '<',\n '<': '<',\n '<': '<',\n '>': '>',\n '>': '>',\n '>': '>',\n '"': '\"',\n '"': '\"',\n '"': '\"',\n ''': \"'\",\n ''': \"'\",\n ''': \"'\",\n };\n\n return text.replace(\n /&(?:amp|#38|#x26|lt|#60|#x3C|gt|#62|#x3E|apos|#39|#x27|quot|#34|#x22);/gi,\n (match) => unescaped[match] ?? match,\n );\n};\n\nexport const escapeHTML = (text: string) => {\n const escaped: { [key: string]: string } = {\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n };\n\n return text.replace(/[&<>\"']/g, (match) => escaped[match] ?? match);\n};\n\nexport interface AsciiSmileyConversion {\n /** The original ASCII smiley as it appeared in the input (e.g. \":-)\"). */\n original: string;\n /** The resulting Unicode emoji (e.g. \"🙂\"). */\n emoji: string;\n}\n\nexport interface ConvertEmojisToUnicodeOptions {\n /** * Optional callback invoked for every ASCII smiley that was successfully * converted to its Unicode emoji counterpart. Conversions are reported in * the order they were processed. Used by the `EmojiInput` component to * enable the \"Backspace reverts the last auto-converted smiley\" UX. */\n onAsciiConversion?: (conversion: AsciiSmileyConversion) => void;\n}\n\nexport const convertEmojisToUnicode = (\n text: string,\n regShortnames: RegExp,\n shortNameList: { [p: string]: string },\n options?: ConvertEmojisToUnicodeOptions,\n): string => {\n let result = text;\n\n result = result.replace(/https?:\\/\\/.*?(?=$|\\s)/gi, (fullMatch) =>\n fullMatch.replace(/:/g, '%3A'),\n );\n\n result = result.replace(regShortnames, (shortname) => {\n if (shortname) {\n const unicode = shortNameList[shortname];\n\n if (unicode) {\n return convert(unicode.toUpperCase());\n }\n }\n\n return shortname;\n });\n\n result = result.replace(/https?%3A\\/\\/.*?(?=$|\\s)/gi, (fullMatch) =>\n fullMatch.replace(/%3A/g, ':'),\n );\n\n result = result.replace(regAscii, (fullMatch, m1, m2, m3) => {\n if (typeof m3 === 'string' && m3 !== '') {\n const unicode = asciiList[unescapeHTML(m3)];\n\n if (unicode) {\n const emoji = convert(unicode.toUpperCase());\n\n if (typeof options?.onAsciiConversion === 'function') {\n options.onAsciiConversion({ original: m3, emoji });\n }\n\n return (m2 as string) + emoji;\n }\n }\n\n return fullMatch;\n });\n\n return result;\n};\n\nexport const addSkinToneToEmoji = (\n emojiList: { [x: string]: { skin_tone_support: any } },\n emoji: string,\n skinTone: string,\n): string =>\n emoji\n .split('\\u{200D}')\n .map((rawEmoji) => {\n const parts = [rawEmoji.replace(/\\ufe0f/, '')];\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (emojiList[rawEmoji]?.skin_tone_support) {\n parts.push(skinTone);\n }\n\n return parts.join('');\n })\n .join('\\u{200D}');\n"],"mappings":"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","ignoreList":[]}
|
package/lib/esm/utils/insert.js
CHANGED
|
@@ -101,4 +101,87 @@ export const replaceText = ({
|
|
|
101
101
|
});
|
|
102
102
|
}
|
|
103
103
|
};
|
|
104
|
+
/** * Reverts the most recent ASCII-smiley-to-emoji conversion at the cursor * position. * * The emoji (and optionally the trigger character following it) is removed * and replaced by a `<span class="no-emoji-convert">{original}</span>` block. * The cursor is moved to the end of the inserted span. The span is then * protected against re-conversion by the existing `regAscii` rule that skips * the contents of any `<span>` element. * * @returns `true` if a revert was performed, `false` otherwise. */
|
|
105
|
+
export const revertAsciiSmileyConversion = ({
|
|
106
|
+
editorElement,
|
|
107
|
+
original,
|
|
108
|
+
emoji,
|
|
109
|
+
shouldRemoveTriggerChar = true
|
|
110
|
+
}) => {
|
|
111
|
+
// Walk all text nodes and find the LAST one that contains the emoji.
|
|
112
|
+
// The just-converted emoji is the most recent occurrence; using the last
|
|
113
|
+
// match is correct because the conversion always inserts the emoji at
|
|
114
|
+
// the (former) cursor position and the cursor is at the end of that
|
|
115
|
+
// insertion when Backspace is pressed.
|
|
116
|
+
const walker = document.createTreeWalker(editorElement, NodeFilter.SHOW_TEXT);
|
|
117
|
+
let targetNode = null;
|
|
118
|
+
let targetIndex = -1;
|
|
119
|
+
let current = walker.nextNode();
|
|
120
|
+
while (current) {
|
|
121
|
+
const idx = current.nodeValue?.lastIndexOf(emoji) ?? -1;
|
|
122
|
+
if (idx !== -1) {
|
|
123
|
+
targetNode = current;
|
|
124
|
+
targetIndex = idx;
|
|
125
|
+
}
|
|
126
|
+
current = walker.nextNode();
|
|
127
|
+
}
|
|
128
|
+
if (!targetNode || targetIndex === -1) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
const nodeValue = targetNode.nodeValue ?? '';
|
|
132
|
+
const before = nodeValue.slice(0, targetIndex);
|
|
133
|
+
const afterEmoji = nodeValue.slice(targetIndex + emoji.length);
|
|
134
|
+
|
|
135
|
+
// Drop the single trigger char (space, ".", ",", "!", "?", ...) that
|
|
136
|
+
// immediately follows the emoji. If the trigger sits in a different
|
|
137
|
+
// text node or has already been removed, we silently keep the rest.
|
|
138
|
+
const after = shouldRemoveTriggerChar && afterEmoji.length > 0 ? afterEmoji.slice(1) : afterEmoji;
|
|
139
|
+
const parent = targetNode.parentNode;
|
|
140
|
+
if (!parent) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Build the protective span
|
|
145
|
+
const span = document.createElement('span');
|
|
146
|
+
span.className = 'no-emoji-convert';
|
|
147
|
+
span.textContent = original;
|
|
148
|
+
|
|
149
|
+
// Rewrite the original text node + insert span (+ remaining text node)
|
|
150
|
+
targetNode.nodeValue = before;
|
|
151
|
+
parent.insertBefore(span, targetNode.nextSibling);
|
|
152
|
+
|
|
153
|
+
// ALWAYS ensure a real text node exists directly after the span and place
|
|
154
|
+
// the cursor INSIDE it. Without this, contentEditable extends the span
|
|
155
|
+
// when the user keeps typing — which would protect every subsequent
|
|
156
|
+
// character from emoji conversion.
|
|
157
|
+
let cursorNode;
|
|
158
|
+
let cursorOffset;
|
|
159
|
+
if (after) {
|
|
160
|
+
cursorNode = document.createTextNode(after);
|
|
161
|
+
parent.insertBefore(cursorNode, span.nextSibling);
|
|
162
|
+
cursorOffset = 0;
|
|
163
|
+
} else {
|
|
164
|
+
// Insert a zero-width space that is stripped by convertHTMLToText
|
|
165
|
+
// (line 73 in text.ts), so it stays invisible to consumers.
|
|
166
|
+
cursorNode = document.createTextNode('\u200B');
|
|
167
|
+
parent.insertBefore(cursorNode, span.nextSibling);
|
|
168
|
+
cursorOffset = cursorNode.length;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// If the leading text node is now empty, remove it to keep the DOM tidy
|
|
172
|
+
if (before === '') {
|
|
173
|
+
parent.removeChild(targetNode);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Move cursor into the text node that sits OUTSIDE the protection span
|
|
177
|
+
const selection = window.getSelection();
|
|
178
|
+
if (selection) {
|
|
179
|
+
const range = document.createRange();
|
|
180
|
+
range.setStart(cursorNode, cursorOffset);
|
|
181
|
+
range.setEnd(cursorNode, cursorOffset);
|
|
182
|
+
selection.removeAllRanges();
|
|
183
|
+
selection.addRange(range);
|
|
184
|
+
}
|
|
185
|
+
return true;
|
|
186
|
+
};
|
|
104
187
|
//# sourceMappingURL=insert.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insert.js","names":["findAndSelectText","moveSelectionOffset","restoreSelection","saveSelection","setChildIndex","insertTextAtCursorPosition","editorElement","text","shouldUseSavedSelection","selection","window","getSelection","anchorNode","contains","range","getRangeAt","parts","split","firstPart","shift","textNodes","map","part","document","createTextNode","deleteContents","nodeType","Node","TEXT_NODE","nodeValue","slice","startOffset","length","textNode","insertBefore","childNodes","anchorOffset","before","appendChild","textNodeIndex","Array","from","indexOf","brElement","createElement","insertNode","setEndAfter","setStartAfter","forEach","index","collapse","removeAllRanges","addRange","innerText","replaceText","searchText","pasteText","options","rangeToReplace"],"sources":["../../../src/utils/insert.ts"],"sourcesContent":["import {\n findAndSelectText,\n moveSelectionOffset,\n restoreSelection,\n saveSelection,\n setChildIndex,\n type ReplaceTextOptions as IReplaceTextOptions,\n} from './selection';\n\ninterface InsertTextAtCursorPositionOptions {\n editorElement: HTMLDivElement;\n text: string;\n shouldUseSavedSelection?: boolean;\n}\n\n/**\n * This function inserts the passed text at the correct position in the editor element. If the\n * element has the focus, the new emoji is inserted at the cursor position. If not, the emoji\n * will be appended to the back of the input field content.\n *\n * In addition, this function also sets the cursor to the correct position when the input field\n * has the focus. For this purpose, the current position of the cursor or a selection is read to\n * calculate the cursor position after inserting the text.\n *\n * @param {Object} options - Object with element and text to insert\n * @param {HTMLDivElement} options.editorElement - Element to insert text into\n * @param {string} options.text - Text to insert into element\n */\nexport const insertTextAtCursorPosition = ({\n editorElement,\n text,\n shouldUseSavedSelection = false,\n}: InsertTextAtCursorPositionOptions) => {\n if (shouldUseSavedSelection) {\n restoreSelection(editorElement);\n }\n\n const selection = window.getSelection();\n\n saveSelection(editorElement);\n\n if (selection?.anchorNode && editorElement.contains(selection.anchorNode)) {\n let range = selection.getRangeAt(0);\n\n const parts = text.split(/\\r\\n|\\r|\\n/);\n\n const firstPart = parts.shift();\n\n const textNodes = parts.map((part) => document.createTextNode(part));\n\n range.deleteContents();\n\n if (firstPart) {\n if (selection.anchorNode.nodeType === Node.TEXT_NODE) {\n const { nodeValue } = selection.anchorNode;\n\n if (typeof nodeValue === 'string') {\n selection.anchorNode.nodeValue =\n nodeValue.slice(0, range.startOffset) +\n firstPart +\n nodeValue.slice(range.startOffset);\n\n moveSelectionOffset(firstPart.length);\n }\n } else if (selection.anchorNode === editorElement) {\n const textNode = document.createTextNode(firstPart);\n\n // Inserts the text node before the node at the anchor offset.\n // If that node doesn't exist, the text node is appended to the editor, as a fallback. I'm not sure if there is any case where this would happen.\n const insertBefore = editorElement.childNodes[selection.anchorOffset];\n if (insertBefore) {\n insertBefore.before(textNode);\n } else {\n editorElement.appendChild(textNode);\n }\n\n const textNodeIndex = Array.from(editorElement.childNodes).indexOf(textNode);\n\n moveSelectionOffset(firstPart.length);\n setChildIndex(textNodeIndex);\n }\n }\n\n restoreSelection(editorElement);\n\n if (textNodes.length > 0) {\n range = selection.getRangeAt(0);\n\n let brElement = document.createElement('br');\n\n range.insertNode(brElement);\n range.setEndAfter(brElement);\n range.setStartAfter(brElement);\n\n textNodes.forEach((textNode, index) => {\n range.insertNode(textNode);\n range.setEndAfter(textNode);\n range.setStartAfter(textNode);\n\n if (index !== textNodes.length - 1) {\n brElement = document.createElement('br');\n\n range.insertNode(brElement);\n range.setEndAfter(brElement);\n range.setStartAfter(brElement);\n }\n });\n\n range.collapse(false);\n\n selection.removeAllRanges();\n selection.addRange(range);\n }\n } else {\n // eslint-disable-next-line no-param-reassign\n editorElement.innerText += text;\n }\n};\n\nexport interface ReplaceTextOptions {\n editorElement: HTMLDivElement;\n searchText: string;\n pasteText: string;\n options?: IReplaceTextOptions;\n}\n\nexport const replaceText = ({\n editorElement,\n searchText,\n pasteText,\n options,\n}: ReplaceTextOptions) => {\n const selection = window.getSelection();\n\n const rangeToReplace = findAndSelectText({ editorElement, searchText, options });\n\n if (rangeToReplace && selection) {\n selection.removeAllRanges();\n selection.addRange(rangeToReplace);\n\n insertTextAtCursorPosition({ editorElement, text: pasteText });\n }\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"insert.js","names":["findAndSelectText","moveSelectionOffset","restoreSelection","saveSelection","setChildIndex","insertTextAtCursorPosition","editorElement","text","shouldUseSavedSelection","selection","window","getSelection","anchorNode","contains","range","getRangeAt","parts","split","firstPart","shift","textNodes","map","part","document","createTextNode","deleteContents","nodeType","Node","TEXT_NODE","nodeValue","slice","startOffset","length","textNode","insertBefore","childNodes","anchorOffset","before","appendChild","textNodeIndex","Array","from","indexOf","brElement","createElement","insertNode","setEndAfter","setStartAfter","forEach","index","collapse","removeAllRanges","addRange","innerText","replaceText","searchText","pasteText","options","rangeToReplace","revertAsciiSmileyConversion","original","emoji","shouldRemoveTriggerChar","walker","createTreeWalker","NodeFilter","SHOW_TEXT","targetNode","targetIndex","current","nextNode","idx","lastIndexOf","afterEmoji","after","parent","parentNode","span","className","textContent","nextSibling","cursorNode","cursorOffset","removeChild","createRange","setStart","setEnd"],"sources":["../../../src/utils/insert.ts"],"sourcesContent":["import {\n findAndSelectText,\n moveSelectionOffset,\n restoreSelection,\n saveSelection,\n setChildIndex,\n type ReplaceTextOptions as IReplaceTextOptions,\n} from './selection';\n\ninterface InsertTextAtCursorPositionOptions {\n editorElement: HTMLDivElement;\n text: string;\n shouldUseSavedSelection?: boolean;\n}\n\n/**\n * This function inserts the passed text at the correct position in the editor element. If the\n * element has the focus, the new emoji is inserted at the cursor position. If not, the emoji\n * will be appended to the back of the input field content.\n *\n * In addition, this function also sets the cursor to the correct position when the input field\n * has the focus. For this purpose, the current position of the cursor or a selection is read to\n * calculate the cursor position after inserting the text.\n *\n * @param {Object} options - Object with element and text to insert\n * @param {HTMLDivElement} options.editorElement - Element to insert text into\n * @param {string} options.text - Text to insert into element\n */\nexport const insertTextAtCursorPosition = ({\n editorElement,\n text,\n shouldUseSavedSelection = false,\n}: InsertTextAtCursorPositionOptions) => {\n if (shouldUseSavedSelection) {\n restoreSelection(editorElement);\n }\n\n const selection = window.getSelection();\n\n saveSelection(editorElement);\n\n if (selection?.anchorNode && editorElement.contains(selection.anchorNode)) {\n let range = selection.getRangeAt(0);\n\n const parts = text.split(/\\r\\n|\\r|\\n/);\n\n const firstPart = parts.shift();\n\n const textNodes = parts.map((part) => document.createTextNode(part));\n\n range.deleteContents();\n\n if (firstPart) {\n if (selection.anchorNode.nodeType === Node.TEXT_NODE) {\n const { nodeValue } = selection.anchorNode;\n\n if (typeof nodeValue === 'string') {\n selection.anchorNode.nodeValue =\n nodeValue.slice(0, range.startOffset) +\n firstPart +\n nodeValue.slice(range.startOffset);\n\n moveSelectionOffset(firstPart.length);\n }\n } else if (selection.anchorNode === editorElement) {\n const textNode = document.createTextNode(firstPart);\n\n // Inserts the text node before the node at the anchor offset.\n // If that node doesn't exist, the text node is appended to the editor, as a fallback. I'm not sure if there is any case where this would happen.\n const insertBefore = editorElement.childNodes[selection.anchorOffset];\n if (insertBefore) {\n insertBefore.before(textNode);\n } else {\n editorElement.appendChild(textNode);\n }\n\n const textNodeIndex = Array.from(editorElement.childNodes).indexOf(textNode);\n\n moveSelectionOffset(firstPart.length);\n setChildIndex(textNodeIndex);\n }\n }\n\n restoreSelection(editorElement);\n\n if (textNodes.length > 0) {\n range = selection.getRangeAt(0);\n\n let brElement = document.createElement('br');\n\n range.insertNode(brElement);\n range.setEndAfter(brElement);\n range.setStartAfter(brElement);\n\n textNodes.forEach((textNode, index) => {\n range.insertNode(textNode);\n range.setEndAfter(textNode);\n range.setStartAfter(textNode);\n\n if (index !== textNodes.length - 1) {\n brElement = document.createElement('br');\n\n range.insertNode(brElement);\n range.setEndAfter(brElement);\n range.setStartAfter(brElement);\n }\n });\n\n range.collapse(false);\n\n selection.removeAllRanges();\n selection.addRange(range);\n }\n } else {\n // eslint-disable-next-line no-param-reassign\n editorElement.innerText += text;\n }\n};\n\nexport interface ReplaceTextOptions {\n editorElement: HTMLDivElement;\n searchText: string;\n pasteText: string;\n options?: IReplaceTextOptions;\n}\n\nexport const replaceText = ({\n editorElement,\n searchText,\n pasteText,\n options,\n}: ReplaceTextOptions) => {\n const selection = window.getSelection();\n\n const rangeToReplace = findAndSelectText({ editorElement, searchText, options });\n\n if (rangeToReplace && selection) {\n selection.removeAllRanges();\n selection.addRange(rangeToReplace);\n\n insertTextAtCursorPosition({ editorElement, text: pasteText });\n }\n};\n\ninterface RevertAsciiSmileyConversionOptions {\n editorElement: HTMLDivElement;\n /** The original ASCII smiley to restore (e.g. \":-)\"). */\n original: string;\n /** The Unicode emoji that is currently in the DOM and should be replaced. */\n emoji: string;\n /** * Whether to also remove the single character immediately following the * emoji (typically the trigger whitespace / punctuation that caused the * conversion). Defaults to `true` to mirror common autocorrect UX * (Word, IntelliJ, ...). */\n shouldRemoveTriggerChar?: boolean;\n}\n\n/** * Reverts the most recent ASCII-smiley-to-emoji conversion at the cursor * position. * * The emoji (and optionally the trigger character following it) is removed * and replaced by a `<span class=\"no-emoji-convert\">{original}</span>` block. * The cursor is moved to the end of the inserted span. The span is then * protected against re-conversion by the existing `regAscii` rule that skips * the contents of any `<span>` element. * * @returns `true` if a revert was performed, `false` otherwise. */\nexport const revertAsciiSmileyConversion = ({\n editorElement,\n original,\n emoji,\n shouldRemoveTriggerChar = true,\n}: RevertAsciiSmileyConversionOptions): boolean => {\n // Walk all text nodes and find the LAST one that contains the emoji.\n // The just-converted emoji is the most recent occurrence; using the last\n // match is correct because the conversion always inserts the emoji at\n // the (former) cursor position and the cursor is at the end of that\n // insertion when Backspace is pressed.\n const walker = document.createTreeWalker(editorElement, NodeFilter.SHOW_TEXT);\n\n let targetNode: Text | null = null;\n let targetIndex = -1;\n\n let current = walker.nextNode() as Text | null;\n while (current) {\n const idx = current.nodeValue?.lastIndexOf(emoji) ?? -1;\n if (idx !== -1) {\n targetNode = current;\n targetIndex = idx;\n }\n current = walker.nextNode() as Text | null;\n }\n\n if (!targetNode || targetIndex === -1) {\n return false;\n }\n\n const nodeValue = targetNode.nodeValue ?? '';\n const before = nodeValue.slice(0, targetIndex);\n const afterEmoji = nodeValue.slice(targetIndex + emoji.length);\n\n // Drop the single trigger char (space, \".\", \",\", \"!\", \"?\", ...) that\n // immediately follows the emoji. If the trigger sits in a different\n // text node or has already been removed, we silently keep the rest.\n const after =\n shouldRemoveTriggerChar && afterEmoji.length > 0 ? afterEmoji.slice(1) : afterEmoji;\n\n const parent = targetNode.parentNode;\n if (!parent) {\n return false;\n }\n\n // Build the protective span\n const span = document.createElement('span');\n span.className = 'no-emoji-convert';\n span.textContent = original;\n\n // Rewrite the original text node + insert span (+ remaining text node)\n targetNode.nodeValue = before;\n parent.insertBefore(span, targetNode.nextSibling);\n\n // ALWAYS ensure a real text node exists directly after the span and place\n // the cursor INSIDE it. Without this, contentEditable extends the span\n // when the user keeps typing — which would protect every subsequent\n // character from emoji conversion.\n let cursorNode: Text;\n let cursorOffset: number;\n\n if (after) {\n cursorNode = document.createTextNode(after);\n parent.insertBefore(cursorNode, span.nextSibling);\n cursorOffset = 0;\n } else {\n // Insert a zero-width space that is stripped by convertHTMLToText\n // (line 73 in text.ts), so it stays invisible to consumers.\n cursorNode = document.createTextNode('\\u200B');\n parent.insertBefore(cursorNode, span.nextSibling);\n cursorOffset = cursorNode.length;\n }\n\n // If the leading text node is now empty, remove it to keep the DOM tidy\n if (before === '') {\n parent.removeChild(targetNode);\n }\n\n // Move cursor into the text node that sits OUTSIDE the protection span\n const selection = window.getSelection();\n if (selection) {\n const range = document.createRange();\n range.setStart(cursorNode, cursorOffset);\n range.setEnd(cursorNode, cursorOffset);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n\n return true;\n};\n"],"mappings":"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","ignoreList":[]}
|
package/lib/esm/utils/text.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BB_LC_MENTION_REGEX, BB_NER_IGNORE_REGEX, BB_NER_REPLACE_REGEX, HTML_A_TAG_REGEX, HTML_BOLD_REGEX, HTML_LC_MENTION_REGEX, HTML_NER_IGNORE_REGEX, HTML_NER_REPLACE_REGEX } from '../constants/regex';
|
|
1
|
+
import { BB_LC_MENTION_REGEX, BB_NER_IGNORE_REGEX, BB_NER_REPLACE_REGEX, HTML_A_TAG_REGEX, HTML_BOLD_REGEX, HTML_LC_MENTION_REGEX, HTML_NER_IGNORE_REGEX, HTML_NER_REPLACE_REGEX, HTML_NO_EMOJI_REGEX } from '../constants/regex';
|
|
2
2
|
import { escapeHTML, unescapeHTML } from './emoji';
|
|
3
3
|
export const convertTextToHTML = text => {
|
|
4
4
|
const element = document.createElement('div');
|
|
@@ -20,6 +20,11 @@ export const convertHTMLToText = (text, {
|
|
|
20
20
|
preserveSpaces = false
|
|
21
21
|
} = {}) => {
|
|
22
22
|
let result = text;
|
|
23
|
+
|
|
24
|
+
// Unwrap "no-emoji-convert" protection spans so the plain-text
|
|
25
|
+
// representation does not leak the marker HTML to consumers.
|
|
26
|
+
// The protection itself is only relevant inside the live editor DOM.
|
|
27
|
+
result = result.replace(HTML_NO_EMOJI_REGEX, '$1');
|
|
23
28
|
result = result.replace(HTML_A_TAG_REGEX, '$1').replace(HTML_BOLD_REGEX, '[b]$1[/b]').replace(HTML_LC_MENTION_REGEX, '[lc_mention id="$1"]$2[/lc_mention]').replace(HTML_NER_IGNORE_REGEX, '[nerIgnore]$1[/nerIgnore]').replace(HTML_NER_REPLACE_REGEX, (_, prefix, type, value, entity) => {
|
|
24
29
|
const prefixAttr = prefix ? `prefix="${prefix}" ` : '';
|
|
25
30
|
return `[nerReplace ${prefixAttr}type="${type}" value="${value}"]${entity}[/nerReplace]`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","names":["BB_LC_MENTION_REGEX","BB_NER_IGNORE_REGEX","BB_NER_REPLACE_REGEX","HTML_A_TAG_REGEX","HTML_BOLD_REGEX","HTML_LC_MENTION_REGEX","HTML_NER_IGNORE_REGEX","HTML_NER_REPLACE_REGEX","escapeHTML","unescapeHTML","convertTextToHTML","text","element","document","createElement","style","position","opacity","contentEditable","innerText","body","appendChild","result","innerHTML","removeChild","replace","_","prefix","type","value","entity","prefixAttr","convertHTMLToText","preserveSpaces","getElementTextLength","textLength","outerHTML","length","e"],"sources":["../../../src/utils/text.ts"],"sourcesContent":["import {\n BB_LC_MENTION_REGEX,\n BB_NER_IGNORE_REGEX,\n BB_NER_REPLACE_REGEX,\n HTML_A_TAG_REGEX,\n HTML_BOLD_REGEX,\n HTML_LC_MENTION_REGEX,\n HTML_NER_IGNORE_REGEX,\n HTML_NER_REPLACE_REGEX,\n} from '../constants/regex';\nimport { escapeHTML, unescapeHTML } from './emoji';\n\nexport const convertTextToHTML = (text: string) => {\n const element = document.createElement('div');\n\n element.style.position = 'absolute';\n element.style.opacity = '0';\n\n element.contentEditable = 'true';\n element.innerText = text;\n\n document.body.appendChild(element);\n\n let result = element.innerHTML;\n\n document.body.removeChild(element);\n\n result = unescapeHTML(result);\n\n result = result\n .replace(HTML_A_TAG_REGEX, '$1')\n .replace(\n BB_LC_MENTION_REGEX,\n '<lc_mention contenteditable=\"false\" id=\"$1\"><span>@</span>$2</lc_mention>',\n )\n .replace(BB_NER_IGNORE_REGEX, '<nerIgnore contenteditable=\"false\">$1</nerIgnore>')\n .replace(\n BB_NER_REPLACE_REGEX,\n (_, prefix: string | undefined, type: string, value: string, entity: string) => {\n const prefixAttr = prefix ? `prefix=\"${prefix}\" ` : '';\n\n return `<nerReplace contenteditable=\"false\" ${prefixAttr}type=\"${type}\" value=\"${value}\">${entity}</nerReplace>`;\n },\n );\n\n return result;\n};\n\nexport const convertHTMLToText = (text: string, { preserveSpaces = false } = {}) => {\n let result = text;\n\n result = result\n .replace(HTML_A_TAG_REGEX, '$1')\n .replace(HTML_BOLD_REGEX, '[b]$1[/b]')\n .replace(HTML_LC_MENTION_REGEX, '[lc_mention id=\"$1\"]$2[/lc_mention]')\n .replace(HTML_NER_IGNORE_REGEX, '[nerIgnore]$1[/nerIgnore]')\n .replace(\n HTML_NER_REPLACE_REGEX,\n (_, prefix: string | undefined, type: string, value: string, entity: string) => {\n const prefixAttr = prefix ? `prefix=\"${prefix}\" ` : '';\n\n return `[nerReplace ${prefixAttr}type=\"${type}\" value=\"${value}\"]${entity}[/nerReplace]`;\n },\n );\n\n if (preserveSpaces) {\n return result\n .replace(/ /g, '\\u00A0') // non-breaking space\n .replace(/\\u200B/g, ''); // zero-width space (sichtbar gemacht)\n }\n\n // eslint-disable-next-line no-irregular-whitespace\n result = result.replace(//g, '');\n\n result = escapeHTML(result);\n\n const element = document.createElement('div');\n\n element.style.position = 'absolute';\n element.style.opacity = '0';\n\n element.contentEditable = 'true';\n element.innerHTML = result;\n\n document.body.appendChild(element);\n\n result = element.innerText;\n\n document.body.removeChild(element);\n\n return result;\n};\n\nexport const getElementTextLength = (element: Element) => {\n let textLength = 0;\n\n try {\n textLength = convertHTMLToText(element.outerHTML).length;\n } catch (e) {\n // Do nothing\n }\n\n return textLength;\n};\n"],"mappings":"AAAA,SACIA,mBAAmB,EACnBC,mBAAmB,EACnBC,oBAAoB,EACpBC,gBAAgB,EAChBC,eAAe,EACfC,qBAAqB,EACrBC,qBAAqB,EACrBC,sBAAsB,
|
|
1
|
+
{"version":3,"file":"text.js","names":["BB_LC_MENTION_REGEX","BB_NER_IGNORE_REGEX","BB_NER_REPLACE_REGEX","HTML_A_TAG_REGEX","HTML_BOLD_REGEX","HTML_LC_MENTION_REGEX","HTML_NER_IGNORE_REGEX","HTML_NER_REPLACE_REGEX","HTML_NO_EMOJI_REGEX","escapeHTML","unescapeHTML","convertTextToHTML","text","element","document","createElement","style","position","opacity","contentEditable","innerText","body","appendChild","result","innerHTML","removeChild","replace","_","prefix","type","value","entity","prefixAttr","convertHTMLToText","preserveSpaces","getElementTextLength","textLength","outerHTML","length","e"],"sources":["../../../src/utils/text.ts"],"sourcesContent":["import {\n BB_LC_MENTION_REGEX,\n BB_NER_IGNORE_REGEX,\n BB_NER_REPLACE_REGEX,\n HTML_A_TAG_REGEX,\n HTML_BOLD_REGEX,\n HTML_LC_MENTION_REGEX,\n HTML_NER_IGNORE_REGEX,\n HTML_NER_REPLACE_REGEX,\n HTML_NO_EMOJI_REGEX,\n} from '../constants/regex';\nimport { escapeHTML, unescapeHTML } from './emoji';\n\nexport const convertTextToHTML = (text: string) => {\n const element = document.createElement('div');\n\n element.style.position = 'absolute';\n element.style.opacity = '0';\n\n element.contentEditable = 'true';\n element.innerText = text;\n\n document.body.appendChild(element);\n\n let result = element.innerHTML;\n\n document.body.removeChild(element);\n\n result = unescapeHTML(result);\n\n result = result\n .replace(HTML_A_TAG_REGEX, '$1')\n .replace(\n BB_LC_MENTION_REGEX,\n '<lc_mention contenteditable=\"false\" id=\"$1\"><span>@</span>$2</lc_mention>',\n )\n .replace(BB_NER_IGNORE_REGEX, '<nerIgnore contenteditable=\"false\">$1</nerIgnore>')\n .replace(\n BB_NER_REPLACE_REGEX,\n (_, prefix: string | undefined, type: string, value: string, entity: string) => {\n const prefixAttr = prefix ? `prefix=\"${prefix}\" ` : '';\n\n return `<nerReplace contenteditable=\"false\" ${prefixAttr}type=\"${type}\" value=\"${value}\">${entity}</nerReplace>`;\n },\n );\n\n return result;\n};\n\nexport const convertHTMLToText = (text: string, { preserveSpaces = false } = {}) => {\n let result = text;\n\n // Unwrap \"no-emoji-convert\" protection spans so the plain-text\n // representation does not leak the marker HTML to consumers.\n // The protection itself is only relevant inside the live editor DOM.\n result = result.replace(HTML_NO_EMOJI_REGEX, '$1');\n\n result = result\n .replace(HTML_A_TAG_REGEX, '$1')\n .replace(HTML_BOLD_REGEX, '[b]$1[/b]')\n .replace(HTML_LC_MENTION_REGEX, '[lc_mention id=\"$1\"]$2[/lc_mention]')\n .replace(HTML_NER_IGNORE_REGEX, '[nerIgnore]$1[/nerIgnore]')\n .replace(\n HTML_NER_REPLACE_REGEX,\n (_, prefix: string | undefined, type: string, value: string, entity: string) => {\n const prefixAttr = prefix ? `prefix=\"${prefix}\" ` : '';\n\n return `[nerReplace ${prefixAttr}type=\"${type}\" value=\"${value}\"]${entity}[/nerReplace]`;\n },\n );\n\n if (preserveSpaces) {\n return result\n .replace(/ /g, '\\u00A0') // non-breaking space\n .replace(/\\u200B/g, ''); // zero-width space (sichtbar gemacht)\n }\n\n // eslint-disable-next-line no-irregular-whitespace\n result = result.replace(//g, '');\n\n result = escapeHTML(result);\n\n const element = document.createElement('div');\n\n element.style.position = 'absolute';\n element.style.opacity = '0';\n\n element.contentEditable = 'true';\n element.innerHTML = result;\n\n document.body.appendChild(element);\n\n result = element.innerText;\n\n document.body.removeChild(element);\n\n return result;\n};\n\nexport const getElementTextLength = (element: Element) => {\n let textLength = 0;\n\n try {\n textLength = convertHTMLToText(element.outerHTML).length;\n } catch (e) {\n // Do nothing\n }\n\n return textLength;\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
export declare const unescapeHTML: (text: string) => string;
|
|
2
2
|
export declare const escapeHTML: (text: string) => string;
|
|
3
|
+
export interface AsciiSmileyConversion {
|
|
4
|
+
/** The original ASCII smiley as it appeared in the input (e.g. ":-)"). */
|
|
5
|
+
original: string;
|
|
6
|
+
/** The resulting Unicode emoji (e.g. "🙂"). */
|
|
7
|
+
emoji: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ConvertEmojisToUnicodeOptions {
|
|
10
|
+
/** * Optional callback invoked for every ASCII smiley that was successfully * converted to its Unicode emoji counterpart. Conversions are reported in * the order they were processed. Used by the `EmojiInput` component to * enable the "Backspace reverts the last auto-converted smiley" UX. */
|
|
11
|
+
onAsciiConversion?: (conversion: AsciiSmileyConversion) => void;
|
|
12
|
+
}
|
|
3
13
|
export declare const convertEmojisToUnicode: (text: string, regShortnames: RegExp, shortNameList: {
|
|
4
14
|
[p: string]: string;
|
|
5
|
-
}) => string;
|
|
15
|
+
}, options?: ConvertEmojisToUnicodeOptions) => string;
|
|
6
16
|
export declare const addSkinToneToEmoji: (emojiList: {
|
|
7
17
|
[x: string]: {
|
|
8
18
|
skin_tone_support: any;
|
|
@@ -25,4 +25,15 @@ export interface ReplaceTextOptions {
|
|
|
25
25
|
options?: IReplaceTextOptions;
|
|
26
26
|
}
|
|
27
27
|
export declare const replaceText: ({ editorElement, searchText, pasteText, options, }: ReplaceTextOptions) => void;
|
|
28
|
+
interface RevertAsciiSmileyConversionOptions {
|
|
29
|
+
editorElement: HTMLDivElement;
|
|
30
|
+
/** The original ASCII smiley to restore (e.g. ":-)"). */
|
|
31
|
+
original: string;
|
|
32
|
+
/** The Unicode emoji that is currently in the DOM and should be replaced. */
|
|
33
|
+
emoji: string;
|
|
34
|
+
/** * Whether to also remove the single character immediately following the * emoji (typically the trigger whitespace / punctuation that caused the * conversion). Defaults to `true` to mirror common autocorrect UX * (Word, IntelliJ, ...). */
|
|
35
|
+
shouldRemoveTriggerChar?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/** * Reverts the most recent ASCII-smiley-to-emoji conversion at the cursor * position. * * The emoji (and optionally the trigger character following it) is removed * and replaced by a `<span class="no-emoji-convert">{original}</span>` block. * The cursor is moved to the end of the inserted span. The span is then * protected against re-conversion by the existing `regAscii` rule that skips * the contents of any `<span>` element. * * @returns `true` if a revert was performed, `false` otherwise. */
|
|
38
|
+
export declare const revertAsciiSmileyConversion: ({ editorElement, original, emoji, shouldRemoveTriggerChar, }: RevertAsciiSmileyConversionOptions) => boolean;
|
|
28
39
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chayns-components/emoji-input",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.6",
|
|
4
4
|
"description": "Input field that supports HTML elements and emojis",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"browserslist": [
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"typescript": "^5.9.3"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@chayns-components/core": "^5.3.
|
|
76
|
+
"@chayns-components/core": "^5.3.5",
|
|
77
77
|
"@chayns-components/textstring": "^5.2.5",
|
|
78
78
|
"emojilib": "^3.0.12",
|
|
79
79
|
"react-compiler-runtime": "^1.0.0",
|
|
@@ -89,5 +89,5 @@
|
|
|
89
89
|
"publishConfig": {
|
|
90
90
|
"access": "public"
|
|
91
91
|
},
|
|
92
|
-
"gitHead": "
|
|
92
|
+
"gitHead": "f918ca037b18d7835adef89e001bf4f021cfc701"
|
|
93
93
|
}
|