Przeglądaj źródła

Try to prototype mention as element (quick).

Maciej Gołaszewski 6 lat temu
rodzic
commit
467c7223bd

+ 3 - 3
packages/ckeditor5-mention/src/mentionediting.js

@@ -29,6 +29,9 @@ export default class MentionEditing extends Plugin {
 	init() {
 		const editor = this.editor;
 
+		// Allow mention attribute on text nodes.
+		editor.model.schema.extend( '$text', { allowAttributes: 'mention' } );
+
 		editor.conversion.for( 'upcast' ).elementToAttribute( {
 			view: {
 				name: 'span',
@@ -53,9 +56,6 @@ export default class MentionEditing extends Plugin {
 			}
 		} );
 
-		// Allow fontSize attribute on text nodes.
-		editor.model.schema.extend( '$text', { allowAttributes: 'mention' } );
-
 		// Remove mention attribute if text was edited.
 		editor.model.document.registerPostFixer( writer => {
 			const changes = editor.model.document.differ.getChanges();

+ 117 - 0
packages/ckeditor5-mention/src/mentioneditingElement.js

@@ -0,0 +1,117 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module mention/mentionediting
+ */
+
+import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
+import Command from '@ckeditor/ckeditor5-core/src/command';
+import { viewToModelPositionOutsideModelElement } from '@ckeditor/ckeditor5-widget/src/utils';
+
+class MentionCommand extends Command {
+	/**
+	 * @inheritDoc
+	 */
+	refresh() {
+		// @todo implement refresh
+		this.isEnabled = true;
+	}
+
+	/**
+	 * Executes the command.
+	 *
+	 * @protected
+	 * @param {Object} [options] Options for the executed command.
+	 * @param {String} [options.marker='@'] The mention marker.
+	 * @param {String} options.mention.
+	 * @param {String} [options.range].
+	 * @fires execute
+	 */
+	execute( options = {} ) {
+		const model = this.editor.model;
+		const document = model.document;
+		const selection = document.selection;
+
+		const item = options.mention;
+		const range = options.range || selection.getFirstRange();
+
+		const label = item.label || item;
+
+		model.change( writer => {
+			writer.remove( range );
+
+			const mention = writer.createElement( 'mentionElement', { label, item } );
+
+			model.insertContent( mention );
+			writer.insertText( ' ', model.document.selection.focus );
+		} );
+	}
+}
+
+/**
+ * The mention editing feature.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class MentionElementEditing extends Plugin {
+	/**
+	 * @inheritDoc
+	 */
+	static get pluginName() {
+		return 'MentionElementEditing';
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	init() {
+		const editor = this.editor;
+
+		editor.model.schema.register( 'mentionElement', {
+			allowWhere: '$text',
+			isObject: true,
+			isInline: true,
+			allowAttributes: [ 'label', 'item' ]
+		} );
+
+		editor.conversion.for( 'downcast' ).elementToElement( {
+			model: 'mentionElement',
+			view: ( modelItem, viewWriter ) => {
+				const mentionElement = viewWriter.createContainerElement( 'span', { class: 'mention' } );
+
+				const viewText = viewWriter.createText( modelItem.getAttribute( 'label' ) );
+
+				viewWriter.insert( viewWriter.createPositionAt( mentionElement, 0 ), viewText );
+
+				return mentionElement;
+			}
+		} );
+
+		editor.conversion.for( 'upcast' ).elementToElement( {
+			view: 'mentionElement',
+			model: ( viewElement, modelWriter ) => {
+				let label = 'general';
+
+				if ( viewElement.childCount ) {
+					const text = viewElement.getChild( 0 );
+
+					if ( text.is( 'text' ) ) {
+						label = text;
+					}
+				}
+
+				return modelWriter.createElement( 'mentionElement', { label } );
+			}
+		} );
+
+		editor.editing.mapper.on(
+			'viewToModelPosition',
+			viewToModelPositionOutsideModelElement( editor.model, viewElement => viewElement.name == 'mentionElement' )
+		);
+
+		editor.commands.add( 'mention', new MentionCommand( editor ) );
+	}
+}

+ 66 - 5
packages/ckeditor5-mention/tests/manual/mention-custom-view.js

@@ -18,14 +18,18 @@ import Widget from '@ckeditor/ckeditor5-widget/src/widget';
 import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
 import ShiftEnter from '@ckeditor/ckeditor5-enter/src/shiftenter';
 import Table from '@ckeditor/ckeditor5-table/src/table';
-import Mention from '../../src/mention';
 import Link from '@ckeditor/ckeditor5-link/src/link';
 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 MentionUI from '../../src/mentionui';
+// eslint-disable-next-line no-unused-vars
+import MentionEditing from '../../src/mentionediting';
+// eslint-disable-next-line no-unused-vars
+import MentionElementEditing from '../../src/mentioneditingElement';
+
 const HIGHER_THEN_HIGHEST = priorities.highest + 50;
 
 class CustomMentionAttributeView extends Plugin {
@@ -73,11 +77,68 @@ class CustomMentionAttributeView extends Plugin {
 	}
 }
 
+// eslint-disable-next-line no-unused-vars
+class CustomMentionElementView extends Plugin {
+	init() {
+		const editor = this.editor;
+
+		editor.conversion.for( 'upcast' ).elementToElement( {
+			view: {
+				name: 'a',
+				classes: 'mention',
+				attributes: {
+					href: true
+				}
+			},
+			model: ( viewItem, modelWriter ) => {
+				const item = {
+					label: viewItem.getAttribute( 'data-mention' ),
+					link: viewItem.getAttribute( 'href' )
+				};
+
+				const frag = modelWriter.createDocumentFragment();
+				const mention = modelWriter.createElement( 'mention', { item } );
+
+				modelWriter.insert( mention, frag, 0 );
+
+				modelWriter.insertText( item.label, mention, 0 );
+
+				return mention;
+			},
+			converterPriority: HIGHER_THEN_HIGHEST
+		} );
+
+		editor.conversion.for( 'downcast' ).elementToElement( {
+			model: 'mentionElement',
+			view: ( modelElement, viewWriter ) => {
+				const item = modelElement.getAttribute( 'item' );
+
+				const link = viewWriter.createContainerElement( 'a', {
+					class: 'mention',
+					'data-mention': item.label,
+					'href': item.link
+				} );
+
+				return link;
+			},
+			converterPriority: HIGHER_THEN_HIGHEST
+		} );
+	}
+}
+
 ClassicEditor
 	.create( global.document.querySelector( '#editor' ), {
-		plugins: [ Enter, Typing, Paragraph, Heading, Link, Bold, Italic, Underline, Undo, Clipboard, Widget, ShiftEnter, Table,
-			Mention,
-			CustomMentionAttributeView
+		plugins: [ Enter, Typing, Paragraph, Link, Heading, Bold, Italic, Underline, Undo, Clipboard, Widget, ShiftEnter, Table,
+			// 1. Using attributes
+			MentionEditing,
+			CustomMentionAttributeView,
+
+			// 2. Using Element - buggy
+			// MentionElementEditing,
+			// CustomMentionElementView,
+
+			// Common: ui
+			MentionUI
 		],
 		toolbar: [ 'heading', '|', 'bold', 'italic', 'underline', 'link', '|', 'insertTable', '|', 'undo', 'redo' ],
 		mention: [