mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-27 01:13:27 +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 { RefAction, RefInputActionItem, TextEditorHandler, TextFormatCategory } from '../types'
|
||||||
import TextEditor from './TextEditor.svelte'
|
import TextEditor from './TextEditor.svelte'
|
||||||
import { completionConfig } from './extensions'
|
import { completionConfig } from './extensions'
|
||||||
|
import { EmojiExtension } from './extension/emoji'
|
||||||
import Attach from './icons/Attach.svelte'
|
import Attach from './icons/Attach.svelte'
|
||||||
import RIMention from './icons/RIMention.svelte'
|
import RIMention from './icons/RIMention.svelte'
|
||||||
import Send from './icons/Send.svelte'
|
import Send from './icons/Send.svelte'
|
||||||
@ -177,7 +178,7 @@
|
|||||||
updateFocus()
|
updateFocus()
|
||||||
dispatch('focus', focused)
|
dispatch('focus', focused)
|
||||||
}}
|
}}
|
||||||
extensions={[completionPlugin]}
|
extensions={[completionPlugin, EmojiExtension.configure()]}
|
||||||
on:update
|
on:update
|
||||||
placeholder={placeholder ?? textEditorPlugin.string.EditorPlaceholder}
|
placeholder={placeholder ?? textEditorPlugin.string.EditorPlaceholder}
|
||||||
textFormatCategories={[
|
textFormatCategories={[
|
||||||
|
@ -13,10 +13,15 @@
|
|||||||
resizeObserver
|
resizeObserver
|
||||||
} from '@hcengineering/ui'
|
} from '@hcengineering/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
|
import type { AnyExtension } from '@tiptap/core'
|
||||||
|
|
||||||
import { Completion } from '../Completion'
|
import { Completion } from '../Completion'
|
||||||
import textEditorPlugin from '../plugin'
|
import textEditorPlugin from '../plugin'
|
||||||
import StyledTextEditor from './StyledTextEditor.svelte'
|
import StyledTextEditor from './StyledTextEditor.svelte'
|
||||||
|
|
||||||
import { completionConfig } from './extensions'
|
import { completionConfig } from './extensions'
|
||||||
|
import { EmojiExtension } from './extension/emoji'
|
||||||
|
|
||||||
import { ImageRef, FileAttachFunction } from './imageExt'
|
import { ImageRef, FileAttachFunction } from './imageExt'
|
||||||
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||||
|
|
||||||
@ -38,6 +43,7 @@
|
|||||||
export let enableFormatting = false
|
export let enableFormatting = false
|
||||||
export let autofocus = false
|
export let autofocus = false
|
||||||
export let enableBackReferences: boolean = false
|
export let enableBackReferences: boolean = false
|
||||||
|
export let enableEmojiReplace: boolean = true
|
||||||
export let isScrollable: boolean = true
|
export let isScrollable: boolean = true
|
||||||
|
|
||||||
export let attachFile: FileAttachFunction | undefined = undefined
|
export let attachFile: FileAttachFunction | undefined = undefined
|
||||||
@ -136,24 +142,9 @@
|
|||||||
focusManager?.setFocus(idx)
|
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 attachments = new Map<string, ProseMirrorNode>()
|
||||||
|
|
||||||
const imagePlugin = ImageRef.configure({
|
|
||||||
inline: true,
|
|
||||||
HTMLAttributes: {},
|
|
||||||
attachFile,
|
|
||||||
reportNode: (id, node) => {
|
|
||||||
attachments.set(id, node)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@ -163,6 +154,36 @@
|
|||||||
textEditor.removeNode(nde)
|
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>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
@ -195,7 +216,7 @@
|
|||||||
{enableFormatting}
|
{enableFormatting}
|
||||||
{autofocus}
|
{autofocus}
|
||||||
{isScrollable}
|
{isScrollable}
|
||||||
extensions={enableBackReferences ? [completionPlugin, imagePlugin] : [imagePlugin]}
|
{extensions}
|
||||||
bind:content={rawValue}
|
bind:content={rawValue}
|
||||||
bind:this={textEditor}
|
bind:this={textEditor}
|
||||||
on:attach
|
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