8
0
Oskar Wrobel 9 лет назад
Родитель
Сommit
3be58c11b3
1 измененных файлов с 60 добавлено и 38 удалено
  1. 60 38
      packages/ckeditor5-engine/tests/_utils/model.js

+ 60 - 38
packages/ckeditor5-engine/tests/_utils/model.js

@@ -23,7 +23,10 @@ import ViewText from '/ckeditor5/engine/view/text.js';
 import viewWriter from '/ckeditor5/engine/view/writer.js';
 
 import { parse as viewParse, stringify as viewStringify } from '/tests/engine/_utils/view.js';
-import { convertRangeSelection, convertCollapsedSelection } from '/ckeditor5/engine/conversion/model-selection-to-view-converters.js';
+import {
+	convertRangeSelection,
+	convertCollapsedSelection
+} from '/ckeditor5/engine/conversion/model-selection-to-view-converters.js';
 import { convertText, convertToModelFragment } from '/ckeditor5/engine/conversion/view-to-model-converters.js';
 
 // Test utils uses `<$text foo="bar">Lorem ipsum</$text>` notation to create text with attributes, but `$text` is not
@@ -34,6 +37,9 @@ const DATA_STRING_TEXT_WITH_ATTRIBUTES_ELEMENT = '$text';
 /**
  * Writes the contents of the {@link engine.model.Document Document} to an HTML-like string.
  *
+ * ** Note: ** {@link engine.model.Text text} node contains attributes will be represented as:
+ *        <$text attribute="value">Text data</$text>
+ *
  * @param {engine.model.Document} document
  * @param {Object} [options]
  * @param {Boolean} [options.withoutSelection=false] Whether to write the selection. When set to `true` selection will
@@ -61,8 +67,10 @@ getData._stringify = stringify;
  * Sets the contents of the {@link engine.model.Document Document} provided as HTML-like string.
  * It uses {@link engine.model.Document#enqueueChanges enqueueChanges} method.
  *
- * NOTE:
- * Remember to register elements in {@link engine.model.Document#schema document's schema} before inserting them.
+ * ** Note: ** Remember to register elements in {@link engine.model.Document#schema document's schema} before inserting them.
+ *
+ * ** Note: ** To create {@link engine.model.Text text} node witch containing attributes use:
+ *        <$text attribute="value">Text data</$text>
  *
  * @param {engine.model.Document} document
  * @param {String} data HTML-like string to write into Document.
@@ -77,29 +85,37 @@ export function setData( document, data, options = {} ) {
 		throw new TypeError( 'Document needs to be an instance of engine.model.Document.' );
 	}
 
+	let modelDocumentFragment, selection;
 	const mapper = new Mapper();
-	let model, selection;
-	const parseResult = setData._parse( data, document.schema, mapper );
+	const modelRoot = document.getRoot( options.rootName || 'main' );
+
+	// Parse data string to model.
+	const parsedResult = setData._parse( data, document.schema, mapper );
 
-	if ( parseResult.model ) {
-		model = parseResult.model;
-		selection = parseResult.selection;
+	// Retrieve DocumentFragment and Selection from parsed model.
+	if ( parsedResult.model ) {
+		modelDocumentFragment = parsedResult.model;
+		selection = parsedResult.selection;
 	} else {
-		model = parseResult;
+		modelDocumentFragment = parsedResult;
 	}
 
-	// Save to model.
-	const modelRoot = document.getRoot( options.rootName || 'main' );
-
 	document.enqueueChanges( () => {
+		// Replace existing model in document by new one.
 		document.batch( options.batchType || 'transparent' )
-			.remove( Range.createIn( modelRoot ) )
-			.insert( Position.createAt( modelRoot, 0 ), model );
+			.remove( Range.createFromElement( modelRoot ) )
+			.insert( Position.createAt( modelRoot, 0 ), modelDocumentFragment );
 
 		// Clear selection
 		document.selection.clearAttributes();
 		document.selection.removeAllRanges();
 
+		// Set attributes to selection if specified.
+		if ( options.selectionAttributes ) {
+			document.selection.setAttributesTo( options.selectionAttributes );
+		}
+
+		// Convert view selection to model if selection is defined.
 		if ( selection ) {
 			const ranges = [];
 
@@ -108,11 +124,6 @@ export function setData( document, data, options = {} ) {
 			}
 
 			document.selection.setRanges( ranges, selection.isBackward );
-
-			if ( options.selectionAttributes ) {
-				// Something overwrites selection attributes ??!!
-				document.selection.setAttributesTo( options.selectionAttributes );
-			}
 		}
 	} );
 }
@@ -123,6 +134,9 @@ setData._parse = parse;
 /**
  * Converts model nodes to HTML-like string representation.
  *
+ * ** Note: ** {@link engine.model.Text text} node contains attributes will be represented as:
+ *        <$text attribute="value">Text data</$text>
+ *
  * @param {engine.model.RootElement|engine.model.Element|engine.model.Text|
  * engine.model.DocumentFragment} node Node to stringify.
  * @param {engine.model.Selection|engine.model.Position|engine.model.Range} [selectionOrPositionOrRange=null]
@@ -151,6 +165,7 @@ export function stringify( node, selectionOrPositionOrRange = null ) {
 		}
 	}
 
+	// Get selection from passed selection or position or range if at least one is specified.
 	if ( selectionOrPositionOrRange instanceof ModelSelection ) {
 		selection = selectionOrPositionOrRange;
 	} else if ( selectionOrPositionOrRange instanceof Range ) {
@@ -178,7 +193,7 @@ export function stringify( node, selectionOrPositionOrRange = null ) {
 	modelToView.convertSelection( selection );
 	mapper.clearBindings();
 
-	// Return parsed to data model.
+	// Parse view to data string.
 	let data = viewStringify( viewDocumentFragment, viewSelection );
 
 	// Replace valid XML text element name to `$text`.
@@ -188,9 +203,14 @@ export function stringify( node, selectionOrPositionOrRange = null ) {
 /**
  * Parses HTML-like string and returns model {@link engine.model.RootElement rootElement}.
  *
+ * ** Note: ** To create {@link engine.model.Text text} node witch containing attributes use:
+ *        <$text attribute="value">Text data</$text>
+ *
  * @param {String} data HTML-like string to be parsed.
- * @param {engine.model.schema} schema Schema instance for element validation.
- * @param {engine.model.mapper} [mapper=new Mapper()] Mapper instance to keep relation with selection.
+ * @param {engine.model.schema} schema Schema instance uses by converters for validation. Element not registered
+ * in schema won't be created.
+ * @param {engine.model.mapper} [mapper=new Mapper()] Mapper instance uses mainly by `setData` method to map position
+ * between {@link engine.view.document Document} and {@link engine.model.document Document}.
  * @returns {engine.model.Element|engine.model.Text|engine.model.DocumentFragment|Object} Returns parsed model node or
  * object with two fields `model` and `selection` when selection ranges were included in data to parse.
  */
@@ -199,16 +219,16 @@ export function parse( data, schema, mapper = new Mapper() ) {
 	data = data.replace( new RegExp( '\\' + DATA_STRING_TEXT_WITH_ATTRIBUTES_ELEMENT, 'g' ), VIEW_TEXT_WITH_ATTRIBUTES_ELEMENT );
 
 	// Parse data to view using view utils.
-	const view = viewParse( data );
+	const parsedResult = viewParse( data );
 
 	// Retrieve DocumentFragment and Selection from parsed view.
 	let viewDocumentFragment, selection;
 
-	if ( view.view && view.selection ) {
-		viewDocumentFragment = view.view;
-		selection = view.selection;
+	if ( parsedResult.view && parsedResult.selection ) {
+		viewDocumentFragment = parsedResult.view;
+		selection = parsedResult.selection;
 	} else {
-		viewDocumentFragment = view;
+		viewDocumentFragment = parsedResult;
 	}
 
 	viewDocumentFragment = viewDocumentFragment.parent ? viewDocumentFragment.parent : viewDocumentFragment;
@@ -250,19 +270,21 @@ function convertToModelElement() {
 			inside: data.context
 		};
 
-		// `VIEW_TEXT_WITH_ATTRIBUTES_ELEMENT` can not be validate because it won't be registered in schema.
-		if ( data.input.name !== VIEW_TEXT_WITH_ATTRIBUTES_ELEMENT && !conversionApi.schema.check( schemaQuery ) ) {
-			throw new Error( `Conversion error - element ${ schemaQuery.name } not allowed in specified context.` );
-		}
+		// `VIEW_TEXT_WITH_ATTRIBUTES_ELEMENT` is handled in specified way by `convertToModelTextWithAttributes`.
+		if ( data.input.name !== VIEW_TEXT_WITH_ATTRIBUTES_ELEMENT ) {
+			if ( !conversionApi.schema.check( schemaQuery ) ) {
+				throw new Error( `Element '${ schemaQuery.name }' not allowed in context.` );
+			}
 
-		if ( consumable.consume( data.input, { name: true } ) ) {
-			data.output = new ModelElement( data.input.name, data.input.getAttributes() );
+			if ( consumable.consume( data.input, { name: true } ) ) {
+				data.output = new ModelElement( data.input.name, data.input.getAttributes() );
 
-			conversionApi.mapper.bindElements( data.output, data.input );
+				conversionApi.mapper.bindElements( data.output, data.input );
 
-			data.context.push( data.output );
-			data.output.appendChildren( conversionApi.convertChildren( data.input, consumable, data ) );
-			data.context.pop();
+				data.context.push( data.output );
+				data.output.appendChildren( conversionApi.convertChildren( data.input, consumable, data ) );
+				data.context.pop();
+			}
 		}
 	};
 }
@@ -275,7 +297,7 @@ function convertToModelTextWithAttributes() {
 		};
 
 		if ( !conversionApi.schema.check( schemaQuery ) ) {
-			throw new Error( `Conversion error - element ${ schemaQuery.name } not allowed in specified context.` );
+			throw new Error( `Element '${ schemaQuery.name }' not allowed in context.` );
 		}
 
 		if ( conversionApi.schema.check( schemaQuery ) ) {