refactoring

This commit is contained in:
Philipp Kühn
2021-01-18 23:41:38 +01:00
committed by Hans Pagel
parent b4032a17cb
commit ba5d38a621
6 changed files with 64 additions and 45 deletions

View File

@@ -5,7 +5,7 @@
</template> </template>
<script> <script>
import tippy, { sticky } from 'tippy.js' import tippy from 'tippy.js'
import { Editor, EditorContent, VueRenderer } from '@tiptap/vue' import { Editor, EditorContent, VueRenderer } from '@tiptap/vue'
import Document from '@tiptap/extension-document' import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph' import Paragraph from '@tiptap/extension-paragraph'
@@ -34,7 +34,7 @@ export default {
items: query => { items: query => {
return ['Hans', 'Philipp', 'Kris'].filter(item => item.startsWith(query)) return ['Hans', 'Philipp', 'Kris'].filter(item => item.startsWith(query))
}, },
renderer: () => { render: () => {
let component let component
let popup let popup

View File

@@ -147,6 +147,7 @@ Have a look at all of the core commands listed below. They should give you a goo
| .lift() | Removes an existing wrap. | | .lift() | Removes an existing wrap. |
| .liftEmptyBlock() | Lift block if empty. | | .liftEmptyBlock() | Lift block if empty. |
| .newlineInCode() | Add a newline character in code. | | .newlineInCode() | Add a newline character in code. |
| .replace() | Replaces text with a node within a range. |
| .resetNodeAttributes() | Resets all node attributes to the default value. | | .resetNodeAttributes() | Resets all node attributes to the default value. |
| .selectParentNode() | Select the parent node. | | .selectParentNode() | Select the parent node. |
| .setMark() | Add a mark with new attributes. | | .setMark() | Add a mark with new attributes. |

View File

@@ -0,0 +1,29 @@
import { NodeType } from 'prosemirror-model'
import getNodeType from '../helpers/getNodeType'
import { Command } from '../types'
export type Range = {
from: number,
to: number,
}
/**
* Replaces text with a node within a range.
*/
export const replace = (range: Range | null = null, typeOrName: string | NodeType, attrs = {}): Command => ({ tr, state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
const { $from, $to } = state.selection
const index = $from.index()
const from = range ? range.from : $from.pos
const to = range ? range.to : $to.pos
if (!$from.parent.canReplaceWith(index, index, type)) {
return false
}
if (dispatch) {
tr.replaceWith(from, to, type.create(attrs))
}
return true
}

View File

@@ -17,6 +17,7 @@ import * as lift from '../commands/lift'
import * as liftEmptyBlock from '../commands/liftEmptyBlock' import * as liftEmptyBlock from '../commands/liftEmptyBlock'
import * as liftListItem from '../commands/liftListItem' import * as liftListItem from '../commands/liftListItem'
import * as newlineInCode from '../commands/newlineInCode' import * as newlineInCode from '../commands/newlineInCode'
import * as replace from '../commands/replace'
import * as resetNodeAttributes from '../commands/resetNodeAttributes' import * as resetNodeAttributes from '../commands/resetNodeAttributes'
import * as scrollIntoView from '../commands/scrollIntoView' import * as scrollIntoView from '../commands/scrollIntoView'
import * as selectAll from '../commands/selectAll' import * as selectAll from '../commands/selectAll'
@@ -63,6 +64,7 @@ export const Commands = Extension.create({
...liftEmptyBlock, ...liftEmptyBlock,
...liftListItem, ...liftListItem,
...newlineInCode, ...newlineInCode,
...replace,
...resetNodeAttributes, ...resetNodeAttributes,
...scrollIntoView, ...scrollIntoView,
...selectAll, ...selectAll,

View File

@@ -8,7 +8,7 @@ export const Mention = Node.create({
defaultOptions: <MentionOptions>{ defaultOptions: <MentionOptions>{
char: '@', char: '@',
renderer: () => ({}), render: () => ({}),
}, },
group: 'inline', group: 'inline',
@@ -47,6 +47,13 @@ export const Mention = Node.create({
Suggestion({ Suggestion({
editor: this.editor, editor: this.editor,
...this.options, ...this.options,
command: ({ range }) => {
this.editor
.chain()
.replace(range, 'mention')
.insertText(' ')
.run()
},
}), }),
] ]
}, },

View File

@@ -10,9 +10,9 @@ export interface SuggestionOptions {
allowSpaces?: boolean, allowSpaces?: boolean,
startOfLine?: boolean, startOfLine?: boolean,
suggestionClass?: string, suggestionClass?: string,
command?: () => any, command?: (props: any) => any,
items?: (query: string) => any[], items?: (query: string) => any[],
renderer?: () => { render?: () => {
onStart?: (props: any) => void, onStart?: (props: any) => void,
onUpdate?: (props: any) => void, onUpdate?: (props: any) => void,
onExit?: (props: any) => void, onExit?: (props: any) => void,
@@ -21,21 +21,16 @@ export interface SuggestionOptions {
} }
export function Suggestion({ export function Suggestion({
editor,
char = '@', char = '@',
allowSpaces = false, allowSpaces = false,
startOfLine = false, startOfLine = false,
suggestionClass = 'suggestion', suggestionClass = 'suggestion',
command = () => null, command = () => null,
items = () => [], items = () => [],
// onStart = () => null, render = () => ({}),
// onUpdate = () => null,
// onExit = () => null,
// onKeyDown = () => null,
renderer = () => ({}),
}: SuggestionOptions) { }: SuggestionOptions) {
const testRenderer = renderer?.() const renderer = render?.()
return new Plugin({ return new Plugin({
key: new PluginKey('suggestions'), key: new PluginKey('suggestions'),
@@ -67,45 +62,30 @@ export function Suggestion({
range: state.range, range: state.range,
query: state.query, query: state.query,
text: state.text, text: state.text,
items: (handleChange || handleStart)
? await items(state.query)
: [],
command: () => {
command({ range: state.range })
},
decorationNode, decorationNode,
// build a virtual node for popper.js or tippy.js // build a virtual node for popper.js or tippy.js
// this can be used for building popups without a DOM node // this can be used for building popups without a DOM node
virtualNode: decorationNode virtualNode: decorationNode
? getVirtualNode(decorationNode) ? getVirtualNode(decorationNode)
: null, : null,
items: (handleChange || handleStart)
? await items(state.query)
: [],
command: () => {
console.log('command')
},
// command: ({ range, attrs }) => {
// command({
// range,
// attrs,
// schema: view.state.schema,
// })(view.state, view.dispatch, view)
// if (appendText) {
// insertText(appendText)(view.state, view.dispatch, view)
// }
// },
}
// Trigger the hooks when necessary
if (handleExit) {
// onExit(props)
testRenderer?.onExit?.(props)
}
if (handleChange) {
// onUpdate(props)
testRenderer?.onUpdate?.(props)
} }
if (handleStart) { if (handleStart) {
// onStart(props) renderer?.onStart?.(props)
testRenderer?.onStart?.(props) }
if (handleChange) {
renderer?.onUpdate?.(props)
}
if (handleExit) {
renderer?.onExit?.(props)
} }
}, },
} }
@@ -123,8 +103,8 @@ export function Suggestion({
}, },
// Apply changes to the plugin state from a view transaction. // Apply changes to the plugin state from a view transaction.
apply(tr, prev) { apply(transaction, prev) {
const { selection } = tr const { selection } = transaction
const next = { ...prev } const next = { ...prev }
// We can only be suggesting if there is no selection // We can only be suggesting if there is no selection
@@ -178,7 +158,7 @@ export function Suggestion({
return false return false
} }
return testRenderer?.onKeyDown?.({ view, event, range }) || false return renderer?.onKeyDown?.({ view, event, range }) || false
}, },
// Setup decorator on the currently active suggestion. // Setup decorator on the currently active suggestion.