feat(editor): add all slash commands
continuous-integration/drone/pr Build is failing Details

This commit is contained in:
kolaente 2023-10-21 13:00:12 +02:00
parent e81c98fe5b
commit 02ab1b8c0a
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
5 changed files with 249 additions and 102 deletions

View File

@ -8,7 +8,11 @@
:key="index"
@click="selectItem(index)"
>
{{ item }}
<icon :icon="item.icon"/>
<div class="description">
<p>{{ item.title }}</p>
<p>{{ item.description }}</p>
</div>
</button>
</template>
<div class="item" v-else>
@ -99,17 +103,42 @@ export default {
}
.item {
display: block;
display: flex;
align-items: center;
margin: 0;
width: 100%;
text-align: left;
background: transparent;
border-radius: 0.4rem;
border: 1px solid transparent;
border-radius: $radius;
border: 0;
padding: 0.2rem 0.4rem;
transition: background-color $transition;
&.is-selected {
border-color: #000;
&.is-selected, &:hover {
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>

View File

@ -47,7 +47,7 @@ import StarterKit from '@tiptap/starter-kit'
import {EditorContent, useEditor, VueNodeViewRenderer} from '@tiptap/vue-3'
import Commands from './commands'
import suggestion from './suggestion'
import suggestionSetup from './suggestion'
// load all highlight.js languages
import {lowlight} from 'lowlight'
@ -58,6 +58,9 @@ import type {ITask} from '@/modelTypes/ITask'
import type {IAttachment} from '@/modelTypes/IAttachment'
import AttachmentModel from '@/models/attachment'
import AttachmentService from '@/services/attachment'
import {useI18n} from 'vue-i18n'
const {t} = useI18n()
// const CustomDocument = Document.extend({
// content: 'taskList',
@ -204,7 +207,7 @@ const editor = useEditor({
// }).configure({ lowlight }),
Commands.configure({
suggestion,
suggestion: suggestionSetup(t),
}),
],
onUpdate: () => {

View File

@ -3,112 +3,212 @@ import tippy from 'tippy.js'
import CommandsList from './CommandsList.vue'
export default {
items: ({query}: { query: string }) => {
return [
{
title: 'H1',
command: ({editor, range}) => {
editor
.chain()
.focus()
.deleteRange(range)
.setNode('heading', {level: 1})
.run()
export default function suggestionSetup(t) {
return {
items: ({query}: { query: string }) => {
return [
{
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: 'H2',
description: 'Lorem ipsum',
command: ({editor, range}) => {
editor
.chain()
.focus()
.deleteRange(range)
.setNode('heading', {level: 2})
.run()
{
title: t('input.editor.heading1'),
description: t('input.editor.heading1Tooltip'),
icon: 'fa-header',
command: ({editor, range}) => {
editor
.chain()
.focus()
.deleteRange(range)
.setNode('heading', {level: 1})
.run()
},
},
},
{
title: 'bold',
command: ({editor, range}) => {
editor
.chain()
.focus()
.deleteRange(range)
.setMark('bold')
.run()
{
title: t('input.editor.heading2'),
description: t('input.editor.heading2Tooltip'),
icon: 'fa-header',
command: ({editor, range}) => {
editor
.chain()
.focus()
.deleteRange(range)
.setNode('heading', {level: 2})
.run()
},
},
},
{
title: 'italic',
command: ({editor, range}) => {
editor
.chain()
.focus()
.deleteRange(range)
.setMark('italic')
.run()
{
title: t('input.editor.heading3'),
description: t('input.editor.heading3Tooltip'),
icon: 'fa-header',
command: ({editor, range}) => {
editor
.chain()
.focus()
.deleteRange(range)
.setNode('heading', {level: 2})
.run()
},
},
},
].filter(item => item.title.toLowerCase().startsWith(query.toLowerCase())).slice(0, 10)
},
{
title: t('input.editor.bulletList'),
description: t('input.editor.bulletListTooltip'),
icon: 'fa-list-ul',
command: ({editor, range}) => {
editor
.chain()
.focus()
.deleteRange(range)
.toggleBulletList()
.run()
},
},
{
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: () => {
let component: VueRenderer
let popup
render: () => {
let component: VueRenderer
let popup
return {
onStart: props => {
component = new VueRenderer(CommandsList, {
// using vue 2:
// parent: this,
// propsData: props,
props,
editor: props.editor,
})
return {
onStart: props => {
component = new VueRenderer(CommandsList, {
// using vue 2:
// parent: this,
// propsData: props,
props,
editor: props.editor,
})
if (!props.clientRect) {
return
}
if (!props.clientRect) {
return
}
popup = tippy('body', {
getReferenceClientRect: props.clientRect,
appendTo: () => document.body,
content: component.element,
showOnCreate: true,
interactive: true,
trigger: 'manual',
placement: 'bottom-start',
})
},
popup = tippy('body', {
getReferenceClientRect: props.clientRect,
appendTo: () => document.body,
content: component.element,
showOnCreate: true,
interactive: true,
trigger: 'manual',
placement: 'bottom-start',
})
},
onUpdate(props) {
component.updateProps(props)
onUpdate(props) {
component.updateProps(props)
if (!props.clientRect) {
return
}
if (!props.clientRect) {
return
}
popup[0].setProps({
getReferenceClientRect: props.clientRect,
})
},
popup[0].setProps({
getReferenceClientRect: props.clientRect,
})
},
onKeyDown(props) {
if (props.event.key === 'Escape') {
popup[0].hide()
onKeyDown(props) {
if (props.event.key === 'Escape') {
popup[0].hide()
return true
}
return true
}
return component.ref?.onKeyDown(props)
},
return component.ref?.onKeyDown(props)
},
onExit() {
popup[0].destroy()
component.destroy()
},
}
},
onExit() {
popup[0].destroy()
component.destroy()
},
}
},
}
}

View File

@ -73,7 +73,7 @@ import {
faUnlink,
faParagraph,
faTable,
faX, faArrowTurnDown, faListCheck, faXmark, faXmarksLines,
faX, faArrowTurnDown, faListCheck, faXmark, faXmarksLines, faFont, faRulerHorizontal,
} from '@fortawesome/free-solid-svg-icons'
import {
faBellSlash,
@ -183,6 +183,8 @@ library.add(faArrowTurnDown)
library.add(faListCheck)
library.add(faXmark)
library.add(faXmarksLines)
library.add(faFont)
library.add(faRulerHorizontal)
// overwriting the wrong types
export default FontAwesomeIcon as unknown as FontAwesomeIconFixedTypes

View File

@ -514,24 +514,37 @@
"edit": "Edit",
"done": "Done",
"heading1": "Heading 1",
"heading1Tooltip": "Big section heading.",
"heading2": "Heading 2",
"heading2Tooltip": "Medium section heading.",
"heading3": "Heading 3",
"heading3Tooltip": "Smaller section header.",
"headingSmaller": "Heading Smaller",
"headingBigger": "Heading Bigger",
"bold": "Bold",
"italic": "Italic",
"strikethrough": "Strikethrough",
"code": "Code",
"codeTooltip": "Capture a code snippet.",
"quote": "Quote",
"quoteTooltip": "Capture a quote.",
"bulletList": "Bullet list",
"bulletListTooltip": "Create a simple bullet list.",
"unorderedList": "Unordered List",
"orderedList": "Ordered List",
"orderedListTooltip": "Create a list with numbering.",
"cleanBlock": "Clean Block",
"link": "Link",
"image": "Image",
"table": "Table",
"horizontalRule": "Horizontal Rule",
"horizontalRuleTooltip": "Divide a section.",
"sideBySide": "Side By Side",
"guide": "Guide",
"text": "Text",
"textTooltip": "Just start typing with plain text.",
"taskList": "Task list",
"taskListTooltip": "Track tasks with a to-do list.",
"table": {
"insert": "Insert table",
"addColumnBefore": "Add column before",