@ekz/lexical-hashtag 0.40.0

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.
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ var lexicalText = require('@ekz/lexical-text');
12
+ var lexicalUtils = require('@ekz/lexical-utils');
13
+ var lexical = require('@ekz/lexical');
14
+
15
+ /**
16
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
17
+ *
18
+ * This source code is licensed under the MIT license found in the
19
+ * LICENSE file in the root directory of this source tree.
20
+ *
21
+ */
22
+
23
+
24
+ /** @noInheritDoc */
25
+ class HashtagNode extends lexical.TextNode {
26
+ static getType() {
27
+ return 'hashtag';
28
+ }
29
+ static clone(node) {
30
+ return new HashtagNode(node.__text, node.__key);
31
+ }
32
+ createDOM(config) {
33
+ const element = super.createDOM(config);
34
+ lexicalUtils.addClassNamesToElement(element, config.theme.hashtag);
35
+ return element;
36
+ }
37
+ static importJSON(serializedNode) {
38
+ return $createHashtagNode().updateFromJSON(serializedNode);
39
+ }
40
+ canInsertTextBefore() {
41
+ return false;
42
+ }
43
+ isTextEntity() {
44
+ return true;
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Generates a HashtagNode, which is a string following the format of a # followed by some text, eg. #lexical.
50
+ * @param text - The text used inside the HashtagNode.
51
+ * @returns - The HashtagNode with the embedded text.
52
+ */
53
+ function $createHashtagNode(text = '') {
54
+ return lexical.$applyNodeReplacement(new HashtagNode(text));
55
+ }
56
+
57
+ /**
58
+ * Determines if node is a HashtagNode.
59
+ * @param node - The node to be checked.
60
+ * @returns true if node is a HashtagNode, false otherwise.
61
+ */
62
+ function $isHashtagNode(node) {
63
+ return node instanceof HashtagNode;
64
+ }
65
+
66
+ /**
67
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
68
+ *
69
+ * This source code is licensed under the MIT license found in the
70
+ * LICENSE file in the root directory of this source tree.
71
+ *
72
+ */
73
+
74
+ function getHashtagRegexStringChars() {
75
+ // Latin accented characters
76
+ // Excludes 0xd7 from the range
77
+ // (the multiplication sign, confusable with "x").
78
+ // Also excludes 0xf7, the division sign
79
+ const latinAccents = '\xc0-\xd6' + '\xd8-\xf6' + '\xf8-\xff' + '\u0100-\u024f' + '\u0253-\u0254' + '\u0256-\u0257' + '\u0259' + '\u025b' + '\u0263' + '\u0268' + '\u026f' + '\u0272' + '\u0289' + '\u028b' + '\u02bb' + '\u0300-\u036f' + '\u1e00-\u1eff';
80
+
81
+ // Cyrillic (Russian, Ukrainian, etc.)
82
+ const nonLatinChars = '\u0400-\u04ff' +
83
+ // Cyrillic
84
+ '\u0500-\u0527' +
85
+ // Cyrillic Supplement
86
+ '\u2de0-\u2dff' +
87
+ // Cyrillic Extended A
88
+ '\ua640-\ua69f' +
89
+ // Cyrillic Extended B
90
+ '\u0591-\u05bf' +
91
+ // Hebrew
92
+ '\u05c1-\u05c2' + '\u05c4-\u05c5' + '\u05c7' + '\u05d0-\u05ea' + '\u05f0-\u05f4' + '\ufb12-\ufb28' +
93
+ // Hebrew Presentation Forms
94
+ '\ufb2a-\ufb36' + '\ufb38-\ufb3c' + '\ufb3e' + '\ufb40-\ufb41' + '\ufb43-\ufb44' + '\ufb46-\ufb4f' + '\u0610-\u061a' +
95
+ // Arabic
96
+ '\u0620-\u065f' + '\u066e-\u06d3' + '\u06d5-\u06dc' + '\u06de-\u06e8' + '\u06ea-\u06ef' + '\u06fa-\u06fc' + '\u06ff' + '\u0750-\u077f' +
97
+ // Arabic Supplement
98
+ '\u08a0' +
99
+ // Arabic Extended A
100
+ '\u08a2-\u08ac' + '\u08e4-\u08fe' + '\ufb50-\ufbb1' +
101
+ // Arabic Pres. Forms A
102
+ '\ufbd3-\ufd3d' + '\ufd50-\ufd8f' + '\ufd92-\ufdc7' + '\ufdf0-\ufdfb' + '\ufe70-\ufe74' +
103
+ // Arabic Pres. Forms B
104
+ '\ufe76-\ufefc' + '\u200c-\u200c' +
105
+ // Zero-Width Non-Joiner
106
+ '\u0e01-\u0e3a' +
107
+ // Thai
108
+ '\u0e40-\u0e4e' +
109
+ // Hangul (Korean)
110
+ '\u1100-\u11ff' +
111
+ // Hangul Jamo
112
+ '\u3130-\u3185' +
113
+ // Hangul Compatibility Jamo
114
+ '\uA960-\uA97F' +
115
+ // Hangul Jamo Extended-A
116
+ '\uAC00-\uD7AF' +
117
+ // Hangul Syllables
118
+ '\uD7B0-\uD7FF' +
119
+ // Hangul Jamo Extended-B
120
+ '\uFFA1-\uFFDC'; // Half-width Hangul
121
+
122
+ const charCode = String.fromCharCode;
123
+ const cjkChars = '\u30A1-\u30FA\u30FC-\u30FE' +
124
+ // Katakana (full-width)
125
+ '\uFF66-\uFF9F' +
126
+ // Katakana (half-width)
127
+ '\uFF10-\uFF19\uFF21-\uFF3A' + '\uFF41-\uFF5A' +
128
+ // Latin (full-width)
129
+ '\u3041-\u3096\u3099-\u309E' +
130
+ // Hiragana
131
+ '\u3400-\u4DBF' +
132
+ // Kanji (CJK Extension A)
133
+ '\u4E00-\u9FFF' +
134
+ // Kanji (Unified)
135
+ // Disabled as it breaks the Regex.
136
+ // charCode(0x20000) + '-' + charCode(0x2A6DF) + // Kanji (CJK Extension B)
137
+ charCode(0x2a700) + '-' + charCode(0x2b73f) +
138
+ // Kanji (CJK Extension C)
139
+ charCode(0x2b740) + '-' + charCode(0x2b81f) +
140
+ // Kanji (CJK Extension D)
141
+ charCode(0x2f800) + '-' + charCode(0x2fa1f) + '\u3003\u3005\u303B'; // Kanji (CJK supplement)
142
+
143
+ const otherChars = latinAccents + nonLatinChars + cjkChars;
144
+ // equivalent of \p{L}
145
+
146
+ const unicodeLetters = '\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6' + '\u00F8-\u0241\u0250-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EE\u037A\u0386' + '\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03F5\u03F7-\u0481' + '\u048A-\u04CE\u04D0-\u04F9\u0500-\u050F\u0531-\u0556\u0559\u0561-\u0587' + '\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0640-\u064A\u066E-\u066F' + '\u0671-\u06D3\u06D5\u06E5-\u06E6\u06EE-\u06EF\u06FA-\u06FC\u06FF\u0710' + '\u0712-\u072F\u074D-\u076D\u0780-\u07A5\u07B1\u0904-\u0939\u093D\u0950' + '\u0958-\u0961\u097D\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0' + '\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1' + '\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33' + '\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D' + '\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD' + '\u0AD0\u0AE0-\u0AE1\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30' + '\u0B32-\u0B33\u0B35-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B71\u0B83' + '\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F' + '\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10' + '\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C85-\u0C8C' + '\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE' + '\u0CE0-\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39' + '\u0D60-\u0D61\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6' + '\u0E01-\u0E30\u0E32-\u0E33\u0E40-\u0E46\u0E81-\u0E82\u0E84\u0E87-\u0E88' + '\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7' + '\u0EAA-\u0EAB\u0EAD-\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6' + '\u0EDC-\u0EDD\u0F00\u0F40-\u0F47\u0F49-\u0F6A\u0F88-\u0F8B\u1000-\u1021' + '\u1023-\u1027\u1029-\u102A\u1050-\u1055\u10A0-\u10C5\u10D0-\u10FA\u10FC' + '\u1100-\u1159\u115F-\u11A2\u11A8-\u11F9\u1200-\u1248\u124A-\u124D' + '\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0' + '\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310' + '\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C' + '\u166F-\u1676\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711' + '\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7' + '\u17DC\u1820-\u1877\u1880-\u18A8\u1900-\u191C\u1950-\u196D\u1970-\u1974' + '\u1980-\u19A9\u19C1-\u19C7\u1A00-\u1A16\u1D00-\u1DBF\u1E00-\u1E9B' + '\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D' + '\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC' + '\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC' + '\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u2094\u2102\u2107' + '\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D' + '\u212F-\u2131\u2133-\u2139\u213C-\u213F\u2145-\u2149\u2C00-\u2C2E' + '\u2C30-\u2C5E\u2C80-\u2CE4\u2D00-\u2D25\u2D30-\u2D65\u2D6F\u2D80-\u2D96' + '\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6' + '\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3006\u3031-\u3035' + '\u303B-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF' + '\u3105-\u312C\u3131-\u318E\u31A0-\u31B7\u31F0-\u31FF\u3400-\u4DB5' + '\u4E00-\u9FBB\uA000-\uA48C\uA800-\uA801\uA803-\uA805\uA807-\uA80A' + '\uA80C-\uA822\uAC00-\uD7A3\uF900-\uFA2D\uFA30-\uFA6A\uFA70-\uFAD9' + '\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C' + '\uFB3E\uFB40-\uFB41\uFB43-\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F' + '\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A' + '\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7' + '\uFFDA-\uFFDC';
147
+
148
+ // equivalent of \p{Mn}\p{Mc}
149
+ const unicodeAccents = '\u0300-\u036F\u0483-\u0486\u0591-\u05B9\u05BB-\u05BD\u05BF' + '\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u0615\u064B-\u065E\u0670' + '\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0711\u0730-\u074A' + '\u07A6-\u07B0\u0901-\u0903\u093C\u093E-\u094D\u0951-\u0954\u0962-\u0963' + '\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7-\u09C8\u09CB-\u09CD\u09D7' + '\u09E2-\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D' + '\u0A70-\u0A71\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD' + '\u0AE2-\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B43\u0B47-\u0B48\u0B4B-\u0B4D' + '\u0B56-\u0B57\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7' + '\u0C01-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56' + '\u0C82-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5-\u0CD6' + '\u0D02-\u0D03\u0D3E-\u0D43\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D82-\u0D83' + '\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2-\u0DF3\u0E31\u0E34-\u0E3A' + '\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19' + '\u0F35\u0F37\u0F39\u0F3E-\u0F3F\u0F71-\u0F84\u0F86-\u0F87\u0F90-\u0F97' + '\u0F99-\u0FBC\u0FC6\u102C-\u1032\u1036-\u1039\u1056-\u1059\u135F' + '\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17B6-\u17D3\u17DD' + '\u180B-\u180D\u18A9\u1920-\u192B\u1930-\u193B\u19B0-\u19C0\u19C8-\u19C9' + '\u1A17-\u1A1B\u1DC0-\u1DC3\u20D0-\u20DC\u20E1\u20E5-\u20EB\u302A-\u302F' + '\u3099-\u309A\uA802\uA806\uA80B\uA823-\uA827\uFB1E\uFE00-\uFE0F' + '\uFE20-\uFE23';
150
+
151
+ // equivalent of \p{Dn}
152
+ const unicodeDigits = '\u0030-\u0039\u0660-\u0669\u06F0-\u06F9\u0966-\u096F\u09E6-\u09EF' + '\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F' + '\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29' + '\u1040-\u1049\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9' + '\uFF10-\uFF19';
153
+
154
+ // An alpha char is a unicode chars excluding unicode combining marks
155
+ // but including other chars, a hashtag must start with one of these,
156
+ // it does not make sense to have a combining mark before a base character.
157
+ const alpha = unicodeLetters + otherChars;
158
+
159
+ // A numeric character is any with the number digit property, or
160
+ // underscore. These characters can be included in hashtags, but a hashtag
161
+ // cannot have only these characters.
162
+ const numeric = unicodeDigits + '_';
163
+
164
+ // Alphanumeric char is any alpha char or a unicode char with decimal
165
+ // number property \p{Nd}
166
+ const alphanumeric = alpha + unicodeAccents + numeric;
167
+ const hashChars = '#\\uFF03'; // normal '#' or full-width '#'
168
+
169
+ return {
170
+ alpha,
171
+ alphanumeric,
172
+ hashChars
173
+ };
174
+ }
175
+ function getHashtagRegexString() {
176
+ const {
177
+ alpha,
178
+ alphanumeric,
179
+ hashChars
180
+ } = getHashtagRegexStringChars();
181
+ const hashtagAlpha = '[' + alpha + ']';
182
+ const hashtagAlphanumeric = '[' + alphanumeric + ']';
183
+ const hashtagBoundary = '^|$|[^&/' + alphanumeric + ']';
184
+ const hashCharList = '[' + hashChars + ']';
185
+
186
+ // A hashtag contains characters, numbers and underscores,
187
+ // but not all numbers.
188
+ const hashtag = '(' + hashtagBoundary + ')(' + hashCharList + ')(' + hashtagAlphanumeric + '*' + hashtagAlpha + hashtagAlphanumeric + '*)';
189
+ return hashtag;
190
+ }
191
+ const REGEX = new RegExp(getHashtagRegexString(), 'i');
192
+ function getHashtagMatch(text) {
193
+ const matchArr = REGEX.exec(text);
194
+ if (matchArr === null) {
195
+ return null;
196
+ }
197
+ const hashtagLength = matchArr[3].length + 1;
198
+ const startOffset = matchArr.index + matchArr[1].length;
199
+ const endOffset = startOffset + hashtagLength;
200
+ return {
201
+ end: endOffset,
202
+ start: startOffset
203
+ };
204
+ }
205
+
206
+ /** @internal */
207
+ const defaultHashtagConfig = {
208
+ getHashtagMatch
209
+ };
210
+ /** @internal */
211
+ function registerLexicalHashtag(editor, config = defaultHashtagConfig) {
212
+ return lexicalUtils.mergeRegister(...lexicalText.registerLexicalTextEntity(editor, config.getHashtagMatch, HashtagNode, textNode => $createHashtagNode(textNode.getTextContent())));
213
+ }
214
+ /**
215
+ * Add `#hashtag` support to the editor
216
+ */
217
+ const HashtagExtension = lexical.defineExtension({
218
+ config: defaultHashtagConfig,
219
+ name: '@ekz/lexical-hashtag/Hashtag',
220
+ nodes: () => [HashtagNode],
221
+ register: registerLexicalHashtag
222
+ });
223
+
224
+ exports.$createHashtagNode = $createHashtagNode;
225
+ exports.$isHashtagNode = $isHashtagNode;
226
+ exports.HashtagExtension = HashtagExtension;
227
+ exports.HashtagNode = HashtagNode;
228
+ exports.registerLexicalHashtag = registerLexicalHashtag;
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import { registerLexicalTextEntity } from '@ekz/lexical-text';
10
+ import { addClassNamesToElement, mergeRegister } from '@ekz/lexical-utils';
11
+ import { TextNode, $applyNodeReplacement, defineExtension } from '@ekz/lexical';
12
+
13
+ /**
14
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
15
+ *
16
+ * This source code is licensed under the MIT license found in the
17
+ * LICENSE file in the root directory of this source tree.
18
+ *
19
+ */
20
+
21
+
22
+ /** @noInheritDoc */
23
+ class HashtagNode extends TextNode {
24
+ static getType() {
25
+ return 'hashtag';
26
+ }
27
+ static clone(node) {
28
+ return new HashtagNode(node.__text, node.__key);
29
+ }
30
+ createDOM(config) {
31
+ const element = super.createDOM(config);
32
+ addClassNamesToElement(element, config.theme.hashtag);
33
+ return element;
34
+ }
35
+ static importJSON(serializedNode) {
36
+ return $createHashtagNode().updateFromJSON(serializedNode);
37
+ }
38
+ canInsertTextBefore() {
39
+ return false;
40
+ }
41
+ isTextEntity() {
42
+ return true;
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Generates a HashtagNode, which is a string following the format of a # followed by some text, eg. #lexical.
48
+ * @param text - The text used inside the HashtagNode.
49
+ * @returns - The HashtagNode with the embedded text.
50
+ */
51
+ function $createHashtagNode(text = '') {
52
+ return $applyNodeReplacement(new HashtagNode(text));
53
+ }
54
+
55
+ /**
56
+ * Determines if node is a HashtagNode.
57
+ * @param node - The node to be checked.
58
+ * @returns true if node is a HashtagNode, false otherwise.
59
+ */
60
+ function $isHashtagNode(node) {
61
+ return node instanceof HashtagNode;
62
+ }
63
+
64
+ /**
65
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
66
+ *
67
+ * This source code is licensed under the MIT license found in the
68
+ * LICENSE file in the root directory of this source tree.
69
+ *
70
+ */
71
+
72
+ function getHashtagRegexStringChars() {
73
+ // Latin accented characters
74
+ // Excludes 0xd7 from the range
75
+ // (the multiplication sign, confusable with "x").
76
+ // Also excludes 0xf7, the division sign
77
+ const latinAccents = '\xc0-\xd6' + '\xd8-\xf6' + '\xf8-\xff' + '\u0100-\u024f' + '\u0253-\u0254' + '\u0256-\u0257' + '\u0259' + '\u025b' + '\u0263' + '\u0268' + '\u026f' + '\u0272' + '\u0289' + '\u028b' + '\u02bb' + '\u0300-\u036f' + '\u1e00-\u1eff';
78
+
79
+ // Cyrillic (Russian, Ukrainian, etc.)
80
+ const nonLatinChars = '\u0400-\u04ff' +
81
+ // Cyrillic
82
+ '\u0500-\u0527' +
83
+ // Cyrillic Supplement
84
+ '\u2de0-\u2dff' +
85
+ // Cyrillic Extended A
86
+ '\ua640-\ua69f' +
87
+ // Cyrillic Extended B
88
+ '\u0591-\u05bf' +
89
+ // Hebrew
90
+ '\u05c1-\u05c2' + '\u05c4-\u05c5' + '\u05c7' + '\u05d0-\u05ea' + '\u05f0-\u05f4' + '\ufb12-\ufb28' +
91
+ // Hebrew Presentation Forms
92
+ '\ufb2a-\ufb36' + '\ufb38-\ufb3c' + '\ufb3e' + '\ufb40-\ufb41' + '\ufb43-\ufb44' + '\ufb46-\ufb4f' + '\u0610-\u061a' +
93
+ // Arabic
94
+ '\u0620-\u065f' + '\u066e-\u06d3' + '\u06d5-\u06dc' + '\u06de-\u06e8' + '\u06ea-\u06ef' + '\u06fa-\u06fc' + '\u06ff' + '\u0750-\u077f' +
95
+ // Arabic Supplement
96
+ '\u08a0' +
97
+ // Arabic Extended A
98
+ '\u08a2-\u08ac' + '\u08e4-\u08fe' + '\ufb50-\ufbb1' +
99
+ // Arabic Pres. Forms A
100
+ '\ufbd3-\ufd3d' + '\ufd50-\ufd8f' + '\ufd92-\ufdc7' + '\ufdf0-\ufdfb' + '\ufe70-\ufe74' +
101
+ // Arabic Pres. Forms B
102
+ '\ufe76-\ufefc' + '\u200c-\u200c' +
103
+ // Zero-Width Non-Joiner
104
+ '\u0e01-\u0e3a' +
105
+ // Thai
106
+ '\u0e40-\u0e4e' +
107
+ // Hangul (Korean)
108
+ '\u1100-\u11ff' +
109
+ // Hangul Jamo
110
+ '\u3130-\u3185' +
111
+ // Hangul Compatibility Jamo
112
+ '\uA960-\uA97F' +
113
+ // Hangul Jamo Extended-A
114
+ '\uAC00-\uD7AF' +
115
+ // Hangul Syllables
116
+ '\uD7B0-\uD7FF' +
117
+ // Hangul Jamo Extended-B
118
+ '\uFFA1-\uFFDC'; // Half-width Hangul
119
+
120
+ const charCode = String.fromCharCode;
121
+ const cjkChars = '\u30A1-\u30FA\u30FC-\u30FE' +
122
+ // Katakana (full-width)
123
+ '\uFF66-\uFF9F' +
124
+ // Katakana (half-width)
125
+ '\uFF10-\uFF19\uFF21-\uFF3A' + '\uFF41-\uFF5A' +
126
+ // Latin (full-width)
127
+ '\u3041-\u3096\u3099-\u309E' +
128
+ // Hiragana
129
+ '\u3400-\u4DBF' +
130
+ // Kanji (CJK Extension A)
131
+ '\u4E00-\u9FFF' +
132
+ // Kanji (Unified)
133
+ // Disabled as it breaks the Regex.
134
+ // charCode(0x20000) + '-' + charCode(0x2A6DF) + // Kanji (CJK Extension B)
135
+ charCode(0x2a700) + '-' + charCode(0x2b73f) +
136
+ // Kanji (CJK Extension C)
137
+ charCode(0x2b740) + '-' + charCode(0x2b81f) +
138
+ // Kanji (CJK Extension D)
139
+ charCode(0x2f800) + '-' + charCode(0x2fa1f) + '\u3003\u3005\u303B'; // Kanji (CJK supplement)
140
+
141
+ const otherChars = latinAccents + nonLatinChars + cjkChars;
142
+ // equivalent of \p{L}
143
+
144
+ const unicodeLetters = '\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6' + '\u00F8-\u0241\u0250-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EE\u037A\u0386' + '\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03F5\u03F7-\u0481' + '\u048A-\u04CE\u04D0-\u04F9\u0500-\u050F\u0531-\u0556\u0559\u0561-\u0587' + '\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0640-\u064A\u066E-\u066F' + '\u0671-\u06D3\u06D5\u06E5-\u06E6\u06EE-\u06EF\u06FA-\u06FC\u06FF\u0710' + '\u0712-\u072F\u074D-\u076D\u0780-\u07A5\u07B1\u0904-\u0939\u093D\u0950' + '\u0958-\u0961\u097D\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0' + '\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1' + '\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33' + '\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D' + '\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD' + '\u0AD0\u0AE0-\u0AE1\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30' + '\u0B32-\u0B33\u0B35-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B71\u0B83' + '\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F' + '\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10' + '\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C85-\u0C8C' + '\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE' + '\u0CE0-\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39' + '\u0D60-\u0D61\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6' + '\u0E01-\u0E30\u0E32-\u0E33\u0E40-\u0E46\u0E81-\u0E82\u0E84\u0E87-\u0E88' + '\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7' + '\u0EAA-\u0EAB\u0EAD-\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6' + '\u0EDC-\u0EDD\u0F00\u0F40-\u0F47\u0F49-\u0F6A\u0F88-\u0F8B\u1000-\u1021' + '\u1023-\u1027\u1029-\u102A\u1050-\u1055\u10A0-\u10C5\u10D0-\u10FA\u10FC' + '\u1100-\u1159\u115F-\u11A2\u11A8-\u11F9\u1200-\u1248\u124A-\u124D' + '\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0' + '\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310' + '\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C' + '\u166F-\u1676\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711' + '\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7' + '\u17DC\u1820-\u1877\u1880-\u18A8\u1900-\u191C\u1950-\u196D\u1970-\u1974' + '\u1980-\u19A9\u19C1-\u19C7\u1A00-\u1A16\u1D00-\u1DBF\u1E00-\u1E9B' + '\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D' + '\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC' + '\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC' + '\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u2094\u2102\u2107' + '\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D' + '\u212F-\u2131\u2133-\u2139\u213C-\u213F\u2145-\u2149\u2C00-\u2C2E' + '\u2C30-\u2C5E\u2C80-\u2CE4\u2D00-\u2D25\u2D30-\u2D65\u2D6F\u2D80-\u2D96' + '\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6' + '\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3006\u3031-\u3035' + '\u303B-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF' + '\u3105-\u312C\u3131-\u318E\u31A0-\u31B7\u31F0-\u31FF\u3400-\u4DB5' + '\u4E00-\u9FBB\uA000-\uA48C\uA800-\uA801\uA803-\uA805\uA807-\uA80A' + '\uA80C-\uA822\uAC00-\uD7A3\uF900-\uFA2D\uFA30-\uFA6A\uFA70-\uFAD9' + '\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C' + '\uFB3E\uFB40-\uFB41\uFB43-\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F' + '\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A' + '\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7' + '\uFFDA-\uFFDC';
145
+
146
+ // equivalent of \p{Mn}\p{Mc}
147
+ const unicodeAccents = '\u0300-\u036F\u0483-\u0486\u0591-\u05B9\u05BB-\u05BD\u05BF' + '\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u0615\u064B-\u065E\u0670' + '\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0711\u0730-\u074A' + '\u07A6-\u07B0\u0901-\u0903\u093C\u093E-\u094D\u0951-\u0954\u0962-\u0963' + '\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7-\u09C8\u09CB-\u09CD\u09D7' + '\u09E2-\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D' + '\u0A70-\u0A71\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD' + '\u0AE2-\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B43\u0B47-\u0B48\u0B4B-\u0B4D' + '\u0B56-\u0B57\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7' + '\u0C01-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56' + '\u0C82-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5-\u0CD6' + '\u0D02-\u0D03\u0D3E-\u0D43\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D82-\u0D83' + '\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2-\u0DF3\u0E31\u0E34-\u0E3A' + '\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19' + '\u0F35\u0F37\u0F39\u0F3E-\u0F3F\u0F71-\u0F84\u0F86-\u0F87\u0F90-\u0F97' + '\u0F99-\u0FBC\u0FC6\u102C-\u1032\u1036-\u1039\u1056-\u1059\u135F' + '\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17B6-\u17D3\u17DD' + '\u180B-\u180D\u18A9\u1920-\u192B\u1930-\u193B\u19B0-\u19C0\u19C8-\u19C9' + '\u1A17-\u1A1B\u1DC0-\u1DC3\u20D0-\u20DC\u20E1\u20E5-\u20EB\u302A-\u302F' + '\u3099-\u309A\uA802\uA806\uA80B\uA823-\uA827\uFB1E\uFE00-\uFE0F' + '\uFE20-\uFE23';
148
+
149
+ // equivalent of \p{Dn}
150
+ const unicodeDigits = '\u0030-\u0039\u0660-\u0669\u06F0-\u06F9\u0966-\u096F\u09E6-\u09EF' + '\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F' + '\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29' + '\u1040-\u1049\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9' + '\uFF10-\uFF19';
151
+
152
+ // An alpha char is a unicode chars excluding unicode combining marks
153
+ // but including other chars, a hashtag must start with one of these,
154
+ // it does not make sense to have a combining mark before a base character.
155
+ const alpha = unicodeLetters + otherChars;
156
+
157
+ // A numeric character is any with the number digit property, or
158
+ // underscore. These characters can be included in hashtags, but a hashtag
159
+ // cannot have only these characters.
160
+ const numeric = unicodeDigits + '_';
161
+
162
+ // Alphanumeric char is any alpha char or a unicode char with decimal
163
+ // number property \p{Nd}
164
+ const alphanumeric = alpha + unicodeAccents + numeric;
165
+ const hashChars = '#\\uFF03'; // normal '#' or full-width '#'
166
+
167
+ return {
168
+ alpha,
169
+ alphanumeric,
170
+ hashChars
171
+ };
172
+ }
173
+ function getHashtagRegexString() {
174
+ const {
175
+ alpha,
176
+ alphanumeric,
177
+ hashChars
178
+ } = getHashtagRegexStringChars();
179
+ const hashtagAlpha = '[' + alpha + ']';
180
+ const hashtagAlphanumeric = '[' + alphanumeric + ']';
181
+ const hashtagBoundary = '^|$|[^&/' + alphanumeric + ']';
182
+ const hashCharList = '[' + hashChars + ']';
183
+
184
+ // A hashtag contains characters, numbers and underscores,
185
+ // but not all numbers.
186
+ const hashtag = '(' + hashtagBoundary + ')(' + hashCharList + ')(' + hashtagAlphanumeric + '*' + hashtagAlpha + hashtagAlphanumeric + '*)';
187
+ return hashtag;
188
+ }
189
+ const REGEX = new RegExp(getHashtagRegexString(), 'i');
190
+ function getHashtagMatch(text) {
191
+ const matchArr = REGEX.exec(text);
192
+ if (matchArr === null) {
193
+ return null;
194
+ }
195
+ const hashtagLength = matchArr[3].length + 1;
196
+ const startOffset = matchArr.index + matchArr[1].length;
197
+ const endOffset = startOffset + hashtagLength;
198
+ return {
199
+ end: endOffset,
200
+ start: startOffset
201
+ };
202
+ }
203
+
204
+ /** @internal */
205
+ const defaultHashtagConfig = {
206
+ getHashtagMatch
207
+ };
208
+ /** @internal */
209
+ function registerLexicalHashtag(editor, config = defaultHashtagConfig) {
210
+ return mergeRegister(...registerLexicalTextEntity(editor, config.getHashtagMatch, HashtagNode, textNode => $createHashtagNode(textNode.getTextContent())));
211
+ }
212
+ /**
213
+ * Add `#hashtag` support to the editor
214
+ */
215
+ const HashtagExtension = defineExtension({
216
+ config: defaultHashtagConfig,
217
+ name: '@ekz/lexical-hashtag/Hashtag',
218
+ nodes: () => [HashtagNode],
219
+ register: registerLexicalHashtag
220
+ });
221
+
222
+ export { $createHashtagNode, $isHashtagNode, HashtagExtension, HashtagNode, registerLexicalHashtag };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ 'use strict'
10
+ const EkzLexicalHashtag = process.env.NODE_ENV !== 'production' ? require('./EkzLexicalHashtag.dev.js') : require('./EkzLexicalHashtag.prod.js');
11
+ module.exports = EkzLexicalHashtag;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import * as modDev from './EkzLexicalHashtag.dev.mjs';
10
+ import * as modProd from './EkzLexicalHashtag.prod.mjs';
11
+ const mod = process.env.NODE_ENV !== 'production' ? modDev : modProd;
12
+ export const $createHashtagNode = mod.$createHashtagNode;
13
+ export const $isHashtagNode = mod.$isHashtagNode;
14
+ export const HashtagExtension = mod.HashtagExtension;
15
+ export const HashtagNode = mod.HashtagNode;
16
+ export const registerLexicalHashtag = mod.registerLexicalHashtag;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ const mod = await (process.env.NODE_ENV !== 'production' ? import('./EkzLexicalHashtag.dev.mjs') : import('./EkzLexicalHashtag.prod.mjs'));
10
+ export const $createHashtagNode = mod.$createHashtagNode;
11
+ export const $isHashtagNode = mod.$isHashtagNode;
12
+ export const HashtagExtension = mod.HashtagExtension;
13
+ export const HashtagNode = mod.HashtagNode;
14
+ export const registerLexicalHashtag = mod.registerLexicalHashtag;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ "use strict";var e=require("@ekz/lexical-text"),t=require("@ekz/lexical-utils"),n=require("@ekz/lexical");class r extends n.TextNode{static getType(){return"hashtag"}static clone(e){return new r(e.__text,e.__key)}createDOM(e){const n=super.createDOM(e);return t.addClassNamesToElement(n,e.theme.hashtag),n}static importJSON(e){return a().updateFromJSON(e)}canInsertTextBefore(){return!1}isTextEntity(){return!0}}function a(e=""){return n.$applyNodeReplacement(new r(e))}const s=new RegExp(function(){const{alpha:e,alphanumeric:t,hashChars:n}=function(){const e=String.fromCharCode,t="A-Za-zªµºÀ-ÖØ-öø-Ɂɐ-ˁˆ-ˑˠ-ˤˮͺΆΈ-ΊΌΎ-ΡΣ-ώϐ-ϵϷ-ҁҊ-ӎӐ-ӹԀ-ԏԱ-Ֆՙա-ևא-תװ-ײء-غـ-يٮ-ٯٱ-ۓەۥ-ۦۮ-ۯۺ-ۼۿܐܒ-ܯݍ-ݭހ-ޥޱऄ-हऽॐक़-ॡॽঅ-ঌএ-ঐও-নপ-রলশ-হঽৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽૐૠ-ૡଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽଡ଼-ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கங-சஜஞ-டண-தந-பம-ஹఅ-ఌఎ-ఐఒ-నప-ళవ-హౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠ-ೡഅ-ഌഎ-ഐഒ-നപ-ഹൠ-ൡඅ-ඖක-නඳ-රලව-ෆก-ะา-ำเ-ๆກ-ຂຄງ-ຈຊຍດ-ທນ-ຟມ-ຣລວສ-ຫອ-ະາ-ຳຽເ-ໄໆໜ-ໝༀཀ-ཇཉ-ཪྈ-ྋက-အဣ-ဧဩ-ဪၐ-ၕႠ-Ⴥა-ჺჼᄀ-ᅙᅟ-ᆢᆨ-ᇹሀ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏼᐁ-ᙬᙯ-ᙶᚁ-ᚚᚠ-ᛪᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᤀ-ᤜᥐ-ᥭᥰ-ᥴᦀ-ᦩᧁ-ᧇᨀ-ᨖᴀ-ᶿḀ-ẛẠ-ỹἀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₔℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℱℳ-ℹℼ-ℿⅅ-ⅉⰀ-Ⱞⰰ-ⱞⲀ-ⳤⴀ-ⴥⴰ-ⵥⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄬㄱ-ㆎㆠ-ㆷㇰ-ㇿ㐀-䶵一-龻ꀀ-ꒌꠀ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢ가-힣豈-鶴侮-頻並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵÀ-ÖØ-öø-ÿĀ-ɏɓ-ɔɖ-ɗəɛɣɨɯɲʉʋʻ̀-ͯḀ-ỿЀ-ӿԀ-ԧⷠ-ⷿꙀ-֑ꚟ-ֿׁ-ׂׄ-ׇׅא-תװ-״﬒-ﬨשׁ-זּטּ-לּמּנּ-סּףּ-פּצּ-ﭏؐ-ؚؠ-ٟٮ-ۓە-ۜ۞-۪ۨ-ۯۺ-ۼۿݐ-ݿࢠࢢ-ࢬࣤ-ࣾﭐ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼ‌-‌ก-ฺเ-๎ᄀ-ᇿ㄰-ㆅꥠ-꥿가-힯ힰ-퟿ᄀ-ᅵァ-ヺー-ヾヲ-゚0-9A-Za-zぁ-ゖ゙-ゞ㐀-䶿一-鿿"+e(173824)+"-"+e(177983)+e(177984)+"-"+e(178207)+e(194560)+"-"+e(195103)+"〃々〻";return{alpha:t,alphanumeric:t+"̀-ͯ҃-֑҆-ֹֻ-ֽֿׁ-ׂׄ-ׇׅؐ-ًؕ-ٰٞۖ-ۜ۟-ۤۧ-۪ۨ-ܑۭܰ-݊ަ-ްँ-ः़ा-्॑-॔ॢ-ॣঁ-ঃ়া-ৄে-ৈো-্ৗৢ-ৣਁ-ਃ਼ਾ-ੂੇ-ੈੋ-੍ੰ-ੱઁ-ઃ઼ા-ૅે-ૉો-્ૢ-ૣଁ-ଃ଼ା-ୃେ-ୈୋ-୍ୖ-ୗஂா-ூெ-ைொ-்ௗఁ-ఃా-ౄె-ైొ-్ౕ-ౖಂ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕ-ೖം-ഃാ-ൃെ-ൈൊ-്ൗං-ඃ්ා-ුූෘ-ෟෲ-ෳัิ-ฺ็-๎ັິ-ູົ-ຼ່-ໍ༘-༹༙༵༷༾-༿ཱ-྄྆-྇ྐ-ྗྙ-ྼ࿆ာ-ဲံ-္ၖ-ၙ፟ᜒ-᜔ᜲ-᜴ᝒ-ᝓᝲ-ᝳា-៓៝᠋-᠍ᢩᤠ-ᤫᤰ-᤻ᦰ-ᧀᧈ-ᧉᨗ-ᨛ᷀-᷃⃐-⃥⃜⃡-⃫〪-゙〯-゚ꠂ꠆ꠋꠣ-ꠧﬞ︀-️︠-︣0-9٠-٩۰-۹०-९০-৯੦-੯૦-૯୦-୯௦-௯౦-౯೦-೯൦-൯๐-๙໐-໙༠-༩၀-၉០-៩᠐-᠙᥆-᥏᧐-᧙0-9_",hashChars:"#\\uFF03"}}(),r="["+t+"]";return"("+("^|$|[^&/"+t+"]")+")("+("["+n+"]")+")("+r+"*"+("["+e+"]")+r+"*)"}(),"i");const i={getHashtagMatch:function(e){const t=s.exec(e);if(null===t)return null;const n=t[3].length+1,r=t.index+t[1].length;return{end:r+n,start:r}}};function c(n,s=i){return t.mergeRegister(...e.registerLexicalTextEntity(n,s.getHashtagMatch,r,e=>a(e.getTextContent())))}const o=n.defineExtension({config:i,name:"@ekz/lexical-hashtag/Hashtag",nodes:()=>[r],register:c});exports.$createHashtagNode=a,exports.$isHashtagNode=function(e){return e instanceof r},exports.HashtagExtension=o,exports.HashtagNode=r,exports.registerLexicalHashtag=c;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import{registerLexicalTextEntity as t}from"@ekz/lexical-text";import{addClassNamesToElement as e,mergeRegister as n}from"@ekz/lexical-utils";import{TextNode as r,$applyNodeReplacement as a,defineExtension as c}from"@ekz/lexical";class s extends r{static getType(){return"hashtag"}static clone(t){return new s(t.__text,t.__key)}createDOM(t){const n=super.createDOM(t);return e(n,t.theme.hashtag),n}static importJSON(t){return o().updateFromJSON(t)}canInsertTextBefore(){return!1}isTextEntity(){return!0}}function o(t=""){return a(new s(t))}function i(t){return t instanceof s}const u=new RegExp(function(){const{alpha:t,alphanumeric:e,hashChars:n}=function(){const t=String.fromCharCode,e="A-Za-zªµºÀ-ÖØ-öø-Ɂɐ-ˁˆ-ˑˠ-ˤˮͺΆΈ-ΊΌΎ-ΡΣ-ώϐ-ϵϷ-ҁҊ-ӎӐ-ӹԀ-ԏԱ-Ֆՙա-ևא-תװ-ײء-غـ-يٮ-ٯٱ-ۓەۥ-ۦۮ-ۯۺ-ۼۿܐܒ-ܯݍ-ݭހ-ޥޱऄ-हऽॐक़-ॡॽঅ-ঌএ-ঐও-নপ-রলশ-হঽৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽૐૠ-ૡଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽଡ଼-ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கங-சஜஞ-டண-தந-பம-ஹఅ-ఌఎ-ఐఒ-నప-ళవ-హౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠ-ೡഅ-ഌഎ-ഐഒ-നപ-ഹൠ-ൡඅ-ඖක-නඳ-රලව-ෆก-ะา-ำเ-ๆກ-ຂຄງ-ຈຊຍດ-ທນ-ຟມ-ຣລວສ-ຫອ-ະາ-ຳຽເ-ໄໆໜ-ໝༀཀ-ཇཉ-ཪྈ-ྋက-အဣ-ဧဩ-ဪၐ-ၕႠ-Ⴥა-ჺჼᄀ-ᅙᅟ-ᆢᆨ-ᇹሀ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏼᐁ-ᙬᙯ-ᙶᚁ-ᚚᚠ-ᛪᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᤀ-ᤜᥐ-ᥭᥰ-ᥴᦀ-ᦩᧁ-ᧇᨀ-ᨖᴀ-ᶿḀ-ẛẠ-ỹἀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₔℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℱℳ-ℹℼ-ℿⅅ-ⅉⰀ-Ⱞⰰ-ⱞⲀ-ⳤⴀ-ⴥⴰ-ⵥⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄬㄱ-ㆎㆠ-ㆷㇰ-ㇿ㐀-䶵一-龻ꀀ-ꒌꠀ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢ가-힣豈-鶴侮-頻並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵÀ-ÖØ-öø-ÿĀ-ɏɓ-ɔɖ-ɗəɛɣɨɯɲʉʋʻ̀-ͯḀ-ỿЀ-ӿԀ-ԧⷠ-ⷿꙀ-֑ꚟ-ֿׁ-ׂׄ-ׇׅא-תװ-״﬒-ﬨשׁ-זּטּ-לּמּנּ-סּףּ-פּצּ-ﭏؐ-ؚؠ-ٟٮ-ۓە-ۜ۞-۪ۨ-ۯۺ-ۼۿݐ-ݿࢠࢢ-ࢬࣤ-ࣾﭐ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼ‌-‌ก-ฺเ-๎ᄀ-ᇿ㄰-ㆅꥠ-꥿가-힯ힰ-퟿ᄀ-ᅵァ-ヺー-ヾヲ-゚0-9A-Za-zぁ-ゖ゙-ゞ㐀-䶿一-鿿"+t(173824)+"-"+t(177983)+t(177984)+"-"+t(178207)+t(194560)+"-"+t(195103)+"〃々〻";return{alpha:e,alphanumeric:e+"̀-ͯ҃-֑҆-ֹֻ-ֽֿׁ-ׂׄ-ׇׅؐ-ًؕ-ٰٞۖ-ۜ۟-ۤۧ-۪ۨ-ܑۭܰ-݊ަ-ްँ-ः़ा-्॑-॔ॢ-ॣঁ-ঃ়া-ৄে-ৈো-্ৗৢ-ৣਁ-ਃ਼ਾ-ੂੇ-ੈੋ-੍ੰ-ੱઁ-ઃ઼ા-ૅે-ૉો-્ૢ-ૣଁ-ଃ଼ା-ୃେ-ୈୋ-୍ୖ-ୗஂா-ூெ-ைொ-்ௗఁ-ఃా-ౄె-ైొ-్ౕ-ౖಂ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕ-ೖം-ഃാ-ൃെ-ൈൊ-്ൗං-ඃ්ා-ුූෘ-ෟෲ-ෳัิ-ฺ็-๎ັິ-ູົ-ຼ່-ໍ༘-༹༙༵༷༾-༿ཱ-྄྆-྇ྐ-ྗྙ-ྼ࿆ာ-ဲံ-္ၖ-ၙ፟ᜒ-᜔ᜲ-᜴ᝒ-ᝓᝲ-ᝳា-៓៝᠋-᠍ᢩᤠ-ᤫᤰ-᤻ᦰ-ᧀᧈ-ᧉᨗ-ᨛ᷀-᷃⃐-⃥⃜⃡-⃫〪-゙〯-゚ꠂ꠆ꠋꠣ-ꠧﬞ︀-️︠-︣0-9٠-٩۰-۹०-९০-৯੦-੯૦-૯୦-୯௦-௯౦-౯೦-೯൦-൯๐-๙໐-໙༠-༩၀-၉០-៩᠐-᠙᥆-᥏᧐-᧙0-9_",hashChars:"#\\uFF03"}}(),r="["+e+"]";return"("+("^|$|[^&/"+e+"]")+")("+("["+n+"]")+")("+r+"*"+("["+t+"]")+r+"*)"}(),"i");const h={getHashtagMatch:function(t){const e=u.exec(t);if(null===e)return null;const n=e[3].length+1,r=e.index+e[1].length;return{end:r+n,start:r}}};function l(e,r=h){return n(...t(e,r.getHashtagMatch,s,t=>o(t.getTextContent())))}const g=c({config:h,name:"@ekz/lexical-hashtag/Hashtag",nodes:()=>[s],register:l});export{o as $createHashtagNode,i as $isHashtagNode,g as HashtagExtension,s as HashtagNode,l as registerLexicalHashtag};
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Meta Platforms, Inc. and affiliates.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ */
9
+
10
+ import type {
11
+ EditorConfig,
12
+ LexicalNode,
13
+ NodeKey,
14
+ SerializedTextNode,
15
+ LexicalExtension,
16
+ } from '@ekz/lexical';
17
+
18
+ import {TextNode} from '@ekz/lexical';
19
+
20
+ declare export class HashtagNode extends TextNode {
21
+ static getType(): string;
22
+ static clone(node: HashtagNode): HashtagNode;
23
+ static importJSON(serializedNode: SerializedTextNode): HashtagNode;
24
+ constructor(text: string, key?: NodeKey): void;
25
+ createDOM(config: EditorConfig): HTMLElement;
26
+ canInsertTextBefore(): boolean;
27
+ isTextEntity(): true;
28
+ exportJSON(): SerializedTextNode;
29
+ }
30
+ declare export function $createHashtagNode(text?: string): HashtagNode;
31
+ declare export function $isHashtagNode(
32
+ node: ?LexicalNode,
33
+ ): node is HashtagNode;
34
+
35
+
36
+ export type HashtagConfig = {
37
+ getHashtagMatch: (text: string) => null | {start: number; end: number};
38
+ }
39
+ declare export var HashtagExtension: LexicalExtension<HashtagConfig, "@ekz/lexical-hashtag/Hashtag", void, void>;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import { LexicalEditor } from '@ekz/lexical';
9
+ /** @internal */
10
+ declare const defaultHashtagConfig: HashtagConfig;
11
+ /** @internal */
12
+ export declare function registerLexicalHashtag(editor: LexicalEditor, config?: typeof defaultHashtagConfig): () => void;
13
+ export interface HashtagConfig {
14
+ /**
15
+ * The matching function used by the extension. Has a default
16
+ * implementation that should be suitable for most use cases.
17
+ *
18
+ * @param text The string of text to match
19
+ * @returns `null` if no match, otherwise an object with the start and end index of the first `#hashtag` match
20
+ */
21
+ getHashtagMatch: (text: string) => null | {
22
+ start: number;
23
+ end: number;
24
+ };
25
+ }
26
+ /**
27
+ * Add `#hashtag` support to the editor
28
+ */
29
+ export declare const HashtagExtension: import("@ekz/lexical").LexicalExtension<HashtagConfig, "@ekz/lexical-hashtag/Hashtag", unknown, unknown>;
30
+ export {};
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { EditorConfig, LexicalNode, SerializedTextNode } from '@ekz/lexical';
9
+ import { TextNode } from '@ekz/lexical';
10
+ /** @noInheritDoc */
11
+ export declare class HashtagNode extends TextNode {
12
+ static getType(): string;
13
+ static clone(node: HashtagNode): HashtagNode;
14
+ createDOM(config: EditorConfig): HTMLElement;
15
+ static importJSON(serializedNode: SerializedTextNode): HashtagNode;
16
+ canInsertTextBefore(): boolean;
17
+ isTextEntity(): true;
18
+ }
19
+ /**
20
+ * Generates a HashtagNode, which is a string following the format of a # followed by some text, eg. #lexical.
21
+ * @param text - The text used inside the HashtagNode.
22
+ * @returns - The HashtagNode with the embedded text.
23
+ */
24
+ export declare function $createHashtagNode(text?: string): HashtagNode;
25
+ /**
26
+ * Determines if node is a HashtagNode.
27
+ * @param node - The node to be checked.
28
+ * @returns true if node is a HashtagNode, false otherwise.
29
+ */
30
+ export declare function $isHashtagNode(node: LexicalNode | null | undefined): node is HashtagNode;
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # `@lexical/hashtag`
2
+
3
+ [![See API Documentation](https://lexical.dev/img/see-api-documentation.svg)](https://lexical.dev/docs/api/modules/lexical_hashtag)
4
+
5
+ This package contains the functionality for Lexical hashtags.
6
+
7
+ More documentation coming soon.
package/index.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ export { type HashtagConfig, HashtagExtension, registerLexicalHashtag, } from './LexicalHashtagExtension';
9
+ export { $createHashtagNode, $isHashtagNode, HashtagNode, } from './LexicalHashtagNode';
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@ekz/lexical-hashtag",
3
+ "description": "This package contains the functionality for Lexical hashtags.",
4
+ "keywords": [
5
+ "lexical",
6
+ "editor",
7
+ "rich-text",
8
+ "hashtag"
9
+ ],
10
+ "license": "MIT",
11
+ "version": "0.40.0",
12
+ "main": "LexicalHashtag.js",
13
+ "types": "index.d.ts",
14
+ "dependencies": {
15
+ "@ekz/lexical-text": "0.40.0",
16
+ "@ekz/lexical-utils": "0.40.0",
17
+ "@ekz/lexical": "0.40.0"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/facebook/lexical.git",
22
+ "directory": "packages/lexical-hashtag"
23
+ },
24
+ "module": "LexicalHashtag.mjs",
25
+ "sideEffects": false,
26
+ "exports": {
27
+ ".": {
28
+ "import": {
29
+ "types": "./index.d.ts",
30
+ "development": "./LexicalHashtag.dev.mjs",
31
+ "production": "./LexicalHashtag.prod.mjs",
32
+ "node": "./LexicalHashtag.node.mjs",
33
+ "default": "./LexicalHashtag.mjs"
34
+ },
35
+ "require": {
36
+ "types": "./index.d.ts",
37
+ "development": "./LexicalHashtag.dev.js",
38
+ "production": "./LexicalHashtag.prod.js",
39
+ "default": "./LexicalHashtag.js"
40
+ }
41
+ }
42
+ }
43
+ }