diff --git a/demos/src/Examples/Savvy/React/ColorHighlighter.ts b/demos/src/Examples/Savvy/React/ColorHighlighter.ts new file mode 100644 index 00000000..33bf722c --- /dev/null +++ b/demos/src/Examples/Savvy/React/ColorHighlighter.ts @@ -0,0 +1,27 @@ +import { Extension } from '@tiptap/core' +import { Plugin } from 'prosemirror-state' +import findColors from './findColors' + +export const ColorHighlighter = Extension.create({ + name: 'colorHighlighter', + + addProseMirrorPlugins() { + return [ + new Plugin({ + state: { + init(_, { doc }) { + return findColors(doc) + }, + apply(transaction, oldState) { + return transaction.docChanged ? findColors(transaction.doc) : oldState + }, + }, + props: { + decorations(state) { + return this.getState(state) + }, + }, + }), + ] + }, +}) diff --git a/demos/src/Examples/Savvy/React/SmilieReplacer.ts b/demos/src/Examples/Savvy/React/SmilieReplacer.ts new file mode 100644 index 00000000..1c0a6944 --- /dev/null +++ b/demos/src/Examples/Savvy/React/SmilieReplacer.ts @@ -0,0 +1,133 @@ +import { Extension, textInputRule } from '@tiptap/core' + +export const SmilieReplacer = Extension.create({ + name: 'smilieReplacer', + + addInputRules() { + return [ + textInputRule({ find: /-___- $/, replace: '๐ ' }), + textInputRule({ find: /:'-\) $/, replace: '๐ ' }), + textInputRule({ find: /':-\) $/, replace: '๐ ' }), + textInputRule({ find: /':-D $/, replace: '๐ ' }), + textInputRule({ find: />:-\) $/, replace: '๐ ' }), + textInputRule({ find: /-__- $/, replace: '๐ ' }), + textInputRule({ find: /':-\( $/, replace: '๐ ' }), + textInputRule({ find: /:'-\( $/, replace: '๐ข ' }), + textInputRule({ find: />:-\( $/, replace: '๐ ' }), + textInputRule({ find: /O:-\) $/, replace: '๐ ' }), + textInputRule({ find: /0:-3 $/, replace: '๐ ' }), + textInputRule({ find: /0:-\) $/, replace: '๐ ' }), + textInputRule({ find: /0;\^\) $/, replace: '๐ ' }), + textInputRule({ find: /O;-\) $/, replace: '๐ ' }), + textInputRule({ find: /0;-\) $/, replace: '๐ ' }), + textInputRule({ find: /O:-3 $/, replace: '๐ ' }), + textInputRule({ find: /:'\) $/, replace: '๐ ' }), + textInputRule({ find: /:-D $/, replace: '๐ ' }), + textInputRule({ find: /':\) $/, replace: '๐ ' }), + textInputRule({ find: /'=\) $/, replace: '๐ ' }), + textInputRule({ find: /':D $/, replace: '๐ ' }), + textInputRule({ find: /'=D $/, replace: '๐ ' }), + textInputRule({ find: />:\) $/, replace: '๐ ' }), + textInputRule({ find: />;\) $/, replace: '๐ ' }), + textInputRule({ find: />=\) $/, replace: '๐ ' }), + textInputRule({ find: /;-\) $/, replace: '๐ ' }), + textInputRule({ find: /\*-\) $/, replace: '๐ ' }), + textInputRule({ find: /;-\] $/, replace: '๐ ' }), + textInputRule({ find: /;\^\) $/, replace: '๐ ' }), + textInputRule({ find: /B-\) $/, replace: '๐ ' }), + textInputRule({ find: /8-\) $/, replace: '๐ ' }), + textInputRule({ find: /B-D $/, replace: '๐ ' }), + textInputRule({ find: /8-D $/, replace: '๐ ' }), + textInputRule({ find: /:-\* $/, replace: '๐ ' }), + textInputRule({ find: /:\^\* $/, replace: '๐ ' }), + textInputRule({ find: /:-\) $/, replace: '๐ ' }), + textInputRule({ find: /-_- $/, replace: '๐ ' }), + textInputRule({ find: /:-X $/, replace: '๐ถ ' }), + textInputRule({ find: /:-# $/, replace: '๐ถ ' }), + textInputRule({ find: /:-x $/, replace: '๐ถ ' }), + textInputRule({ find: />.< $/, replace: '๐ฃ ' }), + textInputRule({ find: /:-O $/, replace: '๐ฎ ' }), + textInputRule({ find: /:-o $/, replace: '๐ฎ ' }), + textInputRule({ find: /O_O $/, replace: '๐ฎ ' }), + textInputRule({ find: />:O $/, replace: '๐ฎ ' }), + textInputRule({ find: /:-P $/, replace: '๐ ' }), + textInputRule({ find: /:-p $/, replace: '๐ ' }), + textInputRule({ find: /:-ร $/, replace: '๐ ' }), + textInputRule({ find: /:-รพ $/, replace: '๐ ' }), + textInputRule({ find: /:-b $/, replace: '๐ ' }), + textInputRule({ find: />:P $/, replace: '๐ ' }), + textInputRule({ find: /X-P $/, replace: '๐ ' }), + textInputRule({ find: /x-p $/, replace: '๐ ' }), + textInputRule({ find: /':\( $/, replace: '๐ ' }), + textInputRule({ find: /'=\( $/, replace: '๐ ' }), + textInputRule({ find: />:\\ $/, replace: '๐ ' }), + textInputRule({ find: />:\/ $/, replace: '๐ ' }), + textInputRule({ find: /:-\/ $/, replace: '๐ ' }), + textInputRule({ find: /:-. $/, replace: '๐ ' }), + textInputRule({ find: />:\[ $/, replace: '๐ ' }), + textInputRule({ find: /:-\( $/, replace: '๐ ' }), + textInputRule({ find: /:-\[ $/, replace: '๐ ' }), + textInputRule({ find: /:'\( $/, replace: '๐ข ' }), + textInputRule({ find: /;-\( $/, replace: '๐ข ' }), + textInputRule({ find: /#-\) $/, replace: '๐ต ' }), + textInputRule({ find: /%-\) $/, replace: '๐ต ' }), + textInputRule({ find: /X-\) $/, replace: '๐ต ' }), + textInputRule({ find: />:\( $/, replace: '๐ ' }), + textInputRule({ find: /0:3 $/, replace: '๐ ' }), + textInputRule({ find: /0:\) $/, replace: '๐ ' }), + textInputRule({ find: /O:\) $/, replace: '๐ ' }), + textInputRule({ find: /O=\) $/, replace: '๐ ' }), + textInputRule({ find: /O:3 $/, replace: '๐ ' }), + textInputRule({ find: /<\/3 $/, replace: '๐ ' }), + textInputRule({ find: /:D $/, replace: '๐ ' }), + textInputRule({ find: /=D $/, replace: '๐ ' }), + textInputRule({ find: /;\) $/, replace: '๐ ' }), + textInputRule({ find: /\*\) $/, replace: '๐ ' }), + textInputRule({ find: /;\] $/, replace: '๐ ' }), + textInputRule({ find: /;D $/, replace: '๐ ' }), + textInputRule({ find: /B\) $/, replace: '๐ ' }), + textInputRule({ find: /8\) $/, replace: '๐ ' }), + textInputRule({ find: /:\* $/, replace: '๐ ' }), + textInputRule({ find: /=\* $/, replace: '๐ ' }), + textInputRule({ find: /:\) $/, replace: '๐ ' }), + textInputRule({ find: /=\] $/, replace: '๐ ' }), + textInputRule({ find: /=\) $/, replace: '๐ ' }), + textInputRule({ find: /:\] $/, replace: '๐ ' }), + textInputRule({ find: /:X $/, replace: '๐ถ ' }), + textInputRule({ find: /:# $/, replace: '๐ถ ' }), + textInputRule({ find: /=X $/, replace: '๐ถ ' }), + textInputRule({ find: /=x $/, replace: '๐ถ ' }), + textInputRule({ find: /:x $/, replace: '๐ถ ' }), + textInputRule({ find: /=# $/, replace: '๐ถ ' }), + textInputRule({ find: /:O $/, replace: '๐ฎ ' }), + textInputRule({ find: /:o $/, replace: '๐ฎ ' }), + textInputRule({ find: /:P $/, replace: '๐ ' }), + textInputRule({ find: /=P $/, replace: '๐ ' }), + textInputRule({ find: /:p $/, replace: '๐ ' }), + textInputRule({ find: /=p $/, replace: '๐ ' }), + textInputRule({ find: /:ร $/, replace: '๐ ' }), + textInputRule({ find: /:รพ $/, replace: '๐ ' }), + textInputRule({ find: /:b $/, replace: '๐ ' }), + textInputRule({ find: /d: $/, replace: '๐ ' }), + textInputRule({ find: /:\/ $/, replace: '๐ ' }), + textInputRule({ find: /:\\ $/, replace: '๐ ' }), + textInputRule({ find: /=\/ $/, replace: '๐ ' }), + textInputRule({ find: /=\\ $/, replace: '๐ ' }), + textInputRule({ find: /:L $/, replace: '๐ ' }), + textInputRule({ find: /=L $/, replace: '๐ ' }), + textInputRule({ find: /:\( $/, replace: '๐ ' }), + textInputRule({ find: /:\[ $/, replace: '๐ ' }), + textInputRule({ find: /=\( $/, replace: '๐ ' }), + textInputRule({ find: /;\( $/, replace: '๐ข ' }), + textInputRule({ find: /D: $/, replace: '๐จ ' }), + textInputRule({ find: /:\$ $/, replace: '๐ณ ' }), + textInputRule({ find: /=\$ $/, replace: '๐ณ ' }), + textInputRule({ find: /#\) $/, replace: '๐ต ' }), + textInputRule({ find: /%\) $/, replace: '๐ต ' }), + textInputRule({ find: /X\) $/, replace: '๐ต ' }), + textInputRule({ find: /:@ $/, replace: '๐ ' }), + textInputRule({ find: /<3 $/, replace: 'โค๏ธ ' }), + textInputRule({ find: /\/shrug $/, replace: 'ยฏ\\_(ใ)_/ยฏ' }), + ] + }, +}) diff --git a/demos/src/Examples/Savvy/React/findColors.ts b/demos/src/Examples/Savvy/React/findColors.ts new file mode 100644 index 00000000..dd6be4ba --- /dev/null +++ b/demos/src/Examples/Savvy/React/findColors.ts @@ -0,0 +1,28 @@ +import { Decoration, DecorationSet } from 'prosemirror-view' +import { Node } from 'prosemirror-model' + +export default function (doc: Node): DecorationSet { + const hexColor = /(#[0-9a-f]{3,6})\b/gi + const decorations: Decoration[] = [] + + doc.descendants((node, position) => { + if (!node.text) { + return + } + + Array.from(node.text.matchAll(hexColor)).forEach(match => { + const color = match[0] + const index = match.index || 0 + const from = position + index + const to = from + color.length + const decoration = Decoration.inline(from, to, { + class: 'color', + style: `--color: ${color}`, + }) + + decorations.push(decoration) + }) + }) + + return DecorationSet.create(doc, decorations) +} diff --git a/demos/src/Examples/Savvy/React/index.html b/demos/src/Examples/Savvy/React/index.html new file mode 100644 index 00000000..c44f2578 --- /dev/null +++ b/demos/src/Examples/Savvy/React/index.html @@ -0,0 +1,15 @@ + + +
+ + + + + + + + diff --git a/demos/src/Examples/Savvy/React/index.jsx b/demos/src/Examples/Savvy/React/index.jsx new file mode 100644 index 00000000..37b8fcbf --- /dev/null +++ b/demos/src/Examples/Savvy/React/index.jsx @@ -0,0 +1,38 @@ +import React from 'react' +import { useEditor, EditorContent } from '@tiptap/react' +import Document from '@tiptap/extension-document' +import Paragraph from '@tiptap/extension-paragraph' +import Text from '@tiptap/extension-text' +import Code from '@tiptap/extension-code' +import Typography from '@tiptap/extension-typography' +import { ColorHighlighter } from './ColorHighlighter' +import { SmilieReplacer } from './SmilieReplacer' +import './styles.scss' + +export default () => { + const editor = useEditor({ + extensions: [Document, Paragraph, Text, Code, Typography, ColorHighlighter, SmilieReplacer], + content: ` ++ โ With the Typography extension, tiptap understands ยปwhat you meanยซ and adds correct characters to your text โ itโs like a โtypography nerdโ on your side. +
+
+ Try it out and type (c), ->, >>, 1/2, !=, -- or 1x1 here:
+
+ Or add completely custom input rules. We added a custom extension here that replaces smilies like :-), <3 or >:P with emojis. Try it out:
+
+ You can also teach the editor new things. For example to recognize hex colors and add a color swatch on the fly: #FFF, #0D0D0D, #616161, #A975FF, #FB5151, #FD9170, #FFCB6B, #68CEF8, #80cbc4, #9DEF8F +
+ `, + }) + + if (!editor) { + return null + } + + return