show autocomplete

This commit is contained in:
2023-05-04 22:35:50 +02:00
parent 8e7b6d13af
commit 82e4f25b04
3 changed files with 85 additions and 16 deletions

View File

@@ -224,8 +224,8 @@ export default defineComponent({
this.$emit('click', { evt, data }, editor)
})
editor.model.document.on('contextedLinkAutocomplete', (evt, data) => {
this.$emit('contextedLinkAutocomplete', { evt, data })
editor.model.document.on('contextedLinkAutocomplete', (_, data) => {
this.$emit('contextedLinkAutocomplete', data)
})
},
},

View File

@@ -1,5 +1,7 @@
import Plugin from '@ckeditor/ckeditor5-core/src/plugin'
import { TwoStepCaretMovement, inlineHighlight } from 'ckeditor5/src/typing'
import AttributeCommand from '@ckeditor/ckeditor5-basic-styles/src/attributecommand'
import Rect from '@ckeditor/ckeditor5-utils/src/dom/rect'
const HIGHLIGHT_CLASS = 'ck-link_selected'
@@ -10,6 +12,10 @@ export default class ContextedLinkEditing extends Plugin {
const twoStepCaretMovementPlugin = this.editor.plugins.get(TwoStepCaretMovement)
twoStepCaretMovementPlugin.registerAttribute('contextedLink')
inlineHighlight(this.editor, 'contextedLink', 'a', HIGHLIGHT_CLASS)
this.editor.commands.add(
'autocomplete',
new AttributeCommand(this.editor, 'autocomplete')
)
}
afterInit() {
// const editor = this.editor
@@ -28,7 +34,7 @@ export default class ContextedLinkEditing extends Plugin {
// Extend the text node's schema to accept the abbreviation attribute.
schema.extend('$text', {
allowAttributes: ['abbreviation', 'contextedLink'],
allowAttributes: ['contextedLink', 'autocomplete'],
})
}
_defineConverters() {
@@ -62,10 +68,9 @@ export default class ContextedLinkEditing extends Plugin {
_addAutocomplete() {
// Copied from: node_modules/@ckeditor/ckeditor5-autoformat/src/inlineautoformatediting.js
const editor = this.editor
editor.model.document.on('change:data', (_, batch) => {
if (batch.isUndo || !batch.isLocal) {
return
}
// let autocomplete = false
editor.model.document.on('change', (_, batch) => {
if (batch.isUndo || !batch.isLocal) return
const model = editor.model
const selection = model.document.selection
// Do nothing if selection is not collapsed.
@@ -75,7 +80,7 @@ export default class ContextedLinkEditing extends Plugin {
// Typing is represented by only a single change.
if (
changes.length != 1 ||
entry.type !== 'insert' ||
(entry.type !== 'insert' && entry.type !== 'remove') ||
entry.name != '$text' ||
entry.length != 1
) {
@@ -84,21 +89,60 @@ export default class ContextedLinkEditing extends Plugin {
const focus = selection.focus
const block = focus?.parent
if (!block || !focus) return
const { text, range } = getTextAfterCode(
const { text } = getTextAfterCode(
model.createRange(model.createPositionAt(block, 0), focus),
model
)
const inputText = (text as string).split(']]').at(-1)
const autocompleteOpenMatch = (inputText as string).match(/(?<=\[\[).+/g)
const autocompleteCloseMatch = (inputText as string).match(/(?<=\[\[).+?(?=]])/g)
const openAutocomplete = autocompleteOpenMatch && !autocompleteCloseMatch
if (openAutocomplete) {
editor.model.document.fire('contextedLinkAutocomplete', autocompleteOpenMatch)
const autocompleteText = (inputText as string).match(/(?<=\[\[).*/g)
const cursorNodes = [focus.textNode, focus.nodeBefore, focus.nodeAfter]
const autocompleteNode: any = cursorNodes.find((node) =>
node?.hasAttribute('autocomplete')
)
interface AutocompleteEvent {
position?: any
autocompleteText?: string
show: boolean
}
if (Boolean(autocompleteText) || Boolean(autocompleteNode)) {
if (Boolean(autocompleteText) !== Boolean(autocompleteNode)) {
editor.execute('autocomplete')
if (autocompleteNode)
editor.model.document.fire('contextedLinkAutocomplete', { show: false })
} else {
const event: AutocompleteEvent = {
position: getNodePosition(
editor,
editor.model.createPositionFromPath(
autocompleteNode.root,
autocompleteNode.getPath()
)
),
autocompleteText: autocompleteNode.data,
show: true,
}
editor.model.document.fire('contextedLinkAutocomplete', event)
}
}
})
}
}
function getNodePosition(editor: any, modelPosition: any) {
try {
const mapper = editor.editing.mapper
const viewPosition = mapper.toViewPosition(modelPosition)
const viewRange = editor.editing.view.createRange(viewPosition)
const domConverter = editor.editing.view.domConverter
const rangeRects = Rect.getDomRangeRects(
domConverter.viewRangeToDom(viewRange)
).pop()
return rangeRects
} catch (e) {
console.log(e)
}
}
// function testOutputToRanges(start: any, arrays: any[], model: any) {
// return arrays
// .filter((array) => array[0] !== undefined && array[1] !== undefined)