mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-23 05:53:09 +03:00
UBERF-17: Missing smiles auto-conversion in rich texts :) (#3771)
Signed-off-by: Maxim Karmatskikh <mkarmatskih@gmail.com>
This commit is contained in:
parent
3c42b948ac
commit
56f0dc573d
@ -34,6 +34,7 @@
|
||||
import { RefAction, RefInputActionItem, TextEditorHandler, TextFormatCategory } from '../types'
|
||||
import TextEditor from './TextEditor.svelte'
|
||||
import { completionConfig } from './extensions'
|
||||
import { EmojiExtension } from './extension/emoji'
|
||||
import Attach from './icons/Attach.svelte'
|
||||
import RIMention from './icons/RIMention.svelte'
|
||||
import Send from './icons/Send.svelte'
|
||||
@ -177,7 +178,7 @@
|
||||
updateFocus()
|
||||
dispatch('focus', focused)
|
||||
}}
|
||||
extensions={[completionPlugin]}
|
||||
extensions={[completionPlugin, EmojiExtension.configure()]}
|
||||
on:update
|
||||
placeholder={placeholder ?? textEditorPlugin.string.EditorPlaceholder}
|
||||
textFormatCategories={[
|
||||
|
@ -13,10 +13,15 @@
|
||||
resizeObserver
|
||||
} from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import type { AnyExtension } from '@tiptap/core'
|
||||
|
||||
import { Completion } from '../Completion'
|
||||
import textEditorPlugin from '../plugin'
|
||||
import StyledTextEditor from './StyledTextEditor.svelte'
|
||||
|
||||
import { completionConfig } from './extensions'
|
||||
import { EmojiExtension } from './extension/emoji'
|
||||
|
||||
import { ImageRef, FileAttachFunction } from './imageExt'
|
||||
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||
|
||||
@ -38,6 +43,7 @@
|
||||
export let enableFormatting = false
|
||||
export let autofocus = false
|
||||
export let enableBackReferences: boolean = false
|
||||
export let enableEmojiReplace: boolean = true
|
||||
export let isScrollable: boolean = true
|
||||
|
||||
export let attachFile: FileAttachFunction | undefined = undefined
|
||||
@ -136,24 +142,9 @@
|
||||
focusManager?.setFocus(idx)
|
||||
}
|
||||
}
|
||||
const completionPlugin = Completion.configure({
|
||||
...completionConfig,
|
||||
showDoc (event: MouseEvent, _id: string, _class: string) {
|
||||
dispatch('open-document', { event, _id, _class })
|
||||
}
|
||||
})
|
||||
|
||||
const attachments = new Map<string, ProseMirrorNode>()
|
||||
|
||||
const imagePlugin = ImageRef.configure({
|
||||
inline: true,
|
||||
HTMLAttributes: {},
|
||||
attachFile,
|
||||
reportNode: (id, node) => {
|
||||
attachments.set(id, node)
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@ -163,6 +154,36 @@
|
||||
textEditor.removeNode(nde)
|
||||
}
|
||||
}
|
||||
|
||||
function configureExtensions () {
|
||||
const imagePlugin = ImageRef.configure({
|
||||
inline: true,
|
||||
HTMLAttributes: {},
|
||||
attachFile,
|
||||
reportNode: (id, node) => {
|
||||
attachments.set(id, node)
|
||||
}
|
||||
})
|
||||
|
||||
const completionPlugin = Completion.configure({
|
||||
...completionConfig,
|
||||
showDoc (event: MouseEvent, _id: string, _class: string) {
|
||||
dispatch('open-document', { event, _id, _class })
|
||||
}
|
||||
})
|
||||
|
||||
const extensions: AnyExtension[] = [imagePlugin]
|
||||
if (enableBackReferences) {
|
||||
extensions.unshift(completionPlugin)
|
||||
}
|
||||
if (enableEmojiReplace) {
|
||||
extensions.push(EmojiExtension.configure())
|
||||
}
|
||||
|
||||
return extensions
|
||||
}
|
||||
|
||||
const extensions = configureExtensions()
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
@ -195,7 +216,7 @@
|
||||
{enableFormatting}
|
||||
{autofocus}
|
||||
{isScrollable}
|
||||
extensions={enableBackReferences ? [completionPlugin, imagePlugin] : [imagePlugin]}
|
||||
{extensions}
|
||||
bind:content={rawValue}
|
||||
bind:this={textEditor}
|
||||
on:attach
|
||||
|
80
packages/text-editor/src/components/extension/emoji.ts
Normal file
80
packages/text-editor/src/components/extension/emoji.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import { Extension } from '@tiptap/core'
|
||||
|
||||
const emojiReplaceDict = {
|
||||
'0:)': '😇',
|
||||
'0:-)': '😇',
|
||||
'0:-3': '😇',
|
||||
'0:3': '😇',
|
||||
'0;^)': '😇',
|
||||
'O:-)': '😇',
|
||||
'3:)': '😈',
|
||||
'3:-)': '😈',
|
||||
'}:)': '😈',
|
||||
'}:-)': '😈',
|
||||
'>:)': '😈',
|
||||
'>:-)': '😈',
|
||||
'>;)': '😈',
|
||||
':-D': '😁',
|
||||
":')": '😂',
|
||||
":'-)": '😂',
|
||||
':)': '😊',
|
||||
':-)': '😄',
|
||||
':]': '😄',
|
||||
':^)': '😄',
|
||||
':o)': '😄',
|
||||
':}': '😄',
|
||||
'*-)': '😉',
|
||||
':-,': '😉',
|
||||
';)': '😉',
|
||||
';-)': '😉',
|
||||
';-]': '😉',
|
||||
';]': '😉',
|
||||
';^)': '😉',
|
||||
':-|': '😐',
|
||||
':|': '😐',
|
||||
':(': '😞',
|
||||
':-(': '😒',
|
||||
':-<': '😒',
|
||||
':-[': '😒',
|
||||
':-c': '😒',
|
||||
':<': '😒',
|
||||
':[': '😒',
|
||||
':{': '😒',
|
||||
'%)': '😖',
|
||||
'%-)': '😖',
|
||||
':-P': '😜',
|
||||
':-p': '😜',
|
||||
';(': '😜',
|
||||
':-||': '😠',
|
||||
':-.': '😡',
|
||||
':-/': '😡',
|
||||
':/': '😐',
|
||||
":'(": '😢',
|
||||
":'-(": '😢',
|
||||
':-O': '😲',
|
||||
':-o': '😲',
|
||||
':-&': '😶',
|
||||
':-X': '😶'
|
||||
}
|
||||
|
||||
function escapeRegExp (text: string): string {
|
||||
return text.replace(/[[\]{}()*+?.\\^$|#]/g, '\\$&')
|
||||
}
|
||||
|
||||
export const EmojiExtension = Extension.create({
|
||||
addInputRules () {
|
||||
return Object.keys(emojiReplaceDict).map((pattern) => {
|
||||
return {
|
||||
find: new RegExp(escapeRegExp(pattern)),
|
||||
handler: ({ range, match, commands }) => {
|
||||
commands.insertContentAt(range, [
|
||||
{
|
||||
type: 'text',
|
||||
text: emojiReplaceDict[pattern as keyof typeof emojiReplaceDict]
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
Loading…
Reference in New Issue
Block a user