import Link from "@tiptap/extension-link"; import {Editor} from "@tiptap/core"; import StarterKit from "@tiptap/starter-kit"; import Underline from "@tiptap/extension-underline"; import Highlight from "@tiptap/extension-highlight"; import TextAlign from "@tiptap/extension-text-align"; import Typography from "@tiptap/extension-typography"; import {ColorHighlighter} from "./ColourHighter.js"; import {SmileyReplacer} from "./SmileyReplacer.js"; import {Small} from "./Small.js"; import {ExtraSmall} from "./ExtraSmall.js"; import {Box} from "./Box.js"; const editorToggleLink = (editor) => { const previousUrl = editor.getAttributes('link').href const url = window.prompt('URL', previousUrl) if (url === null) { return } if (url === '') { editor.chain().focus().extendMarkRange('link').unsetLink().run() return } editor.chain().focus().extendMarkRange('link').setLink({ href: url }).run() } const CustomLink = Link.extend({ addKeyboardShortcuts() { return { 'Mod-k': () => editorToggleLink(this.editor), 'Mod-Alt-4': () => this.editor.chain().setSmall().focus().run(), 'Mod-Alt-5': () => this.editor.chain().setExtraSmall().focus().run(), } } }); document.addEventListener('alpine:init', () => { Alpine.data('editor', (content) => { let editor // Alpine's reactive engine automatically wraps component properties in proxy objects. Attempting to use a proxied editor instance to apply a transaction will cause a "Range Error: Applying a mismatched transaction", so be sure to unwrap it using Alpine.raw(), or simply avoid storing your editor as a component property, as shown in this example. return { updatedAt: Date.now(), // force Alpine to rerender on selection change content: SM.decodeHtml(content), init() { const _this = this editor = new Editor({ element: this.$refs.element, extensions: [ StarterKit.configure({ link: false, underline: false, }), Highlight, CustomLink.configure({ rel: 'noopener noreferrer', openOnClick: 'whenNotEditable', }), Underline, TextAlign.configure({ types: ['heading', 'paragraph', 'small', 'extraSmall'], }), Typography, ColorHighlighter, SmileyReplacer, Small, ExtraSmall, Box ], editorProps: { attributes: { class: 'tiptap content', }, }, content: content, onCreate({/* editor */}) { _this.updatedAt = Date.now() }, onUpdate({editor}) { _this.updatedAt = Date.now() _this.content = editor.getHTML() }, onSelectionUpdate({/* editor */}) { _this.updatedAt = Date.now() } }) }, isLoaded() { return editor }, isActive(type, opts = {}) { return editor.isActive(type, opts) }, toggleHeading(opts) { editor.chain().toggleHeading(opts).focus().run() }, toggleBold() { editor.chain().toggleBold().focus().run() }, toggleItalic() { editor.chain().toggleItalic().focus().run() }, toggleUnderline() { editor.chain().toggleUnderline().focus().run() }, toggleStrike() { editor.chain().toggleStrike().focus().run() }, setParagraph() { editor.chain().setParagraph().focus().run() }, toggleCode() { editor.chain().toggleCode().focus().run() }, toggleBulletList() { editor.chain().toggleBulletList().focus().run() }, toggleOrderedList() { editor.chain().toggleOrderedList().focus().run() }, toggleBlockquote() { editor.chain().toggleBlockquote().focus().run() }, toggleCodeBlock() { editor.chain().toggleCodeBlock().focus().run() }, toggleLink() { editorToggleLink(editor) }, clearLink() { editor.chain().focus().extendMarkRange('link').unsetLink().run() }, toggleHighlight() { editor.chain().toggleHighlight().focus().run() }, toggleSubscript() { editor.chain().toggleSubscript().focus().run() }, toggleSuperscript() { editor.chain().toggleSuperscript().focus().run() }, undo() { editor.chain().undo().focus().run() }, redo() { editor.chain().redo().focus().run() }, unsetAllMarks() { editor.chain().focus().unsetAllMarks().run() }, clearNodes() { editor.chain().focus().clearNodes().run() }, clearNotes() { editor.chain().focus().clearNodes().run() }, setTextAlign(value) { editor.chain().setTextAlign(value).focus().run() }, setSmall() { editor.chain().focus().setSmall().run() }, setExtraSmall() { editor.chain().focus().setExtraSmall().run() }, toggleBox(opts) { editor.chain().toggleBox(opts).focus().run() }, } }) })