show autocomplete
This commit is contained in:
@@ -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)
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user