@milkdown/plugin-emoji 5.1.0 → 5.2.1
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/filter/style.d.ts.map +1 -1
- package/lib/index.cjs.js +58 -0
- package/lib/index.cjs.js.map +1 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.es.js +489 -0
- package/lib/index.es.js.map +1 -0
- package/lib/node.d.ts +1 -1
- package/lib/node.d.ts.map +1 -1
- package/package.json +18 -7
- package/src/filter/index.ts +1 -1
- package/src/filter/style.ts +6 -4
- package/src/node.ts +4 -2
- package/lib/constant.js +0 -6
- package/lib/constant.js.map +0 -1
- package/lib/filter/helper.js +0 -64
- package/lib/filter/helper.js.map +0 -1
- package/lib/filter/index.js +0 -131
- package/lib/filter/index.js.map +0 -1
- package/lib/filter/style.js +0 -41
- package/lib/filter/style.js.map +0 -1
- package/lib/index.js +0 -6
- package/lib/index.js.map +0 -1
- package/lib/node.js +0 -92
- package/lib/node.js.map +0 -1
- package/lib/parse.js +0 -4
- package/lib/parse.js.map +0 -1
- package/lib/picker.js +0 -113
- package/lib/picker.js.map +0 -1
- package/lib/remark-twemoji.js +0 -52
- package/lib/remark-twemoji.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/filter/style.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,eAAO,MAAM,WAAW,mCAAoC,SAAS,
|
|
1
|
+
{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/filter/style.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,eAAO,MAAM,WAAW,mCAAoC,SAAS,WAsCpE,CAAC"}
|
package/lib/index.cjs.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";var S=Object.defineProperty,C=Object.defineProperties;var N=Object.getOwnPropertyDescriptors;var x=Object.getOwnPropertySymbols;var H=Object.prototype.hasOwnProperty,q=Object.prototype.propertyIsEnumerable;var $=(n,t,e)=>t in n?S(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e,j=(n,t)=>{for(var e in t||(t={}))H.call(t,e)&&$(n,e,t[e]);if(x)for(var e of x(t))q.call(t,e)&&$(n,e,t[e]);return n},y=(n,t)=>C(n,N(t));Object.defineProperty(exports,"__esModule",{value:!0});exports[Symbol.toStringTag]="Module";var P=require("@milkdown/utils"),w=require("@emotion/css"),h=require("@milkdown/prose"),T=require("node-emoji"),A=require("remark-emoji"),B=require("twemoji"),F=require("@joeattardi/emoji-button"),O=require("emoji-regex");function k(n){return n&&typeof n=="object"&&"default"in n?n:{default:n}}var R=k(T),I=k(A),z=k(B),K=k(O);const W=/:\+1|:-1|:[\w-]+/,U=/:\+1:|:-1:|:[\w-]+:/,G=/(:([^:\s]+):)$/,v=n=>z.default.parse(n,{attributes:t=>({title:t})}),J=(n,t,e,i,s,c)=>{if(n.composing)return!1;const{state:a}=n,o=a.doc.resolve(t);if(o.parent.type.spec.code)return!1;const r=o.parent.textBetween(Math.max(0,o.parentOffset-10),o.parentOffset,void 0,"\uFFFC")+i;if(U.test(r))return!1;const d=W.exec(r);if(d&&r.endsWith(d[0])){const l=d[0];return s(t-(l.length-i.length),e),c(l),!0}return!1},Q=(n,t,e,i,s)=>{t.innerHTML="",n.forEach(({emoji:c,key:a},o)=>{const r=document.createElement("div");r.className="milkdown-emoji-filter_item";const d=document.createElement("span");d.innerHTML=v(c),d.className="milkdown-emoji-filter_item-emoji";const l=document.createElement("span");l.textContent=":"+a+":",l.className="milkdown-emoji-filter_item-key",r.appendChild(d),r.appendChild(l),t.appendChild(r),o===0&&(r.classList.add("active"),s(r)),r.addEventListener("mouseenter",u=>{e&&e.classList.remove("active");const{target:m}=u;m instanceof HTMLElement&&(m.classList.add("active"),s(m))}),r.addEventListener("mouseleave",u=>{const{target:m}=u;m instanceof HTMLElement&&m.classList.remove("active")}),r.addEventListener("mousedown",u=>{i(),u.preventDefault()})})},X=({size:n,mixin:t,palette:e,font:i})=>{var o,r;const s=(o=t.border)==null?void 0:o.call(t),c=(r=t.shadow)==null?void 0:r.call(t),a=w.css`
|
|
2
|
+
position: absolute;
|
|
3
|
+
&.hide {
|
|
4
|
+
display: none;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
border-radius: ${n.radius};
|
|
8
|
+
background: ${e("surface")};
|
|
9
|
+
|
|
10
|
+
.milkdown-emoji-filter_item {
|
|
11
|
+
display: flex;
|
|
12
|
+
gap: 0.5rem;
|
|
13
|
+
height: 2.25rem;
|
|
14
|
+
padding: 0 1rem;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: flex-start;
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
line-height: 2;
|
|
19
|
+
font-family: ${i.typography};
|
|
20
|
+
font-size: 0.875rem;
|
|
21
|
+
&.active {
|
|
22
|
+
background: ${e("secondary",.12)};
|
|
23
|
+
color: ${e("primary")};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.emoji {
|
|
28
|
+
height: 1em;
|
|
29
|
+
width: 1em;
|
|
30
|
+
margin: 0 0.05em 0 0.1em;
|
|
31
|
+
vertical-align: -0.1em;
|
|
32
|
+
}
|
|
33
|
+
`;return w.cx(s,c,a)},Y=n=>{let t=!1,e=0,i="",s=null;const c=()=>{t=!1,e=0,i="",s=null};return new h.Plugin({props:{handleKeyDown(a,o){return["Delete","Backspace"].includes(o.key)?(i=i.slice(0,-1),i.length<=1&&c(),!1):!(!t||!["ArrowUp","ArrowDown","Enter"].includes(o.key))},handleTextInput(a,o,r,d){return t=J(a,o,r,d,l=>{e=l},l=>{i=l}),t||c(),!1}},view:a=>{const{parentNode:o}=a.dom;if(!o)throw new Error;const r=document.createElement("div"),d=n.getStyle(X);d&&d.split(" ").forEach(u=>r.classList.add(u)),r.classList.add("milkdown-emoji-filter","hide");const l=()=>{var f;if(!s)return;const{tr:u}=a.state,m=a.state.schema.node("emoji",{html:(f=s.firstElementChild)==null?void 0:f.innerHTML});a.dispatch(u.delete(e,e+i.length).insert(e,m)),c(),r.classList.add("hide")};return o.appendChild(r),o.addEventListener("keydown",u=>{if(!t||!(u instanceof KeyboardEvent))return;const{key:m}=u;if(m==="Enter"){l();return}if(["ArrowDown","ArrowUp"].includes(m)){const f=m==="ArrowDown"?(s==null?void 0:s.nextElementSibling)||r.firstElementChild:(s==null?void 0:s.previousElementSibling)||r.lastElementChild;if(s&&s.classList.remove("active"),!f)return;f.classList.add("active"),s=f;return}}),o.addEventListener("mousedown",u=>{!t||(u.stopPropagation(),c(),r.classList.add("hide"))}),{update:u=>{if(!t)return r.classList.add("hide"),null;const m=T.search(i).slice(0,5),{node:f}=u.domAtPos(e);return m.length===0||!f?(r.classList.add("hide"),null):(r.classList.remove("hide"),Q(m,r,s,l,p=>{s=p}),h.calculateNodePosition(u,r,(p,g,E)=>{const _=u.coordsAtPos(e);let L=_.left-E.left,M=p.bottom-E.top+14;return L<0&&(L=0),window.innerHeight-_.bottom<g.height&&(M=p.top-E.top-g.height-14),[M,L]}),null)}}}})},b=":emoji:",Z=(n,t,e,i,s)=>{if(n.composing)return!1;const{state:c}=n,a=c.doc.resolve(t);return a.parent.type.spec.code?!1:a.parent.textBetween(a.parentOffset-b.length+1,a.parentOffset,void 0,"\uFFFC")+i===b?(s(t-b.length+1,e+1),!0):!1},V=n=>{let t=!1;const e=document.createElement("span");let i=0,s=0;const c=()=>{t=!1,i=0,s=0};return new h.Plugin({props:{handleKeyDown(){return c(),!1},handleClick(){return c(),!1},handleTextInput(o,r,d,l){return t=Z(o,r,d,l,(u,m)=>{i=u,s=m}),t||c(),!1},decorations(o){return t?h.DecorationSet.create(o.doc,[h.Decoration.widget(o.selection.to,e)]):null}},view:o=>{const{parentNode:r}=o.dom;if(!r)throw new Error;n.getStyle(({palette:l,font:u})=>{w.injectGlobal`
|
|
34
|
+
.emoji-picker {
|
|
35
|
+
--dark-search-background-color: ${l("surface")} !important;
|
|
36
|
+
--dark-text-color: ${l("neutral",.87)} !important;
|
|
37
|
+
--dark-background-color: ${l("background")} !important;
|
|
38
|
+
--dark-border-color: ${l("shadow")} !important;
|
|
39
|
+
--dark-hover-color: ${l("secondary",.12)} !important;
|
|
40
|
+
--dark-blue-color: ${l("primary")} !important;
|
|
41
|
+
--dark-search-icon-color: ${l("primary")} !important;
|
|
42
|
+
--dark-category-button-color: ${l("secondary",.4)} !important;
|
|
43
|
+
--font: ${u.typography} !important;
|
|
44
|
+
--font-size: 1rem !important;
|
|
45
|
+
}
|
|
46
|
+
`});const d=new F.EmojiButton({rootElement:r,autoFocusSearch:!1,style:"twemoji",theme:"dark",zIndex:99});return d.on("emoji",l=>{const u=i,m=s;c();const f=v(l.emoji),p=o.state.schema.node("emoji",{html:f}),{tr:g}=o.state;o.dispatch(g.replaceRangeWith(u,m,p))}),{update:()=>t?(d.showPicker(e),null):(d.hidePicker(),null),destroy:()=>{d.destroyPicker()}}}})},ee=K.default(),te=n=>!!n.children,re=n=>!!n.value;function ne(n,t){return e(n,0,null)[0];function e(i,s,c){if(te(i)){const a=[];for(let o=0,r=i.children.length;o<r;o++){const d=e(i.children[o],o,i);if(d)for(let l=0,u=d.length;l<u;l++)a.push(d[l])}i.children=a}return t(i,s,c)}}const oe=()=>{function n(t){ne(t,e=>{if(!re(e))return[e];const i=e.value,s=[];let c,a=i;for(;c=ee.exec(a);){const{index:o}=c,r=c[0];o>0&&s.push(y(j({},e),{value:a.slice(0,o)})),s.push(y(j({},e),{value:v(r),type:"emoji"})),a=a.slice(o+r.length)}return a.length&&s.push(y(j({},e),{value:a})),s})}return n},D=P.createNode(n=>{const t=n.getStyle(()=>w.css`
|
|
47
|
+
display: inline-flex;
|
|
48
|
+
justify-content: center;
|
|
49
|
+
align-items: center;
|
|
50
|
+
|
|
51
|
+
.emoji {
|
|
52
|
+
height: 1em;
|
|
53
|
+
width: 1em;
|
|
54
|
+
margin: 0 0.05em 0 0.1em;
|
|
55
|
+
vertical-align: -0.1em;
|
|
56
|
+
}
|
|
57
|
+
`);return{id:"emoji",schema:()=>({group:"inline",inline:!0,selectable:!1,attrs:{html:{default:""}},parseDOM:[{tag:'span[data-type="emoji"]',getAttrs:e=>{if(!(e instanceof HTMLElement))throw new Error;return{html:e.innerHTML}}}],toDOM:e=>{const i=document.createElement("span");return i.dataset.type="emoji",t&&i.classList.add(t),i.classList.add("emoji-wrapper"),i.innerHTML=e.attrs.html,{dom:i}},parseMarkdown:{match:({type:e})=>e==="emoji",runner:(e,i,s)=>{e.addNode(s,{html:i.value})}},toMarkdown:{match:e=>e.type.name==="emoji",runner:(e,i)=>{const s=document.createElement("span");s.innerHTML=i.attrs.html;const c=s.querySelector("img"),a=c==null?void 0:c.title;s.remove(),e.addNode("text",void 0,a)}}}),inputRules:e=>[new h.InputRule(G,(i,s,c,a)=>{const o=s[0];if(!o)return null;const r=R.default.get(o);if(!r||o.includes(r))return null;const d=v(r);return i.tr.setMeta("emoji",!0).replaceRangeWith(c,a,e.create({html:d})).scrollIntoView()})],remarkPlugins:()=>[I.default,oe],prosePlugins:()=>[V(n),Y(n)]}}),se=P.AtomList.create([D()]);exports.emoji=se;exports.emojiNode=D;
|
|
58
|
+
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs.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 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 { css, cx } from '@emotion/css';\nimport type { ThemeTool } from '@milkdown/core';\n\nexport const injectStyle = ({ size, mixin, palette, font }: ThemeTool) => {\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 if (!trigger) {\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 start = view.coordsAtPos(_from);\n let left = start.left - parent.left;\n let top = selected.bottom - parent.top + 14;\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;\n }\n return [top, left];\n });\n\n return null;\n },\n };\n },\n });\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { injectGlobal } from '@emotion/css';\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 }) => {\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 { css } from '@emotion/css';\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`\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":["twemoji","checkTrigger","css","cx","Plugin","search","DecorationSet","Decoration","injectGlobal","EmojiButton","emojiRegex","createNode","InputRule","nodeEmoji","remarkEmoji","AtomList"],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +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
|
|
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
3
|
export { emojiNode } from './node';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +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,
|
|
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
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
import { createNode, AtomList } from "@milkdown/utils";
|
|
21
|
+
import { css, cx, injectGlobal } from "@emotion/css";
|
|
22
|
+
import { Plugin, calculateNodePosition, DecorationSet, Decoration, InputRule } from "@milkdown/prose";
|
|
23
|
+
import nodeEmoji, { search } from "node-emoji";
|
|
24
|
+
import remarkEmoji from "remark-emoji";
|
|
25
|
+
import twemoji from "twemoji";
|
|
26
|
+
import { EmojiButton } from "@joeattardi/emoji-button";
|
|
27
|
+
import emojiRegex from "emoji-regex";
|
|
28
|
+
const part = /:\+1|:-1|:[\w-]+/;
|
|
29
|
+
const full = /:\+1:|:-1:|:[\w-]+:/;
|
|
30
|
+
const input = /(:([^:\s]+):)$/;
|
|
31
|
+
const parse = (emoji2) => twemoji.parse(emoji2, { attributes: (text) => ({ title: text }) });
|
|
32
|
+
const checkTrigger$1 = (view, from, to, text, setRange, setSearch) => {
|
|
33
|
+
if (view.composing)
|
|
34
|
+
return false;
|
|
35
|
+
const { state } = view;
|
|
36
|
+
const $from = state.doc.resolve(from);
|
|
37
|
+
if ($from.parent.type.spec.code)
|
|
38
|
+
return false;
|
|
39
|
+
const textBefore = $from.parent.textBetween(Math.max(0, $from.parentOffset - 10), $from.parentOffset, void 0, "\uFFFC") + text;
|
|
40
|
+
if (full.test(textBefore)) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const regex2 = part.exec(textBefore);
|
|
44
|
+
if (regex2 && textBefore.endsWith(regex2[0])) {
|
|
45
|
+
const match = regex2[0];
|
|
46
|
+
setRange(from - (match.length - text.length), to);
|
|
47
|
+
setSearch(match);
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
};
|
|
52
|
+
const renderDropdownList = (list, dropDown, $active, onConfirm, setActive) => {
|
|
53
|
+
dropDown.innerHTML = "";
|
|
54
|
+
list.forEach(({ emoji: emoji2, key }, i) => {
|
|
55
|
+
const container = document.createElement("div");
|
|
56
|
+
container.className = "milkdown-emoji-filter_item";
|
|
57
|
+
const emojiSpan = document.createElement("span");
|
|
58
|
+
emojiSpan.innerHTML = parse(emoji2);
|
|
59
|
+
emojiSpan.className = "milkdown-emoji-filter_item-emoji";
|
|
60
|
+
const keySpan = document.createElement("span");
|
|
61
|
+
keySpan.textContent = ":" + key + ":";
|
|
62
|
+
keySpan.className = "milkdown-emoji-filter_item-key";
|
|
63
|
+
container.appendChild(emojiSpan);
|
|
64
|
+
container.appendChild(keySpan);
|
|
65
|
+
dropDown.appendChild(container);
|
|
66
|
+
if (i === 0) {
|
|
67
|
+
container.classList.add("active");
|
|
68
|
+
setActive(container);
|
|
69
|
+
}
|
|
70
|
+
container.addEventListener("mouseenter", (e) => {
|
|
71
|
+
if ($active) {
|
|
72
|
+
$active.classList.remove("active");
|
|
73
|
+
}
|
|
74
|
+
const { target } = e;
|
|
75
|
+
if (!(target instanceof HTMLElement))
|
|
76
|
+
return;
|
|
77
|
+
target.classList.add("active");
|
|
78
|
+
setActive(target);
|
|
79
|
+
});
|
|
80
|
+
container.addEventListener("mouseleave", (e) => {
|
|
81
|
+
const { target } = e;
|
|
82
|
+
if (!(target instanceof HTMLElement))
|
|
83
|
+
return;
|
|
84
|
+
target.classList.remove("active");
|
|
85
|
+
});
|
|
86
|
+
container.addEventListener("mousedown", (e) => {
|
|
87
|
+
onConfirm();
|
|
88
|
+
e.preventDefault();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
const injectStyle = ({ size, mixin, palette, font }) => {
|
|
93
|
+
var _a, _b;
|
|
94
|
+
const border = (_a = mixin.border) == null ? void 0 : _a.call(mixin);
|
|
95
|
+
const shadow = (_b = mixin.shadow) == null ? void 0 : _b.call(mixin);
|
|
96
|
+
const style = css`
|
|
97
|
+
position: absolute;
|
|
98
|
+
&.hide {
|
|
99
|
+
display: none;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
border-radius: ${size.radius};
|
|
103
|
+
background: ${palette("surface")};
|
|
104
|
+
|
|
105
|
+
.milkdown-emoji-filter_item {
|
|
106
|
+
display: flex;
|
|
107
|
+
gap: 0.5rem;
|
|
108
|
+
height: 2.25rem;
|
|
109
|
+
padding: 0 1rem;
|
|
110
|
+
align-items: center;
|
|
111
|
+
justify-content: flex-start;
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
line-height: 2;
|
|
114
|
+
font-family: ${font.typography};
|
|
115
|
+
font-size: 0.875rem;
|
|
116
|
+
&.active {
|
|
117
|
+
background: ${palette("secondary", 0.12)};
|
|
118
|
+
color: ${palette("primary")};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.emoji {
|
|
123
|
+
height: 1em;
|
|
124
|
+
width: 1em;
|
|
125
|
+
margin: 0 0.05em 0 0.1em;
|
|
126
|
+
vertical-align: -0.1em;
|
|
127
|
+
}
|
|
128
|
+
`;
|
|
129
|
+
return cx(border, shadow, style);
|
|
130
|
+
};
|
|
131
|
+
const filter = (utils) => {
|
|
132
|
+
let trigger = false;
|
|
133
|
+
let _from = 0;
|
|
134
|
+
let _search = "";
|
|
135
|
+
let $active = null;
|
|
136
|
+
const off = () => {
|
|
137
|
+
trigger = false;
|
|
138
|
+
_from = 0;
|
|
139
|
+
_search = "";
|
|
140
|
+
$active = null;
|
|
141
|
+
};
|
|
142
|
+
return new Plugin({
|
|
143
|
+
props: {
|
|
144
|
+
handleKeyDown(_, event) {
|
|
145
|
+
if (["Delete", "Backspace"].includes(event.key)) {
|
|
146
|
+
_search = _search.slice(0, -1);
|
|
147
|
+
if (_search.length <= 1) {
|
|
148
|
+
off();
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
if (!trigger)
|
|
153
|
+
return false;
|
|
154
|
+
if (!["ArrowUp", "ArrowDown", "Enter"].includes(event.key)) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
return true;
|
|
158
|
+
},
|
|
159
|
+
handleTextInput(view, from, to, text) {
|
|
160
|
+
trigger = checkTrigger$1(view, from, to, text, (from2) => {
|
|
161
|
+
_from = from2;
|
|
162
|
+
}, (search2) => {
|
|
163
|
+
_search = search2;
|
|
164
|
+
});
|
|
165
|
+
if (!trigger) {
|
|
166
|
+
off();
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
view: (editorView) => {
|
|
172
|
+
const { parentNode } = editorView.dom;
|
|
173
|
+
if (!parentNode) {
|
|
174
|
+
throw new Error();
|
|
175
|
+
}
|
|
176
|
+
const dropDown = document.createElement("div");
|
|
177
|
+
const style = utils.getStyle(injectStyle);
|
|
178
|
+
if (style) {
|
|
179
|
+
style.split(" ").forEach((x) => dropDown.classList.add(x));
|
|
180
|
+
}
|
|
181
|
+
dropDown.classList.add("milkdown-emoji-filter", "hide");
|
|
182
|
+
const replace = () => {
|
|
183
|
+
var _a;
|
|
184
|
+
if (!$active)
|
|
185
|
+
return;
|
|
186
|
+
const { tr } = editorView.state;
|
|
187
|
+
const node = editorView.state.schema.node("emoji", { html: (_a = $active.firstElementChild) == null ? void 0 : _a.innerHTML });
|
|
188
|
+
editorView.dispatch(tr.delete(_from, _from + _search.length).insert(_from, node));
|
|
189
|
+
off();
|
|
190
|
+
dropDown.classList.add("hide");
|
|
191
|
+
};
|
|
192
|
+
parentNode.appendChild(dropDown);
|
|
193
|
+
parentNode.addEventListener("keydown", (e) => {
|
|
194
|
+
if (!trigger || !(e instanceof KeyboardEvent))
|
|
195
|
+
return;
|
|
196
|
+
const { key } = e;
|
|
197
|
+
if (key === "Enter") {
|
|
198
|
+
replace();
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (["ArrowDown", "ArrowUp"].includes(key)) {
|
|
202
|
+
const next = key === "ArrowDown" ? ($active == null ? void 0 : $active.nextElementSibling) || dropDown.firstElementChild : ($active == null ? void 0 : $active.previousElementSibling) || dropDown.lastElementChild;
|
|
203
|
+
if ($active) {
|
|
204
|
+
$active.classList.remove("active");
|
|
205
|
+
}
|
|
206
|
+
if (!next)
|
|
207
|
+
return;
|
|
208
|
+
next.classList.add("active");
|
|
209
|
+
$active = next;
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
parentNode.addEventListener("mousedown", (e) => {
|
|
214
|
+
if (!trigger)
|
|
215
|
+
return;
|
|
216
|
+
e.stopPropagation();
|
|
217
|
+
off();
|
|
218
|
+
dropDown.classList.add("hide");
|
|
219
|
+
});
|
|
220
|
+
return {
|
|
221
|
+
update: (view) => {
|
|
222
|
+
if (!trigger) {
|
|
223
|
+
dropDown.classList.add("hide");
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
const result = search(_search).slice(0, 5);
|
|
227
|
+
const { node } = view.domAtPos(_from);
|
|
228
|
+
if (result.length === 0 || !node) {
|
|
229
|
+
dropDown.classList.add("hide");
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
dropDown.classList.remove("hide");
|
|
233
|
+
renderDropdownList(result, dropDown, $active, replace, (a) => {
|
|
234
|
+
$active = a;
|
|
235
|
+
});
|
|
236
|
+
calculateNodePosition(view, dropDown, (selected, target, parent) => {
|
|
237
|
+
const start = view.coordsAtPos(_from);
|
|
238
|
+
let left = start.left - parent.left;
|
|
239
|
+
let top = selected.bottom - parent.top + 14;
|
|
240
|
+
if (left < 0) {
|
|
241
|
+
left = 0;
|
|
242
|
+
}
|
|
243
|
+
if (window.innerHeight - start.bottom < target.height) {
|
|
244
|
+
top = selected.top - parent.top - target.height - 14;
|
|
245
|
+
}
|
|
246
|
+
return [top, left];
|
|
247
|
+
});
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
};
|
|
254
|
+
const keyword = ":emoji:";
|
|
255
|
+
const checkTrigger = (view, from, to, text, setRange) => {
|
|
256
|
+
if (view.composing)
|
|
257
|
+
return false;
|
|
258
|
+
const { state } = view;
|
|
259
|
+
const $from = state.doc.resolve(from);
|
|
260
|
+
if ($from.parent.type.spec.code)
|
|
261
|
+
return false;
|
|
262
|
+
const textBefore = $from.parent.textBetween($from.parentOffset - keyword.length + 1, $from.parentOffset, void 0, "\uFFFC") + text;
|
|
263
|
+
if (textBefore === keyword) {
|
|
264
|
+
setRange(from - keyword.length + 1, to + 1);
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
return false;
|
|
268
|
+
};
|
|
269
|
+
const picker = (utils) => {
|
|
270
|
+
let trigger = false;
|
|
271
|
+
const holder = document.createElement("span");
|
|
272
|
+
let _from = 0;
|
|
273
|
+
let _to = 0;
|
|
274
|
+
const off = () => {
|
|
275
|
+
trigger = false;
|
|
276
|
+
_from = 0;
|
|
277
|
+
_to = 0;
|
|
278
|
+
};
|
|
279
|
+
const plugin = new Plugin({
|
|
280
|
+
props: {
|
|
281
|
+
handleKeyDown() {
|
|
282
|
+
off();
|
|
283
|
+
return false;
|
|
284
|
+
},
|
|
285
|
+
handleClick() {
|
|
286
|
+
off();
|
|
287
|
+
return false;
|
|
288
|
+
},
|
|
289
|
+
handleTextInput(view, from, to, text) {
|
|
290
|
+
trigger = checkTrigger(view, from, to, text, (from2, to2) => {
|
|
291
|
+
_from = from2;
|
|
292
|
+
_to = to2;
|
|
293
|
+
});
|
|
294
|
+
if (!trigger) {
|
|
295
|
+
off();
|
|
296
|
+
}
|
|
297
|
+
return false;
|
|
298
|
+
},
|
|
299
|
+
decorations(state) {
|
|
300
|
+
if (!trigger)
|
|
301
|
+
return null;
|
|
302
|
+
return DecorationSet.create(state.doc, [Decoration.widget(state.selection.to, holder)]);
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
view: (editorView) => {
|
|
306
|
+
const { parentNode } = editorView.dom;
|
|
307
|
+
if (!parentNode) {
|
|
308
|
+
throw new Error();
|
|
309
|
+
}
|
|
310
|
+
utils.getStyle(({ palette, font }) => {
|
|
311
|
+
const css2 = injectGlobal;
|
|
312
|
+
css2`
|
|
313
|
+
.emoji-picker {
|
|
314
|
+
--dark-search-background-color: ${palette("surface")} !important;
|
|
315
|
+
--dark-text-color: ${palette("neutral", 0.87)} !important;
|
|
316
|
+
--dark-background-color: ${palette("background")} !important;
|
|
317
|
+
--dark-border-color: ${palette("shadow")} !important;
|
|
318
|
+
--dark-hover-color: ${palette("secondary", 0.12)} !important;
|
|
319
|
+
--dark-blue-color: ${palette("primary")} !important;
|
|
320
|
+
--dark-search-icon-color: ${palette("primary")} !important;
|
|
321
|
+
--dark-category-button-color: ${palette("secondary", 0.4)} !important;
|
|
322
|
+
--font: ${font.typography} !important;
|
|
323
|
+
--font-size: 1rem !important;
|
|
324
|
+
}
|
|
325
|
+
`;
|
|
326
|
+
});
|
|
327
|
+
const emojiPicker = new EmojiButton({
|
|
328
|
+
rootElement: parentNode,
|
|
329
|
+
autoFocusSearch: false,
|
|
330
|
+
style: "twemoji",
|
|
331
|
+
theme: "dark",
|
|
332
|
+
zIndex: 99
|
|
333
|
+
});
|
|
334
|
+
emojiPicker.on("emoji", (selection) => {
|
|
335
|
+
const start = _from;
|
|
336
|
+
const end = _to;
|
|
337
|
+
off();
|
|
338
|
+
const html = parse(selection.emoji);
|
|
339
|
+
const node = editorView.state.schema.node("emoji", { html });
|
|
340
|
+
const { tr } = editorView.state;
|
|
341
|
+
editorView.dispatch(tr.replaceRangeWith(start, end, node));
|
|
342
|
+
});
|
|
343
|
+
return {
|
|
344
|
+
update: () => {
|
|
345
|
+
if (!trigger) {
|
|
346
|
+
emojiPicker.hidePicker();
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
emojiPicker.showPicker(holder);
|
|
350
|
+
return null;
|
|
351
|
+
},
|
|
352
|
+
destroy: () => {
|
|
353
|
+
emojiPicker.destroyPicker();
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
return plugin;
|
|
359
|
+
};
|
|
360
|
+
const regex = emojiRegex();
|
|
361
|
+
const isParent = (node) => !!node.children;
|
|
362
|
+
const isLiteral = (node) => !!node.value;
|
|
363
|
+
function flatMap(ast, fn) {
|
|
364
|
+
return transform(ast, 0, null)[0];
|
|
365
|
+
function transform(node, index, parent) {
|
|
366
|
+
if (isParent(node)) {
|
|
367
|
+
const out = [];
|
|
368
|
+
for (let i = 0, n = node.children.length; i < n; i++) {
|
|
369
|
+
const xs = transform(node.children[i], i, node);
|
|
370
|
+
if (xs) {
|
|
371
|
+
for (let j = 0, m = xs.length; j < m; j++) {
|
|
372
|
+
out.push(xs[j]);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
node.children = out;
|
|
377
|
+
}
|
|
378
|
+
return fn(node, index, parent);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const twemojiPlugin = () => {
|
|
382
|
+
function transformer(tree) {
|
|
383
|
+
flatMap(tree, (node) => {
|
|
384
|
+
if (!isLiteral(node)) {
|
|
385
|
+
return [node];
|
|
386
|
+
}
|
|
387
|
+
const value = node.value;
|
|
388
|
+
const output = [];
|
|
389
|
+
let match;
|
|
390
|
+
let str = value;
|
|
391
|
+
while (match = regex.exec(str)) {
|
|
392
|
+
const { index } = match;
|
|
393
|
+
const emoji2 = match[0];
|
|
394
|
+
if (index > 0) {
|
|
395
|
+
output.push(__spreadProps(__spreadValues({}, node), { value: str.slice(0, index) }));
|
|
396
|
+
}
|
|
397
|
+
output.push(__spreadProps(__spreadValues({}, node), { value: parse(emoji2), type: "emoji" }));
|
|
398
|
+
str = str.slice(index + emoji2.length);
|
|
399
|
+
}
|
|
400
|
+
if (str.length) {
|
|
401
|
+
output.push(__spreadProps(__spreadValues({}, node), { value: str }));
|
|
402
|
+
}
|
|
403
|
+
return output;
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
return transformer;
|
|
407
|
+
};
|
|
408
|
+
const emojiNode = createNode((utils) => {
|
|
409
|
+
const style = utils.getStyle(() => css`
|
|
410
|
+
display: inline-flex;
|
|
411
|
+
justify-content: center;
|
|
412
|
+
align-items: center;
|
|
413
|
+
|
|
414
|
+
.emoji {
|
|
415
|
+
height: 1em;
|
|
416
|
+
width: 1em;
|
|
417
|
+
margin: 0 0.05em 0 0.1em;
|
|
418
|
+
vertical-align: -0.1em;
|
|
419
|
+
}
|
|
420
|
+
`);
|
|
421
|
+
return {
|
|
422
|
+
id: "emoji",
|
|
423
|
+
schema: () => ({
|
|
424
|
+
group: "inline",
|
|
425
|
+
inline: true,
|
|
426
|
+
selectable: false,
|
|
427
|
+
attrs: {
|
|
428
|
+
html: {
|
|
429
|
+
default: ""
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
parseDOM: [
|
|
433
|
+
{
|
|
434
|
+
tag: 'span[data-type="emoji"]',
|
|
435
|
+
getAttrs: (dom) => {
|
|
436
|
+
if (!(dom instanceof HTMLElement)) {
|
|
437
|
+
throw new Error();
|
|
438
|
+
}
|
|
439
|
+
return { html: dom.innerHTML };
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
],
|
|
443
|
+
toDOM: (node) => {
|
|
444
|
+
const span = document.createElement("span");
|
|
445
|
+
span.dataset.type = "emoji";
|
|
446
|
+
if (style) {
|
|
447
|
+
span.classList.add(style);
|
|
448
|
+
}
|
|
449
|
+
span.classList.add("emoji-wrapper");
|
|
450
|
+
span.innerHTML = node.attrs.html;
|
|
451
|
+
return { dom: span };
|
|
452
|
+
},
|
|
453
|
+
parseMarkdown: {
|
|
454
|
+
match: ({ type }) => type === "emoji",
|
|
455
|
+
runner: (state, node, type) => {
|
|
456
|
+
state.addNode(type, { html: node.value });
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
toMarkdown: {
|
|
460
|
+
match: (node) => node.type.name === "emoji",
|
|
461
|
+
runner: (state, node) => {
|
|
462
|
+
const span = document.createElement("span");
|
|
463
|
+
span.innerHTML = node.attrs.html;
|
|
464
|
+
const img = span.querySelector("img");
|
|
465
|
+
const title = img == null ? void 0 : img.title;
|
|
466
|
+
span.remove();
|
|
467
|
+
state.addNode("text", void 0, title);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}),
|
|
471
|
+
inputRules: (nodeType) => [
|
|
472
|
+
new InputRule(input, (state, match, start, end) => {
|
|
473
|
+
const content = match[0];
|
|
474
|
+
if (!content)
|
|
475
|
+
return null;
|
|
476
|
+
const got = nodeEmoji.get(content);
|
|
477
|
+
if (!got || content.includes(got))
|
|
478
|
+
return null;
|
|
479
|
+
const html = parse(got);
|
|
480
|
+
return state.tr.setMeta("emoji", true).replaceRangeWith(start, end, nodeType.create({ html })).scrollIntoView();
|
|
481
|
+
})
|
|
482
|
+
],
|
|
483
|
+
remarkPlugins: () => [remarkEmoji, twemojiPlugin],
|
|
484
|
+
prosePlugins: () => [picker(utils), filter(utils)]
|
|
485
|
+
};
|
|
486
|
+
});
|
|
487
|
+
const emoji = AtomList.create([emojiNode()]);
|
|
488
|
+
export { emoji, emojiNode };
|
|
489
|
+
//# sourceMappingURL=index.es.js.map
|