Skeleton for Image Node for Tiptap
parent
a28673c8e2
commit
ebdf9cfe41
|
|
@ -623,6 +623,14 @@
|
||||||
<img src="#{request.contextPath}/icons/cms-editor/table-split-cells.svg" />
|
<img src="#{request.contextPath}/icons/cms-editor/table-split-cells.svg" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="px-2 cms-tiptap-editor-button-row cms-tiptap-editor-media">
|
||||||
|
<button
|
||||||
|
class="btn btn-outline-dark tiptap-insert-image"
|
||||||
|
title="#{CmsAdminMessage['cms_editor.buttons.media.insert_image']}"
|
||||||
|
type="button">
|
||||||
|
<bootstrap:svgIcon icon="image" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="cms-tiptap-editor-canvas border"
|
class="cms-tiptap-editor-canvas border"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import "bootstrap";
|
import "bootstrap";
|
||||||
import * as $ from "jquery";
|
import * as $ from "jquery";
|
||||||
import { ChainedCommands, Editor } from "@tiptap/core";
|
import { ChainedCommands, Editor, Node } from "@tiptap/core";
|
||||||
import Gapcursor from "@tiptap/extension-gapcursor";
|
import Gapcursor from "@tiptap/extension-gapcursor";
|
||||||
import StarterKit from "@tiptap/starter-kit";
|
import StarterKit from "@tiptap/starter-kit";
|
||||||
import Subscript from "@tiptap/extension-subscript";
|
import Subscript from "@tiptap/extension-subscript";
|
||||||
|
|
@ -13,75 +13,46 @@ import TableHeader from "@tiptap/extension-table-header";
|
||||||
const BUTTONS: CmsEditorButton[] = [
|
const BUTTONS: CmsEditorButton[] = [
|
||||||
{
|
{
|
||||||
selector: ".tiptap-emph",
|
selector: ".tiptap-emph",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().toggleItalic().run();
|
return cmsEditor.getEditor().chain().focus().toggleItalic().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().toggleItalic().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleItalic()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-strong-emph",
|
selector: ".tiptap-strong-emph",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().toggleBold().run();
|
return cmsEditor.getEditor().chain().focus().toggleBold().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().toggleBold().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleBold()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-code",
|
selector: ".tiptap-code",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().toggleCode().run();
|
return cmsEditor.getEditor().chain().focus().toggleCode().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().toggleCode().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleCode()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-strikethrough",
|
selector: ".tiptap-strikethrough",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().toggleStrike().run();
|
return cmsEditor.getEditor().chain().focus().toggleStrike().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().toggleStrike().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleStrike()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-subscript",
|
selector: ".tiptap-subscript",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().chain().focus().toggleSubscript().run();
|
||||||
.getEditor()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleSubscript()
|
|
||||||
.run();
|
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -89,19 +60,14 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleSubscript()
|
.toggleSubscript()
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-superscript",
|
selector: ".tiptap-superscript",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().chain().focus().toggleSuperscript().run();
|
||||||
.getEditor()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleSuperscript()
|
|
||||||
.run();
|
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -109,11 +75,11 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleSuperscript()
|
.toggleSuperscript()
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-h1",
|
selector: ".tiptap-h1",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -121,7 +87,7 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.toggleHeading({ level: 1 })
|
.toggleHeading({ level: 1 })
|
||||||
.run();
|
.run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -129,11 +95,11 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleHeading({ level: 1 })
|
.toggleHeading({ level: 1 })
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-h2",
|
selector: ".tiptap-h2",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -141,7 +107,7 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.toggleHeading({ level: 2 })
|
.toggleHeading({ level: 2 })
|
||||||
.run();
|
.run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -149,11 +115,11 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleHeading({ level: 2 })
|
.toggleHeading({ level: 2 })
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-h3",
|
selector: ".tiptap-h3",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -161,7 +127,7 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.toggleHeading({ level: 3 })
|
.toggleHeading({ level: 3 })
|
||||||
.run();
|
.run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -169,11 +135,11 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleHeading({ level: 3 })
|
.toggleHeading({ level: 3 })
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-h5",
|
selector: ".tiptap-h5",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -181,7 +147,7 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.toggleHeading({ level: 5 })
|
.toggleHeading({ level: 5 })
|
||||||
.run();
|
.run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -189,11 +155,11 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleHeading({ level: 5 })
|
.toggleHeading({ level: 5 })
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-h6",
|
selector: ".tiptap-h6",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -201,7 +167,7 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.toggleHeading({ level: 6 })
|
.toggleHeading({ level: 6 })
|
||||||
.run();
|
.run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -209,34 +175,23 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleHeading({ level: 6 })
|
.toggleHeading({ level: 6 })
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-paragraph",
|
selector: ".tiptap-paragraph",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().clearNodes().run();
|
return cmsEditor.getEditor().chain().focus().clearNodes().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().clearNodes().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.clearNodes()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-blockquote",
|
selector: ".tiptap-blockquote",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().chain().focus().toggleBlockquote().run();
|
||||||
.getEditor()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleBlockquote()
|
|
||||||
.run();
|
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -244,19 +199,14 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleBlockquote()
|
.toggleBlockquote()
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-codeblock",
|
selector: ".tiptap-codeblock",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().chain().focus().toggleCodeBlock().run();
|
||||||
.getEditor()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleCodeBlock()
|
|
||||||
.run();
|
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -264,19 +214,14 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleCodeBlock()
|
.toggleCodeBlock()
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-ul",
|
selector: ".tiptap-ul",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().chain().focus().toggleBulletList().run();
|
||||||
.getEditor()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleBulletList()
|
|
||||||
.run();
|
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -284,19 +229,14 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleBulletList()
|
.toggleBulletList()
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-ol",
|
selector: ".tiptap-ol",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().chain().focus().toggleOrderedList().run();
|
||||||
.getEditor()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleOrderedList()
|
|
||||||
.run();
|
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -304,38 +244,28 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleOrderedList()
|
.toggleOrderedList()
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".cms-editor-insert-table-dialog",
|
selector: ".cms-editor-insert-table-dialog",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().insertTable().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.insertTable()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".cms-editor-insert-table-dialog .btn-success",
|
selector: ".cms-editor-insert-table-dialog .btn-success",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
const dialog = cmsEditor
|
const dialog = cmsEditor
|
||||||
.getEditorElem()
|
.getEditorElem()
|
||||||
.querySelector(".cms-editor-insert-table-dialog");
|
.querySelector(".cms-editor-insert-table-dialog");
|
||||||
if (!dialog) {
|
if (!dialog) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const rowsInput = dialog.querySelector(
|
const rowsInput = dialog.querySelector("input#rows") as HTMLInputElement;
|
||||||
"input#rows"
|
const colsInput = dialog.querySelector("input#cols") as HTMLInputElement;
|
||||||
) as HTMLInputElement;
|
|
||||||
const colsInput = dialog.querySelector(
|
|
||||||
"input#cols"
|
|
||||||
) as HTMLInputElement;
|
|
||||||
const headerRowInput = dialog.querySelector(
|
const headerRowInput = dialog.querySelector(
|
||||||
"input#headerRow"
|
"input#headerRow"
|
||||||
) as HTMLInputElement;
|
) as HTMLInputElement;
|
||||||
|
|
@ -357,55 +287,38 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
cols: cols,
|
cols: cols,
|
||||||
// headerRow: headerRow,
|
// headerRow: headerRow,
|
||||||
// resizable: true,
|
// resizable: true,
|
||||||
rows: rows
|
rows: rows,
|
||||||
})
|
})
|
||||||
.run();
|
.run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-insert-table-row-before",
|
selector: ".tiptap-insert-table-row-before",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().addRowBefore().run();
|
return cmsEditor.getEditor().chain().focus().addRowBefore().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().addRowBefore().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.addRowBefore()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-insert-table-row-after",
|
selector: ".tiptap-insert-table-row-after",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().addRowAfter().run();
|
return cmsEditor.getEditor().chain().focus().addRowAfter().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().addRowAfter().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.addRowAfter()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-insert-table-column-before",
|
selector: ".tiptap-insert-table-column-before",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().chain().focus().addColumnBefore().run();
|
||||||
.getEditor()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.addColumnBefore()
|
|
||||||
.run();
|
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -413,79 +326,50 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.addColumnBefore()
|
.addColumnBefore()
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-insert-table-column-after",
|
selector: ".tiptap-insert-table-column-after",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().addColumnAfter().run();
|
return cmsEditor.getEditor().chain().focus().addColumnAfter().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().addColumnAfter().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.addColumnAfter()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-remove-table-row",
|
selector: ".tiptap-remove-table-row",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().deleteRow().run();
|
return cmsEditor.getEditor().chain().focus().deleteRow().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().deleteRow().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.deleteRow()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-remove-table-column",
|
selector: ".tiptap-remove-table-column",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().deleteColumn().run();
|
return cmsEditor.getEditor().chain().focus().deleteColumn().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().deleteColumn().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.deleteColumn()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-remove-table",
|
selector: ".tiptap-remove-table",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().deleteTable().run();
|
return cmsEditor.getEditor().chain().focus().deleteTable().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().deleteTable().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.deleteTable()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-toggle-table-header-row",
|
selector: ".tiptap-toggle-table-header-row",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().chain().focus().toggleHeaderRow().run();
|
||||||
.getEditor()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleHeaderRow()
|
|
||||||
.run();
|
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -493,19 +377,14 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleHeaderRow()
|
.toggleHeaderRow()
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-toggle-table-header-column",
|
selector: ".tiptap-toggle-table-header-column",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().chain().focus().toggleHeaderColumn().run();
|
||||||
.getEditor()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleHeaderColumn()
|
|
||||||
.run();
|
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
|
|
@ -513,43 +392,41 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
.focus()
|
.focus()
|
||||||
.toggleHeaderColumn()
|
.toggleHeaderColumn()
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-merge-table-cells",
|
selector: ".tiptap-merge-table-cells",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().mergeCells().run();
|
return cmsEditor.getEditor().chain().focus().mergeCells().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor.getEditor().can().chain().focus().mergeCells().run();
|
||||||
.getEditor()
|
},
|
||||||
.can()
|
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.mergeCells()
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: ".tiptap-split-table-cell",
|
selector: ".tiptap-split-table-cell",
|
||||||
command: cmsEditor => {
|
command: (cmsEditor) => {
|
||||||
return cmsEditor.getEditor().chain().focus().splitCell().run();
|
return cmsEditor.getEditor().chain().focus().splitCell().run();
|
||||||
},
|
},
|
||||||
can: cmsEditor => {
|
can: (cmsEditor) => {
|
||||||
|
return cmsEditor.getEditor().can().chain().focus().splitCell().run();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: ".tiptap-insert-image",
|
||||||
|
command: (cmsEditor) => {
|
||||||
|
return cmsEditor.getEditor().chain().focus().setLibreCmsImage().run();
|
||||||
|
},
|
||||||
|
can: (cmsEditor) => {
|
||||||
return cmsEditor
|
return cmsEditor
|
||||||
.getEditor()
|
.getEditor()
|
||||||
.can()
|
.can()
|
||||||
.chain()
|
.chain()
|
||||||
.focus()
|
.focus()
|
||||||
.splitCell()
|
.setLibreCmsImage()
|
||||||
.run();
|
.run();
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
// {
|
|
||||||
// selector: "",
|
|
||||||
// command: cmsEditor => {},
|
|
||||||
// can: cmsEditor => {}
|
|
||||||
// },
|
|
||||||
// {
|
// {
|
||||||
// selector: "",
|
// selector: "",
|
||||||
// command: cmsEditor => {},
|
// command: cmsEditor => {},
|
||||||
|
|
@ -567,29 +444,68 @@ const BUTTONS: CmsEditorButton[] = [
|
||||||
// }
|
// }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
declare module "@tiptap/core" {
|
||||||
|
interface Commands<ReturnType> {
|
||||||
|
libreCmsImageNode: {
|
||||||
|
setLibreCmsImage: (attributes?: { language: string }) => ReturnType;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImageNode = Node.create({
|
||||||
|
name: "libreCmsImageNode",
|
||||||
|
|
||||||
|
content: "inline*",
|
||||||
|
|
||||||
|
marks: '',
|
||||||
|
|
||||||
|
group: 'block',
|
||||||
|
|
||||||
|
code: false,
|
||||||
|
|
||||||
|
defining: true,
|
||||||
|
|
||||||
|
addCommands() {
|
||||||
|
return {
|
||||||
|
setLibreCmsImage:
|
||||||
|
(attributes) =>
|
||||||
|
({ commands }) => {
|
||||||
|
return commands.setNode("libreCmsImageNode", attributes);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
parseHTML() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
tag: "figure",
|
||||||
|
"data-librecms-editor-node": "image",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
renderHTML({ HTMLAttributes }) {
|
||||||
|
return ["figure", HTMLAttributes, ["img"], ["figcaption"]];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
class CmsEditor {
|
class CmsEditor {
|
||||||
private editor: Editor;
|
private editor: Editor;
|
||||||
private editorElem: HTMLElement;
|
private editorElem: HTMLElement;
|
||||||
private saveUrl: string;
|
private saveUrl: string;
|
||||||
|
|
||||||
public constructor(
|
public constructor(editor: Editor, editorElem: HTMLElement, saveUrl: string) {
|
||||||
editor: Editor,
|
|
||||||
editorElem: HTMLElement,
|
|
||||||
saveUrl: string
|
|
||||||
) {
|
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
this.editorElem = editorElem;
|
this.editorElem = editorElem;
|
||||||
this.saveUrl = saveUrl;
|
this.saveUrl = saveUrl;
|
||||||
|
|
||||||
console.log("initializing editor buttons");
|
console.log("initializing editor buttons");
|
||||||
const buttonsElem = editorElem.querySelector(
|
const buttonsElem = editorElem.querySelector(".cms-tiptap-editor-buttons");
|
||||||
".cms-tiptap-editor-buttons"
|
|
||||||
);
|
|
||||||
if (buttonsElem) {
|
if (buttonsElem) {
|
||||||
for (const button of BUTTONS) {
|
for (const button of BUTTONS) {
|
||||||
const buttonElem = buttonsElem.querySelector(button.selector);
|
const buttonElem = buttonsElem.querySelector(button.selector);
|
||||||
if (buttonElem) {
|
if (buttonElem) {
|
||||||
buttonElem.addEventListener("click", event => {
|
buttonElem.addEventListener("click", (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
button.command(this);
|
button.command(this);
|
||||||
});
|
});
|
||||||
|
|
@ -628,7 +544,7 @@ class CmsEditor {
|
||||||
console.log(`editorElem = ${editorElem}`);
|
console.log(`editorElem = ${editorElem}`);
|
||||||
|
|
||||||
const saveButton = editorElem.querySelector(".cms-editor-save-button");
|
const saveButton = editorElem.querySelector(".cms-editor-save-button");
|
||||||
saveButton?.addEventListener("click", event => this.save(event));
|
saveButton?.addEventListener("click", (event) => this.save(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async save(event: Event) {
|
protected async save(event: Event) {
|
||||||
|
|
@ -642,16 +558,13 @@ class CmsEditor {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/x-www-form-urlencoded"
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
},
|
},
|
||||||
body: params
|
body: params,
|
||||||
});
|
});
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
} else {
|
} else {
|
||||||
this.showSaveFailedMessage(
|
this.showSaveFailedMessage(response.status, response.statusText);
|
||||||
response.status,
|
|
||||||
response.statusText
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.showSaveFailedErrMessage(error as string);
|
this.showSaveFailedErrMessage(error as string);
|
||||||
|
|
@ -715,6 +628,7 @@ class CmsEditorBuilder {
|
||||||
element: canvasElement,
|
element: canvasElement,
|
||||||
extensions: [
|
extensions: [
|
||||||
Gapcursor,
|
Gapcursor,
|
||||||
|
ImageNode,
|
||||||
StarterKit,
|
StarterKit,
|
||||||
Subscript,
|
Subscript,
|
||||||
Superscript,
|
Superscript,
|
||||||
|
|
@ -722,13 +636,13 @@ class CmsEditorBuilder {
|
||||||
allowTableNodeSelection: true,
|
allowTableNodeSelection: true,
|
||||||
cellMinWidth: 100,
|
cellMinWidth: 100,
|
||||||
handleWidth: 25,
|
handleWidth: 25,
|
||||||
resizable: true
|
resizable: true,
|
||||||
}),
|
}),
|
||||||
TableRow,
|
TableRow,
|
||||||
TableHeader,
|
TableHeader,
|
||||||
TableCell
|
TableCell,
|
||||||
],
|
],
|
||||||
content: variant
|
content: variant,
|
||||||
});
|
});
|
||||||
|
|
||||||
return new CmsEditor(editor, this.editorElem, this.saveUrl);
|
return new CmsEditor(editor, this.editorElem, this.saveUrl);
|
||||||
|
|
@ -738,16 +652,13 @@ class CmsEditorBuilder {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(variantUrl, {
|
const response = await fetch(variantUrl, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include"
|
credentials: "include",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
return await response.text();
|
return await response.text();
|
||||||
} else {
|
} else {
|
||||||
this.showLoadVariantFailedMessage(
|
this.showLoadVariantFailedMessage(response.status, response.statusText);
|
||||||
response.status,
|
|
||||||
response.statusText
|
|
||||||
);
|
|
||||||
throw `Failed to load variant. Status: ${response.status}, Status Text: ${response.statusText}`;
|
throw `Failed to load variant. Status: ${response.status}, Status Text: ${response.statusText}`;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue