@ckeditor/ckeditor5-mention 40.0.0 → 40.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +3 -3
- package/package.json +2 -2
- package/src/augmentation.d.ts +23 -23
- package/src/augmentation.js +5 -5
- package/src/index.d.ts +13 -13
- package/src/index.js +11 -11
- package/src/mention.d.ts +77 -77
- package/src/mention.js +33 -33
- package/src/mentioncommand.d.ts +77 -77
- package/src/mentioncommand.js +145 -145
- package/src/mentionconfig.d.ts +265 -265
- package/src/mentionconfig.js +5 -5
- package/src/mentionediting.d.ts +43 -43
- package/src/mentionediting.js +231 -231
- package/src/mentionui.d.ts +102 -102
- package/src/mentionui.js +618 -618
- package/src/ui/domwrapperview.d.ts +41 -41
- package/src/ui/domwrapperview.js +57 -57
- package/src/ui/mentionlistitemview.d.ts +15 -15
- package/src/ui/mentionlistitemview.js +18 -18
- package/src/ui/mentionsview.d.ts +60 -60
- package/src/ui/mentionsview.js +104 -104
- package/build/mention.js.map +0 -1
package/src/mentionediting.js
CHANGED
@@ -1,231 +1,231 @@
|
|
1
|
-
/**
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
-
*/
|
5
|
-
/**
|
6
|
-
* @module mention/mentionediting
|
7
|
-
*/
|
8
|
-
import { Plugin } from 'ckeditor5/src/core';
|
9
|
-
import { uid } from 'ckeditor5/src/utils';
|
10
|
-
import MentionCommand from './mentioncommand';
|
11
|
-
/**
|
12
|
-
* The mention editing feature.
|
13
|
-
*
|
14
|
-
* It introduces the {@link module:mention/mentioncommand~MentionCommand command} and the `mention`
|
15
|
-
* attribute in the {@link module:engine/model/model~Model model} which renders in the {@link module:engine/view/view view}
|
16
|
-
* as a `<span class="mention" data-mention="@mention">`.
|
17
|
-
*/
|
18
|
-
export default class MentionEditing extends Plugin {
|
19
|
-
/**
|
20
|
-
* @inheritDoc
|
21
|
-
*/
|
22
|
-
static get pluginName() {
|
23
|
-
return 'MentionEditing';
|
24
|
-
}
|
25
|
-
/**
|
26
|
-
* @inheritDoc
|
27
|
-
*/
|
28
|
-
init() {
|
29
|
-
const editor = this.editor;
|
30
|
-
const model = editor.model;
|
31
|
-
const doc = model.document;
|
32
|
-
// Allow the mention attribute on all text nodes.
|
33
|
-
model.schema.extend('$text', { allowAttributes: 'mention' });
|
34
|
-
// Upcast conversion.
|
35
|
-
editor.conversion.for('upcast').elementToAttribute({
|
36
|
-
view: {
|
37
|
-
name: 'span',
|
38
|
-
key: 'data-mention',
|
39
|
-
classes: 'mention'
|
40
|
-
},
|
41
|
-
model: {
|
42
|
-
key: 'mention',
|
43
|
-
value: (viewElement) => _toMentionAttribute(viewElement)
|
44
|
-
}
|
45
|
-
});
|
46
|
-
// Downcast conversion.
|
47
|
-
editor.conversion.for('downcast').attributeToElement({
|
48
|
-
model: 'mention',
|
49
|
-
view: createViewMentionElement
|
50
|
-
});
|
51
|
-
editor.conversion.for('downcast').add(preventPartialMentionDowncast);
|
52
|
-
doc.registerPostFixer(writer => removePartialMentionPostFixer(writer, doc, model.schema));
|
53
|
-
doc.registerPostFixer(writer => extendAttributeOnMentionPostFixer(writer, doc));
|
54
|
-
doc.registerPostFixer(writer => selectionMentionAttributePostFixer(writer, doc));
|
55
|
-
editor.commands.add('mention', new MentionCommand(editor));
|
56
|
-
}
|
57
|
-
}
|
58
|
-
/**
|
59
|
-
* @internal
|
60
|
-
*/
|
61
|
-
export function _addMentionAttributes(baseMentionData, data) {
|
62
|
-
return Object.assign({ uid: uid() }, baseMentionData, data || {});
|
63
|
-
}
|
64
|
-
/**
|
65
|
-
* Creates a mention attribute value from the provided view element and optional data.
|
66
|
-
*
|
67
|
-
* This function is exposed as
|
68
|
-
* {@link module:mention/mention~Mention#toMentionAttribute `editor.plugins.get( 'Mention' ).toMentionAttribute()`}.
|
69
|
-
*
|
70
|
-
* @internal
|
71
|
-
*/
|
72
|
-
export function _toMentionAttribute(viewElementOrMention, data) {
|
73
|
-
const dataMention = viewElementOrMention.getAttribute('data-mention');
|
74
|
-
const textNode = viewElementOrMention.getChild(0);
|
75
|
-
// Do not convert empty mentions.
|
76
|
-
if (!textNode) {
|
77
|
-
return;
|
78
|
-
}
|
79
|
-
const baseMentionData = {
|
80
|
-
id: dataMention,
|
81
|
-
_text: textNode.data
|
82
|
-
};
|
83
|
-
return _addMentionAttributes(baseMentionData, data);
|
84
|
-
}
|
85
|
-
/**
|
86
|
-
* A converter that blocks partial mention from being converted.
|
87
|
-
*
|
88
|
-
* This converter is registered with 'highest' priority in order to consume mention attribute before it is converted by
|
89
|
-
* any other converters. This converter only consumes partial mention - those whose `_text` attribute is not equal to text with mention
|
90
|
-
* attribute. This may happen when copying part of mention text.
|
91
|
-
*/
|
92
|
-
function preventPartialMentionDowncast(dispatcher) {
|
93
|
-
dispatcher.on('attribute:mention', (evt, data, conversionApi) => {
|
94
|
-
const mention = data.attributeNewValue;
|
95
|
-
if (!data.item.is('$textProxy') || !mention) {
|
96
|
-
return;
|
97
|
-
}
|
98
|
-
const start = data.range.start;
|
99
|
-
const textNode = start.textNode || start.nodeAfter;
|
100
|
-
if (textNode.data != mention._text) {
|
101
|
-
// Consume item to prevent partial mention conversion.
|
102
|
-
conversionApi.consumable.consume(data.item, evt.name);
|
103
|
-
}
|
104
|
-
}, { priority: 'highest' });
|
105
|
-
}
|
106
|
-
/**
|
107
|
-
* Creates a mention element from the mention data.
|
108
|
-
*/
|
109
|
-
function createViewMentionElement(mention, { writer }) {
|
110
|
-
if (!mention) {
|
111
|
-
return;
|
112
|
-
}
|
113
|
-
const attributes = {
|
114
|
-
class: 'mention',
|
115
|
-
'data-mention': mention.id
|
116
|
-
};
|
117
|
-
const options = {
|
118
|
-
id: mention.uid,
|
119
|
-
priority: 20
|
120
|
-
};
|
121
|
-
return writer.createAttributeElement('span', attributes, options);
|
122
|
-
}
|
123
|
-
/**
|
124
|
-
* Model post-fixer that disallows typing with selection when the selection is placed after the text node with the mention attribute or
|
125
|
-
* before a text node with mention attribute.
|
126
|
-
*/
|
127
|
-
function selectionMentionAttributePostFixer(writer, doc) {
|
128
|
-
const selection = doc.selection;
|
129
|
-
const focus = selection.focus;
|
130
|
-
if (selection.isCollapsed && selection.hasAttribute('mention') && shouldNotTypeWithMentionAt(focus)) {
|
131
|
-
writer.removeSelectionAttribute('mention');
|
132
|
-
return true;
|
133
|
-
}
|
134
|
-
return false;
|
135
|
-
}
|
136
|
-
/**
|
137
|
-
* Helper function to detect if mention attribute should be removed from selection.
|
138
|
-
* This check makes only sense if the selection has mention attribute.
|
139
|
-
*
|
140
|
-
* The mention attribute should be removed from a selection when selection focus is placed:
|
141
|
-
* a) after a text node
|
142
|
-
* b) the position is at parents start - the selection will set attributes from node after.
|
143
|
-
*/
|
144
|
-
function shouldNotTypeWithMentionAt(position) {
|
145
|
-
const isAtStart = position.isAtStart;
|
146
|
-
const isAfterAMention = position.nodeBefore && position.nodeBefore.is('$text');
|
147
|
-
return isAfterAMention || isAtStart;
|
148
|
-
}
|
149
|
-
/**
|
150
|
-
* Model post-fixer that removes the mention attribute from the modified text node.
|
151
|
-
*/
|
152
|
-
function removePartialMentionPostFixer(writer, doc, schema) {
|
153
|
-
const changes = doc.differ.getChanges();
|
154
|
-
let wasChanged = false;
|
155
|
-
for (const change of changes) {
|
156
|
-
if (change.type == 'attribute') {
|
157
|
-
continue;
|
158
|
-
}
|
159
|
-
// Checks the text node on the current position.
|
160
|
-
const position = change.position;
|
161
|
-
if (change.name == '$text') {
|
162
|
-
const nodeAfterInsertedTextNode = position.textNode && position.textNode.nextSibling;
|
163
|
-
// Checks the text node where the change occurred.
|
164
|
-
wasChanged = checkAndFix(position.textNode, writer) || wasChanged;
|
165
|
-
// Occurs on paste inside a text node with mention.
|
166
|
-
wasChanged = checkAndFix(nodeAfterInsertedTextNode, writer) || wasChanged;
|
167
|
-
wasChanged = checkAndFix(position.nodeBefore, writer) || wasChanged;
|
168
|
-
wasChanged = checkAndFix(position.nodeAfter, writer) || wasChanged;
|
169
|
-
}
|
170
|
-
// Checks text nodes in inserted elements (might occur when splitting a paragraph or pasting content inside text with mention).
|
171
|
-
if (change.name != '$text' && change.type == 'insert') {
|
172
|
-
const insertedNode = position.nodeAfter;
|
173
|
-
for (const item of writer.createRangeIn(insertedNode).getItems()) {
|
174
|
-
wasChanged = checkAndFix(item, writer) || wasChanged;
|
175
|
-
}
|
176
|
-
}
|
177
|
-
// Inserted inline elements might break mention.
|
178
|
-
if (change.type == 'insert' && schema.isInline(change.name)) {
|
179
|
-
const nodeAfterInserted = position.nodeAfter && position.nodeAfter.nextSibling;
|
180
|
-
wasChanged = checkAndFix(position.nodeBefore, writer) || wasChanged;
|
181
|
-
wasChanged = checkAndFix(nodeAfterInserted, writer) || wasChanged;
|
182
|
-
}
|
183
|
-
}
|
184
|
-
return wasChanged;
|
185
|
-
}
|
186
|
-
/**
|
187
|
-
* This post-fixer will extend the attribute applied on the part of the mention so the whole text node of the mention will have
|
188
|
-
* the added attribute.
|
189
|
-
*/
|
190
|
-
function extendAttributeOnMentionPostFixer(writer, doc) {
|
191
|
-
const changes = doc.differ.getChanges();
|
192
|
-
let wasChanged = false;
|
193
|
-
for (const change of changes) {
|
194
|
-
if (change.type === 'attribute' && change.attributeKey != 'mention') {
|
195
|
-
// Checks the node on the left side of the range...
|
196
|
-
const nodeBefore = change.range.start.nodeBefore;
|
197
|
-
// ... and on the right side of the range.
|
198
|
-
const nodeAfter = change.range.end.nodeAfter;
|
199
|
-
for (const node of [nodeBefore, nodeAfter]) {
|
200
|
-
if (isBrokenMentionNode(node) && node.getAttribute(change.attributeKey) != change.attributeNewValue) {
|
201
|
-
writer.setAttribute(change.attributeKey, change.attributeNewValue, node);
|
202
|
-
wasChanged = true;
|
203
|
-
}
|
204
|
-
}
|
205
|
-
}
|
206
|
-
}
|
207
|
-
return wasChanged;
|
208
|
-
}
|
209
|
-
/**
|
210
|
-
* Checks if a node has a correct mention attribute if present.
|
211
|
-
* Returns `true` if the node is text and has a mention attribute whose text does not match the expected mention text.
|
212
|
-
*/
|
213
|
-
function isBrokenMentionNode(node) {
|
214
|
-
if (!node || !(node.is('$text') || node.is('$textProxy')) || !node.hasAttribute('mention')) {
|
215
|
-
return false;
|
216
|
-
}
|
217
|
-
const text = node.data;
|
218
|
-
const mention = node.getAttribute('mention');
|
219
|
-
const expectedText = mention._text;
|
220
|
-
return text != expectedText;
|
221
|
-
}
|
222
|
-
/**
|
223
|
-
* Fixes a mention on a text node if it needs a fix.
|
224
|
-
*/
|
225
|
-
function checkAndFix(textNode, writer) {
|
226
|
-
if (isBrokenMentionNode(textNode)) {
|
227
|
-
writer.removeAttribute('mention', textNode);
|
228
|
-
return true;
|
229
|
-
}
|
230
|
-
return false;
|
231
|
-
}
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module mention/mentionediting
|
7
|
+
*/
|
8
|
+
import { Plugin } from 'ckeditor5/src/core';
|
9
|
+
import { uid } from 'ckeditor5/src/utils';
|
10
|
+
import MentionCommand from './mentioncommand';
|
11
|
+
/**
|
12
|
+
* The mention editing feature.
|
13
|
+
*
|
14
|
+
* It introduces the {@link module:mention/mentioncommand~MentionCommand command} and the `mention`
|
15
|
+
* attribute in the {@link module:engine/model/model~Model model} which renders in the {@link module:engine/view/view view}
|
16
|
+
* as a `<span class="mention" data-mention="@mention">`.
|
17
|
+
*/
|
18
|
+
export default class MentionEditing extends Plugin {
|
19
|
+
/**
|
20
|
+
* @inheritDoc
|
21
|
+
*/
|
22
|
+
static get pluginName() {
|
23
|
+
return 'MentionEditing';
|
24
|
+
}
|
25
|
+
/**
|
26
|
+
* @inheritDoc
|
27
|
+
*/
|
28
|
+
init() {
|
29
|
+
const editor = this.editor;
|
30
|
+
const model = editor.model;
|
31
|
+
const doc = model.document;
|
32
|
+
// Allow the mention attribute on all text nodes.
|
33
|
+
model.schema.extend('$text', { allowAttributes: 'mention' });
|
34
|
+
// Upcast conversion.
|
35
|
+
editor.conversion.for('upcast').elementToAttribute({
|
36
|
+
view: {
|
37
|
+
name: 'span',
|
38
|
+
key: 'data-mention',
|
39
|
+
classes: 'mention'
|
40
|
+
},
|
41
|
+
model: {
|
42
|
+
key: 'mention',
|
43
|
+
value: (viewElement) => _toMentionAttribute(viewElement)
|
44
|
+
}
|
45
|
+
});
|
46
|
+
// Downcast conversion.
|
47
|
+
editor.conversion.for('downcast').attributeToElement({
|
48
|
+
model: 'mention',
|
49
|
+
view: createViewMentionElement
|
50
|
+
});
|
51
|
+
editor.conversion.for('downcast').add(preventPartialMentionDowncast);
|
52
|
+
doc.registerPostFixer(writer => removePartialMentionPostFixer(writer, doc, model.schema));
|
53
|
+
doc.registerPostFixer(writer => extendAttributeOnMentionPostFixer(writer, doc));
|
54
|
+
doc.registerPostFixer(writer => selectionMentionAttributePostFixer(writer, doc));
|
55
|
+
editor.commands.add('mention', new MentionCommand(editor));
|
56
|
+
}
|
57
|
+
}
|
58
|
+
/**
|
59
|
+
* @internal
|
60
|
+
*/
|
61
|
+
export function _addMentionAttributes(baseMentionData, data) {
|
62
|
+
return Object.assign({ uid: uid() }, baseMentionData, data || {});
|
63
|
+
}
|
64
|
+
/**
|
65
|
+
* Creates a mention attribute value from the provided view element and optional data.
|
66
|
+
*
|
67
|
+
* This function is exposed as
|
68
|
+
* {@link module:mention/mention~Mention#toMentionAttribute `editor.plugins.get( 'Mention' ).toMentionAttribute()`}.
|
69
|
+
*
|
70
|
+
* @internal
|
71
|
+
*/
|
72
|
+
export function _toMentionAttribute(viewElementOrMention, data) {
|
73
|
+
const dataMention = viewElementOrMention.getAttribute('data-mention');
|
74
|
+
const textNode = viewElementOrMention.getChild(0);
|
75
|
+
// Do not convert empty mentions.
|
76
|
+
if (!textNode) {
|
77
|
+
return;
|
78
|
+
}
|
79
|
+
const baseMentionData = {
|
80
|
+
id: dataMention,
|
81
|
+
_text: textNode.data
|
82
|
+
};
|
83
|
+
return _addMentionAttributes(baseMentionData, data);
|
84
|
+
}
|
85
|
+
/**
|
86
|
+
* A converter that blocks partial mention from being converted.
|
87
|
+
*
|
88
|
+
* This converter is registered with 'highest' priority in order to consume mention attribute before it is converted by
|
89
|
+
* any other converters. This converter only consumes partial mention - those whose `_text` attribute is not equal to text with mention
|
90
|
+
* attribute. This may happen when copying part of mention text.
|
91
|
+
*/
|
92
|
+
function preventPartialMentionDowncast(dispatcher) {
|
93
|
+
dispatcher.on('attribute:mention', (evt, data, conversionApi) => {
|
94
|
+
const mention = data.attributeNewValue;
|
95
|
+
if (!data.item.is('$textProxy') || !mention) {
|
96
|
+
return;
|
97
|
+
}
|
98
|
+
const start = data.range.start;
|
99
|
+
const textNode = start.textNode || start.nodeAfter;
|
100
|
+
if (textNode.data != mention._text) {
|
101
|
+
// Consume item to prevent partial mention conversion.
|
102
|
+
conversionApi.consumable.consume(data.item, evt.name);
|
103
|
+
}
|
104
|
+
}, { priority: 'highest' });
|
105
|
+
}
|
106
|
+
/**
|
107
|
+
* Creates a mention element from the mention data.
|
108
|
+
*/
|
109
|
+
function createViewMentionElement(mention, { writer }) {
|
110
|
+
if (!mention) {
|
111
|
+
return;
|
112
|
+
}
|
113
|
+
const attributes = {
|
114
|
+
class: 'mention',
|
115
|
+
'data-mention': mention.id
|
116
|
+
};
|
117
|
+
const options = {
|
118
|
+
id: mention.uid,
|
119
|
+
priority: 20
|
120
|
+
};
|
121
|
+
return writer.createAttributeElement('span', attributes, options);
|
122
|
+
}
|
123
|
+
/**
|
124
|
+
* Model post-fixer that disallows typing with selection when the selection is placed after the text node with the mention attribute or
|
125
|
+
* before a text node with mention attribute.
|
126
|
+
*/
|
127
|
+
function selectionMentionAttributePostFixer(writer, doc) {
|
128
|
+
const selection = doc.selection;
|
129
|
+
const focus = selection.focus;
|
130
|
+
if (selection.isCollapsed && selection.hasAttribute('mention') && shouldNotTypeWithMentionAt(focus)) {
|
131
|
+
writer.removeSelectionAttribute('mention');
|
132
|
+
return true;
|
133
|
+
}
|
134
|
+
return false;
|
135
|
+
}
|
136
|
+
/**
|
137
|
+
* Helper function to detect if mention attribute should be removed from selection.
|
138
|
+
* This check makes only sense if the selection has mention attribute.
|
139
|
+
*
|
140
|
+
* The mention attribute should be removed from a selection when selection focus is placed:
|
141
|
+
* a) after a text node
|
142
|
+
* b) the position is at parents start - the selection will set attributes from node after.
|
143
|
+
*/
|
144
|
+
function shouldNotTypeWithMentionAt(position) {
|
145
|
+
const isAtStart = position.isAtStart;
|
146
|
+
const isAfterAMention = position.nodeBefore && position.nodeBefore.is('$text');
|
147
|
+
return isAfterAMention || isAtStart;
|
148
|
+
}
|
149
|
+
/**
|
150
|
+
* Model post-fixer that removes the mention attribute from the modified text node.
|
151
|
+
*/
|
152
|
+
function removePartialMentionPostFixer(writer, doc, schema) {
|
153
|
+
const changes = doc.differ.getChanges();
|
154
|
+
let wasChanged = false;
|
155
|
+
for (const change of changes) {
|
156
|
+
if (change.type == 'attribute') {
|
157
|
+
continue;
|
158
|
+
}
|
159
|
+
// Checks the text node on the current position.
|
160
|
+
const position = change.position;
|
161
|
+
if (change.name == '$text') {
|
162
|
+
const nodeAfterInsertedTextNode = position.textNode && position.textNode.nextSibling;
|
163
|
+
// Checks the text node where the change occurred.
|
164
|
+
wasChanged = checkAndFix(position.textNode, writer) || wasChanged;
|
165
|
+
// Occurs on paste inside a text node with mention.
|
166
|
+
wasChanged = checkAndFix(nodeAfterInsertedTextNode, writer) || wasChanged;
|
167
|
+
wasChanged = checkAndFix(position.nodeBefore, writer) || wasChanged;
|
168
|
+
wasChanged = checkAndFix(position.nodeAfter, writer) || wasChanged;
|
169
|
+
}
|
170
|
+
// Checks text nodes in inserted elements (might occur when splitting a paragraph or pasting content inside text with mention).
|
171
|
+
if (change.name != '$text' && change.type == 'insert') {
|
172
|
+
const insertedNode = position.nodeAfter;
|
173
|
+
for (const item of writer.createRangeIn(insertedNode).getItems()) {
|
174
|
+
wasChanged = checkAndFix(item, writer) || wasChanged;
|
175
|
+
}
|
176
|
+
}
|
177
|
+
// Inserted inline elements might break mention.
|
178
|
+
if (change.type == 'insert' && schema.isInline(change.name)) {
|
179
|
+
const nodeAfterInserted = position.nodeAfter && position.nodeAfter.nextSibling;
|
180
|
+
wasChanged = checkAndFix(position.nodeBefore, writer) || wasChanged;
|
181
|
+
wasChanged = checkAndFix(nodeAfterInserted, writer) || wasChanged;
|
182
|
+
}
|
183
|
+
}
|
184
|
+
return wasChanged;
|
185
|
+
}
|
186
|
+
/**
|
187
|
+
* This post-fixer will extend the attribute applied on the part of the mention so the whole text node of the mention will have
|
188
|
+
* the added attribute.
|
189
|
+
*/
|
190
|
+
function extendAttributeOnMentionPostFixer(writer, doc) {
|
191
|
+
const changes = doc.differ.getChanges();
|
192
|
+
let wasChanged = false;
|
193
|
+
for (const change of changes) {
|
194
|
+
if (change.type === 'attribute' && change.attributeKey != 'mention') {
|
195
|
+
// Checks the node on the left side of the range...
|
196
|
+
const nodeBefore = change.range.start.nodeBefore;
|
197
|
+
// ... and on the right side of the range.
|
198
|
+
const nodeAfter = change.range.end.nodeAfter;
|
199
|
+
for (const node of [nodeBefore, nodeAfter]) {
|
200
|
+
if (isBrokenMentionNode(node) && node.getAttribute(change.attributeKey) != change.attributeNewValue) {
|
201
|
+
writer.setAttribute(change.attributeKey, change.attributeNewValue, node);
|
202
|
+
wasChanged = true;
|
203
|
+
}
|
204
|
+
}
|
205
|
+
}
|
206
|
+
}
|
207
|
+
return wasChanged;
|
208
|
+
}
|
209
|
+
/**
|
210
|
+
* Checks if a node has a correct mention attribute if present.
|
211
|
+
* Returns `true` if the node is text and has a mention attribute whose text does not match the expected mention text.
|
212
|
+
*/
|
213
|
+
function isBrokenMentionNode(node) {
|
214
|
+
if (!node || !(node.is('$text') || node.is('$textProxy')) || !node.hasAttribute('mention')) {
|
215
|
+
return false;
|
216
|
+
}
|
217
|
+
const text = node.data;
|
218
|
+
const mention = node.getAttribute('mention');
|
219
|
+
const expectedText = mention._text;
|
220
|
+
return text != expectedText;
|
221
|
+
}
|
222
|
+
/**
|
223
|
+
* Fixes a mention on a text node if it needs a fix.
|
224
|
+
*/
|
225
|
+
function checkAndFix(textNode, writer) {
|
226
|
+
if (isBrokenMentionNode(textNode)) {
|
227
|
+
writer.removeAttribute('mention', textNode);
|
228
|
+
return true;
|
229
|
+
}
|
230
|
+
return false;
|
231
|
+
}
|
package/src/mentionui.d.ts
CHANGED
@@ -1,102 +1,102 @@
|
|
1
|
-
/**
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
-
*/
|
5
|
-
/**
|
6
|
-
* @module mention/mentionui
|
7
|
-
*/
|
8
|
-
import { Plugin, type Editor } from 'ckeditor5/src/core';
|
9
|
-
import { ContextualBalloon } from 'ckeditor5/src/ui';
|
10
|
-
/**
|
11
|
-
* The mention UI feature.
|
12
|
-
*/
|
13
|
-
export default class MentionUI extends Plugin {
|
14
|
-
/**
|
15
|
-
* The mention view.
|
16
|
-
*/
|
17
|
-
private readonly _mentionsView;
|
18
|
-
/**
|
19
|
-
* Stores mention feeds configurations.
|
20
|
-
*/
|
21
|
-
private _mentionsConfigurations;
|
22
|
-
/**
|
23
|
-
* The contextual balloon plugin instance.
|
24
|
-
*/
|
25
|
-
private _balloon;
|
26
|
-
private _items;
|
27
|
-
private _lastRequested?;
|
28
|
-
/**
|
29
|
-
* Debounced feed requester. It uses `lodash#debounce` method to delay function call.
|
30
|
-
*/
|
31
|
-
private _requestFeedDebounced;
|
32
|
-
/**
|
33
|
-
* @inheritDoc
|
34
|
-
*/
|
35
|
-
static get pluginName(): "MentionUI";
|
36
|
-
/**
|
37
|
-
* @inheritDoc
|
38
|
-
*/
|
39
|
-
static get requires(): readonly [typeof ContextualBalloon];
|
40
|
-
/**
|
41
|
-
* @inheritDoc
|
42
|
-
*/
|
43
|
-
constructor(editor: Editor);
|
44
|
-
/**
|
45
|
-
* @inheritDoc
|
46
|
-
*/
|
47
|
-
init(): void;
|
48
|
-
/**
|
49
|
-
* @inheritDoc
|
50
|
-
*/
|
51
|
-
destroy(): void;
|
52
|
-
/**
|
53
|
-
* Returns true when {@link #_mentionsView} is in the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon} and it is
|
54
|
-
* currently visible.
|
55
|
-
*/
|
56
|
-
private get _isUIVisible();
|
57
|
-
/**
|
58
|
-
* Creates the {@link #_mentionsView}.
|
59
|
-
*/
|
60
|
-
private _createMentionView;
|
61
|
-
/**
|
62
|
-
* Returns item renderer for the marker.
|
63
|
-
*/
|
64
|
-
private _getItemRenderer;
|
65
|
-
/**
|
66
|
-
* Requests a feed from a configured callbacks.
|
67
|
-
*/
|
68
|
-
private _requestFeed;
|
69
|
-
/**
|
70
|
-
* Registers a text watcher for the marker.
|
71
|
-
*/
|
72
|
-
private _setupTextWatcher;
|
73
|
-
/**
|
74
|
-
* Handles the feed response event data.
|
75
|
-
*/
|
76
|
-
private _handleFeedResponse;
|
77
|
-
/**
|
78
|
-
* Shows the mentions balloon. If the panel is already visible, it will reposition it.
|
79
|
-
*/
|
80
|
-
private _showOrUpdateUI;
|
81
|
-
/**
|
82
|
-
* Hides the mentions balloon and removes the 'mention' marker from the markers collection.
|
83
|
-
*/
|
84
|
-
private _hideUIAndRemoveMarker;
|
85
|
-
/**
|
86
|
-
* Renders a single item in the autocomplete list.
|
87
|
-
*/
|
88
|
-
private _renderItem;
|
89
|
-
/**
|
90
|
-
* Creates a position options object used to position the balloon panel.
|
91
|
-
*
|
92
|
-
* @param mentionMarker
|
93
|
-
* @param preferredPosition The name of the last matched position name.
|
94
|
-
*/
|
95
|
-
private _getBalloonPanelPositionData;
|
96
|
-
}
|
97
|
-
/**
|
98
|
-
* Creates a RegExp pattern for the marker.
|
99
|
-
*
|
100
|
-
* Function has to be exported to achieve 100% code coverage.
|
101
|
-
*/
|
102
|
-
export declare function createRegExp(marker: string, minimumCharacters: number): RegExp;
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module mention/mentionui
|
7
|
+
*/
|
8
|
+
import { Plugin, type Editor } from 'ckeditor5/src/core';
|
9
|
+
import { ContextualBalloon } from 'ckeditor5/src/ui';
|
10
|
+
/**
|
11
|
+
* The mention UI feature.
|
12
|
+
*/
|
13
|
+
export default class MentionUI extends Plugin {
|
14
|
+
/**
|
15
|
+
* The mention view.
|
16
|
+
*/
|
17
|
+
private readonly _mentionsView;
|
18
|
+
/**
|
19
|
+
* Stores mention feeds configurations.
|
20
|
+
*/
|
21
|
+
private _mentionsConfigurations;
|
22
|
+
/**
|
23
|
+
* The contextual balloon plugin instance.
|
24
|
+
*/
|
25
|
+
private _balloon;
|
26
|
+
private _items;
|
27
|
+
private _lastRequested?;
|
28
|
+
/**
|
29
|
+
* Debounced feed requester. It uses `lodash#debounce` method to delay function call.
|
30
|
+
*/
|
31
|
+
private _requestFeedDebounced;
|
32
|
+
/**
|
33
|
+
* @inheritDoc
|
34
|
+
*/
|
35
|
+
static get pluginName(): "MentionUI";
|
36
|
+
/**
|
37
|
+
* @inheritDoc
|
38
|
+
*/
|
39
|
+
static get requires(): readonly [typeof ContextualBalloon];
|
40
|
+
/**
|
41
|
+
* @inheritDoc
|
42
|
+
*/
|
43
|
+
constructor(editor: Editor);
|
44
|
+
/**
|
45
|
+
* @inheritDoc
|
46
|
+
*/
|
47
|
+
init(): void;
|
48
|
+
/**
|
49
|
+
* @inheritDoc
|
50
|
+
*/
|
51
|
+
destroy(): void;
|
52
|
+
/**
|
53
|
+
* Returns true when {@link #_mentionsView} is in the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon} and it is
|
54
|
+
* currently visible.
|
55
|
+
*/
|
56
|
+
private get _isUIVisible();
|
57
|
+
/**
|
58
|
+
* Creates the {@link #_mentionsView}.
|
59
|
+
*/
|
60
|
+
private _createMentionView;
|
61
|
+
/**
|
62
|
+
* Returns item renderer for the marker.
|
63
|
+
*/
|
64
|
+
private _getItemRenderer;
|
65
|
+
/**
|
66
|
+
* Requests a feed from a configured callbacks.
|
67
|
+
*/
|
68
|
+
private _requestFeed;
|
69
|
+
/**
|
70
|
+
* Registers a text watcher for the marker.
|
71
|
+
*/
|
72
|
+
private _setupTextWatcher;
|
73
|
+
/**
|
74
|
+
* Handles the feed response event data.
|
75
|
+
*/
|
76
|
+
private _handleFeedResponse;
|
77
|
+
/**
|
78
|
+
* Shows the mentions balloon. If the panel is already visible, it will reposition it.
|
79
|
+
*/
|
80
|
+
private _showOrUpdateUI;
|
81
|
+
/**
|
82
|
+
* Hides the mentions balloon and removes the 'mention' marker from the markers collection.
|
83
|
+
*/
|
84
|
+
private _hideUIAndRemoveMarker;
|
85
|
+
/**
|
86
|
+
* Renders a single item in the autocomplete list.
|
87
|
+
*/
|
88
|
+
private _renderItem;
|
89
|
+
/**
|
90
|
+
* Creates a position options object used to position the balloon panel.
|
91
|
+
*
|
92
|
+
* @param mentionMarker
|
93
|
+
* @param preferredPosition The name of the last matched position name.
|
94
|
+
*/
|
95
|
+
private _getBalloonPanelPositionData;
|
96
|
+
}
|
97
|
+
/**
|
98
|
+
* Creates a RegExp pattern for the marker.
|
99
|
+
*
|
100
|
+
* Function has to be exported to achieve 100% code coverage.
|
101
|
+
*/
|
102
|
+
export declare function createRegExp(marker: string, minimumCharacters: number): RegExp;
|