|
|
@@ -23,6 +23,8 @@ import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
|
|
|
import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline';
|
|
|
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
|
|
|
import priorities from '@ckeditor/ckeditor5-utils/src/priorities';
|
|
|
+import ModelSelection from '@ckeditor/ckeditor5-engine/src/model/selection';
|
|
|
+import DocumentSelection from '@ckeditor/ckeditor5-engine/src/model/documentselection';
|
|
|
|
|
|
import MentionUI from '../../src/mentionui';
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
|
@@ -30,7 +32,7 @@ import MentionEditing from '../../src/mentionediting';
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
|
import MentionElementEditing from '../../src/mentioneditingelement';
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
|
-import MentionMarkerEditing from '../../src/mentioneditingmarker';
|
|
|
+import MentionMarkerEditing, { createMentionMarkerId } from '../../src/mentioneditingmarker';
|
|
|
|
|
|
const HIGHER_THEN_HIGHEST = priorities.highest + 50;
|
|
|
|
|
|
@@ -129,6 +131,60 @@ class CustomMentionElementView extends Plugin {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// eslint-disable-next-line no-unused-vars
|
|
|
+class CustomMentionMarkerView extends Plugin {
|
|
|
+ init() {
|
|
|
+ const editor = this.editor;
|
|
|
+
|
|
|
+ // Convert marker v->m.
|
|
|
+ editor.conversion.for( 'upcast' ).elementToMarker( {
|
|
|
+ view: {
|
|
|
+ name: 'a',
|
|
|
+ attribute: {
|
|
|
+ 'data-mention': /^\w/
|
|
|
+ }
|
|
|
+ },
|
|
|
+ model: viewElement => createMentionMarkerId( viewElement.getAttribute( 'data-mention' ) )
|
|
|
+ } );
|
|
|
+
|
|
|
+ editor.conversion.for( 'downcast' ).add( dispatcher => {
|
|
|
+ dispatcher.on( 'addMarker:mention', ( evt, data, conversionApi ) => {
|
|
|
+ const { id } = data.markerName.split( ':' )[ 1 ];
|
|
|
+
|
|
|
+ if ( !conversionApi.consumable.consume( data.item, evt.name ) ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const viewWriter = conversionApi.writer;
|
|
|
+
|
|
|
+ // OMG I just wanted to change `<span>` to `<a>`...
|
|
|
+ const viewElement = viewWriter.createAttributeElement( 'a', {
|
|
|
+ class: [ 'mention' ],
|
|
|
+ 'data-mention': id
|
|
|
+ } );
|
|
|
+ const viewSelection = viewWriter.document.selection;
|
|
|
+
|
|
|
+ if ( data.item instanceof ModelSelection || data.item instanceof DocumentSelection ) {
|
|
|
+ viewWriter.wrap( viewSelection.getFirstRange(), viewElement, viewSelection );
|
|
|
+ } else {
|
|
|
+ const viewRange = conversionApi.mapper.toViewRange( data.range );
|
|
|
+ const rangeAfterWrap = viewWriter.wrap( viewRange, viewElement );
|
|
|
+
|
|
|
+ for ( const element of rangeAfterWrap.getItems() ) {
|
|
|
+ if ( element.is( 'attributeElement' ) && element.isSimilar( viewElement ) ) {
|
|
|
+ conversionApi.mapper.bindElementToMarker( element, data.markerName );
|
|
|
+
|
|
|
+ // One attribute element is enough, because all of them are bound together by the view writer.
|
|
|
+ // Mapper uses this binding to get all the elements no matter how many of them are registered in the mapper.
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, { priority: HIGHER_THEN_HIGHEST } );
|
|
|
+ } );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
ClassicEditor
|
|
|
.create( global.document.querySelector( '#editor' ), {
|
|
|
plugins: [ Enter, Typing, Paragraph, Link, Heading, Bold, Italic, Underline, Undo, Clipboard, Widget, ShiftEnter, Table,
|
|
|
@@ -140,7 +196,9 @@ ClassicEditor
|
|
|
// MentionElementEditing,
|
|
|
// CustomMentionElementView,
|
|
|
|
|
|
+ // 3. Using marker - promising
|
|
|
MentionMarkerEditing,
|
|
|
+ CustomMentionMarkerView,
|
|
|
|
|
|
// Common: ui
|
|
|
MentionUI
|