@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.
- package/EkzLexicalHashtag.dev.js +228 -0
- package/EkzLexicalHashtag.dev.mjs +222 -0
- package/EkzLexicalHashtag.js +11 -0
- package/EkzLexicalHashtag.mjs +16 -0
- package/EkzLexicalHashtag.node.mjs +14 -0
- package/EkzLexicalHashtag.prod.js +9 -0
- package/EkzLexicalHashtag.prod.mjs +9 -0
- package/LICENSE +21 -0
- package/LexicalHashtag.js.flow +39 -0
- package/LexicalHashtagExtension.d.ts +30 -0
- package/LexicalHashtagNode.d.ts +30 -0
- package/README.md +7 -0
- package/index.d.ts +9 -0
- package/package.json +43 -0
|
@@ -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
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
|
+
}
|