@milkdown/plugin-emoji 5.4.0 → 6.0.0-next.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/lib/{src/constant.d.ts → constant.d.ts} +0 -0
- package/lib/constant.d.ts.map +1 -0
- package/lib/{src/filter → filter}/helper.d.ts +0 -0
- package/lib/filter/helper.d.ts.map +1 -0
- package/lib/filter/index.d.ts +5 -0
- package/lib/filter/index.d.ts.map +1 -0
- package/lib/filter/style.d.ts +3 -0
- package/lib/filter/style.d.ts.map +1 -0
- package/lib/index.d.ts +4 -1
- package/lib/index.d.ts.map +1 -0
- package/lib/index.es.js +98 -64
- package/lib/index.es.js.map +1 -1
- package/lib/{src/node.d.ts → node.d.ts} +1 -1
- package/lib/node.d.ts.map +1 -0
- package/lib/{src/parse.d.ts → parse.d.ts} +0 -0
- package/lib/parse.d.ts.map +1 -0
- package/lib/picker.d.ts +5 -0
- package/lib/picker.d.ts.map +1 -0
- package/lib/{src/remark-twemoji.d.ts → remark-twemoji.d.ts} +0 -0
- package/lib/remark-twemoji.d.ts.map +1 -0
- package/package.json +34 -10
- package/src/filter/helper.ts +17 -9
- package/src/filter/index.ts +22 -9
- package/src/filter/style.ts +22 -10
- package/src/node.ts +24 -20
- package/src/picker.ts +9 -4
- package/src/remark-twemoji.ts +16 -8
- package/lib/src/constant.d.ts.map +0 -1
- package/lib/src/filter/helper.d.ts.map +0 -1
- package/lib/src/filter/index.d.ts +0 -4
- package/lib/src/filter/index.d.ts.map +0 -1
- package/lib/src/filter/style.d.ts +0 -3
- package/lib/src/filter/style.d.ts.map +0 -1
- package/lib/src/index.d.ts +0 -4
- package/lib/src/index.d.ts.map +0 -1
- package/lib/src/node.d.ts.map +0 -1
- package/lib/src/parse.d.ts.map +0 -1
- package/lib/src/picker.d.ts +0 -4
- package/lib/src/picker.d.ts.map +0 -1
- package/lib/src/remark-twemoji.d.ts.map +0 -1
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constant.d.ts","sourceRoot":"","sources":["../src/constant.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,IAAI,QAAqB,CAAC;AACvC,eAAO,MAAM,IAAI,QAAwB,CAAC;AAC1C,eAAO,MAAM,KAAK,QAAmB,CAAC;AACtC,eAAO,MAAM,OAAO,YAAY,CAAC"}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../../src/filter/helper.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAKnC,eAAO,MAAM,YAAY,SACf,UAAU,QACV,MAAM,MACR,MAAM,QACJ,MAAM,mBACK,MAAM,MAAM,MAAM,KAAK,IAAI,qBACzB,MAAM,KAAK,IAAI,YAoBrC,CAAC;AAEF,eAAO,MAAM,kBAAkB,SACrB,KAAK,EAAE,YACH,WAAW,WACZ,WAAW,GAAG,IAAI,aAChB,MAAM,IAAI,sBACD,WAAW,GAAG,IAAI,KAAK,IAAI,SAmDlD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/filter/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAyB,MAAM,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAMxC,eAAO,MAAM,GAAG,qBAAgD,CAAC;AAEjE,eAAO,MAAM,MAAM,UAAW,KAAK,qBAmKlC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/filter/style.ts"],"names":[],"mappings":"AACA,OAAO,EAEH,OAAO,EAIP,YAAY,EAGf,MAAM,gBAAgB,CAAC;AAExB,eAAO,MAAM,WAAW,iBAAkB,YAAY,eAAe,OAAO,WAyC3E,CAAC"}
|
package/lib/index.d.ts
CHANGED
|
@@ -1 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { AtomList } from '@milkdown/utils';
|
|
2
|
+
export declare const emoji: AtomList<import("@milkdown/utils/lib/types").Metadata<import("@milkdown/utils/lib/types").GetPlugin<string, import("@milkdown/utils").UnknownRecord>> & import("@milkdown/core").MilkdownPlugin>;
|
|
3
|
+
export { emojiNode } from './node';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAI3C,eAAO,MAAM,KAAK,kMAAiC,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC"}
|
package/lib/index.es.js
CHANGED
|
@@ -4,7 +4,7 @@ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
|
4
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
6
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
-
var __defNormalProp = (obj,
|
|
7
|
+
var __defNormalProp = (obj, key2, value) => key2 in obj ? __defProp(obj, key2, { enumerable: true, configurable: true, writable: true, value }) : obj[key2] = value;
|
|
8
8
|
var __spreadValues = (a, b) => {
|
|
9
9
|
for (var prop in b || (b = {}))
|
|
10
10
|
if (__hasOwnProp.call(b, prop))
|
|
@@ -18,10 +18,11 @@ var __spreadValues = (a, b) => {
|
|
|
18
18
|
};
|
|
19
19
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
20
|
import { createNode, AtomList } from "@milkdown/utils";
|
|
21
|
-
import { Plugin, calculateNodePosition, DecorationSet, Decoration, InputRule } from "@milkdown/prose";
|
|
21
|
+
import { PluginKey, Plugin, calculateNodePosition, DecorationSet, Decoration, InputRule } from "@milkdown/prose";
|
|
22
22
|
import nodeEmoji, { search } from "node-emoji";
|
|
23
23
|
import remarkEmoji from "remark-emoji";
|
|
24
24
|
import twemoji from "twemoji";
|
|
25
|
+
import { ThemeBorder, ThemeShadow, ThemeSize, ThemeFont, ThemeColor } from "@milkdown/core";
|
|
25
26
|
import { EmojiButton } from "@joeattardi/emoji-button";
|
|
26
27
|
import emojiRegex from "emoji-regex";
|
|
27
28
|
const part = /:\+1|:-1|:[\w-]+/;
|
|
@@ -40,7 +41,7 @@ const checkTrigger$1 = (view, from, to, text, setRange, setSearch) => {
|
|
|
40
41
|
return false;
|
|
41
42
|
}
|
|
42
43
|
const regex2 = part.exec(textBefore);
|
|
43
|
-
if (regex2 && textBefore.endsWith(regex2[0])) {
|
|
44
|
+
if (regex2 && regex2[0] && textBefore.endsWith(regex2[0])) {
|
|
44
45
|
const match = regex2[0];
|
|
45
46
|
setRange(from - (match.length - text.length), to);
|
|
46
47
|
setSearch(match);
|
|
@@ -49,15 +50,17 @@ const checkTrigger$1 = (view, from, to, text, setRange, setSearch) => {
|
|
|
49
50
|
return false;
|
|
50
51
|
};
|
|
51
52
|
const renderDropdownList = (list, dropDown, $active, onConfirm, setActive) => {
|
|
52
|
-
dropDown.
|
|
53
|
-
|
|
53
|
+
while (dropDown.firstChild) {
|
|
54
|
+
dropDown.firstChild.remove();
|
|
55
|
+
}
|
|
56
|
+
list.forEach(({ emoji: emoji2, key: key2 }, i) => {
|
|
54
57
|
const container = document.createElement("div");
|
|
55
58
|
container.className = "milkdown-emoji-filter_item";
|
|
56
59
|
const emojiSpan = document.createElement("span");
|
|
57
60
|
emojiSpan.innerHTML = parse(emoji2);
|
|
58
61
|
emojiSpan.className = "milkdown-emoji-filter_item-emoji";
|
|
59
62
|
const keySpan = document.createElement("span");
|
|
60
|
-
keySpan.textContent = ":" +
|
|
63
|
+
keySpan.textContent = ":" + key2 + ":";
|
|
61
64
|
keySpan.className = "milkdown-emoji-filter_item-key";
|
|
62
65
|
container.appendChild(emojiSpan);
|
|
63
66
|
container.appendChild(keySpan);
|
|
@@ -66,7 +69,7 @@ const renderDropdownList = (list, dropDown, $active, onConfirm, setActive) => {
|
|
|
66
69
|
container.classList.add("active");
|
|
67
70
|
setActive(container);
|
|
68
71
|
}
|
|
69
|
-
|
|
72
|
+
const onEnter = (e) => {
|
|
70
73
|
if ($active) {
|
|
71
74
|
$active.classList.remove("active");
|
|
72
75
|
}
|
|
@@ -75,43 +78,48 @@ const renderDropdownList = (list, dropDown, $active, onConfirm, setActive) => {
|
|
|
75
78
|
return;
|
|
76
79
|
target.classList.add("active");
|
|
77
80
|
setActive(target);
|
|
78
|
-
}
|
|
79
|
-
|
|
81
|
+
};
|
|
82
|
+
const onLeave = (e) => {
|
|
80
83
|
const { target } = e;
|
|
81
84
|
if (!(target instanceof HTMLElement))
|
|
82
85
|
return;
|
|
83
86
|
target.classList.remove("active");
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
onConfirm();
|
|
87
|
+
};
|
|
88
|
+
const onClick = (e) => {
|
|
87
89
|
e.preventDefault();
|
|
88
|
-
|
|
90
|
+
onConfirm();
|
|
91
|
+
};
|
|
92
|
+
container.addEventListener("mouseenter", onEnter);
|
|
93
|
+
container.addEventListener("mouseleave", onLeave);
|
|
94
|
+
container.addEventListener("mousedown", onClick);
|
|
89
95
|
});
|
|
90
96
|
};
|
|
91
|
-
const injectStyle = (
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
const
|
|
97
|
+
const injectStyle = (themeManager, { css, cx }) => {
|
|
98
|
+
const border = themeManager.get(ThemeBorder, void 0);
|
|
99
|
+
const shadow = themeManager.get(ThemeShadow, void 0);
|
|
100
|
+
const radius = themeManager.get(ThemeSize, "radius");
|
|
101
|
+
const typography = themeManager.get(ThemeFont, "typography");
|
|
102
|
+
const palette = (color, opacity = 1) => themeManager.get(ThemeColor, [color, opacity]);
|
|
95
103
|
const style = css`
|
|
96
104
|
position: absolute;
|
|
97
105
|
&.hide {
|
|
98
106
|
display: none;
|
|
99
107
|
}
|
|
100
108
|
|
|
101
|
-
border-radius: ${
|
|
109
|
+
border-radius: ${radius};
|
|
102
110
|
background: ${palette("surface")};
|
|
103
111
|
|
|
104
112
|
.milkdown-emoji-filter_item {
|
|
105
113
|
display: flex;
|
|
106
|
-
gap: 0.
|
|
107
|
-
height: 2.
|
|
108
|
-
padding: 0
|
|
114
|
+
gap: 0.5em;
|
|
115
|
+
height: 2.57143em;
|
|
116
|
+
padding: 0 1em;
|
|
109
117
|
align-items: center;
|
|
110
118
|
justify-content: flex-start;
|
|
111
119
|
cursor: pointer;
|
|
112
120
|
line-height: 2;
|
|
113
|
-
font-family: ${
|
|
114
|
-
font-size: 0.
|
|
121
|
+
font-family: ${typography};
|
|
122
|
+
font-size: 0.875em;
|
|
115
123
|
&.active {
|
|
116
124
|
background: ${palette("secondary", 0.12)};
|
|
117
125
|
color: ${palette("primary")};
|
|
@@ -127,6 +135,7 @@ const injectStyle = ({ size, mixin, palette, font }, { css, cx }) => {
|
|
|
127
135
|
`;
|
|
128
136
|
return cx(border, shadow, style);
|
|
129
137
|
};
|
|
138
|
+
const key$1 = new PluginKey("MILKDOWN_PLUGIN_EMOJI_FILTER");
|
|
130
139
|
const filter = (utils) => {
|
|
131
140
|
let trigger = false;
|
|
132
141
|
let _from = 0;
|
|
@@ -139,6 +148,7 @@ const filter = (utils) => {
|
|
|
139
148
|
$active = null;
|
|
140
149
|
};
|
|
141
150
|
return new Plugin({
|
|
151
|
+
key: key$1,
|
|
142
152
|
props: {
|
|
143
153
|
handleKeyDown(_, event) {
|
|
144
154
|
if (["Delete", "Backspace"].includes(event.key)) {
|
|
@@ -173,10 +183,12 @@ const filter = (utils) => {
|
|
|
173
183
|
throw new Error();
|
|
174
184
|
}
|
|
175
185
|
const dropDown = document.createElement("div");
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
186
|
+
utils.themeManager.onFlush(() => {
|
|
187
|
+
const style = utils.getStyle(injectStyle);
|
|
188
|
+
if (style) {
|
|
189
|
+
style.split(" ").forEach((x) => dropDown.classList.add(x));
|
|
190
|
+
}
|
|
191
|
+
});
|
|
180
192
|
dropDown.classList.add("milkdown-emoji-filter", "hide");
|
|
181
193
|
const replace = () => {
|
|
182
194
|
var _a;
|
|
@@ -189,16 +201,16 @@ const filter = (utils) => {
|
|
|
189
201
|
dropDown.classList.add("hide");
|
|
190
202
|
};
|
|
191
203
|
parentNode.appendChild(dropDown);
|
|
192
|
-
|
|
204
|
+
const onKeydown = (e) => {
|
|
193
205
|
if (!trigger || !(e instanceof KeyboardEvent))
|
|
194
206
|
return;
|
|
195
|
-
const { key } = e;
|
|
196
|
-
if (
|
|
207
|
+
const { key: key2 } = e;
|
|
208
|
+
if (key2 === "Enter") {
|
|
197
209
|
replace();
|
|
198
210
|
return;
|
|
199
211
|
}
|
|
200
|
-
if (["ArrowDown", "ArrowUp"].includes(
|
|
201
|
-
const next =
|
|
212
|
+
if (["ArrowDown", "ArrowUp"].includes(key2)) {
|
|
213
|
+
const next = key2 === "ArrowDown" ? ($active == null ? void 0 : $active.nextElementSibling) || dropDown.firstElementChild : ($active == null ? void 0 : $active.previousElementSibling) || dropDown.lastElementChild;
|
|
202
214
|
if ($active) {
|
|
203
215
|
$active.classList.remove("active");
|
|
204
216
|
}
|
|
@@ -208,14 +220,16 @@ const filter = (utils) => {
|
|
|
208
220
|
$active = next;
|
|
209
221
|
return;
|
|
210
222
|
}
|
|
211
|
-
}
|
|
212
|
-
|
|
223
|
+
};
|
|
224
|
+
const onClick = (e) => {
|
|
213
225
|
if (!trigger)
|
|
214
226
|
return;
|
|
215
227
|
e.stopPropagation();
|
|
216
228
|
off();
|
|
217
229
|
dropDown.classList.add("hide");
|
|
218
|
-
}
|
|
230
|
+
};
|
|
231
|
+
parentNode.addEventListener("keydown", onKeydown);
|
|
232
|
+
parentNode.addEventListener("mousedown", onClick);
|
|
219
233
|
return {
|
|
220
234
|
update: (view) => {
|
|
221
235
|
const { selection } = view.state;
|
|
@@ -251,12 +265,18 @@ const filter = (utils) => {
|
|
|
251
265
|
return [top, left];
|
|
252
266
|
});
|
|
253
267
|
return null;
|
|
268
|
+
},
|
|
269
|
+
destroy: () => {
|
|
270
|
+
parentNode.removeEventListener("keydown", onKeydown);
|
|
271
|
+
parentNode.removeEventListener("mousedown", onClick);
|
|
272
|
+
dropDown.remove();
|
|
254
273
|
}
|
|
255
274
|
};
|
|
256
275
|
}
|
|
257
276
|
});
|
|
258
277
|
};
|
|
259
278
|
const keyword = ":emoji:";
|
|
279
|
+
const key = new PluginKey("MILKDOWN_PLUGIN_EMOJI_PICKER");
|
|
260
280
|
const checkTrigger = (view, from, to, text, setRange) => {
|
|
261
281
|
if (view.composing)
|
|
262
282
|
return false;
|
|
@@ -282,6 +302,7 @@ const picker = (utils) => {
|
|
|
282
302
|
_to = 0;
|
|
283
303
|
};
|
|
284
304
|
const plugin = new Plugin({
|
|
305
|
+
key,
|
|
285
306
|
props: {
|
|
286
307
|
handleKeyDown() {
|
|
287
308
|
off();
|
|
@@ -312,7 +333,9 @@ const picker = (utils) => {
|
|
|
312
333
|
if (!parentNode) {
|
|
313
334
|
throw new Error();
|
|
314
335
|
}
|
|
315
|
-
utils.getStyle((
|
|
336
|
+
utils.getStyle((themeManager, { injectGlobal }) => {
|
|
337
|
+
const palette = (color, opacity = 1) => themeManager.get(ThemeColor, [color, opacity]);
|
|
338
|
+
const typography = themeManager.get(ThemeFont, "typography");
|
|
316
339
|
const css = injectGlobal;
|
|
317
340
|
css`
|
|
318
341
|
.emoji-picker {
|
|
@@ -324,8 +347,8 @@ const picker = (utils) => {
|
|
|
324
347
|
--dark-blue-color: ${palette("primary")} !important;
|
|
325
348
|
--dark-search-icon-color: ${palette("primary")} !important;
|
|
326
349
|
--dark-category-button-color: ${palette("secondary", 0.4)} !important;
|
|
327
|
-
--font: ${
|
|
328
|
-
--font-size:
|
|
350
|
+
--font: ${typography} !important;
|
|
351
|
+
--font-size: 1em !important;
|
|
329
352
|
}
|
|
330
353
|
`;
|
|
331
354
|
});
|
|
@@ -371,10 +394,16 @@ function flatMap(ast, fn) {
|
|
|
371
394
|
if (isParent(node)) {
|
|
372
395
|
const out = [];
|
|
373
396
|
for (let i = 0, n = node.children.length; i < n; i++) {
|
|
374
|
-
const
|
|
375
|
-
if (
|
|
376
|
-
|
|
377
|
-
|
|
397
|
+
const nthChild = node.children[i];
|
|
398
|
+
if (nthChild) {
|
|
399
|
+
const xs = transform(nthChild, i, node);
|
|
400
|
+
if (xs) {
|
|
401
|
+
for (let j = 0, m = xs.length; j < m; j++) {
|
|
402
|
+
const item = xs[j];
|
|
403
|
+
if (item) {
|
|
404
|
+
out.push(item);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
378
407
|
}
|
|
379
408
|
}
|
|
380
409
|
}
|
|
@@ -396,11 +425,13 @@ const twemojiPlugin = () => {
|
|
|
396
425
|
while (match = regex.exec(str)) {
|
|
397
426
|
const { index } = match;
|
|
398
427
|
const emoji2 = match[0];
|
|
399
|
-
if (
|
|
400
|
-
|
|
428
|
+
if (emoji2) {
|
|
429
|
+
if (index > 0) {
|
|
430
|
+
output.push(__spreadProps(__spreadValues({}, node), { value: str.slice(0, index) }));
|
|
431
|
+
}
|
|
432
|
+
output.push(__spreadProps(__spreadValues({}, node), { value: parse(emoji2), type: "emoji" }));
|
|
433
|
+
str = str.slice(index + emoji2.length);
|
|
401
434
|
}
|
|
402
|
-
output.push(__spreadProps(__spreadValues({}, node), { value: parse(emoji2), type: "emoji" }));
|
|
403
|
-
str = str.slice(index + emoji2.length);
|
|
404
435
|
}
|
|
405
436
|
if (str.length) {
|
|
406
437
|
output.push(__spreadProps(__spreadValues({}, node), { value: str }));
|
|
@@ -411,18 +442,18 @@ const twemojiPlugin = () => {
|
|
|
411
442
|
return transformer;
|
|
412
443
|
};
|
|
413
444
|
const emojiNode = createNode((utils) => {
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
445
|
+
const getStyle = () => utils.getStyle((_, { css }) => css`
|
|
446
|
+
display: inline-flex;
|
|
447
|
+
justify-content: center;
|
|
448
|
+
align-items: center;
|
|
418
449
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
450
|
+
.emoji {
|
|
451
|
+
height: 1em;
|
|
452
|
+
width: 1em;
|
|
453
|
+
margin: 0 0.05em 0 0.1em;
|
|
454
|
+
vertical-align: -0.1em;
|
|
455
|
+
}
|
|
456
|
+
`);
|
|
426
457
|
return {
|
|
427
458
|
id: "emoji",
|
|
428
459
|
schema: () => ({
|
|
@@ -447,25 +478,28 @@ const emojiNode = createNode((utils) => {
|
|
|
447
478
|
],
|
|
448
479
|
toDOM: (node) => {
|
|
449
480
|
const span = document.createElement("span");
|
|
450
|
-
span.dataset
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
481
|
+
span.dataset["type"] = "emoji";
|
|
482
|
+
utils.themeManager.onFlush(() => {
|
|
483
|
+
const style = getStyle();
|
|
484
|
+
if (style) {
|
|
485
|
+
span.classList.add(style);
|
|
486
|
+
}
|
|
487
|
+
});
|
|
454
488
|
span.classList.add("emoji-wrapper");
|
|
455
|
-
span.innerHTML = node.attrs
|
|
489
|
+
span.innerHTML = node.attrs["html"];
|
|
456
490
|
return { dom: span };
|
|
457
491
|
},
|
|
458
492
|
parseMarkdown: {
|
|
459
493
|
match: ({ type }) => type === "emoji",
|
|
460
494
|
runner: (state, node, type) => {
|
|
461
|
-
state.addNode(type, { html: node
|
|
495
|
+
state.addNode(type, { html: node["value"] });
|
|
462
496
|
}
|
|
463
497
|
},
|
|
464
498
|
toMarkdown: {
|
|
465
499
|
match: (node) => node.type.name === "emoji",
|
|
466
500
|
runner: (state, node) => {
|
|
467
501
|
const span = document.createElement("span");
|
|
468
|
-
span.innerHTML = node.attrs
|
|
502
|
+
span.innerHTML = node.attrs["html"];
|
|
469
503
|
const img = span.querySelector("img");
|
|
470
504
|
const title = img == null ? void 0 : img.title;
|
|
471
505
|
span.remove();
|
package/lib/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../src/constant.ts","../src/parse.ts","../src/filter/helper.ts","../src/filter/style.ts","../src/filter/index.ts","../src/picker.ts","../src/remark-twemoji.ts","../src/node.ts","../src/index.ts"],"sourcesContent":["/* Copyright 2021, Milkdown by Mirone. */\nexport const part = /:\\+1|:-1|:[\\w-]+/;\nexport const full = /:\\+1:|:-1:|:[\\w-]+:/;\nexport const input = /(:([^:\\s]+):)$/;\nexport const keyword = ':emoji:';\n","/* Copyright 2021, Milkdown by Mirone. */\nimport twemoji from 'twemoji';\n\nexport const parse = (emoji: string) => twemoji.parse(emoji, { attributes: (text) => ({ title: text }) });\n","/* Copyright 2021, Milkdown by Mirone. */\n\nimport { EditorView } from '@milkdown/prose';\nimport { Emoji } from 'node-emoji';\n\nimport { full, part } from '../constant';\nimport { parse } from '../parse';\n\nexport const checkTrigger = (\n view: EditorView,\n from: number,\n to: number,\n text: string,\n setRange: (from: number, to: number) => void,\n setSearch: (words: string) => void,\n) => {\n if (view.composing) return false;\n const { state } = view;\n const $from = state.doc.resolve(from);\n if ($from.parent.type.spec.code) return false;\n const textBefore = (\n $from.parent.textBetween(Math.max(0, $from.parentOffset - 10), $from.parentOffset, undefined, '\\ufffc') + text\n ).toLowerCase();\n if (full.test(textBefore)) {\n return false;\n }\n const regex = part.exec(textBefore);\n if (regex && textBefore.endsWith(regex[0])) {\n const match = regex[0];\n setRange(from - (match.length - text.length), to);\n setSearch(match);\n return true;\n }\n return false;\n};\n\nexport const renderDropdownList = (\n list: Emoji[],\n dropDown: HTMLElement,\n $active: HTMLElement | null,\n onConfirm: () => void,\n setActive: (active: HTMLElement | null) => void,\n) => {\n dropDown.innerHTML = '';\n list.forEach(({ emoji, key }, i) => {\n const container = document.createElement('div');\n container.className = 'milkdown-emoji-filter_item';\n\n const emojiSpan = document.createElement('span');\n emojiSpan.innerHTML = parse(emoji);\n\n emojiSpan.className = 'milkdown-emoji-filter_item-emoji';\n const keySpan = document.createElement('span');\n keySpan.textContent = ':' + key + ':';\n keySpan.className = 'milkdown-emoji-filter_item-key';\n\n container.appendChild(emojiSpan);\n container.appendChild(keySpan);\n dropDown.appendChild(container);\n\n if (i === 0) {\n container.classList.add('active');\n setActive(container);\n }\n\n container.addEventListener('mouseenter', (e) => {\n if ($active) {\n $active.classList.remove('active');\n }\n const { target } = e;\n if (!(target instanceof HTMLElement)) return;\n target.classList.add('active');\n setActive(target);\n });\n container.addEventListener('mouseleave', (e) => {\n const { target } = e;\n if (!(target instanceof HTMLElement)) return;\n target.classList.remove('active');\n });\n container.addEventListener('mousedown', (e) => {\n onConfirm();\n e.preventDefault();\n });\n });\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport type { Emotion, ThemeTool } from '@milkdown/core';\n\nexport const injectStyle = ({ size, mixin, palette, font }: ThemeTool, { css, cx }: Emotion) => {\n const border = mixin.border?.();\n const shadow = mixin.shadow?.();\n\n const style = css`\n position: absolute;\n &.hide {\n display: none;\n }\n\n border-radius: ${size.radius};\n background: ${palette('surface')};\n\n .milkdown-emoji-filter_item {\n display: flex;\n gap: 0.5rem;\n height: 2.25rem;\n padding: 0 1rem;\n align-items: center;\n justify-content: flex-start;\n cursor: pointer;\n line-height: 2;\n font-family: ${font.typography};\n font-size: 0.875rem;\n &.active {\n background: ${palette('secondary', 0.12)};\n color: ${palette('primary')};\n }\n }\n\n .emoji {\n height: 1em;\n width: 1em;\n margin: 0 0.05em 0 0.1em;\n vertical-align: -0.1em;\n }\n `;\n return cx(border, shadow, style);\n};\n","/* Copyright 2021, Milkdown by Mirone. */\n\nimport { calculateNodePosition, Plugin } from '@milkdown/prose';\nimport { Utils } from '@milkdown/utils';\nimport { search } from 'node-emoji';\n\nimport { checkTrigger, renderDropdownList } from './helper';\nimport { injectStyle } from './style';\n\nexport const filter = (utils: Utils) => {\n let trigger = false;\n let _from = 0;\n let _search = '';\n let $active: null | HTMLElement = null;\n\n const off = () => {\n trigger = false;\n _from = 0;\n _search = '';\n $active = null;\n };\n\n return new Plugin({\n props: {\n handleKeyDown(_, event) {\n if (['Delete', 'Backspace'].includes(event.key)) {\n _search = _search.slice(0, -1);\n if (_search.length <= 1) {\n off();\n }\n return false;\n }\n if (!trigger) return false;\n if (!['ArrowUp', 'ArrowDown', 'Enter'].includes(event.key)) {\n return false;\n }\n return true;\n },\n handleTextInput(view, from, to, text) {\n trigger = checkTrigger(\n view,\n from,\n to,\n text,\n (from) => {\n _from = from;\n },\n (search) => {\n _search = search;\n },\n );\n if (!trigger) {\n off();\n }\n return false;\n },\n },\n view: (editorView) => {\n const { parentNode } = editorView.dom;\n if (!parentNode) {\n throw new Error();\n }\n\n const dropDown = document.createElement('div');\n const style = utils.getStyle(injectStyle);\n\n if (style) {\n style.split(' ').forEach((x) => dropDown.classList.add(x));\n }\n\n dropDown.classList.add('milkdown-emoji-filter', 'hide');\n\n const replace = () => {\n if (!$active) return;\n\n const { tr } = editorView.state;\n const node = editorView.state.schema.node('emoji', { html: $active.firstElementChild?.innerHTML });\n\n editorView.dispatch(tr.delete(_from, _from + _search.length).insert(_from, node));\n off();\n dropDown.classList.add('hide');\n };\n\n parentNode.appendChild(dropDown);\n parentNode.addEventListener('keydown', (e) => {\n if (!trigger || !(e instanceof KeyboardEvent)) return;\n\n const { key } = e;\n\n if (key === 'Enter') {\n replace();\n return;\n }\n\n if (['ArrowDown', 'ArrowUp'].includes(key)) {\n const next =\n key === 'ArrowDown'\n ? $active?.nextElementSibling || dropDown.firstElementChild\n : $active?.previousElementSibling || dropDown.lastElementChild;\n if ($active) {\n $active.classList.remove('active');\n }\n if (!next) return;\n next.classList.add('active');\n $active = next as HTMLElement;\n\n return;\n }\n });\n parentNode.addEventListener('mousedown', (e) => {\n if (!trigger) return;\n\n e.stopPropagation();\n off();\n dropDown.classList.add('hide');\n });\n\n return {\n update: (view) => {\n const { selection } = view.state;\n\n if (selection.from - selection.to !== 0 || !trigger) {\n off();\n dropDown.classList.add('hide');\n return null;\n }\n const result = search(_search).slice(0, 5);\n const { node } = view.domAtPos(_from);\n if (result.length === 0 || !node) {\n dropDown.classList.add('hide');\n return null;\n }\n\n dropDown.classList.remove('hide');\n renderDropdownList(result, dropDown, $active, replace, (a) => {\n $active = a;\n });\n calculateNodePosition(view, dropDown, (selected, target, parent) => {\n const $editor = dropDown.parentElement;\n if (!$editor) {\n throw new Error();\n }\n const start = view.coordsAtPos(_from);\n let left = start.left - parent.left;\n let top = selected.bottom - parent.top + 14 + $editor.scrollTop;\n\n if (left < 0) {\n left = 0;\n }\n\n if (window.innerHeight - start.bottom < target.height) {\n top = selected.top - parent.top - target.height - 14 + $editor.scrollTop;\n }\n return [top, left];\n });\n\n return null;\n },\n };\n },\n });\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { EmojiButton } from '@joeattardi/emoji-button';\nimport { Decoration, DecorationSet, EditorView, Plugin } from '@milkdown/prose';\nimport { Utils } from '@milkdown/utils';\n\nimport { parse } from './parse';\n\nconst keyword = ':emoji:';\n\nconst checkTrigger = (\n view: EditorView,\n from: number,\n to: number,\n text: string,\n setRange: (from: number, to: number) => void,\n) => {\n if (view.composing) return false;\n const { state } = view;\n const $from = state.doc.resolve(from);\n if ($from.parent.type.spec.code) return false;\n const textBefore =\n $from.parent.textBetween($from.parentOffset - keyword.length + 1, $from.parentOffset, undefined, '\\ufffc') +\n text;\n if (textBefore === keyword) {\n setRange(from - keyword.length + 1, to + 1);\n return true;\n }\n return false;\n};\n\nexport const picker = (utils: Utils) => {\n let trigger = false;\n const holder = document.createElement('span');\n let _from = 0;\n let _to = 0;\n const off = () => {\n trigger = false;\n _from = 0;\n _to = 0;\n };\n\n const plugin = new Plugin({\n props: {\n handleKeyDown() {\n off();\n return false;\n },\n handleClick() {\n off();\n return false;\n },\n handleTextInput(view, from, to, text) {\n trigger = checkTrigger(view, from, to, text, (from, to) => {\n _from = from;\n _to = to;\n });\n\n if (!trigger) {\n off();\n }\n return false;\n },\n decorations(state) {\n if (!trigger) return null;\n\n return DecorationSet.create(state.doc, [Decoration.widget(state.selection.to, holder)]);\n },\n },\n view: (editorView) => {\n const { parentNode } = editorView.dom;\n if (!parentNode) {\n throw new Error();\n }\n utils.getStyle(({ palette, font }, { injectGlobal }) => {\n const css = injectGlobal;\n css`\n .emoji-picker {\n --dark-search-background-color: ${palette('surface')} !important;\n --dark-text-color: ${palette('neutral', 0.87)} !important;\n --dark-background-color: ${palette('background')} !important;\n --dark-border-color: ${palette('shadow')} !important;\n --dark-hover-color: ${palette('secondary', 0.12)} !important;\n --dark-blue-color: ${palette('primary')} !important;\n --dark-search-icon-color: ${palette('primary')} !important;\n --dark-category-button-color: ${palette('secondary', 0.4)} !important;\n --font: ${font.typography} !important;\n --font-size: 1rem !important;\n }\n `;\n });\n const emojiPicker = new EmojiButton({\n rootElement: parentNode as HTMLElement,\n autoFocusSearch: false,\n style: 'twemoji',\n theme: 'dark',\n zIndex: 99,\n });\n emojiPicker.on('emoji', (selection) => {\n const start = _from;\n const end = _to;\n off();\n const html = parse(selection.emoji);\n const node = editorView.state.schema.node('emoji', { html });\n const { tr } = editorView.state;\n\n editorView.dispatch(tr.replaceRangeWith(start, end, node));\n });\n return {\n update: () => {\n if (!trigger) {\n emojiPicker.hidePicker();\n return null;\n }\n emojiPicker.showPicker(holder);\n return null;\n },\n destroy: () => {\n emojiPicker.destroyPicker();\n },\n };\n },\n });\n\n return plugin;\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport emojiRegex from 'emoji-regex';\nimport { Literal, Node, Parent } from 'unist';\n\nimport { parse } from './parse';\n\nconst regex = emojiRegex();\n\nconst isParent = (node: Node): node is Parent => !!(node as Parent).children;\nconst isLiteral = (node: Node): node is Literal => !!(node as Literal).value;\n\nfunction flatMap(ast: Node, fn: (node: Node, index: number, parent: Node | null) => Node[]) {\n return transform(ast, 0, null)[0];\n\n function transform(node: Node, index: number, parent: Node | null) {\n if (isParent(node)) {\n const out = [];\n for (let i = 0, n = node.children.length; i < n; i++) {\n const xs = transform(node.children[i], i, node);\n if (xs) {\n for (let j = 0, m = xs.length; j < m; j++) {\n out.push(xs[j]);\n }\n }\n }\n node.children = out;\n }\n\n return fn(node, index, parent);\n }\n}\n\nexport const twemojiPlugin = () => {\n function transformer(tree: Node) {\n flatMap(tree, (node) => {\n if (!isLiteral(node)) {\n return [node];\n }\n const value = node.value as string;\n const output: Literal<string>[] = [];\n let match;\n let str = value;\n while ((match = regex.exec(str))) {\n const { index } = match;\n const emoji = match[0];\n if (index > 0) {\n output.push({ ...node, value: str.slice(0, index) });\n }\n output.push({ ...node, value: parse(emoji), type: 'emoji' });\n str = str.slice(index + emoji.length);\n }\n if (str.length) {\n output.push({ ...node, value: str });\n }\n return output;\n });\n }\n return transformer;\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { RemarkPlugin } from '@milkdown/core';\nimport { InputRule } from '@milkdown/prose';\nimport { createNode } from '@milkdown/utils';\nimport nodeEmoji from 'node-emoji';\nimport remarkEmoji from 'remark-emoji';\n\nimport { input } from './constant';\nimport { filter } from './filter';\nimport { parse } from './parse';\nimport { picker } from './picker';\nimport { twemojiPlugin } from './remark-twemoji';\n\nexport const emojiNode = createNode((utils) => {\n const style = utils.getStyle(\n (_, { css }) => css`\n display: inline-flex;\n justify-content: center;\n align-items: center;\n\n .emoji {\n height: 1em;\n width: 1em;\n margin: 0 0.05em 0 0.1em;\n vertical-align: -0.1em;\n }\n `,\n );\n return {\n id: 'emoji',\n schema: () => ({\n group: 'inline',\n inline: true,\n selectable: false,\n attrs: {\n html: {\n default: '',\n },\n },\n parseDOM: [\n {\n tag: 'span[data-type=\"emoji\"]',\n getAttrs: (dom) => {\n if (!(dom instanceof HTMLElement)) {\n throw new Error();\n }\n return { html: dom.innerHTML };\n },\n },\n ],\n toDOM: (node) => {\n const span = document.createElement('span');\n span.dataset.type = 'emoji';\n if (style) {\n span.classList.add(style);\n }\n span.classList.add('emoji-wrapper');\n span.innerHTML = node.attrs.html;\n return { dom: span };\n },\n parseMarkdown: {\n match: ({ type }) => type === 'emoji',\n runner: (state, node, type) => {\n state.addNode(type, { html: node.value as string });\n },\n },\n toMarkdown: {\n match: (node) => node.type.name === 'emoji',\n runner: (state, node) => {\n const span = document.createElement('span');\n span.innerHTML = node.attrs.html;\n const img = span.querySelector('img');\n const title = img?.title;\n span.remove();\n state.addNode('text', undefined, title);\n },\n },\n }),\n inputRules: (nodeType) => [\n new InputRule(input, (state, match, start, end) => {\n const content = match[0];\n if (!content) return null;\n const got = nodeEmoji.get(content);\n if (!got || content.includes(got)) return null;\n\n const html = parse(got);\n\n return state.tr\n .setMeta('emoji', true)\n .replaceRangeWith(start, end, nodeType.create({ html }))\n .scrollIntoView();\n }),\n ],\n remarkPlugins: () => [remarkEmoji as RemarkPlugin, twemojiPlugin],\n prosePlugins: () => [picker(utils), filter(utils)],\n };\n});\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { AtomList } from '@milkdown/utils';\n\nimport { emojiNode } from './node';\n\nexport const emoji = AtomList.create([emojiNode()]);\n\nexport { emojiNode } from './node';\n"],"names":["checkTrigger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../src/constant.ts","../src/parse.ts","../src/filter/helper.ts","../src/filter/style.ts","../src/filter/index.ts","../src/picker.ts","../src/remark-twemoji.ts","../src/node.ts","../src/index.ts"],"sourcesContent":["/* Copyright 2021, Milkdown by Mirone. */\nexport const part = /:\\+1|:-1|:[\\w-]+/;\nexport const full = /:\\+1:|:-1:|:[\\w-]+:/;\nexport const input = /(:([^:\\s]+):)$/;\nexport const keyword = ':emoji:';\n","/* Copyright 2021, Milkdown by Mirone. */\nimport twemoji from 'twemoji';\n\nexport const parse = (emoji: string) => twemoji.parse(emoji, { attributes: (text) => ({ title: text }) });\n","/* Copyright 2021, Milkdown by Mirone. */\n\nimport { EditorView } from '@milkdown/prose';\nimport { Emoji } from 'node-emoji';\n\nimport { full, part } from '../constant';\nimport { parse } from '../parse';\n\nexport const checkTrigger = (\n view: EditorView,\n from: number,\n to: number,\n text: string,\n setRange: (from: number, to: number) => void,\n setSearch: (words: string) => void,\n) => {\n if (view.composing) return false;\n const { state } = view;\n const $from = state.doc.resolve(from);\n if ($from.parent.type.spec.code) return false;\n const textBefore = (\n $from.parent.textBetween(Math.max(0, $from.parentOffset - 10), $from.parentOffset, undefined, '\\ufffc') + text\n ).toLowerCase();\n if (full.test(textBefore)) {\n return false;\n }\n const regex = part.exec(textBefore);\n if (regex && regex[0] && textBefore.endsWith(regex[0])) {\n const match = regex[0];\n setRange(from - (match.length - text.length), to);\n setSearch(match);\n return true;\n }\n return false;\n};\n\nexport const renderDropdownList = (\n list: Emoji[],\n dropDown: HTMLElement,\n $active: HTMLElement | null,\n onConfirm: () => void,\n setActive: (active: HTMLElement | null) => void,\n) => {\n while (dropDown.firstChild) {\n dropDown.firstChild.remove();\n }\n list.forEach(({ emoji, key }, i) => {\n const container = document.createElement('div');\n container.className = 'milkdown-emoji-filter_item';\n\n const emojiSpan = document.createElement('span');\n emojiSpan.innerHTML = parse(emoji);\n\n emojiSpan.className = 'milkdown-emoji-filter_item-emoji';\n const keySpan = document.createElement('span');\n keySpan.textContent = ':' + key + ':';\n keySpan.className = 'milkdown-emoji-filter_item-key';\n\n container.appendChild(emojiSpan);\n container.appendChild(keySpan);\n dropDown.appendChild(container);\n\n if (i === 0) {\n container.classList.add('active');\n setActive(container);\n }\n\n const onEnter = (e: MouseEvent) => {\n if ($active) {\n $active.classList.remove('active');\n }\n const { target } = e;\n if (!(target instanceof HTMLElement)) return;\n target.classList.add('active');\n setActive(target);\n };\n\n const onLeave = (e: MouseEvent) => {\n const { target } = e;\n if (!(target instanceof HTMLElement)) return;\n target.classList.remove('active');\n };\n\n const onClick = (e: MouseEvent) => {\n e.preventDefault();\n onConfirm();\n };\n\n container.addEventListener('mouseenter', onEnter);\n container.addEventListener('mouseleave', onLeave);\n container.addEventListener('mousedown', onClick);\n });\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport {\n Color,\n Emotion,\n ThemeBorder,\n ThemeColor,\n ThemeFont,\n ThemeManager,\n ThemeShadow,\n ThemeSize,\n} from '@milkdown/core';\n\nexport const injectStyle = (themeManager: ThemeManager, { css, cx }: Emotion) => {\n const border = themeManager.get(ThemeBorder, undefined);\n const shadow = themeManager.get(ThemeShadow, undefined);\n const radius = themeManager.get(ThemeSize, 'radius');\n const typography = themeManager.get(ThemeFont, 'typography');\n const palette = (color: Color, opacity = 1) => themeManager.get(ThemeColor, [color, opacity]);\n\n const style = css`\n position: absolute;\n &.hide {\n display: none;\n }\n\n border-radius: ${radius};\n background: ${palette('surface')};\n\n .milkdown-emoji-filter_item {\n display: flex;\n gap: 0.5em;\n height: 2.57143em;\n padding: 0 1em;\n align-items: center;\n justify-content: flex-start;\n cursor: pointer;\n line-height: 2;\n font-family: ${typography};\n font-size: 0.875em;\n &.active {\n background: ${palette('secondary', 0.12)};\n color: ${palette('primary')};\n }\n }\n\n .emoji {\n height: 1em;\n width: 1em;\n margin: 0 0.05em 0 0.1em;\n vertical-align: -0.1em;\n }\n `;\n return cx(border, shadow, style);\n};\n","/* Copyright 2021, Milkdown by Mirone. */\n\nimport { calculateNodePosition, Plugin, PluginKey } from '@milkdown/prose';\nimport { Utils } from '@milkdown/utils';\nimport { search } from 'node-emoji';\n\nimport { checkTrigger, renderDropdownList } from './helper';\nimport { injectStyle } from './style';\n\nexport const key = new PluginKey('MILKDOWN_PLUGIN_EMOJI_FILTER');\n\nexport const filter = (utils: Utils) => {\n let trigger = false;\n let _from = 0;\n let _search = '';\n let $active: null | HTMLElement = null;\n\n const off = () => {\n trigger = false;\n _from = 0;\n _search = '';\n $active = null;\n };\n\n return new Plugin({\n key,\n props: {\n handleKeyDown(_, event) {\n if (['Delete', 'Backspace'].includes(event.key)) {\n _search = _search.slice(0, -1);\n if (_search.length <= 1) {\n off();\n }\n return false;\n }\n if (!trigger) return false;\n if (!['ArrowUp', 'ArrowDown', 'Enter'].includes(event.key)) {\n return false;\n }\n return true;\n },\n handleTextInput(view, from, to, text) {\n trigger = checkTrigger(\n view,\n from,\n to,\n text,\n (from) => {\n _from = from;\n },\n (search) => {\n _search = search;\n },\n );\n if (!trigger) {\n off();\n }\n return false;\n },\n },\n view: (editorView) => {\n const { parentNode } = editorView.dom;\n if (!parentNode) {\n throw new Error();\n }\n\n const dropDown = document.createElement('div');\n\n utils.themeManager.onFlush(() => {\n const style = utils.getStyle(injectStyle);\n if (style) {\n style.split(' ').forEach((x) => dropDown.classList.add(x));\n }\n });\n\n dropDown.classList.add('milkdown-emoji-filter', 'hide');\n\n const replace = () => {\n if (!$active) return;\n\n const { tr } = editorView.state;\n const node = editorView.state.schema.node('emoji', { html: $active.firstElementChild?.innerHTML });\n\n editorView.dispatch(tr.delete(_from, _from + _search.length).insert(_from, node));\n off();\n dropDown.classList.add('hide');\n };\n\n parentNode.appendChild(dropDown);\n const onKeydown = (e: Event) => {\n if (!trigger || !(e instanceof KeyboardEvent)) return;\n\n const { key } = e;\n\n if (key === 'Enter') {\n replace();\n return;\n }\n\n if (['ArrowDown', 'ArrowUp'].includes(key)) {\n const next =\n key === 'ArrowDown'\n ? $active?.nextElementSibling || dropDown.firstElementChild\n : $active?.previousElementSibling || dropDown.lastElementChild;\n if ($active) {\n $active.classList.remove('active');\n }\n if (!next) return;\n next.classList.add('active');\n $active = next as HTMLElement;\n\n return;\n }\n };\n const onClick = (e: Event) => {\n if (!trigger) return;\n\n e.stopPropagation();\n off();\n dropDown.classList.add('hide');\n };\n parentNode.addEventListener('keydown', onKeydown);\n parentNode.addEventListener('mousedown', onClick);\n\n return {\n update: (view) => {\n const { selection } = view.state;\n\n if (selection.from - selection.to !== 0 || !trigger) {\n off();\n dropDown.classList.add('hide');\n return null;\n }\n const result = search(_search).slice(0, 5);\n const { node } = view.domAtPos(_from);\n if (result.length === 0 || !node) {\n dropDown.classList.add('hide');\n return null;\n }\n\n dropDown.classList.remove('hide');\n renderDropdownList(result, dropDown, $active, replace, (a) => {\n $active = a;\n });\n calculateNodePosition(view, dropDown, (selected, target, parent) => {\n const $editor = dropDown.parentElement;\n if (!$editor) {\n throw new Error();\n }\n const start = view.coordsAtPos(_from);\n let left = start.left - parent.left;\n let top = selected.bottom - parent.top + 14 + $editor.scrollTop;\n\n if (left < 0) {\n left = 0;\n }\n\n if (window.innerHeight - start.bottom < target.height) {\n top = selected.top - parent.top - target.height - 14 + $editor.scrollTop;\n }\n return [top, left];\n });\n\n return null;\n },\n\n destroy: () => {\n parentNode.removeEventListener('keydown', onKeydown);\n parentNode.removeEventListener('mousedown', onClick);\n dropDown.remove();\n },\n };\n },\n });\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { EmojiButton } from '@joeattardi/emoji-button';\nimport { Color, ThemeColor, ThemeFont } from '@milkdown/core';\nimport { Decoration, DecorationSet, EditorView, Plugin, PluginKey } from '@milkdown/prose';\nimport { Utils } from '@milkdown/utils';\n\nimport { parse } from './parse';\n\nconst keyword = ':emoji:';\nexport const key = new PluginKey('MILKDOWN_PLUGIN_EMOJI_PICKER');\n\nconst checkTrigger = (\n view: EditorView,\n from: number,\n to: number,\n text: string,\n setRange: (from: number, to: number) => void,\n) => {\n if (view.composing) return false;\n const { state } = view;\n const $from = state.doc.resolve(from);\n if ($from.parent.type.spec.code) return false;\n const textBefore =\n $from.parent.textBetween($from.parentOffset - keyword.length + 1, $from.parentOffset, undefined, '\\ufffc') +\n text;\n if (textBefore === keyword) {\n setRange(from - keyword.length + 1, to + 1);\n return true;\n }\n return false;\n};\n\nexport const picker = (utils: Utils) => {\n let trigger = false;\n const holder = document.createElement('span');\n let _from = 0;\n let _to = 0;\n const off = () => {\n trigger = false;\n _from = 0;\n _to = 0;\n };\n\n const plugin = new Plugin({\n key,\n props: {\n handleKeyDown() {\n off();\n return false;\n },\n handleClick() {\n off();\n return false;\n },\n handleTextInput(view, from, to, text) {\n trigger = checkTrigger(view, from, to, text, (from, to) => {\n _from = from;\n _to = to;\n });\n\n if (!trigger) {\n off();\n }\n return false;\n },\n decorations(state) {\n if (!trigger) return null;\n\n return DecorationSet.create(state.doc, [Decoration.widget(state.selection.to, holder)]);\n },\n },\n view: (editorView) => {\n const { parentNode } = editorView.dom;\n if (!parentNode) {\n throw new Error();\n }\n utils.getStyle((themeManager, { injectGlobal }) => {\n const palette = (color: Color, opacity = 1) => themeManager.get(ThemeColor, [color, opacity]);\n const typography = themeManager.get(ThemeFont, 'typography');\n const css = injectGlobal;\n css`\n .emoji-picker {\n --dark-search-background-color: ${palette('surface')} !important;\n --dark-text-color: ${palette('neutral', 0.87)} !important;\n --dark-background-color: ${palette('background')} !important;\n --dark-border-color: ${palette('shadow')} !important;\n --dark-hover-color: ${palette('secondary', 0.12)} !important;\n --dark-blue-color: ${palette('primary')} !important;\n --dark-search-icon-color: ${palette('primary')} !important;\n --dark-category-button-color: ${palette('secondary', 0.4)} !important;\n --font: ${typography} !important;\n --font-size: 1em !important;\n }\n `;\n });\n const emojiPicker = new EmojiButton({\n rootElement: parentNode as HTMLElement,\n autoFocusSearch: false,\n style: 'twemoji',\n theme: 'dark',\n zIndex: 99,\n });\n emojiPicker.on('emoji', (selection) => {\n const start = _from;\n const end = _to;\n off();\n const html = parse(selection.emoji);\n const node = editorView.state.schema.node('emoji', { html });\n const { tr } = editorView.state;\n\n editorView.dispatch(tr.replaceRangeWith(start, end, node));\n });\n return {\n update: () => {\n if (!trigger) {\n emojiPicker.hidePicker();\n return null;\n }\n emojiPicker.showPicker(holder);\n return null;\n },\n destroy: () => {\n emojiPicker.destroyPicker();\n },\n };\n },\n });\n\n return plugin;\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport emojiRegex from 'emoji-regex';\nimport { Literal, Node, Parent } from 'unist';\n\nimport { parse } from './parse';\n\nconst regex = emojiRegex();\n\nconst isParent = (node: Node): node is Parent => !!(node as Parent).children;\nconst isLiteral = (node: Node): node is Literal => !!(node as Literal).value;\n\nfunction flatMap(ast: Node, fn: (node: Node, index: number, parent: Node | null) => Node[]) {\n return transform(ast, 0, null)[0];\n\n function transform(node: Node, index: number, parent: Node | null) {\n if (isParent(node)) {\n const out = [];\n for (let i = 0, n = node.children.length; i < n; i++) {\n const nthChild = node.children[i];\n if (nthChild) {\n const xs = transform(nthChild, i, node);\n if (xs) {\n for (let j = 0, m = xs.length; j < m; j++) {\n const item = xs[j];\n if (item) {\n out.push(item);\n }\n }\n }\n }\n }\n node.children = out;\n }\n\n return fn(node, index, parent);\n }\n}\n\nexport const twemojiPlugin = () => {\n function transformer(tree: Node) {\n flatMap(tree, (node) => {\n if (!isLiteral(node)) {\n return [node];\n }\n const value = node.value as string;\n const output: Literal<string>[] = [];\n let match;\n let str = value;\n while ((match = regex.exec(str))) {\n const { index } = match;\n const emoji = match[0];\n if (emoji) {\n if (index > 0) {\n output.push({ ...node, value: str.slice(0, index) });\n }\n output.push({ ...node, value: parse(emoji), type: 'emoji' });\n str = str.slice(index + emoji.length);\n }\n }\n if (str.length) {\n output.push({ ...node, value: str });\n }\n return output;\n });\n }\n return transformer;\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { RemarkPlugin } from '@milkdown/core';\nimport { InputRule } from '@milkdown/prose';\nimport { createNode } from '@milkdown/utils';\nimport nodeEmoji from 'node-emoji';\nimport remarkEmoji from 'remark-emoji';\n\nimport { input } from './constant';\nimport { filter } from './filter';\nimport { parse } from './parse';\nimport { picker } from './picker';\nimport { twemojiPlugin } from './remark-twemoji';\n\nexport const emojiNode = createNode((utils) => {\n const getStyle = () =>\n utils.getStyle(\n (_, { css }) => css`\n display: inline-flex;\n justify-content: center;\n align-items: center;\n\n .emoji {\n height: 1em;\n width: 1em;\n margin: 0 0.05em 0 0.1em;\n vertical-align: -0.1em;\n }\n `,\n );\n return {\n id: 'emoji',\n schema: () => ({\n group: 'inline',\n inline: true,\n selectable: false,\n attrs: {\n html: {\n default: '',\n },\n },\n parseDOM: [\n {\n tag: 'span[data-type=\"emoji\"]',\n getAttrs: (dom) => {\n if (!(dom instanceof HTMLElement)) {\n throw new Error();\n }\n return { html: dom.innerHTML };\n },\n },\n ],\n toDOM: (node) => {\n const span = document.createElement('span');\n span.dataset['type'] = 'emoji';\n utils.themeManager.onFlush(() => {\n const style = getStyle();\n if (style) {\n span.classList.add(style);\n }\n });\n span.classList.add('emoji-wrapper');\n span.innerHTML = node.attrs['html'];\n return { dom: span };\n },\n parseMarkdown: {\n match: ({ type }) => type === 'emoji',\n runner: (state, node, type) => {\n state.addNode(type, { html: node['value'] as string });\n },\n },\n toMarkdown: {\n match: (node) => node.type.name === 'emoji',\n runner: (state, node) => {\n const span = document.createElement('span');\n span.innerHTML = node.attrs['html'];\n const img = span.querySelector('img');\n const title = img?.title;\n span.remove();\n state.addNode('text', undefined, title);\n },\n },\n }),\n inputRules: (nodeType) => [\n new InputRule(input, (state, match, start, end) => {\n const content = match[0];\n if (!content) return null;\n const got = nodeEmoji.get(content);\n if (!got || content.includes(got)) return null;\n\n const html = parse(got);\n\n return state.tr\n .setMeta('emoji', true)\n .replaceRangeWith(start, end, nodeType.create({ html }))\n .scrollIntoView();\n }),\n ],\n remarkPlugins: () => [remarkEmoji as RemarkPlugin, twemojiPlugin],\n prosePlugins: () => [picker(utils), filter(utils)],\n };\n});\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { AtomList } from '@milkdown/utils';\n\nimport { emojiNode } from './node';\n\nexport const emoji = AtomList.create([emojiNode()]);\n\nexport { emojiNode } from './node';\n"],"names":["checkTrigger","key"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const emojiNode: import("@milkdown/utils/lib/
|
|
1
|
+
export declare const emojiNode: import("@milkdown/utils/lib/types").WithExtend<string, import("@milkdown/utils").UnknownRecord, import("prosemirror-model").NodeType<any>, {
|
|
2
2
|
id: string;
|
|
3
3
|
schema: (ctx: import("@milkdown/core").Ctx) => import("@milkdown/core").NodeSchema;
|
|
4
4
|
view?: ((ctx: import("@milkdown/core").Ctx) => import("@milkdown/prose").NodeViewFactory) | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,SAAS;;;;EAuFpB,CAAC"}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,KAAK,UAAW,MAAM,WAAsE,CAAC"}
|
package/lib/picker.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picker.d.ts","sourceRoot":"","sources":["../src/picker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAyC,MAAM,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC3F,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAKxC,eAAO,MAAM,GAAG,qBAAgD,CAAC;AAuBjE,eAAO,MAAM,MAAM,UAAW,KAAK,qBAiGlC,CAAC"}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remark-twemoji.d.ts","sourceRoot":"","sources":["../src/remark-twemoji.ts"],"names":[],"mappings":"AAEA,OAAO,EAAW,IAAI,EAAU,MAAM,OAAO,CAAC;AAoC9C,eAAO,MAAM,aAAa,eACK,IAAI,SA2BlC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milkdown/plugin-emoji",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0-next.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./lib/index.es.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -15,30 +15,54 @@
|
|
|
15
15
|
"milkdown plugin"
|
|
16
16
|
],
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@milkdown/core": "
|
|
19
|
-
"@milkdown/prose": "
|
|
18
|
+
"@milkdown/core": "6.0.0-next.0",
|
|
19
|
+
"@milkdown/prose": "6.0.0-next.0"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
|
-
"@milkdown/core": "^
|
|
23
|
-
"@milkdown/prose": "^
|
|
22
|
+
"@milkdown/core": "^6.0.0-next.0",
|
|
23
|
+
"@milkdown/prose": "^6.0.0-next.0"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@joeattardi/emoji-button": "^4.6.
|
|
27
|
-
"@milkdown/utils": "
|
|
26
|
+
"@joeattardi/emoji-button": "^4.6.4",
|
|
27
|
+
"@milkdown/utils": "6.0.0-next.0",
|
|
28
28
|
"@types/node-emoji": "^1.8.1",
|
|
29
29
|
"@types/twemoji": "^12.1.2",
|
|
30
30
|
"emoji-regex": "^10.0.0",
|
|
31
31
|
"node-emoji": "^1.10.0",
|
|
32
32
|
"remark-emoji": "^3.0.1",
|
|
33
33
|
"tslib": "^2.3.1",
|
|
34
|
-
"twemoji": "
|
|
34
|
+
"twemoji": "~12.1.2",
|
|
35
35
|
"unist-util-visit": "^4.0.0"
|
|
36
36
|
},
|
|
37
|
+
"nx": {
|
|
38
|
+
"targets": {
|
|
39
|
+
"build": {
|
|
40
|
+
"outputs": [
|
|
41
|
+
"packages/plugin-emoji/lib"
|
|
42
|
+
],
|
|
43
|
+
"dependsOn": [
|
|
44
|
+
{
|
|
45
|
+
"target": "build",
|
|
46
|
+
"projects": "dependencies"
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
"tsc": {
|
|
51
|
+
"outputs": [],
|
|
52
|
+
"dependsOn": [
|
|
53
|
+
{
|
|
54
|
+
"target": "build",
|
|
55
|
+
"projects": "dependencies"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
37
61
|
"scripts": {
|
|
38
|
-
"start": "vite build --watch",
|
|
62
|
+
"start": "concurrently -n es,dts \"vite build --watch\" \"tsc --emitDeclarationOnly --watch\"",
|
|
39
63
|
"test": "vitest",
|
|
40
64
|
"tsc": "tsc --noEmit",
|
|
41
|
-
"build": "vite build"
|
|
65
|
+
"build": "vite build && tsc --emitDeclarationOnly"
|
|
42
66
|
},
|
|
43
67
|
"readme": "# @milkdown/plugin-emoji\n\nEmoji plugin for [milkdown](https://saul-mirone.github.io/milkdown/).\nAdd support for emoji through [shortcuts](https://www.webfx.com/tools/emoji-cheat-sheet/).\nRendered by [twemoji](https://github.com/twitter/twemoji).\n\n# Example Usage\n\n```typescript\nimport { Editor } from '@milkdown/core';\nimport { commonmark } from '@milkdown/preset-commonmark';\nimport { nord } from '@milkdown/theme-nord';\n\nimport { emoji } from '@milkdown/plugin-emoji';\n\nEditor.make().use(nord).use(commonmark).use(emoji).create();\n```\n\n# License\n\nMilkdown is open sourced software licensed under [MIT license](https://github.com/Saul-Mirone/milkdown/blob/main/LICENSE).\n"
|
|
44
68
|
}
|
package/src/filter/helper.ts
CHANGED
|
@@ -25,7 +25,7 @@ export const checkTrigger = (
|
|
|
25
25
|
return false;
|
|
26
26
|
}
|
|
27
27
|
const regex = part.exec(textBefore);
|
|
28
|
-
if (regex && textBefore.endsWith(regex[0])) {
|
|
28
|
+
if (regex && regex[0] && textBefore.endsWith(regex[0])) {
|
|
29
29
|
const match = regex[0];
|
|
30
30
|
setRange(from - (match.length - text.length), to);
|
|
31
31
|
setSearch(match);
|
|
@@ -41,7 +41,9 @@ export const renderDropdownList = (
|
|
|
41
41
|
onConfirm: () => void,
|
|
42
42
|
setActive: (active: HTMLElement | null) => void,
|
|
43
43
|
) => {
|
|
44
|
-
dropDown.
|
|
44
|
+
while (dropDown.firstChild) {
|
|
45
|
+
dropDown.firstChild.remove();
|
|
46
|
+
}
|
|
45
47
|
list.forEach(({ emoji, key }, i) => {
|
|
46
48
|
const container = document.createElement('div');
|
|
47
49
|
container.className = 'milkdown-emoji-filter_item';
|
|
@@ -63,7 +65,7 @@ export const renderDropdownList = (
|
|
|
63
65
|
setActive(container);
|
|
64
66
|
}
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
const onEnter = (e: MouseEvent) => {
|
|
67
69
|
if ($active) {
|
|
68
70
|
$active.classList.remove('active');
|
|
69
71
|
}
|
|
@@ -71,15 +73,21 @@ export const renderDropdownList = (
|
|
|
71
73
|
if (!(target instanceof HTMLElement)) return;
|
|
72
74
|
target.classList.add('active');
|
|
73
75
|
setActive(target);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const onLeave = (e: MouseEvent) => {
|
|
76
79
|
const { target } = e;
|
|
77
80
|
if (!(target instanceof HTMLElement)) return;
|
|
78
81
|
target.classList.remove('active');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const onClick = (e: MouseEvent) => {
|
|
82
85
|
e.preventDefault();
|
|
83
|
-
|
|
86
|
+
onConfirm();
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
container.addEventListener('mouseenter', onEnter);
|
|
90
|
+
container.addEventListener('mouseleave', onLeave);
|
|
91
|
+
container.addEventListener('mousedown', onClick);
|
|
84
92
|
});
|
|
85
93
|
};
|
package/src/filter/index.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
2
|
|
|
3
|
-
import { calculateNodePosition, Plugin } from '@milkdown/prose';
|
|
3
|
+
import { calculateNodePosition, Plugin, PluginKey } from '@milkdown/prose';
|
|
4
4
|
import { Utils } from '@milkdown/utils';
|
|
5
5
|
import { search } from 'node-emoji';
|
|
6
6
|
|
|
7
7
|
import { checkTrigger, renderDropdownList } from './helper';
|
|
8
8
|
import { injectStyle } from './style';
|
|
9
9
|
|
|
10
|
+
export const key = new PluginKey('MILKDOWN_PLUGIN_EMOJI_FILTER');
|
|
11
|
+
|
|
10
12
|
export const filter = (utils: Utils) => {
|
|
11
13
|
let trigger = false;
|
|
12
14
|
let _from = 0;
|
|
@@ -21,6 +23,7 @@ export const filter = (utils: Utils) => {
|
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
return new Plugin({
|
|
26
|
+
key,
|
|
24
27
|
props: {
|
|
25
28
|
handleKeyDown(_, event) {
|
|
26
29
|
if (['Delete', 'Backspace'].includes(event.key)) {
|
|
@@ -62,11 +65,13 @@ export const filter = (utils: Utils) => {
|
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
const dropDown = document.createElement('div');
|
|
65
|
-
const style = utils.getStyle(injectStyle);
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
style
|
|
69
|
-
|
|
69
|
+
utils.themeManager.onFlush(() => {
|
|
70
|
+
const style = utils.getStyle(injectStyle);
|
|
71
|
+
if (style) {
|
|
72
|
+
style.split(' ').forEach((x) => dropDown.classList.add(x));
|
|
73
|
+
}
|
|
74
|
+
});
|
|
70
75
|
|
|
71
76
|
dropDown.classList.add('milkdown-emoji-filter', 'hide');
|
|
72
77
|
|
|
@@ -82,7 +87,7 @@ export const filter = (utils: Utils) => {
|
|
|
82
87
|
};
|
|
83
88
|
|
|
84
89
|
parentNode.appendChild(dropDown);
|
|
85
|
-
|
|
90
|
+
const onKeydown = (e: Event) => {
|
|
86
91
|
if (!trigger || !(e instanceof KeyboardEvent)) return;
|
|
87
92
|
|
|
88
93
|
const { key } = e;
|
|
@@ -106,14 +111,16 @@ export const filter = (utils: Utils) => {
|
|
|
106
111
|
|
|
107
112
|
return;
|
|
108
113
|
}
|
|
109
|
-
}
|
|
110
|
-
|
|
114
|
+
};
|
|
115
|
+
const onClick = (e: Event) => {
|
|
111
116
|
if (!trigger) return;
|
|
112
117
|
|
|
113
118
|
e.stopPropagation();
|
|
114
119
|
off();
|
|
115
120
|
dropDown.classList.add('hide');
|
|
116
|
-
}
|
|
121
|
+
};
|
|
122
|
+
parentNode.addEventListener('keydown', onKeydown);
|
|
123
|
+
parentNode.addEventListener('mousedown', onClick);
|
|
117
124
|
|
|
118
125
|
return {
|
|
119
126
|
update: (view) => {
|
|
@@ -156,6 +163,12 @@ export const filter = (utils: Utils) => {
|
|
|
156
163
|
|
|
157
164
|
return null;
|
|
158
165
|
},
|
|
166
|
+
|
|
167
|
+
destroy: () => {
|
|
168
|
+
parentNode.removeEventListener('keydown', onKeydown);
|
|
169
|
+
parentNode.removeEventListener('mousedown', onClick);
|
|
170
|
+
dropDown.remove();
|
|
171
|
+
},
|
|
159
172
|
};
|
|
160
173
|
},
|
|
161
174
|
});
|
package/src/filter/style.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
Color,
|
|
4
|
+
Emotion,
|
|
5
|
+
ThemeBorder,
|
|
6
|
+
ThemeColor,
|
|
7
|
+
ThemeFont,
|
|
8
|
+
ThemeManager,
|
|
9
|
+
ThemeShadow,
|
|
10
|
+
ThemeSize,
|
|
11
|
+
} from '@milkdown/core';
|
|
3
12
|
|
|
4
|
-
export const injectStyle = (
|
|
5
|
-
const border =
|
|
6
|
-
const shadow =
|
|
13
|
+
export const injectStyle = (themeManager: ThemeManager, { css, cx }: Emotion) => {
|
|
14
|
+
const border = themeManager.get(ThemeBorder, undefined);
|
|
15
|
+
const shadow = themeManager.get(ThemeShadow, undefined);
|
|
16
|
+
const radius = themeManager.get(ThemeSize, 'radius');
|
|
17
|
+
const typography = themeManager.get(ThemeFont, 'typography');
|
|
18
|
+
const palette = (color: Color, opacity = 1) => themeManager.get(ThemeColor, [color, opacity]);
|
|
7
19
|
|
|
8
20
|
const style = css`
|
|
9
21
|
position: absolute;
|
|
@@ -11,20 +23,20 @@ export const injectStyle = ({ size, mixin, palette, font }: ThemeTool, { css, cx
|
|
|
11
23
|
display: none;
|
|
12
24
|
}
|
|
13
25
|
|
|
14
|
-
border-radius: ${
|
|
26
|
+
border-radius: ${radius};
|
|
15
27
|
background: ${palette('surface')};
|
|
16
28
|
|
|
17
29
|
.milkdown-emoji-filter_item {
|
|
18
30
|
display: flex;
|
|
19
|
-
gap: 0.
|
|
20
|
-
height: 2.
|
|
21
|
-
padding: 0
|
|
31
|
+
gap: 0.5em;
|
|
32
|
+
height: 2.57143em;
|
|
33
|
+
padding: 0 1em;
|
|
22
34
|
align-items: center;
|
|
23
35
|
justify-content: flex-start;
|
|
24
36
|
cursor: pointer;
|
|
25
37
|
line-height: 2;
|
|
26
|
-
font-family: ${
|
|
27
|
-
font-size: 0.
|
|
38
|
+
font-family: ${typography};
|
|
39
|
+
font-size: 0.875em;
|
|
28
40
|
&.active {
|
|
29
41
|
background: ${palette('secondary', 0.12)};
|
|
30
42
|
color: ${palette('primary')};
|
package/src/node.ts
CHANGED
|
@@ -12,20 +12,21 @@ import { picker } from './picker';
|
|
|
12
12
|
import { twemojiPlugin } from './remark-twemoji';
|
|
13
13
|
|
|
14
14
|
export const emojiNode = createNode((utils) => {
|
|
15
|
-
const
|
|
16
|
-
(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
const getStyle = () =>
|
|
16
|
+
utils.getStyle(
|
|
17
|
+
(_, { css }) => css`
|
|
18
|
+
display: inline-flex;
|
|
19
|
+
justify-content: center;
|
|
20
|
+
align-items: center;
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
.emoji {
|
|
23
|
+
height: 1em;
|
|
24
|
+
width: 1em;
|
|
25
|
+
margin: 0 0.05em 0 0.1em;
|
|
26
|
+
vertical-align: -0.1em;
|
|
27
|
+
}
|
|
28
|
+
`,
|
|
29
|
+
);
|
|
29
30
|
return {
|
|
30
31
|
id: 'emoji',
|
|
31
32
|
schema: () => ({
|
|
@@ -50,25 +51,28 @@ export const emojiNode = createNode((utils) => {
|
|
|
50
51
|
],
|
|
51
52
|
toDOM: (node) => {
|
|
52
53
|
const span = document.createElement('span');
|
|
53
|
-
span.dataset
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
span.dataset['type'] = 'emoji';
|
|
55
|
+
utils.themeManager.onFlush(() => {
|
|
56
|
+
const style = getStyle();
|
|
57
|
+
if (style) {
|
|
58
|
+
span.classList.add(style);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
57
61
|
span.classList.add('emoji-wrapper');
|
|
58
|
-
span.innerHTML = node.attrs
|
|
62
|
+
span.innerHTML = node.attrs['html'];
|
|
59
63
|
return { dom: span };
|
|
60
64
|
},
|
|
61
65
|
parseMarkdown: {
|
|
62
66
|
match: ({ type }) => type === 'emoji',
|
|
63
67
|
runner: (state, node, type) => {
|
|
64
|
-
state.addNode(type, { html: node
|
|
68
|
+
state.addNode(type, { html: node['value'] as string });
|
|
65
69
|
},
|
|
66
70
|
},
|
|
67
71
|
toMarkdown: {
|
|
68
72
|
match: (node) => node.type.name === 'emoji',
|
|
69
73
|
runner: (state, node) => {
|
|
70
74
|
const span = document.createElement('span');
|
|
71
|
-
span.innerHTML = node.attrs
|
|
75
|
+
span.innerHTML = node.attrs['html'];
|
|
72
76
|
const img = span.querySelector('img');
|
|
73
77
|
const title = img?.title;
|
|
74
78
|
span.remove();
|
package/src/picker.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
2
|
import { EmojiButton } from '@joeattardi/emoji-button';
|
|
3
|
-
import {
|
|
3
|
+
import { Color, ThemeColor, ThemeFont } from '@milkdown/core';
|
|
4
|
+
import { Decoration, DecorationSet, EditorView, Plugin, PluginKey } from '@milkdown/prose';
|
|
4
5
|
import { Utils } from '@milkdown/utils';
|
|
5
6
|
|
|
6
7
|
import { parse } from './parse';
|
|
7
8
|
|
|
8
9
|
const keyword = ':emoji:';
|
|
10
|
+
export const key = new PluginKey('MILKDOWN_PLUGIN_EMOJI_PICKER');
|
|
9
11
|
|
|
10
12
|
const checkTrigger = (
|
|
11
13
|
view: EditorView,
|
|
@@ -40,6 +42,7 @@ export const picker = (utils: Utils) => {
|
|
|
40
42
|
};
|
|
41
43
|
|
|
42
44
|
const plugin = new Plugin({
|
|
45
|
+
key,
|
|
43
46
|
props: {
|
|
44
47
|
handleKeyDown() {
|
|
45
48
|
off();
|
|
@@ -71,7 +74,9 @@ export const picker = (utils: Utils) => {
|
|
|
71
74
|
if (!parentNode) {
|
|
72
75
|
throw new Error();
|
|
73
76
|
}
|
|
74
|
-
utils.getStyle((
|
|
77
|
+
utils.getStyle((themeManager, { injectGlobal }) => {
|
|
78
|
+
const palette = (color: Color, opacity = 1) => themeManager.get(ThemeColor, [color, opacity]);
|
|
79
|
+
const typography = themeManager.get(ThemeFont, 'typography');
|
|
75
80
|
const css = injectGlobal;
|
|
76
81
|
css`
|
|
77
82
|
.emoji-picker {
|
|
@@ -83,8 +88,8 @@ export const picker = (utils: Utils) => {
|
|
|
83
88
|
--dark-blue-color: ${palette('primary')} !important;
|
|
84
89
|
--dark-search-icon-color: ${palette('primary')} !important;
|
|
85
90
|
--dark-category-button-color: ${palette('secondary', 0.4)} !important;
|
|
86
|
-
--font: ${
|
|
87
|
-
--font-size:
|
|
91
|
+
--font: ${typography} !important;
|
|
92
|
+
--font-size: 1em !important;
|
|
88
93
|
}
|
|
89
94
|
`;
|
|
90
95
|
});
|
package/src/remark-twemoji.ts
CHANGED
|
@@ -16,10 +16,16 @@ function flatMap(ast: Node, fn: (node: Node, index: number, parent: Node | null)
|
|
|
16
16
|
if (isParent(node)) {
|
|
17
17
|
const out = [];
|
|
18
18
|
for (let i = 0, n = node.children.length; i < n; i++) {
|
|
19
|
-
const
|
|
20
|
-
if (
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const nthChild = node.children[i];
|
|
20
|
+
if (nthChild) {
|
|
21
|
+
const xs = transform(nthChild, i, node);
|
|
22
|
+
if (xs) {
|
|
23
|
+
for (let j = 0, m = xs.length; j < m; j++) {
|
|
24
|
+
const item = xs[j];
|
|
25
|
+
if (item) {
|
|
26
|
+
out.push(item);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
}
|
|
@@ -43,11 +49,13 @@ export const twemojiPlugin = () => {
|
|
|
43
49
|
while ((match = regex.exec(str))) {
|
|
44
50
|
const { index } = match;
|
|
45
51
|
const emoji = match[0];
|
|
46
|
-
if (
|
|
47
|
-
|
|
52
|
+
if (emoji) {
|
|
53
|
+
if (index > 0) {
|
|
54
|
+
output.push({ ...node, value: str.slice(0, index) });
|
|
55
|
+
}
|
|
56
|
+
output.push({ ...node, value: parse(emoji), type: 'emoji' });
|
|
57
|
+
str = str.slice(index + emoji.length);
|
|
48
58
|
}
|
|
49
|
-
output.push({ ...node, value: parse(emoji), type: 'emoji' });
|
|
50
|
-
str = str.slice(index + emoji.length);
|
|
51
59
|
}
|
|
52
60
|
if (str.length) {
|
|
53
61
|
output.push({ ...node, value: str });
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constant.d.ts","sourceRoot":"","sources":["constant.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,IAAI,QAAqB,CAAC;AACvC,eAAO,MAAM,IAAI,QAAwB,CAAC;AAC1C,eAAO,MAAM,KAAK,QAAmB,CAAC;AACtC,eAAO,MAAM,OAAO,YAAY,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["helper.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAKnC,eAAO,MAAM,YAAY,SACf,UAAU,QACV,MAAM,MACR,MAAM,QACJ,MAAM,mBACK,MAAM,MAAM,MAAM,KAAK,IAAI,qBACzB,MAAM,KAAK,IAAI,YAoBrC,CAAC;AAEF,eAAO,MAAM,kBAAkB,SACrB,KAAK,EAAE,YACH,WAAW,WACZ,WAAW,GAAG,IAAI,aAChB,MAAM,IAAI,sBACD,WAAW,GAAG,IAAI,KAAK,IAAI,SA2ClD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAyB,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAMxC,eAAO,MAAM,MAAM,UAAW,KAAK,qBAwJlC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["style.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEzD,eAAO,MAAM,WAAW,mCAAoC,SAAS,eAAe,OAAO,WAsC1F,CAAC"}
|
package/lib/src/index.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { AtomList } from '@milkdown/utils';
|
|
2
|
-
export declare const emoji: AtomList<import("@milkdown/utils/lib/src/types").Metadata<import("@milkdown/utils/lib/src/types").GetPlugin<string, import("@milkdown/utils").UnknownRecord>> & import("@milkdown/core").MilkdownPlugin>;
|
|
3
|
-
export { emojiNode } from './node';
|
|
4
|
-
//# sourceMappingURL=index.d.ts.map
|
package/lib/src/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAI3C,eAAO,MAAM,KAAK,0MAAiC,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC"}
|
package/lib/src/node.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["node.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,SAAS;;;;EAmFpB,CAAC"}
|
package/lib/src/parse.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["parse.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,KAAK,UAAW,MAAM,WAAsE,CAAC"}
|
package/lib/src/picker.d.ts
DELETED
package/lib/src/picker.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"picker.d.ts","sourceRoot":"","sources":["picker.ts"],"names":[],"mappings":"AAEA,OAAO,EAAyC,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAChF,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AA2BxC,eAAO,MAAM,MAAM,UAAW,KAAK,qBA8FlC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remark-twemoji.d.ts","sourceRoot":"","sources":["remark-twemoji.ts"],"names":[],"mappings":"AAEA,OAAO,EAAW,IAAI,EAAU,MAAM,OAAO,CAAC;AA8B9C,eAAO,MAAM,aAAa,eACK,IAAI,SAyBlC,CAAC"}
|