Răsfoiți Sursa

Added data pipeline conversion for todo lists.

Oskar Wróbel 6 ani în urmă
părinte
comite
05253e7217

+ 2 - 1
packages/ckeditor5-list/src/listediting.js

@@ -80,7 +80,8 @@ export default class ListEditing extends Plugin {
 
 		editing.downcastDispatcher.on( 'attribute:listType:listItem', modelViewChangeType, { priority: 'high' } );
 		editing.downcastDispatcher.on( 'attribute:listType:listItem', modelViewMergeAfterChangeType, { priority: 'low' } );
-		data.downcastDispatcher.on( 'attribute:listType:listItem', modelViewChangeType );
+		data.downcastDispatcher.on( 'attribute:listType:listItem', modelViewChangeType, { priority: 'high' } );
+		data.downcastDispatcher.on( 'attribute:listType:listItem', modelViewMergeAfterChangeType, { priority: 'low' } );
 		editing.downcastDispatcher.on( 'attribute:listIndent:listItem', modelViewChangeIndent( editor.model ) );
 		data.downcastDispatcher.on( 'attribute:listIndent:listItem', modelViewChangeIndent( editor.model ) );
 

+ 75 - 1
packages/ckeditor5-list/src/todolistconverters.js

@@ -49,7 +49,7 @@ export function modelViewInsertion( model ) {
 }
 
 /**
- * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute
+ * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert
  * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.
  * @param {Object} data Additional information about the change.
  * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.
@@ -70,6 +70,80 @@ export function modelViewTextInsertion( evt, data, conversionApi ) {
 	viewWriter.insert( viewPosition.offset ? viewPosition : viewPosition.getShiftedBy( 1 ), viewText );
 }
 
+/**
+ * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert
+ * @param {module:engine/model/model~Model} model Model instance.
+ * @returns {Function} Returns a conversion callback.
+ */
+export function dataModelViewInsertion( model ) {
+	return ( evt, data, conversionApi ) => {
+		const consumable = conversionApi.consumable;
+
+		if ( !consumable.test( data.item, 'insert' ) ||
+			!consumable.test( data.item, 'attribute:listType' ) ||
+			!consumable.test( data.item, 'attribute:listIndent' )
+		) {
+			return;
+		}
+
+		if ( data.item.getAttribute( 'listType' ) != 'todo' ) {
+			return;
+		}
+
+		consumable.consume( data.item, 'insert' );
+		consumable.consume( data.item, 'attribute:listType' );
+		consumable.consume( data.item, 'attribute:listIndent' );
+
+		const viewWriter = conversionApi.writer;
+		const modelItem = data.item;
+		const viewItem = generateLiInUl( modelItem, conversionApi );
+
+		viewWriter.addClass( 'todo-list', viewItem.parent );
+
+		const label = viewWriter.createAttributeElement( 'label' );
+		const checkbox = viewWriter.createEmptyElement( 'input', {
+			type: 'checkbox',
+			disabled: 'disabled',
+			class: 'todo-list__checkmark'
+		} );
+
+		if ( data.item.getAttribute( 'listChecked' ) ) {
+			viewWriter.setAttribute( 'checked', 'checked', checkbox );
+		}
+
+		viewWriter.insert( viewWriter.createPositionAt( viewItem, 0 ), checkbox );
+		viewWriter.wrap( viewWriter.createRangeOn( checkbox ), label );
+
+		injectViewList( modelItem, viewItem, conversionApi, model );
+	};
+}
+
+/**
+ * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert
+ * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.
+ * @param {Object} data Additional information about the change.
+ * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.
+ */
+export function dataModelViewTextInsertion( evt, data, conversionApi ) {
+	const parent = data.range.start.parent;
+
+	if ( parent.name != 'listItem' || parent.getAttribute( 'listType' ) != 'todo' ) {
+		return;
+	}
+
+	conversionApi.consumable.consume( data.item, 'insert' );
+
+	const viewWriter = conversionApi.writer;
+	const viewPosition = conversionApi.mapper.toViewPosition( data.range.start );
+	const viewText = viewWriter.createText( data.item.data );
+	const span = viewWriter.createAttributeElement( 'span', { class: 'todo-list__label' } );
+	const label = viewWriter.createAttributeElement( 'label' );
+
+	viewWriter.insert( viewWriter.createPositionAt( viewPosition.parent, 'end' ), viewText );
+	viewWriter.wrap( viewWriter.createRangeOn( viewText ), span );
+	viewWriter.wrap( viewWriter.createRangeOn( viewText.parent ), label );
+}
+
 /**
  * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute
  * @param {module:engine/model/model~Model} model Model instance.

+ 5 - 1
packages/ckeditor5-list/src/todolistediting.js

@@ -14,7 +14,9 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 
 import {
 	modelViewInsertion,
+	dataModelViewInsertion,
 	modelViewTextInsertion,
+	dataModelViewTextInsertion,
 	modelViewChangeChecked,
 	modelViewChangeType
 } from './todolistconverters';
@@ -35,7 +37,7 @@ export default class TodoListEditing extends Plugin {
 	 */
 	init() {
 		const editor = this.editor;
-		const { editing } = editor;
+		const { editing, data } = editor;
 		const viewDocument = editing.view.document;
 
 		editor.model.schema.extend( 'listItem', {
@@ -45,6 +47,8 @@ export default class TodoListEditing extends Plugin {
 		// Converters.
 		editing.downcastDispatcher.on( 'insert:listItem', modelViewInsertion( editor.model ), { priority: 'high' } );
 		editing.downcastDispatcher.on( 'insert:$text', modelViewTextInsertion, { priority: 'high' } );
+		data.downcastDispatcher.on( 'insert:listItem', dataModelViewInsertion( editor.model ), { priority: 'high' } );
+		data.downcastDispatcher.on( 'insert:$text', dataModelViewTextInsertion, { priority: 'high' } );
 
 		editing.downcastDispatcher.on( 'attribute:listType:listItem', modelViewChangeType( editor.model ) );
 		editing.downcastDispatcher.on( 'attribute:listChecked:listItem', modelViewChangeChecked( editor.model ) );