feat(editor): add all slash commands
This commit is contained in:
parent
e81c98fe5b
commit
02ab1b8c0a
@ -8,7 +8,11 @@
|
|||||||
:key="index"
|
:key="index"
|
||||||
@click="selectItem(index)"
|
@click="selectItem(index)"
|
||||||
>
|
>
|
||||||
{{ item }}
|
<icon :icon="item.icon"/>
|
||||||
|
<div class="description">
|
||||||
|
<p>{{ item.title }}</p>
|
||||||
|
<p>{{ item.description }}</p>
|
||||||
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
<div class="item" v-else>
|
<div class="item" v-else>
|
||||||
@ -99,17 +103,42 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
display: block;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 0.4rem;
|
border-radius: $radius;
|
||||||
border: 1px solid transparent;
|
border: 0;
|
||||||
padding: 0.2rem 0.4rem;
|
padding: 0.2rem 0.4rem;
|
||||||
|
transition: background-color $transition;
|
||||||
|
|
||||||
&.is-selected {
|
&.is-selected, &:hover {
|
||||||
border-color: #000;
|
background: var(--grey-100);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
> svg {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
border: 1px solid var(--grey-300);
|
||||||
|
padding: .5rem;
|
||||||
|
margin-right: .5rem;
|
||||||
|
border-radius: $radius;
|
||||||
|
color: var(--grey-700);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: .9rem;
|
||||||
|
|
||||||
|
p:last-child {
|
||||||
|
font-size: .75rem;
|
||||||
|
color: var(--grey-500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -47,7 +47,7 @@ import StarterKit from '@tiptap/starter-kit'
|
|||||||
import {EditorContent, useEditor, VueNodeViewRenderer} from '@tiptap/vue-3'
|
import {EditorContent, useEditor, VueNodeViewRenderer} from '@tiptap/vue-3'
|
||||||
|
|
||||||
import Commands from './commands'
|
import Commands from './commands'
|
||||||
import suggestion from './suggestion'
|
import suggestionSetup from './suggestion'
|
||||||
|
|
||||||
// load all highlight.js languages
|
// load all highlight.js languages
|
||||||
import {lowlight} from 'lowlight'
|
import {lowlight} from 'lowlight'
|
||||||
@ -58,6 +58,9 @@ import type {ITask} from '@/modelTypes/ITask'
|
|||||||
import type {IAttachment} from '@/modelTypes/IAttachment'
|
import type {IAttachment} from '@/modelTypes/IAttachment'
|
||||||
import AttachmentModel from '@/models/attachment'
|
import AttachmentModel from '@/models/attachment'
|
||||||
import AttachmentService from '@/services/attachment'
|
import AttachmentService from '@/services/attachment'
|
||||||
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
|
const {t} = useI18n()
|
||||||
|
|
||||||
// const CustomDocument = Document.extend({
|
// const CustomDocument = Document.extend({
|
||||||
// content: 'taskList',
|
// content: 'taskList',
|
||||||
@ -204,7 +207,7 @@ const editor = useEditor({
|
|||||||
// }).configure({ lowlight }),
|
// }).configure({ lowlight }),
|
||||||
|
|
||||||
Commands.configure({
|
Commands.configure({
|
||||||
suggestion,
|
suggestion: suggestionSetup(t),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
onUpdate: () => {
|
onUpdate: () => {
|
||||||
|
@ -3,11 +3,27 @@ import tippy from 'tippy.js'
|
|||||||
|
|
||||||
import CommandsList from './CommandsList.vue'
|
import CommandsList from './CommandsList.vue'
|
||||||
|
|
||||||
export default {
|
export default function suggestionSetup(t) {
|
||||||
|
return {
|
||||||
items: ({query}: { query: string }) => {
|
items: ({query}: { query: string }) => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: 'H1',
|
title: t('input.editor.text'),
|
||||||
|
description: t('input.editor.textTooltip'),
|
||||||
|
icon: 'fa-font',
|
||||||
|
command: ({editor, range}) => {
|
||||||
|
editor
|
||||||
|
.chain()
|
||||||
|
.focus()
|
||||||
|
.deleteRange(range)
|
||||||
|
.setNode('paragraph', {level: 1})
|
||||||
|
.run()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('input.editor.heading1'),
|
||||||
|
description: t('input.editor.heading1Tooltip'),
|
||||||
|
icon: 'fa-header',
|
||||||
command: ({editor, range}) => {
|
command: ({editor, range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
@ -18,8 +34,9 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'H2',
|
title: t('input.editor.heading2'),
|
||||||
description: 'Lorem ipsum',
|
description: t('input.editor.heading2Tooltip'),
|
||||||
|
icon: 'fa-header',
|
||||||
command: ({editor, range}) => {
|
command: ({editor, range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
@ -30,28 +47,110 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bold',
|
title: t('input.editor.heading3'),
|
||||||
|
description: t('input.editor.heading3Tooltip'),
|
||||||
|
icon: 'fa-header',
|
||||||
command: ({editor, range}) => {
|
command: ({editor, range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
.focus()
|
.focus()
|
||||||
.deleteRange(range)
|
.deleteRange(range)
|
||||||
.setMark('bold')
|
.setNode('heading', {level: 2})
|
||||||
.run()
|
.run()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'italic',
|
title: t('input.editor.bulletList'),
|
||||||
|
description: t('input.editor.bulletListTooltip'),
|
||||||
|
icon: 'fa-list-ul',
|
||||||
command: ({editor, range}) => {
|
command: ({editor, range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
.focus()
|
.focus()
|
||||||
.deleteRange(range)
|
.deleteRange(range)
|
||||||
.setMark('italic')
|
.toggleBulletList()
|
||||||
.run()
|
.run()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
].filter(item => item.title.toLowerCase().startsWith(query.toLowerCase())).slice(0, 10)
|
{
|
||||||
|
title: t('input.editor.orderedList'),
|
||||||
|
description: t('input.editor.orderedListTooltip'),
|
||||||
|
icon: 'fa-list-ol',
|
||||||
|
command: ({editor, range}) => {
|
||||||
|
editor
|
||||||
|
.chain()
|
||||||
|
.focus()
|
||||||
|
.deleteRange(range)
|
||||||
|
.toggleOrderedList()
|
||||||
|
.run()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('input.editor.taskList'),
|
||||||
|
description: t('input.editor.taskListTooltip'),
|
||||||
|
icon: 'fa-list-check',
|
||||||
|
command: ({editor, range}) => {
|
||||||
|
editor
|
||||||
|
.chain()
|
||||||
|
.focus()
|
||||||
|
.deleteRange(range)
|
||||||
|
.toggleTaskList()
|
||||||
|
.run()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('input.editor.quote'),
|
||||||
|
description: t('input.editor.quoteTooltip'),
|
||||||
|
icon: 'fa-quote-right',
|
||||||
|
command: ({editor, range}) => {
|
||||||
|
editor
|
||||||
|
.chain()
|
||||||
|
.focus()
|
||||||
|
.deleteRange(range)
|
||||||
|
.toggleBlockquote()
|
||||||
|
.run()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('input.editor.code'),
|
||||||
|
description: t('input.editor.codeTooltip'),
|
||||||
|
icon: 'fa-code',
|
||||||
|
command: ({editor, range}) => {
|
||||||
|
editor
|
||||||
|
.chain()
|
||||||
|
.focus()
|
||||||
|
.deleteRange(range)
|
||||||
|
.toggleCodeBlock()
|
||||||
|
.run()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: t('input.editor.')'Image',
|
||||||
|
// description: t('input.editor.')'Upload an image from your computer',
|
||||||
|
// icon: 'fa-image',
|
||||||
|
// command: ({editor, range}) => {
|
||||||
|
// editor
|
||||||
|
// .chain()
|
||||||
|
// .focus()
|
||||||
|
// .deleteRange(range)
|
||||||
|
// .toggle()
|
||||||
|
// .run()
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: t('input.editor.horizontalRule'),
|
||||||
|
description: t('input.editor.horizontalRuleTooltip'),
|
||||||
|
icon: 'fa-ruler-horizontal',
|
||||||
|
command: ({editor, range}) => {
|
||||||
|
editor
|
||||||
|
.chain()
|
||||||
|
.focus()
|
||||||
|
.deleteRange(range)
|
||||||
|
.setHorizontalRule()
|
||||||
|
.run()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
].filter(item => item.title.toLowerCase().startsWith(query.toLowerCase()))
|
||||||
},
|
},
|
||||||
|
|
||||||
render: () => {
|
render: () => {
|
||||||
@ -112,3 +211,4 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
@ -73,7 +73,7 @@ import {
|
|||||||
faUnlink,
|
faUnlink,
|
||||||
faParagraph,
|
faParagraph,
|
||||||
faTable,
|
faTable,
|
||||||
faX, faArrowTurnDown, faListCheck, faXmark, faXmarksLines,
|
faX, faArrowTurnDown, faListCheck, faXmark, faXmarksLines, faFont, faRulerHorizontal,
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
import {
|
import {
|
||||||
faBellSlash,
|
faBellSlash,
|
||||||
@ -183,6 +183,8 @@ library.add(faArrowTurnDown)
|
|||||||
library.add(faListCheck)
|
library.add(faListCheck)
|
||||||
library.add(faXmark)
|
library.add(faXmark)
|
||||||
library.add(faXmarksLines)
|
library.add(faXmarksLines)
|
||||||
|
library.add(faFont)
|
||||||
|
library.add(faRulerHorizontal)
|
||||||
|
|
||||||
// overwriting the wrong types
|
// overwriting the wrong types
|
||||||
export default FontAwesomeIcon as unknown as FontAwesomeIconFixedTypes
|
export default FontAwesomeIcon as unknown as FontAwesomeIconFixedTypes
|
@ -514,24 +514,37 @@
|
|||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"heading1": "Heading 1",
|
"heading1": "Heading 1",
|
||||||
|
"heading1Tooltip": "Big section heading.",
|
||||||
"heading2": "Heading 2",
|
"heading2": "Heading 2",
|
||||||
|
"heading2Tooltip": "Medium section heading.",
|
||||||
"heading3": "Heading 3",
|
"heading3": "Heading 3",
|
||||||
|
"heading3Tooltip": "Smaller section header.",
|
||||||
"headingSmaller": "Heading Smaller",
|
"headingSmaller": "Heading Smaller",
|
||||||
"headingBigger": "Heading Bigger",
|
"headingBigger": "Heading Bigger",
|
||||||
"bold": "Bold",
|
"bold": "Bold",
|
||||||
"italic": "Italic",
|
"italic": "Italic",
|
||||||
"strikethrough": "Strikethrough",
|
"strikethrough": "Strikethrough",
|
||||||
"code": "Code",
|
"code": "Code",
|
||||||
|
"codeTooltip": "Capture a code snippet.",
|
||||||
"quote": "Quote",
|
"quote": "Quote",
|
||||||
|
"quoteTooltip": "Capture a quote.",
|
||||||
|
"bulletList": "Bullet list",
|
||||||
|
"bulletListTooltip": "Create a simple bullet list.",
|
||||||
"unorderedList": "Unordered List",
|
"unorderedList": "Unordered List",
|
||||||
"orderedList": "Ordered List",
|
"orderedList": "Ordered List",
|
||||||
|
"orderedListTooltip": "Create a list with numbering.",
|
||||||
"cleanBlock": "Clean Block",
|
"cleanBlock": "Clean Block",
|
||||||
"link": "Link",
|
"link": "Link",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"table": "Table",
|
"table": "Table",
|
||||||
"horizontalRule": "Horizontal Rule",
|
"horizontalRule": "Horizontal Rule",
|
||||||
|
"horizontalRuleTooltip": "Divide a section.",
|
||||||
"sideBySide": "Side By Side",
|
"sideBySide": "Side By Side",
|
||||||
"guide": "Guide",
|
"guide": "Guide",
|
||||||
|
"text": "Text",
|
||||||
|
"textTooltip": "Just start typing with plain text.",
|
||||||
|
"taskList": "Task list",
|
||||||
|
"taskListTooltip": "Track tasks with a to-do list.",
|
||||||
"table": {
|
"table": {
|
||||||
"insert": "Insert table",
|
"insert": "Insert table",
|
||||||
"addColumnBefore": "Add column before",
|
"addColumnBefore": "Add column before",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user