1
0
elk/composables/tiptap/emoji.ts

90 lines
1.6 KiB
TypeScript
Raw Normal View History

import {
Node,
mergeAttributes,
nodeInputRule,
nodePasteRule,
} from '@tiptap/core'
import { emojiRegEx, getEmojiAttributes } from '~/config/emojis'
const createEmojiRule = <NR extends typeof nodeInputRule | typeof nodePasteRule>(
nodeRule: NR,
type: Parameters<NR>[0]['type'],
): ReturnType<NR>[] => {
const rule = nodeRule({
find: emojiRegEx as RegExp,
type,
getAttributes: (match) => {
const [native] = match
return getEmojiAttributes(native)
},
}) as ReturnType<NR>
// Error catch for unsupported emoji
const handler = rule.handler.bind(rule)
rule.handler = (...args) => {
try {
return handler(...args)
}
catch (e) {
return null
}
}
return [
rule,
]
}
2023-01-16 20:40:47 +09:00
export const TiptapPluginEmoji = Node.create({
2022-12-28 04:13:50 +09:00
name: 'em-emoji',
2022-12-28 04:13:50 +09:00
inline: () => true,
group: () => 'inline',
draggable: false,
2022-12-28 04:13:50 +09:00
parseHTML() {
return [
{
tag: 'img.iconify-emoji',
2022-12-28 04:13:50 +09:00
},
]
},
addAttributes() {
return {
alt: {
default: null,
},
src: {
default: null,
},
class: {
2022-12-28 05:42:58 +09:00
default: null,
},
}
},
2022-12-28 04:13:50 +09:00
renderHTML(args) {
return ['img', mergeAttributes(this.options.HTMLAttributes, args.HTMLAttributes)]
},
addCommands() {
return {
insertEmoji: code => ({ commands }) => {
return commands.insertContent({
type: this.name,
attrs: getEmojiAttributes(code),
})
},
}
},
addInputRules() {
return createEmojiRule(nodeInputRule, this.type)
},
addPasteRules() {
return createEmojiRule(nodePasteRule, this.type)
},
})