8
0
Просмотр исходного кода

Merge branch 'master' into i/7890

Piotrek Koszuliński 5 лет назад
Родитель
Сommit
a54e0705d6
100 измененных файлов с 746 добавлено и 622 удалено
  1. 13 1
      docs/builds/guides/migrate.md
  2. 2 2
      packages/ckeditor-cloud-services-core/src/token/token.js
  3. 5 5
      packages/ckeditor-cloud-services-core/src/uploadgateway/fileuploader.js
  4. 2 2
      packages/ckeditor-cloud-services-core/src/uploadgateway/uploadgateway.js
  5. 2 2
      packages/ckeditor5-autoformat/tests/autoformat.js
  6. 6 1
      packages/ckeditor5-ckfinder/src/ckfindercommand.js
  7. 1 1
      packages/ckeditor5-ckfinder/tests/ckfindercommand.js
  8. 30 6
      packages/ckeditor5-clipboard/src/clipboard.js
  9. 49 0
      packages/ckeditor5-clipboard/src/pasteplaintext.js
  10. 5 3
      packages/ckeditor5-clipboard/src/utils/plaintexttohtml.js
  11. 3 0
      packages/ckeditor5-clipboard/src/utils/viewtoplaintext.js
  12. 94 1
      packages/ckeditor5-clipboard/tests/clipboard.js
  13. 96 0
      packages/ckeditor5-clipboard/tests/pasteplaintext.js
  14. 13 5
      packages/ckeditor5-clipboard/tests/utils/plaintexttohtml.js
  15. 16 0
      packages/ckeditor5-clipboard/tests/utils/viewtoplaintext.js
  16. 3 3
      packages/ckeditor5-code-block/src/codeblockediting.js
  17. 1 1
      packages/ckeditor5-core/src/commandcollection.js
  18. 4 6
      packages/ckeditor5-core/src/context.js
  19. 1 1
      packages/ckeditor5-core/src/editor/utils/attachtoform.js
  20. 1 1
      packages/ckeditor5-core/src/editor/utils/elementapimixin.js
  21. 1 2
      packages/ckeditor5-core/src/editor/utils/securesourceelement.js
  22. 1 1
      packages/ckeditor5-core/src/pendingactions.js
  23. 3 4
      packages/ckeditor5-core/src/plugincollection.js
  24. 1 1
      packages/ckeditor5-core/tests/_utils-tests/classictesteditor.js
  25. 2 5
      packages/ckeditor5-core/tests/_utils/classictesteditor.js
  26. 3 3
      packages/ckeditor5-core/tests/commandcollection.js
  27. 3 3
      packages/ckeditor5-core/tests/context.js
  28. 3 2
      packages/ckeditor5-core/tests/editor/editor.js
  29. 9 9
      packages/ckeditor5-core/tests/plugincollection.js
  30. 4 9
      packages/ckeditor5-editor-balloon/src/ballooneditor.js
  31. 3 12
      packages/ckeditor5-editor-balloon/tests/ballooneditor.js
  32. 2 5
      packages/ckeditor5-editor-classic/src/classiceditor.js
  33. 4 7
      packages/ckeditor5-editor-decoupled/src/decouplededitor.js
  34. 3 10
      packages/ckeditor5-editor-decoupled/tests/decouplededitor.js
  35. 4 7
      packages/ckeditor5-editor-inline/src/inlineeditor.js
  36. 3 12
      packages/ckeditor5-editor-inline/tests/inlineeditor.js
  37. 5 5
      packages/ckeditor5-engine/src/controller/datacontroller.js
  38. 3 4
      packages/ckeditor5-engine/src/conversion/conversion.js
  39. 1 2
      packages/ckeditor5-engine/src/conversion/downcasthelpers.js
  40. 1 1
      packages/ckeditor5-engine/src/conversion/upcastdispatcher.js
  41. 1 1
      packages/ckeditor5-engine/src/conversion/viewconsumable.js
  42. 5 13
      packages/ckeditor5-engine/src/model/document.js
  43. 2 2
      packages/ckeditor5-engine/src/model/documentselection.js
  44. 2 5
      packages/ckeditor5-engine/src/model/liveposition.js
  45. 12 7
      packages/ckeditor5-engine/src/model/markercollection.js
  46. 8 2
      packages/ckeditor5-engine/src/model/node.js
  47. 5 8
      packages/ckeditor5-engine/src/model/nodelist.js
  48. 3 4
      packages/ckeditor5-engine/src/model/operation/attributeoperation.js
  49. 1 1
      packages/ckeditor5-engine/src/model/operation/detachoperation.js
  50. 1 1
      packages/ckeditor5-engine/src/model/operation/insertoperation.js
  51. 3 3
      packages/ckeditor5-engine/src/model/operation/mergeoperation.js
  52. 3 3
      packages/ckeditor5-engine/src/model/operation/moveoperation.js
  53. 2 2
      packages/ckeditor5-engine/src/model/operation/renameoperation.js
  54. 5 10
      packages/ckeditor5-engine/src/model/operation/rootattributeoperation.js
  55. 4 4
      packages/ckeditor5-engine/src/model/operation/splitoperation.js
  56. 2 4
      packages/ckeditor5-engine/src/model/operation/utils.js
  57. 25 29
      packages/ckeditor5-engine/src/model/position.js
  58. 1 1
      packages/ckeditor5-engine/src/model/range.js
  59. 4 4
      packages/ckeditor5-engine/src/model/schema.js
  60. 8 19
      packages/ckeditor5-engine/src/model/selection.js
  61. 2 2
      packages/ckeditor5-engine/src/model/textproxy.js
  62. 7 6
      packages/ckeditor5-engine/src/model/treewalker.js
  63. 2 3
      packages/ckeditor5-engine/src/model/utils/insertcontent.js
  64. 31 37
      packages/ckeditor5-engine/src/model/writer.js
  65. 1 2
      packages/ckeditor5-engine/src/view/attributeelement.js
  66. 11 18
      packages/ckeditor5-engine/src/view/downcastwriter.js
  67. 1 1
      packages/ckeditor5-engine/src/view/emptyelement.js
  68. 1 1
      packages/ckeditor5-engine/src/view/node.js
  69. 4 8
      packages/ckeditor5-engine/src/view/position.js
  70. 1 1
      packages/ckeditor5-engine/src/view/rawelement.js
  71. 3 3
      packages/ckeditor5-engine/src/view/renderer.js
  72. 8 16
      packages/ckeditor5-engine/src/view/selection.js
  73. 2 2
      packages/ckeditor5-engine/src/view/textproxy.js
  74. 7 6
      packages/ckeditor5-engine/src/view/treewalker.js
  75. 1 1
      packages/ckeditor5-engine/src/view/uielement.js
  76. 1 3
      packages/ckeditor5-engine/src/view/view.js
  77. 6 6
      packages/ckeditor5-engine/tests/controller/datacontroller.js
  78. 1 1
      packages/ckeditor5-engine/tests/dev-utils/operationreplayer.js
  79. 2 2
      packages/ckeditor5-engine/tests/model/document.js
  80. 2 2
      packages/ckeditor5-engine/tests/model/markercollection.js
  81. 2 0
      packages/ckeditor5-engine/tests/model/model.js
  82. 1 1
      packages/ckeditor5-engine/tests/model/nodelist.js
  83. 1 1
      packages/ckeditor5-engine/tests/model/operation/operation.js
  84. 0 39
      packages/ckeditor5-engine/tests/model/operation/transform.js
  85. 12 12
      packages/ckeditor5-engine/tests/model/position.js
  86. 32 34
      packages/ckeditor5-engine/tests/model/schema.js
  87. 10 20
      packages/ckeditor5-engine/tests/model/selection.js
  88. 8 8
      packages/ckeditor5-engine/tests/model/writer.js
  89. 2 2
      packages/ckeditor5-engine/tests/tickets/ckeditor5-692.js
  90. 5 21
      packages/ckeditor5-engine/tests/view/documentselection.js
  91. 58 58
      packages/ckeditor5-engine/tests/view/domconverter/dom-to-view.js
  92. 3 3
      packages/ckeditor5-engine/tests/view/emptyelement.js
  93. 1 1
      packages/ckeditor5-engine/tests/view/node.js
  94. 1 1
      packages/ckeditor5-engine/tests/view/position.js
  95. 3 3
      packages/ckeditor5-engine/tests/view/rawelement.js
  96. 5 15
      packages/ckeditor5-engine/tests/view/selection.js
  97. 0 9
      packages/ckeditor5-engine/tests/view/styles/utils.js
  98. 3 3
      packages/ckeditor5-engine/tests/view/uielement.js
  99. 1 0
      packages/ckeditor5-engine/tests/view/view/view.js
  100. 1 2
      packages/ckeditor5-font/src/fontsize/fontsizeediting.js

Разница между файлами не показана из-за своего большого размера
+ 13 - 1
docs/builds/guides/migrate.md


+ 2 - 2
packages/ckeditor-cloud-services-core/src/token/token.js

@@ -41,7 +41,7 @@ class Token {
 			 * @error token-missing-token-url
 			 */
 			throw new CKEditorError(
-				'token-missing-token-url: A `tokenUrl` must be provided as the first constructor argument.',
+				'token-missing-token-url',
 				this
 			);
 		}
@@ -185,7 +185,7 @@ function defaultRefreshToken( tokenUrl ) {
 				 * @error token-cannot-download-new-token
 				 */
 				return reject(
-					new CKEditorError( 'token-cannot-download-new-token: Cannot download new token from the provided url.', null )
+					new CKEditorError( 'token-cannot-download-new-token', null )
 				);
 			}
 

+ 5 - 5
packages/ckeditor-cloud-services-core/src/uploadgateway/fileuploader.js

@@ -33,7 +33,7 @@ export default class FileUploader {
 			 *
 			 * @error fileuploader-missing-file
 			 */
-			throw new CKEditorError( 'fileuploader-missing-file: File must be provided as the first argument', null );
+			throw new CKEditorError( 'fileuploader-missing-file', null );
 		}
 
 		if ( !token ) {
@@ -42,7 +42,7 @@ export default class FileUploader {
 			 *
 			 * @error fileuploader-missing-token
 			 */
-			throw new CKEditorError( 'fileuploader-missing-token: Token must be provided as the second argument.', null );
+			throw new CKEditorError( 'fileuploader-missing-token', null );
 		}
 
 		if ( !apiAddress ) {
@@ -51,7 +51,7 @@ export default class FileUploader {
 			 *
 			 * @error fileuploader-missing-api-address
 			 */
-			throw new CKEditorError( 'fileuploader-missing-api-address: Api address must be provided as the third argument.', null );
+			throw new CKEditorError( 'fileuploader-missing-api-address', null );
 		}
 
 		/**
@@ -201,7 +201,7 @@ export default class FileUploader {
 						 * @error fileuploader-uploading-data-failed
 						 */
 						return reject( new CKEditorError(
-							'fileuploader-uploading-data-failed: Uploading file failed.',
+							'fileuploader-uploading-data-failed',
 							this,
 							{ message: xhrResponse.message }
 						) );
@@ -270,7 +270,7 @@ function _base64ToBlob( base64, sliceSize = 512 ) {
 		 *
 		 * @error fileuploader-decoding-image-data-error
 		 */
-		throw new CKEditorError( 'fileuploader-decoding-image-data-error: Problem with decoding Base64 image data.', null );
+		throw new CKEditorError( 'fileuploader-decoding-image-data-error', null );
 	}
 }
 

+ 2 - 2
packages/ckeditor-cloud-services-core/src/uploadgateway/uploadgateway.js

@@ -27,7 +27,7 @@ export default class UploadGateway {
 			 *
 			 * @error uploadgateway-missing-token
 			 */
-			throw new CKEditorError( 'uploadgateway-missing-token: Token must be provided.', null );
+			throw new CKEditorError( 'uploadgateway-missing-token', null );
 		}
 
 		if ( !apiAddress ) {
@@ -36,7 +36,7 @@ export default class UploadGateway {
 			 *
 			 * @error uploadgateway-missing-api-address
 			 */
-			throw new CKEditorError( 'uploadgateway-missing-api-address: Api address must be provided.', null );
+			throw new CKEditorError( 'uploadgateway-missing-api-address', null );
 		}
 
 		/**

+ 2 - 2
packages/ckeditor5-autoformat/tests/autoformat.js

@@ -486,7 +486,7 @@ describe( 'Autoformat', () => {
 		} );
 
 		describe( 'with code element', () => {
-			describe( 'should not format', () => {
+			describe( 'should not format (inside)', () => {
 				it( '* inside', () => {
 					setData( model, '<paragraph><$text code="true">fo*obar[]</$text></paragraph>' );
 
@@ -532,7 +532,7 @@ describe( 'Autoformat', () => {
 				} );
 			} );
 
-			describe( 'should not format', () => {
+			describe( 'should not format (across)', () => {
 				it( '* across', () => {
 					setData( model, '<paragraph><$text code="true">fo*o</$text>bar[]</paragraph>' );
 

+ 6 - 1
packages/ckeditor5-ckfinder/src/ckfindercommand.js

@@ -60,7 +60,12 @@ export default class CKFinderCommand extends Command {
 		const openerMethod = this.editor.config.get( 'ckfinder.openerMethod' ) || 'modal';
 
 		if ( openerMethod != 'popup' && openerMethod != 'modal' ) {
-			throw new CKEditorError( 'ckfinder-unknown-openerMethod: The openerMethod config option must by "popup" or "modal".', editor );
+			/**
+			 * The `ckfinder.openerMethod` must be one of: "popup" or "modal".
+			 *
+			 * @error ckfinder-unknown-openermethod
+			 */
+			throw new CKEditorError( 'ckfinder-unknown-openermethod', editor );
 		}
 
 		const options = this.editor.config.get( 'ckfinder.options' ) || {};

+ 1 - 1
packages/ckeditor5-ckfinder/tests/ckfindercommand.js

@@ -178,7 +178,7 @@ describe( 'CKFinderCommand', () => {
 
 			expectToThrowCKEditorError( () => {
 				command.execute();
-			}, /ckfinder-unknown-openerMethod/, editor );
+			}, 'ckfinder-unknown-openermethod', editor );
 		} );
 
 		it( 'should insert single chosen image', () => {

+ 30 - 6
packages/ckeditor5-clipboard/src/clipboard.js

@@ -8,6 +8,7 @@
  */
 
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
+import PastePlainText from './pasteplaintext';
 
 import ClipboardObserver from './clipboardobserver';
 
@@ -35,6 +36,13 @@ export default class Clipboard extends Plugin {
 		return 'Clipboard';
 	}
 
+	/**
+	 * @inheritDoc
+	 */
+	static get requires() {
+		return [ PastePlainText ];
+	}
+
 	/**
 	 * @inheritDoc
 	 */
@@ -77,7 +85,11 @@ export default class Clipboard extends Plugin {
 			content = this._htmlDataProcessor.toView( content );
 
 			const eventInfo = new EventInfo( this, 'inputTransformation' );
-			this.fire( eventInfo, { content, dataTransfer } );
+			this.fire( eventInfo, {
+				content,
+				dataTransfer,
+				asPlainText: data.asPlainText
+			} );
 
 			// If CKEditor handled the input, do not bubble the original event any further.
 			// This helps external integrations recognize that fact and act accordingly.
@@ -103,16 +115,27 @@ export default class Clipboard extends Plugin {
 					return;
 				}
 
-				// While pasting plain text, apply selection attributes on the text.
-				if ( isPlainText( modelFragment ) ) {
-					const node = modelFragment.getChild( 0 );
+				// Plain text can be determined based on event flag (#7799) or auto detection (#1006). If detected
+				// preserve selection attributes on pasted items.
+				if ( data.asPlainText || isPlainTextFragment( modelFragment ) ) {
+					// Consider only formatting attributes.
+					const textAttributes = new Map( Array.from( modelDocument.selection.getAttributes() ).filter(
+						keyValuePair => editor.model.schema.getAttributeProperties( keyValuePair[ 0 ] ).isFormatting
+					) );
 
 					model.change( writer => {
-						writer.setAttributes( modelDocument.selection.getAttributes(), node );
+						const range = writer.createRangeIn( modelFragment );
+
+						for ( const item of range.getItems() ) {
+							if ( item.is( '$text' ) || item.is( '$textProxy' ) ) {
+								writer.setAttributes( textAttributes, item );
+							}
+						}
 					} );
 				}
 
 				model.insertContent( modelFragment );
+
 				evt.stop();
 			}
 		}, { priority: 'low' } );
@@ -168,6 +191,7 @@ export default class Clipboard extends Plugin {
  * It can be modified by the event listeners. Read more about the clipboard pipelines in
  * {@glink framework/guides/deep-dive/clipboard "Clipboard" deep dive}.
  * @param {module:clipboard/datatransfer~DataTransfer} data.dataTransfer Data transfer instance.
+ * @param {Boolean} data.asPlainText If set to `true` content is pasted as plain text.
  */
 
 /**
@@ -212,7 +236,7 @@ export default class Clipboard extends Plugin {
 //
 // @param {module:engine/view/documentfragment~DocumentFragment} documentFragment
 // @returns {Boolean}
-function isPlainText( documentFragment ) {
+function isPlainTextFragment( documentFragment ) {
 	if ( documentFragment.childCount > 1 ) {
 		return false;
 	}

+ 49 - 0
packages/ckeditor5-clipboard/src/pasteplaintext.js

@@ -0,0 +1,49 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module clipboard/clipboard
+ */
+
+import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
+
+import ClipboardObserver from './clipboardobserver';
+
+/**
+ * The plugin detects user intentions for pasting plain text.
+ *
+ * For example, it detects <kbd>ctrl/cmd</kbd> + <kbd>shift</kbd> + <kbd>ctrl/v</kbd> keystroke.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class PastePlainText extends Plugin {
+	/**
+	 * @inheritDoc
+	 */
+	static get pluginName() {
+		return 'PastePlainText';
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	init() {
+		const view = this.editor.editing.view;
+		const viewDocument = view.document;
+		let shiftPressed = false;
+
+		view.addObserver( ClipboardObserver );
+
+		this.listenTo( viewDocument, 'keydown', ( evt, data ) => {
+			shiftPressed = data.shiftKey;
+		} );
+
+		this.listenTo( viewDocument, 'clipboardInput', ( evt, data ) => {
+			if ( shiftPressed ) {
+				data.asPlainText = true;
+			}
+		}, { priority: 'high' } );
+	}
+}

+ 5 - 3
packages/ckeditor5-clipboard/src/utils/plaintexttohtml.js

@@ -18,15 +18,17 @@ export default function plainTextToHtml( text ) {
 		// Encode <>.
 		.replace( /</g, '&lt;' )
 		.replace( />/g, '&gt;' )
-		// Creates paragraphs for every line breaks.
-		.replace( /\n/g, '</p><p>' )
+		// Creates a paragraph for each double line break.
+		.replace( /\r?\n\r?\n/g, '</p><p>' )
+		// Creates a line break for each single line break.
+		.replace( /\r?\n/g, '<br>' )
 		// Preserve trailing spaces (only the first and last one – the rest is handled below).
 		.replace( /^\s/, '&nbsp;' )
 		.replace( /\s$/, '&nbsp;' )
 		// Preserve other subsequent spaces now.
 		.replace( /\s\s/g, ' &nbsp;' );
 
-	if ( text.indexOf( '</p><p>' ) > -1 ) {
+	if ( text.includes( '</p><p>' ) || text.includes( '<br>' ) ) {
 		// If we created paragraphs above, add the trailing ones.
 		text = `<p>${ text }</p>`;
 	}

+ 3 - 0
packages/ckeditor5-clipboard/src/utils/viewtoplaintext.js

@@ -27,6 +27,9 @@ export default function viewToPlainText( viewItem ) {
 	} else if ( viewItem.is( 'element', 'img' ) && viewItem.hasAttribute( 'alt' ) ) {
 		// Special case for images - use alt attribute if it is provided.
 		text = viewItem.getAttribute( 'alt' );
+	} else if ( viewItem.is( 'element', 'br' ) ) {
+		// A soft break should be converted into a single line break (#8045).
+		text = '\n';
 	} else {
 		// Other elements are document fragments, attribute elements or container elements.
 		// They don't have their own text value, so convert their children.

+ 94 - 1
packages/ckeditor5-clipboard/tests/clipboard.js

@@ -112,7 +112,7 @@ describe( 'Clipboard feature', () => {
 				clipboardPlugin.on( 'inputTransformation', ( evt, data ) => {
 					expect( data.content ).is.instanceOf( ViewDocumentFragment );
 					expect( data.dataTransfer ).to.equal( dataTransferMock );
-					expect( stringifyView( data.content ) ).to.equal( '<p>x</p><p></p><p>y  z</p>' );
+					expect( stringifyView( data.content ) ).to.equal( '<p>x</p><p>y  z</p>' );
 
 					done();
 				} );
@@ -351,6 +351,19 @@ describe( 'Clipboard feature', () => {
 				model = editor.model;
 
 				model.schema.extend( '$text', { allowAttributes: 'bold' } );
+				model.schema.extend( '$text', { allowAttributes: 'test' } );
+
+				editor.model.schema.setAttributeProperties( 'bold', { isFormatting: true } );
+
+				model.schema.register( 'softBreak', {
+					allowWhere: '$text',
+					isInline: true
+				} );
+				editor.conversion.for( 'upcast' )
+					.elementToElement( {
+						model: 'softBreak',
+						view: 'br'
+					} );
 			} );
 
 			it( 'should inherit selection attributes (collapsed selection)', () => {
@@ -451,6 +464,86 @@ describe( 'Clipboard feature', () => {
 
 				expect( getModelData( model ) ).to.equal( '<paragraph><$text bold="true">Bolded foo[]text.</$text></paragraph>' );
 			} );
+
+			it( 'should inherit selection attributes with data.asPlainText switch set', () => {
+				setModelData( model, '<paragraph><$text bold="true">Bolded []text.</$text></paragraph>' );
+
+				const dataTransferMock = createDataTransfer( {
+					'text/html': 'foo',
+					'text/plain': 'foo'
+				} );
+
+				viewDocument.fire( 'clipboardInput', {
+					dataTransfer: dataTransferMock,
+					asPlainText: true,
+					stopPropagation() {},
+					preventDefault() {}
+				} );
+
+				expect( getModelData( model ) ).to.equal( '<paragraph><$text bold="true">Bolded foo[]text.</$text></paragraph>' );
+			} );
+
+			it( 'should discard selection attributes with data.asPlainText switch set to false', () => {
+				setModelData( model, '<paragraph><$text bold="true">Bolded []text.</$text></paragraph>' );
+
+				const dataTransferMock = createDataTransfer( {
+					'text/html': 'foo<br>bar',
+					'text/plain': 'foo\nbar'
+				} );
+
+				viewDocument.fire( 'clipboardInput', {
+					dataTransfer: dataTransferMock,
+					asPlainText: false,
+					stopPropagation() {},
+					preventDefault() {}
+				} );
+
+				expect( getModelData( model ) ).to.equal( '<paragraph><$text bold="true">Bolded </$text>' +
+					'foo<softBreak></softBreak>bar[]' +
+					'<$text bold="true">text.</$text></paragraph>' );
+			} );
+
+			it( 'should work if the insertContent event is cancelled', () => {
+				// (#7887).
+				setModelData( model, '<paragraph><$text bold="true">Bolded []text.</$text></paragraph>' );
+
+				const dataTransferMock = createDataTransfer( {
+					'text/html': 'foo',
+					'text/plain': 'foo'
+				} );
+
+				model.on( 'insertContent', event => {
+					event.stop();
+				}, { priority: 'high' } );
+
+				viewDocument.fire( 'clipboardInput', {
+					dataTransfer: dataTransferMock,
+					asPlainText: false,
+					stopPropagation() {},
+					preventDefault() {}
+				} );
+
+				expect( getModelData( model ) ).to.equal( '<paragraph><$text bold="true">Bolded []text.</$text></paragraph>' );
+			} );
+
+			it( 'ignores non-formatting text attributes', () => {
+				setModelData( model, '<paragraph><$text test="true">Bolded []text.</$text></paragraph>' );
+
+				const dataTransferMock = createDataTransfer( {
+					'text/html': 'foo',
+					'text/plain': 'foo'
+				} );
+
+				viewDocument.fire( 'clipboardInput', {
+					dataTransfer: dataTransferMock,
+					asPlainText: false,
+					stopPropagation() {},
+					preventDefault() {}
+				} );
+
+				expect( getModelData( model ) ).to.equal(
+					'<paragraph><$text test="true">Bolded </$text>foo[]<$text test="true">text.</$text></paragraph>' );
+			} );
 		} );
 
 		function createDataTransfer( data ) {

+ 96 - 0
packages/ckeditor5-clipboard/tests/pasteplaintext.js

@@ -0,0 +1,96 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
+
+import PastePlainText from '../src/pasteplaintext';
+import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
+
+import { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard';
+
+/* global document */
+
+describe( 'PastePlainText', () => {
+	let editor, viewDocument;
+
+	beforeEach( () => {
+		return VirtualTestEditor
+			.create( {
+				plugins: [ PastePlainText, Paragraph ]
+			} )
+			.then( newEditor => {
+				editor = newEditor;
+				viewDocument = editor.editing.view.document;
+			} );
+	} );
+
+	it( 'marks clipboard input as plain text with shift pressed', () => {
+		const dataTransferMock = createDataTransfer( { 'text/html': '<p>x</p>', 'text/plain': 'y' } );
+
+		viewDocument.on( 'clipboardInput', ( event, data ) => {
+			expect( data.asPlainText ).to.be.true;
+
+			// No need for further execution.
+			event.stop();
+		} );
+
+		viewDocument.fire( 'keydown', {
+			keyCode: getCode( 'v' ),
+			shiftKey: true,
+			ctrlKey: true,
+			preventDefault: () => {},
+			domTarget: document.body
+		} );
+
+		viewDocument.fire( 'clipboardInput', {
+			dataTransfer: dataTransferMock
+		} );
+	} );
+
+	it( 'ignores clipboard input as plain text when shift was released', () => {
+		const dataTransferMock = createDataTransfer( { 'text/html': '<p>x</p>', 'text/plain': 'y' } );
+
+		viewDocument.on( 'clipboardInput', ( event, data ) => {
+			expect( data.asPlainText ).to.be.undefined;
+
+			// No need for further execution.
+			event.stop();
+		} );
+
+		viewDocument.fire( 'keydown', {
+			keyCode: getCode( 'a' ),
+			shiftKey: true,
+			preventDefault: () => {},
+			domTarget: document.body
+		} );
+
+		viewDocument.fire( 'keyup', {
+			keyCode: getCode( 'a' ),
+			shiftKey: true,
+			preventDefault: () => {},
+			domTarget: document.body
+		} );
+
+		viewDocument.fire( 'keydown', {
+			keyCode: getCode( 'v' ),
+			shiftKey: false,
+			ctrlKey: true,
+			preventDefault: () => {},
+			domTarget: document.body
+		} );
+
+		viewDocument.fire( 'clipboardInput', {
+			dataTransfer: dataTransferMock
+		} );
+	} );
+
+	function createDataTransfer( data ) {
+		return {
+			getData( type ) {
+				return data[ type ];
+			}
+		};
+	}
+} );

+ 13 - 5
packages/ckeditor5-clipboard/tests/utils/plaintexttohtml.js

@@ -10,16 +10,24 @@ describe( 'plainTextToHtml()', () => {
 		expect( plainTextToHtml( 'x y <z>' ) ).to.equal( 'x y &lt;z&gt;' );
 	} );
 
-	it( 'turns a single line break into paragraphs', () => {
-		expect( plainTextToHtml( 'x\ny\nz' ) ).to.equal( '<p>x</p><p>y</p><p>z</p>' );
+	it( 'turns double line breaks into paragraphs (Linux/Mac EOL style)', () => {
+		expect( plainTextToHtml( 'x\n\ny\n\nz' ) ).to.equal( '<p>x</p><p>y</p><p>z</p>' );
 	} );
 
-	it( 'turns double line breaks into paragraphs', () => {
-		expect( plainTextToHtml( 'x\n\ny\n\nz' ) ).to.equal( '<p>x</p><p></p><p>y</p><p></p><p>z</p>' );
+	it( 'turns double line breaks into paragraphs (Windows EOL style)', () => {
+		expect( plainTextToHtml( 'x\r\n\r\ny\r\n\r\nz' ) ).to.equal( '<p>x</p><p>y</p><p>z</p>' );
+	} );
+
+	it( 'turns single line breaks into soft breaks (Linux/Mac EOL style)', () => {
+		expect( plainTextToHtml( 'x\ny\nz' ) ).to.equal( '<p>x<br>y<br>z</p>' );
+	} );
+
+	it( 'turns single line breaks into soft breaks (Windows EOL style)', () => {
+		expect( plainTextToHtml( 'x\r\ny\r\nz' ) ).to.equal( '<p>x<br>y<br>z</p>' );
 	} );
 
 	it( 'turns combination of different amount of line breaks to paragraphs', () => {
-		expect( plainTextToHtml( 'a\nb\n\nc\n\n\nd' ) ).to.equal( '<p>a</p><p>b</p><p></p><p>c</p><p></p><p></p><p>d</p>' );
+		expect( plainTextToHtml( 'a\n\nb\nc\n\n\n\nd\ne' ) ).to.equal( '<p>a</p><p>b<br>c</p><p></p><p>d<br>e</p>' );
 	} );
 
 	it( 'preserves trailing spaces', () => {

+ 16 - 0
packages/ckeditor5-clipboard/tests/utils/viewtoplaintext.js

@@ -34,6 +34,22 @@ describe( 'viewToPlainText()', () => {
 		);
 	} );
 
+	it( 'should turn a soft break into a single empty line', () => {
+		testViewToPlainText(
+			'<container:p>Foo<empty:br />Bar</container:p>',
+
+			'Foo\nBar'
+		);
+	} );
+
+	it( 'should turn multiple soft breaks into empty lines', () => {
+		testViewToPlainText(
+			'<container:p>Foo<empty:br /><empty:br />Bar</container:p>',
+
+			'Foo\n\nBar'
+		);
+	} );
+
 	it( 'should output alt attribute of image elements', () => {
 		testViewToPlainText(
 			'<container:p>Foo</container:p>' +

+ 3 - 3
packages/ckeditor5-code-block/src/codeblockediting.js

@@ -214,9 +214,9 @@ export default class CodeBlockEditing extends Plugin {
 				return;
 			}
 
-			leaveBlockStartOnEnter( editor, data.isSoft ) ||
-			leaveBlockEndOnEnter( editor, data.isSoft ) ||
-			breakLineOnEnter( editor );
+			if ( !leaveBlockStartOnEnter( editor, data.isSoft ) && !leaveBlockEndOnEnter( editor, data.isSoft ) ) {
+				breakLineOnEnter( editor );
+			}
 
 			data.preventDefault();
 			evt.stop();

+ 1 - 1
packages/ckeditor5-core/src/commandcollection.js

@@ -63,7 +63,7 @@ export default class CommandCollection {
 			 * @error commandcollection-command-not-found
 			 * @param {String} commandName Name of the command.
 			 */
-			throw new CKEditorError( 'commandcollection-command-not-found: Command does not exist.', this, { commandName } );
+			throw new CKEditorError( 'commandcollection-command-not-found', this, { commandName } );
 		}
 
 		return command.execute( ...args );

+ 4 - 6
packages/ckeditor5-core/src/context.js

@@ -125,7 +125,7 @@ export default class Context {
 				 * @error context-initplugins-constructor-only
 				 */
 				throw new CKEditorError(
-					'context-initplugins-constructor-only: Only a constructor function is allowed as a context plugin.',
+					'context-initplugins-constructor-only',
 					null,
 					{ Plugin }
 				);
@@ -139,7 +139,7 @@ export default class Context {
 				 * @error context-initplugins-invalid-plugin
 				 */
 				throw new CKEditorError(
-					'context-initplugins-invalid-plugin: Only a plugin marked as a context plugin is allowed to be used with a context.',
+					'context-initplugins-invalid-plugin',
 					null,
 					{ Plugin }
 				);
@@ -177,11 +177,9 @@ export default class Context {
 			/**
 			 * Cannot add multiple editors to the context which is created by the editor.
 			 *
-			 * @error context-addEditor-private-context
+			 * @error context-addeditor-private-context
 			 */
-			throw new CKEditorError(
-				'context-addEditor-private-context: Cannot add multiple editors to the context which is created by the editor.'
-			);
+			throw new CKEditorError( 'context-addeditor-private-context' );
 		}
 
 		this.editors.add( editor );

+ 1 - 1
packages/ckeditor5-core/src/editor/utils/attachtoform.js

@@ -27,7 +27,7 @@ export default function attachToForm( editor ) {
 		 * @error attachtoform-missing-elementapi-interface
 		 */
 		throw new CKEditorError(
-			'attachtoform-missing-elementapi-interface: Editor passed to attachToForm() must implement ElementApi.',
+			'attachtoform-missing-elementapi-interface',
 			editor
 		);
 	}

+ 1 - 1
packages/ckeditor5-core/src/editor/utils/elementapimixin.js

@@ -31,7 +31,7 @@ const ElementApiMixin = {
 			 * @error editor-missing-sourceelement
 			 */
 			throw new CKEditorError(
-				'editor-missing-sourceelement: Cannot update the source element of a detached editor.',
+				'editor-missing-sourceelement',
 				this
 			);
 		}

+ 1 - 2
packages/ckeditor5-core/src/editor/utils/securesourceelement.js

@@ -36,8 +36,7 @@ export default function secureSourceElement( editor ) {
 		 * @param {HTMLElement} element DOM element that caused the collision.
 		 */
 		throw new CKEditorError(
-			'editor-source-element-already-used: ' +
-			'The DOM element cannot be used to create multiple editor instances.',
+			'editor-source-element-already-used',
 			editor
 		);
 	}

+ 1 - 1
packages/ckeditor5-core/src/pendingactions.js

@@ -99,7 +99,7 @@ export default class PendingActions extends ContextPlugin {
 			 *
 			 * @error pendingactions-add-invalid-message
 			 */
-			throw new CKEditorError( 'pendingactions-add-invalid-message: The message must be a string.', this );
+			throw new CKEditorError( 'pendingactions-add-invalid-message', this );
 		}
 
 		const action = Object.create( ObservableMixin );

+ 3 - 4
packages/ckeditor5-core/src/plugincollection.js

@@ -295,7 +295,7 @@ export default class PluginCollection {
 							 * @param {String} requiredBy The name of the parent plugin.
 							 */
 							throw new CKEditorError(
-								'plugincollection-context-required: Context plugin can not require plugin which is not a context plugin',
+								'plugincollection-context-required',
 								null,
 								{ plugin: RequiredPluginConstructor.name, requiredBy: PluginConstructor.name }
 							);
@@ -310,8 +310,7 @@ export default class PluginCollection {
 							 * @param {String} requiredBy The name of the parent plugin.
 							 */
 							throw new CKEditorError(
-								'plugincollection-required: Cannot load a plugin because one of its dependencies is listed in' +
-								'the `removePlugins` option.',
+								'plugincollection-required',
 								context,
 								{ plugin: RequiredPluginConstructor.name, requiredBy: PluginConstructor.name }
 							);
@@ -421,7 +420,7 @@ export default class PluginCollection {
 			 * @param {Function} plugin2 The second plugin constructor.
 			 */
 			throw new CKEditorError(
-				'plugincollection-plugin-name-conflict: Two plugins with the same name were loaded.',
+				'plugincollection-plugin-name-conflict',
 				null,
 				{ pluginName, plugin1: this._plugins.get( pluginName ).constructor, plugin2: PluginConstructor }
 			);

+ 1 - 1
packages/ckeditor5-core/tests/_utils-tests/classictesteditor.js

@@ -232,7 +232,7 @@ describe( 'ClassicTestEditor', () => {
 				.then( () => {
 					throw new Error( 'It should throw an error' );
 				}, err => {
-					assertCKEditorError( err, /^editor-create-initial-data:/, null );
+					assertCKEditorError( err, 'editor-create-initial-data', null );
 					removeEditorBodyOrphans();
 				} );
 		} );

+ 2 - 5
packages/ckeditor5-core/tests/_utils/classictesteditor.js

@@ -77,11 +77,8 @@ export default class ClassicTestEditor extends Editor {
 					.then( () => {
 						if ( !isElement( sourceElementOrData ) && config.initialData ) {
 							// Documented in core/editor/editorconfig.jsdoc.
-							throw new CKEditorError(
-								'editor-create-initial-data: ' +
-								'The config.initialData option cannot be used together with initial data passed in Editor.create().',
-								null
-							);
+							// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
+							throw new CKEditorError( 'editor-create-initial-data', null );
 						}
 
 						editor.data.init( config.initialData || getInitialData( sourceElementOrData ) );

+ 3 - 3
packages/ckeditor5-core/tests/commandcollection.js

@@ -75,7 +75,7 @@ describe( 'CommandCollection', () => {
 
 			expectToThrowCKEditorError( () => {
 				collection.execute( 'foo' );
-			}, /^commandcollection-command-not-found:/, editor );
+			}, 'commandcollection-command-not-found', editor );
 		} );
 	} );
 
@@ -135,8 +135,8 @@ describe( 'CommandCollection', () => {
 		} );
 	} );
 
-	describe( 'commands()', () => {
-		it( 'returns iterator of commands', () => {
+	describe( 'destroy()', () => {
+		it( 'should destroy commands', () => {
 			const c1 = new SomeCommand( editor );
 			const c2 = new SomeCommand( editor );
 

+ 3 - 3
packages/ckeditor5-core/tests/context.js

@@ -113,7 +113,7 @@ describe( 'Context', () => {
 
 			expect( caughtError ).to.instanceof( CKEditorError );
 			expect( caughtError.message )
-				.match( /^context-initplugins-invalid-plugin:/ );
+				.match( /^context-initplugins-invalid-plugin/ );
 		} );
 
 		it( 'should throw when plugin added to the context is not marked as a ContextPlugin (Function)', async () => {
@@ -129,7 +129,7 @@ describe( 'Context', () => {
 
 			expect( caughtError ).to.instanceof( CKEditorError );
 			expect( caughtError.message )
-				.match( /^context-initplugins-invalid-plugin:/ );
+				.match( /^context-initplugins-invalid-plugin/ );
 		} );
 
 		it( 'should throw when plugin is added to the context by name', async () => {
@@ -143,7 +143,7 @@ describe( 'Context', () => {
 
 			expect( caughtError ).to.instanceof( CKEditorError );
 			expect( caughtError.message )
-				.match( /^context-initplugins-constructor-only:/ );
+				.match( /^context-initplugins-constructor-only/ );
 		} );
 
 		it( 'should not throw when plugin as a function, marked as a ContextPlugin is added to the context', async () => {

+ 3 - 2
packages/ckeditor5-core/tests/editor/editor.js

@@ -201,7 +201,7 @@ describe( 'Editor', () => {
 			expectToThrowCKEditorError( () => {
 				// eslint-disable-next-line no-new
 				new TestEditor( { context: editor._context } );
-			}, /^context-addEditor-private-context/ );
+			}, 'context-addeditor-private-context' );
 		} );
 
 		it( 'should destroy context created by the editor at the end of the editor destroy chain', async () => {
@@ -510,7 +510,7 @@ describe( 'Editor', () => {
 
 			expectToThrowCKEditorError( () => {
 				editor.execute( 'command' );
-			}, /^commandcollection-command-not-found:/, editor );
+			}, /^commandcollection-command-not-found/, editor );
 		} );
 
 		it( 'should rethrow native errors as they are in the debug=true mode', () => {
@@ -543,6 +543,7 @@ describe( 'Editor', () => {
 					this.isEnabled = true;
 				}
 				execute() {
+					// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
 					throw new CKEditorError( 'foo', editor );
 				}
 			}

+ 9 - 9
packages/ckeditor5-core/tests/plugincollection.js

@@ -255,7 +255,7 @@ describe( 'PluginCollection', () => {
 					expect( err ).to.have.property( 'message', 'Some error inside a plugin' );
 
 					sinon.assert.calledOnce( consoleErrorStub );
-					expect( consoleErrorStub.args[ 0 ][ 0 ] ).to.match( /^plugincollection-load:/ );
+					expect( consoleErrorStub.args[ 0 ][ 0 ] ).to.match( /^plugincollection-load/ );
 				} );
 		} );
 
@@ -270,10 +270,10 @@ describe( 'PluginCollection', () => {
 					throw new Error( 'Test error: this promise should not be resolved successfully' );
 				} )
 				.catch( err => {
-					assertCKEditorError( err, /^plugincollection-plugin-not-found/, editor );
+					assertCKEditorError( err, 'plugincollection-plugin-not-found', editor );
 
 					sinon.assert.calledOnce( consoleErrorStub );
-					expect( consoleErrorStub.args[ 0 ][ 0 ] ).to.match( /^plugincollection-plugin-not-found:/ );
+					expect( consoleErrorStub.args[ 0 ][ 0 ] ).to.match( /^plugincollection-plugin-not-found/ );
 				} );
 		} );
 
@@ -409,7 +409,7 @@ describe( 'PluginCollection', () => {
 					throw new Error( 'The `init()` method should fail.' );
 				} )
 				.catch( err => {
-					assertCKEditorError( err, /^plugincollection-plugin-name-conflict:/, null, {
+					assertCKEditorError( err, /^plugincollection-plugin-name-conflict/, null, {
 						pluginName: 'Foo',
 						plugin1: PluginFoo,
 						plugin2: AnotherPluginFoo
@@ -429,7 +429,7 @@ describe( 'PluginCollection', () => {
 					throw new Error( 'The `init()` method should fail.' );
 				} )
 				.catch( err => {
-					assertCKEditorError( err, /^plugincollection-plugin-name-conflict:/, null );
+					assertCKEditorError( err, /^plugincollection-plugin-name-conflict/, null );
 
 					sinon.assert.calledOnce( consoleErrorStub );
 				} );
@@ -447,7 +447,7 @@ describe( 'PluginCollection', () => {
 					throw new Error( 'The `init()` method should fail.' );
 				} )
 				.catch( err => {
-					assertCKEditorError( err, /^plugincollection-plugin-name-conflict:/, null );
+					assertCKEditorError( err, /^plugincollection-plugin-name-conflict/, null );
 					sinon.assert.calledOnce( consoleErrorStub );
 				} );
 		} );
@@ -521,7 +521,7 @@ describe( 'PluginCollection', () => {
 
 			return plugins.init( [] ).then( () => {
 				expectToThrowCKEditorError( () => plugins.get( 'foo' ),
-					/^plugincollection-plugin-not-loaded:/, editor, { plugin: 'foo' }
+					/^plugincollection-plugin-not-loaded/, editor, { plugin: 'foo' }
 				);
 			} );
 		} );
@@ -534,7 +534,7 @@ describe( 'PluginCollection', () => {
 
 			return plugins.init( [] ).then( () => {
 				expectToThrowCKEditorError( () => plugins.get( SomePlugin ),
-					/^plugincollection-plugin-not-loaded:/, editor, { plugin: 'foo' } );
+					/^plugincollection-plugin-not-loaded/, editor, { plugin: 'foo' } );
 			} );
 		} );
 
@@ -545,7 +545,7 @@ describe( 'PluginCollection', () => {
 
 			return plugins.init( [] ).then( () => {
 				expectToThrowCKEditorError( () => plugins.get( SomePlugin ),
-					/^plugincollection-plugin-not-loaded:/,
+					/^plugincollection-plugin-not-loaded/,
 					editor, { plugin: 'SomePlugin' }
 				);
 			} );

+ 4 - 9
packages/ckeditor5-editor-balloon/src/ballooneditor.js

@@ -203,10 +203,8 @@ export default class BalloonEditor extends Editor {
 
 			if ( isHTMLElement && sourceElementOrData.tagName === 'TEXTAREA' ) {
 				// Documented in core/editor/editor.js
-				throw new CKEditorError(
-					'editor-wrong-element: This type of editor cannot be initialized inside <textarea> element.',
-					null
-				);
+				// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
+				throw new CKEditorError( 'editor-wrong-element', null );
 			}
 
 			const editor = new this( sourceElementOrData, config );
@@ -219,11 +217,8 @@ export default class BalloonEditor extends Editor {
 					.then( () => {
 						if ( !isHTMLElement && config.initialData ) {
 							// Documented in core/editor/editorconfig.jdoc.
-							throw new CKEditorError(
-								'editor-create-initial-data: ' +
-								'The config.initialData option cannot be used together with initial data passed in Editor.create().',
-								null
-							);
+							// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
+							throw new CKEditorError( 'editor-create-initial-data', null );
 						}
 
 						const initialData = config.initialData || getInitialData( sourceElementOrData );

+ 3 - 12
packages/ckeditor5-editor-balloon/tests/ballooneditor.js

@@ -96,9 +96,7 @@ describe( 'BalloonEditor', () => {
 						expect.fail( 'Balloon editor should not initialize on an element already used by other instance.' );
 					},
 					err => {
-						assertCKEditorError( err,
-							/^editor-source-element-already-used/
-						);
+						assertCKEditorError( err, 'editor-source-element-already-used' );
 					}
 				)
 				.then( done )
@@ -199,11 +197,7 @@ describe( 'BalloonEditor', () => {
 						expect.fail( 'Balloon editor should throw an error when both initial data are passed' );
 					},
 					err => {
-						assertCKEditorError( err,
-							// eslint-disable-next-line max-len
-							/^editor-create-initial-data: The config\.initialData option cannot be used together with initial data passed in Editor\.create\(\)\./,
-							null
-						);
+						assertCKEditorError( err, 'editor-create-initial-data', null );
 					}
 				)
 				.then( () => {
@@ -247,10 +241,7 @@ describe( 'BalloonEditor', () => {
 						expect.fail( 'Balloon editor should throw an error when is initialized in textarea.' );
 					},
 					err => {
-						assertCKEditorError( err,
-							/^editor-wrong-element: This type of editor cannot be initialized inside <textarea> element\./,
-							null
-						);
+						assertCKEditorError( err, 'editor-wrong-element', null );
 					}
 				)
 				.then( done )

+ 2 - 5
packages/ckeditor5-editor-classic/src/classiceditor.js

@@ -200,11 +200,8 @@ export default class ClassicEditor extends Editor {
 					.then( () => {
 						if ( !isElement( sourceElementOrData ) && config.initialData ) {
 							// Documented in core/editor/editorconfig.jdoc.
-							throw new CKEditorError(
-								'editor-create-initial-data: ' +
-								'The config.initialData option cannot be used together with initial data passed in Editor.create().',
-								null
-							);
+							// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
+							throw new CKEditorError( 'editor-create-initial-data', null );
 						}
 
 						const initialData = config.initialData || getInitialData( sourceElementOrData );

+ 4 - 7
packages/ckeditor5-editor-decoupled/src/decouplededitor.js

@@ -226,8 +226,8 @@ export default class DecoupledEditor extends Editor {
 
 			if ( isHTMLElement && sourceElementOrData.tagName === 'TEXTAREA' ) {
 				// Documented in core/editor/editor.js
-				throw new CKEditorError(
-					'editor-wrong-element: This type of editor cannot be initialized inside <textarea> element.', null );
+				// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
+				throw new CKEditorError( 'editor-wrong-element', null );
 			}
 
 			const editor = new this( sourceElementOrData, config );
@@ -240,11 +240,8 @@ export default class DecoupledEditor extends Editor {
 					.then( () => {
 						if ( !isHTMLElement && config.initialData ) {
 							// Documented in core/editor/editorconfig.jdoc.
-							throw new CKEditorError(
-								'editor-create-initial-data: ' +
-								'The config.initialData option cannot be used together with initial data passed in Editor.create().',
-								null
-							);
+							// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
+							throw new CKEditorError( 'editor-create-initial-data', null );
 						}
 
 						const initialData = config.initialData || getInitialData( sourceElementOrData );

+ 3 - 10
packages/ckeditor5-editor-decoupled/tests/decouplededitor.js

@@ -163,7 +163,7 @@ describe( 'DecoupledEditor', () => {
 						expect.fail( 'Decoupled editor should not initialize on an element already used by other instance.' );
 					},
 					err => {
-						assertCKEditorError( err, /^editor-source-element-already-used/ );
+						assertCKEditorError( err, 'editor-source-element-already-used' );
 					}
 				)
 				.then( done )
@@ -180,11 +180,7 @@ describe( 'DecoupledEditor', () => {
 						expect.fail( 'Decoupled editor should throw an error when both initial data are passed' );
 					},
 					err => {
-						assertCKEditorError( err,
-							// eslint-disable-next-line max-len
-							/^editor-create-initial-data: The config\.initialData option cannot be used together with initial data passed in Editor\.create\(\)\./,
-							null
-						);
+						assertCKEditorError( err, 'editor-create-initial-data' );
 					}
 				)
 				.then( () => {
@@ -201,10 +197,7 @@ describe( 'DecoupledEditor', () => {
 						expect.fail( 'Decoupled editor should throw an error when is initialized in textarea.' );
 					},
 					err => {
-						assertCKEditorError( err,
-							/^editor-wrong-element: This type of editor cannot be initialized inside <textarea> element\./,
-							null
-						);
+						assertCKEditorError( err, 'editor-wrong-element', null );
 					}
 				)
 				.then( done )

+ 4 - 7
packages/ckeditor5-editor-inline/src/inlineeditor.js

@@ -199,8 +199,8 @@ export default class InlineEditor extends Editor {
 
 			if ( isHTMLElement && sourceElementOrData.tagName === 'TEXTAREA' ) {
 				// Documented in core/editor/editor.js
-				throw new CKEditorError(
-					'editor-wrong-element: This type of editor cannot be initialized inside <textarea> element.', null );
+				// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
+				throw new CKEditorError( 'editor-wrong-element', null );
 			}
 
 			const editor = new this( sourceElementOrData, config );
@@ -213,11 +213,8 @@ export default class InlineEditor extends Editor {
 					.then( () => {
 						if ( !isHTMLElement && config.initialData ) {
 							// Documented in core/editor/editorconfig.jdoc.
-							throw new CKEditorError(
-								'editor-create-initial-data: ' +
-								'The config.initialData option cannot be used together with initial data passed in Editor.create().',
-								null
-							);
+							// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
+							throw new CKEditorError( 'editor-create-initial-data', null );
 						}
 
 						const initialData = config.initialData || getInitialData( sourceElementOrData );

+ 3 - 12
packages/ckeditor5-editor-inline/tests/inlineeditor.js

@@ -97,9 +97,7 @@ describe( 'InlineEditor', () => {
 						expect.fail( 'Inline editor should not initialize on an element already used by other instance.' );
 					},
 					err => {
-						assertCKEditorError( err,
-							/^editor-source-element-already-used/
-						);
+						assertCKEditorError( err, 'editor-source-element-already-used' );
 					}
 				)
 				.then( done )
@@ -209,11 +207,7 @@ describe( 'InlineEditor', () => {
 						expect.fail( 'Inline editor should throw an error when both initial data are passed' );
 					},
 					err => {
-						assertCKEditorError( err,
-							/* eslint-disable-next-line max-len */
-							/^editor-create-initial-data: The config\.initialData option cannot be used together with initial data passed in Editor\.create\(\)\./,
-							null
-						);
+						assertCKEditorError( err, 'editor-create-initial-data', null );
 					}
 				)
 				.then( () => {
@@ -257,10 +251,7 @@ describe( 'InlineEditor', () => {
 						expect.fail( 'Inline editor should throw an error when is initialized in textarea.' );
 					},
 					err => {
-						assertCKEditorError( err,
-							/^editor-wrong-element: This type of editor cannot be initialized inside <textarea> element\./,
-							null
-						);
+						assertCKEditorError( err, 'editor-wrong-element', null );
 					}
 				)
 				.then( done )

+ 5 - 5
packages/ckeditor5-engine/src/controller/datacontroller.js

@@ -72,7 +72,7 @@ export default class DataController {
 		 *
 		 * @member {module:engine/dataprocessor/dataprocessor~DataProcessor} #processor
 		 */
-		this.processor;
+		this.processor = undefined;
 
 		/**
 		 * Mapper used for the conversion. It has no permanent bindings, because they are created when getting data and
@@ -176,7 +176,7 @@ export default class DataController {
 			 *
 			 * @error datacontroller-get-non-existent-root
 			 */
-			throw new CKEditorError( 'datacontroller-get-non-existent-root: Attempting to get data from a non-existing root.', this );
+			throw new CKEditorError( 'datacontroller-get-non-existent-root', this );
 		}
 
 		const root = this.model.document.getRoot( rootName );
@@ -283,7 +283,7 @@ export default class DataController {
 			 *
 			 * @error datacontroller-init-document-not-empty
 			 */
-			throw new CKEditorError( 'datacontroller-init-document-not-empty: Trying to set initial data to not empty document.', this );
+			throw new CKEditorError( 'datacontroller-init-document-not-empty', this );
 		}
 
 		let initialData = {};
@@ -305,7 +305,7 @@ export default class DataController {
 			 *
 			 * @error datacontroller-init-non-existent-root
 			 */
-			throw new CKEditorError( 'datacontroller-init-non-existent-root: Attempting to init data on a non-existing root.', this );
+			throw new CKEditorError( 'datacontroller-init-non-existent-root', this );
 		}
 
 		this.model.enqueueChange( 'transparent', writer => {
@@ -360,7 +360,7 @@ export default class DataController {
 			 *
 			 * @error datacontroller-set-non-existent-root
 			 */
-			throw new CKEditorError( 'datacontroller-set-non-existent-root: Attempting to set data on a non-existing root.', this );
+			throw new CKEditorError( 'datacontroller-set-non-existent-root', this );
 		}
 
 		this.model.enqueueChange( 'transparent', writer => {

+ 3 - 4
packages/ckeditor5-engine/src/conversion/conversion.js

@@ -106,8 +106,7 @@ export default class Conversion {
 			 * @error conversion-add-alias-dispatcher-not-registered
 			 */
 			throw new CKEditorError(
-				'conversion-add-alias-dispatcher-not-registered: ' +
-				'Trying to register and alias for a dispatcher that nas not been registered.',
+				'conversion-add-alias-dispatcher-not-registered',
 				this
 			);
 		}
@@ -183,7 +182,7 @@ export default class Conversion {
 			 *
 			 * @error conversion-for-unknown-group
 			 */
-			throw new CKEditorError( 'conversion-for-unknown-group: Trying to add a converter to an unknown dispatchers group.', this );
+			throw new CKEditorError( 'conversion-for-unknown-group', this );
 		}
 
 		return this._helpers.get( groupName );
@@ -588,7 +587,7 @@ export default class Conversion {
 			 *
 			 * @error conversion-group-exists
 			 */
-			throw new CKEditorError( 'conversion-group-exists: Trying to register a group name that has already been registered.', this );
+			throw new CKEditorError( 'conversion-group-exists', this );
 		}
 
 		const helpers = isDowncast ? new DowncastHelpers( dispatchers ) : new UpcastHelpers( dispatchers );

+ 1 - 2
packages/ckeditor5-engine/src/conversion/downcasthelpers.js

@@ -1110,8 +1110,7 @@ function changeAttribute( attributeCreator ) {
 			 * @error conversion-attribute-to-attribute-on-text
 			 */
 			throw new CKEditorError(
-				'conversion-attribute-to-attribute-on-text: ' +
-				'Trying to convert text node\'s attribute with attribute-to-attribute converter.',
+				'conversion-attribute-to-attribute-on-text',
 				[ data, conversionApi ]
 			);
 		}

+ 1 - 1
packages/ckeditor5-engine/src/conversion/upcastdispatcher.js

@@ -262,7 +262,7 @@ export default class UpcastDispatcher {
 			 *
 			 * @error view-conversion-dispatcher-incorrect-result
 			 */
-			throw new CKEditorError( 'view-conversion-dispatcher-incorrect-result: Incorrect conversion result was dropped.', this );
+			throw new CKEditorError( 'view-conversion-dispatcher-incorrect-result', this );
 		}
 
 		return { modelRange: data.modelRange, modelCursor: data.modelCursor };

+ 1 - 1
packages/ckeditor5-engine/src/conversion/viewconsumable.js

@@ -513,7 +513,7 @@ class ViewElementConsumables {
 				 *
 				 * @error viewconsumable-invalid-attribute
 				 */
-				throw new CKEditorError( 'viewconsumable-invalid-attribute: Classes and styles should be handled separately.', this );
+				throw new CKEditorError( 'viewconsumable-invalid-attribute', this );
 			}
 
 			consumables.set( name, true );

+ 5 - 13
packages/ckeditor5-engine/src/model/document.js

@@ -57,7 +57,7 @@ export default class Document {
 		 * operations are applied on a proper document version.
 		 *
 		 * If the {@link module:engine/model/operation/operation~Operation#baseVersion base version} does not match the document version,
-		 * a {@link module:utils/ckeditorerror~CKEditorError model-document-applyOperation-wrong-version} error is thrown.
+		 * a {@link module:utils/ckeditorerror~CKEditorError model-document-applyoperation-wrong-version} error is thrown.
 		 *
 		 * @type {Number}
 		 */
@@ -123,14 +123,10 @@ export default class Document {
 				/**
 				 * Only operations with matching versions can be applied.
 				 *
-				 * @error document-applyOperation-wrong-version
+				 * @error model-document-applyoperation-wrong-version
 				 * @param {module:engine/model/operation/operation~Operation} operation
 				 */
-				throw new CKEditorError(
-					'model-document-applyOperation-wrong-version: Only operations with matching versions can be applied.',
-					this,
-					{ operation }
-				);
+				throw new CKEditorError( 'model-document-applyoperation-wrong-version', this, { operation } );
 			}
 		}, { priority: 'highest' } );
 
@@ -197,15 +193,11 @@ export default class Document {
 			/**
 			 * A root with the specified name already exists.
 			 *
-			 * @error model-document-createRoot-name-exists
+			 * @error model-document-createroot-name-exists
 			 * @param {module:engine/model/document~Document} doc
 			 * @param {String} name
 			 */
-			throw new CKEditorError(
-				'model-document-createRoot-name-exists: Root with specified name already exists.',
-				this,
-				{ name: rootName }
-			);
+			throw new CKEditorError( 'model-document-createroot-name-exists', this, { name: rootName } );
 		}
 
 		const root = new RootElement( this, elementName, rootName );

+ 2 - 2
packages/ckeditor5-engine/src/model/documentselection.js

@@ -653,7 +653,7 @@ class LiveSelection extends Selection {
 					 * @param {module:engine/model/range~Range} range
 					 */
 					throw new CKEditorError(
-						'document-selection-wrong-position: Range from document selection starts or ends at incorrect position.',
+						'document-selection-wrong-position',
 						this,
 						{ range }
 					);
@@ -784,7 +784,7 @@ class LiveSelection extends Selection {
 			 * {@link module:engine/model/documentselection~DocumentSelection#_overrideGravity}.
 			 */
 			throw new CKEditorError(
-				'document-selection-gravity-wrong-restore: Attempting to restore the selection gravity for an unknown UID.',
+				'document-selection-gravity-wrong-restore',
 				this,
 				{ uid }
 			);

+ 2 - 5
packages/ckeditor5-engine/src/model/liveposition.js

@@ -43,12 +43,9 @@ export default class LivePosition extends Position {
 			/**
 			 * LivePosition's root has to be an instance of RootElement.
 			 *
-			 * @error liveposition-root-not-rootelement
+			 * @error model-liveposition-root-not-rootelement
 			 */
-			throw new CKEditorError(
-				'model-liveposition-root-not-rootelement: LivePosition\'s root has to be an instance of RootElement.',
-				root
-			);
+			throw new CKEditorError( 'model-liveposition-root-not-rootelement', root );
 		}
 
 		bindWithDocument.call( this );

+ 12 - 7
packages/ckeditor5-engine/src/model/markercollection.js

@@ -99,7 +99,7 @@ export default class MarkerCollection {
 			 *
 			 * @error markercollection-incorrect-marker-name
 			 */
-			throw new CKEditorError( 'markercollection-incorrect-marker-name: Marker name cannot contain the "," character.', this );
+			throw new CKEditorError( 'markercollection-incorrect-marker-name', this );
 		}
 
 		const oldMarker = this._markers.get( markerName );
@@ -177,7 +177,12 @@ export default class MarkerCollection {
 		const marker = this._markers.get( markerName );
 
 		if ( !marker ) {
-			throw new CKEditorError( 'markercollection-refresh-marker-not-exists: Marker with provided name does not exists.', this );
+			/**
+			 * Marker with provided name does not exists.
+			 *
+			 * @error markercollection-refresh-marker-not-exists
+			 */
+			throw new CKEditorError( 'markercollection-refresh-marker-not-exists', this );
 		}
 
 		const range = marker.getRange();
@@ -393,7 +398,7 @@ class Marker {
 	 */
 	get managedUsingOperations() {
 		if ( !this._liveRange ) {
-			throw new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.', this );
+			throw new CKEditorError( 'marker-destroyed', this );
 		}
 
 		return this._managedUsingOperations;
@@ -406,7 +411,7 @@ class Marker {
 	 */
 	get affectsData() {
 		if ( !this._liveRange ) {
-			throw new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.', this );
+			throw new CKEditorError( 'marker-destroyed', this );
 		}
 
 		return this._affectsData;
@@ -419,7 +424,7 @@ class Marker {
 	 */
 	getStart() {
 		if ( !this._liveRange ) {
-			throw new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.', this );
+			throw new CKEditorError( 'marker-destroyed', this );
 		}
 
 		return this._liveRange.start.clone();
@@ -432,7 +437,7 @@ class Marker {
 	 */
 	getEnd() {
 		if ( !this._liveRange ) {
-			throw new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.', this );
+			throw new CKEditorError( 'marker-destroyed', this );
 		}
 
 		return this._liveRange.end.clone();
@@ -452,7 +457,7 @@ class Marker {
 	 */
 	getRange() {
 		if ( !this._liveRange ) {
-			throw new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.', this );
+			throw new CKEditorError( 'marker-destroyed', this );
 		}
 
 		return this._liveRange.toRange();

+ 8 - 2
packages/ckeditor5-engine/src/model/node.js

@@ -87,7 +87,7 @@ export default class Node {
 		}
 
 		if ( ( pos = this.parent.getChildIndex( this ) ) === null ) {
-			throw new CKEditorError( 'model-node-not-found-in-parent: The node\'s parent does not contain this node.', this );
+			throw new CKEditorError( 'model-node-not-found-in-parent', this );
 		}
 
 		return pos;
@@ -111,7 +111,7 @@ export default class Node {
 		}
 
 		if ( ( pos = this.parent.getChildStartOffset( this ) ) === null ) {
-			throw new CKEditorError( 'model-node-not-found-in-parent: The node\'s parent does not contain this node.', this );
+			throw new CKEditorError( 'model-node-not-found-in-parent', this );
 		}
 
 		return pos;
@@ -499,3 +499,9 @@ export default class Node {
 		this._attrs.clear();
 	}
 }
+
+/**
+ * The node's parent does not contain this node.
+ *
+ * @error model-node-not-found-in-parent
+ */

+ 5 - 8
packages/ckeditor5-engine/src/model/nodelist.js

@@ -122,9 +122,9 @@ export default class NodeList {
 			/**
 			 * Given index cannot be found in the node list.
 			 *
-			 * @error nodelist-index-out-of-bounds
+			 * @error model-nodelist-index-out-of-bounds
 			 */
-			throw new CKEditorError( 'model-nodelist-index-out-of-bounds: Given index cannot be found in the node list.', this );
+			throw new CKEditorError( 'model-nodelist-index-out-of-bounds', this );
 		}
 
 		return this.getNodeStartOffset( node );
@@ -158,7 +158,7 @@ export default class NodeList {
 			 * @param {Number} offset
 			 * @param {module:engine/model/nodelist~NodeList} nodeList Stringified node list.
 			 */
-			throw new CKEditorError( 'model-nodelist-offset-out-of-bounds: Given offset cannot be found in the node list.',
+			throw new CKEditorError( 'model-nodelist-offset-out-of-bounds',
 				this,
 				{
 					offset,
@@ -184,12 +184,9 @@ export default class NodeList {
 				/**
 				 * Trying to insert an object which is not a Node instance.
 				 *
-				 * @error nodelist-insertNodes-not-node
+				 * @error model-nodelist-insertnodes-not-node
 				 */
-				throw new CKEditorError(
-					'model-nodelist-insertNodes-not-node: Trying to insert an object which is not a Node instance.',
-					this
-				);
+				throw new CKEditorError( 'model-nodelist-insertnodes-not-node', this );
 			}
 		}
 

+ 3 - 4
packages/ckeditor5-engine/src/model/operation/attributeoperation.js

@@ -128,7 +128,7 @@ export default class AttributeOperation extends Operation {
 			 *
 			 * @error attribute-operation-range-not-flat
 			 */
-			throw new CKEditorError( 'attribute-operation-range-not-flat: The range to change is not flat.', this );
+			throw new CKEditorError( 'attribute-operation-range-not-flat', this );
 		}
 
 		for ( const item of this.range.getItems( { shallow: true } ) ) {
@@ -142,8 +142,7 @@ export default class AttributeOperation extends Operation {
 				 * @param {*} value
 				 */
 				throw new CKEditorError(
-					'attribute-operation-wrong-old-value: Changed node has different attribute value than operation\'s ' +
-					'old attribute value.',
+					'attribute-operation-wrong-old-value',
 					this,
 					{ item, key: this.key, value: this.oldValue }
 				);
@@ -158,7 +157,7 @@ export default class AttributeOperation extends Operation {
 				 * @param {String} key
 				 */
 				throw new CKEditorError(
-					'attribute-operation-attribute-exists: The attribute with given key already exists.',
+					'attribute-operation-attribute-exists',
 					this,
 					{ node: item, key: this.key }
 				);

+ 1 - 1
packages/ckeditor5-engine/src/model/operation/detachoperation.js

@@ -75,7 +75,7 @@ export default class DetachOperation extends Operation {
 			 *
 			 * @error detach-operation-on-document-node
 			 */
-			throw new CKEditorError( 'detach-operation-on-document-node: Cannot detach document node.', this );
+			throw new CKEditorError( 'detach-operation-on-document-node', this );
 		}
 	}
 

+ 1 - 1
packages/ckeditor5-engine/src/model/operation/insertoperation.js

@@ -115,7 +115,7 @@ export default class InsertOperation extends Operation {
 			 * @error insert-operation-position-invalid
 			 */
 			throw new CKEditorError(
-				'insert-operation-position-invalid: Insertion position is invalid.',
+				'insert-operation-position-invalid',
 				this
 			);
 		}

+ 3 - 3
packages/ckeditor5-engine/src/model/operation/mergeoperation.js

@@ -147,21 +147,21 @@ export default class MergeOperation extends Operation {
 			 *
 			 * @error merge-operation-source-position-invalid
 			 */
-			throw new CKEditorError( 'merge-operation-source-position-invalid: Merge source position is invalid.', this );
+			throw new CKEditorError( 'merge-operation-source-position-invalid', this );
 		} else if ( !targetElement.parent ) {
 			/**
 			 * Merge target position is invalid. The element to be merged must have a parent node.
 			 *
 			 * @error merge-operation-target-position-invalid
 			 */
-			throw new CKEditorError( 'merge-operation-target-position-invalid: Merge target position is invalid.', this );
+			throw new CKEditorError( 'merge-operation-target-position-invalid', this );
 		} else if ( this.howMany != sourceElement.maxOffset ) {
 			/**
 			 * Merge operation specifies wrong number of nodes to move.
 			 *
 			 * @error merge-operation-how-many-invalid
 			 */
-			throw new CKEditorError( 'merge-operation-how-many-invalid: Merge operation specifies wrong number of nodes to move.', this );
+			throw new CKEditorError( 'merge-operation-how-many-invalid', this );
 		}
 	}
 

+ 3 - 3
packages/ckeditor5-engine/src/model/operation/moveoperation.js

@@ -132,7 +132,7 @@ export default class MoveOperation extends Operation {
 			 * @error move-operation-nodes-do-not-exist
 			 */
 			throw new CKEditorError(
-				'move-operation-nodes-do-not-exist: The nodes which should be moved do not exist.', this
+				'move-operation-nodes-do-not-exist', this
 			);
 		} else if ( sourceElement === targetElement && sourceOffset < targetOffset && targetOffset < sourceOffset + this.howMany ) {
 			/**
@@ -141,7 +141,7 @@ export default class MoveOperation extends Operation {
 			 * @error move-operation-range-into-itself
 			 */
 			throw new CKEditorError(
-				'move-operation-range-into-itself: Trying to move a range of nodes to the inside of that range.', this
+				'move-operation-range-into-itself', this
 			);
 		} else if ( this.sourcePosition.root == this.targetPosition.root ) {
 			if ( compareArrays( this.sourcePosition.getParentPath(), this.targetPosition.getParentPath() ) == 'prefix' ) {
@@ -154,7 +154,7 @@ export default class MoveOperation extends Operation {
 					 * @error move-operation-node-into-itself
 					 */
 					throw new CKEditorError(
-						'move-operation-node-into-itself: Trying to move a range of nodes into one of nodes from that range.', this
+						'move-operation-node-into-itself', this
 					);
 				}
 			}

+ 2 - 2
packages/ckeditor5-engine/src/model/operation/renameoperation.js

@@ -94,7 +94,7 @@ export default class RenameOperation extends Operation {
 			 * @error rename-operation-wrong-position
 			 */
 			throw new CKEditorError(
-				'rename-operation-wrong-position: Given position is invalid or node after it is not an instance of Element.',
+				'rename-operation-wrong-position',
 				this
 			);
 		} else if ( element.name !== this.oldName ) {
@@ -104,7 +104,7 @@ export default class RenameOperation extends Operation {
 			 * @error rename-operation-wrong-name
 			 */
 			throw new CKEditorError(
-				'rename-operation-wrong-name: Element to change has different name than operation\'s old name.',
+				'rename-operation-wrong-name',
 				this
 			);
 		}

+ 5 - 10
packages/ckeditor5-engine/src/model/operation/rootattributeoperation.js

@@ -115,7 +115,7 @@ export default class RootAttributeOperation extends Operation {
 			 * @param {*} value
 			 */
 			throw new CKEditorError(
-				'rootattribute-operation-not-a-root: The element to change is not a root element.',
+				'rootattribute-operation-not-a-root',
 				this,
 				{ root: this.root, key: this.key }
 			);
@@ -131,8 +131,7 @@ export default class RootAttributeOperation extends Operation {
 			 * @param {*} value
 			 */
 			throw new CKEditorError(
-				'rootattribute-operation-wrong-old-value: Changed node has different attribute value than operation\'s ' +
-				'old attribute value.',
+				'rootattribute-operation-wrong-old-value',
 				this,
 				{ root: this.root, key: this.key }
 			);
@@ -147,7 +146,7 @@ export default class RootAttributeOperation extends Operation {
 			 * @param {String} key
 			 */
 			throw new CKEditorError(
-				'rootattribute-operation-attribute-exists: The attribute with given key already exists.',
+				'rootattribute-operation-attribute-exists',
 				this,
 				{ root: this.root, key: this.key }
 			);
@@ -195,14 +194,10 @@ export default class RootAttributeOperation extends Operation {
 			/**
 			 * Cannot create RootAttributeOperation for document. Root with specified name does not exist.
 			 *
-			 * @error rootattributeoperation-fromjson-no-root
+			 * @error rootattribute-operation-fromjson-no-root
 			 * @param {String} rootName
 			 */
-			throw new CKEditorError(
-				'rootattribute-operation-fromjson-no-root: Cannot create RootAttributeOperation. Root with specified name does not exist.',
-				this,
-				{ rootName: json.root }
-			);
+			throw new CKEditorError( 'rootattribute-operation-fromjson-no-root', this, { rootName: json.root } );
 		}
 
 		return new RootAttributeOperation( document.getRoot( json.root ), json.key, json.oldValue, json.newValue, json.baseVersion );

+ 4 - 4
packages/ckeditor5-engine/src/model/operation/splitoperation.js

@@ -149,28 +149,28 @@ export default class SplitOperation extends Operation {
 			 *
 			 * @error split-operation-position-invalid
 			 */
-			throw new CKEditorError( 'split-operation-position-invalid: Split position is invalid.', this );
+			throw new CKEditorError( 'split-operation-position-invalid', this );
 		} else if ( !element.parent ) {
 			/**
 			 * Cannot split root element.
 			 *
 			 * @error split-operation-split-in-root
 			 */
-			throw new CKEditorError( 'split-operation-split-in-root: Cannot split root element.', this );
+			throw new CKEditorError( 'split-operation-split-in-root', this );
 		} else if ( this.howMany != element.maxOffset - this.splitPosition.offset ) {
 			/**
 			 * Split operation specifies wrong number of nodes to move.
 			 *
 			 * @error split-operation-how-many-invalid
 			 */
-			throw new CKEditorError( 'split-operation-how-many-invalid: Split operation specifies wrong number of nodes to move.', this );
+			throw new CKEditorError( 'split-operation-how-many-invalid', this );
 		} else if ( this.graveyardPosition && !this.graveyardPosition.nodeAfter ) {
 			/**
 			 * Graveyard position invalid.
 			 *
 			 * @error split-operation-graveyard-position-invalid
 			 */
-			throw new CKEditorError( 'split-operation-graveyard-position-invalid: Graveyard position invalid.', this );
+			throw new CKEditorError( 'split-operation-graveyard-position-invalid', this );
 		}
 	}
 

+ 2 - 4
packages/ckeditor5-engine/src/model/operation/utils.js

@@ -70,8 +70,7 @@ export function _remove( range ) {
 		 * @error operation-utils-remove-range-not-flat
 		 */
 		throw new CKEditorError(
-			'operation-utils-remove-range-not-flat: ' +
-			'Trying to remove a range which starts and ends in different element.',
+			'operation-utils-remove-range-not-flat',
 			this
 		);
 	}
@@ -109,8 +108,7 @@ export function _move( sourceRange, targetPosition ) {
 		 * @error operation-utils-move-range-not-flat
 		 */
 		throw new CKEditorError(
-			'operation-utils-move-range-not-flat: ' +
-			'Trying to move a range which starts and ends in different element.',
+			'operation-utils-move-range-not-flat',
 			this
 		);
 	}

+ 25 - 29
packages/ckeditor5-engine/src/model/position.js

@@ -60,7 +60,7 @@ export default class Position {
 			 * @error model-position-root-invalid
 			 */
 			throw new CKEditorError(
-				'model-position-root-invalid: Position root invalid.',
+				'model-position-root-invalid',
 				root
 			);
 		}
@@ -73,7 +73,7 @@ export default class Position {
 			 * @param path
 			 */
 			throw new CKEditorError(
-				'model-position-path-incorrect-format: Position path must be an array with at least one item.',
+				'model-position-path-incorrect-format',
 				root,
 				{ path }
 			);
@@ -169,27 +169,27 @@ export default class Position {
 			parent = parent.getChild( parent.offsetToIndex( this.path[ i ] ) );
 
 			if ( !parent ) {
-				throw new CKEditorError( 'model-position-path-incorrect: The position\'s path is incorrect.', this, { position: this } );
+				/**
+				 * The position's path is incorrect. This means that a position does not point to
+				 * a correct place in the tree and hence, some of its methods and getters cannot work correctly.
+				 *
+				 * **Note**: Unlike DOM and view positions, in the model, the
+				 * {@link module:engine/model/position~Position#parent position's parent} is always an element or a document fragment.
+				 * The last offset in the {@link module:engine/model/position~Position#path position's path} is the point in this element
+				 * where this position points.
+				 *
+				 * Read more about model positions and offsets in
+				 * the {@glink framework/guides/architecture/editing-engine#indexes-and-offsets Editing engine architecture guide}.
+				 *
+				 * @error model-position-path-incorrect
+				 * @param {module:engine/model/position~Position} position The incorrect position.
+				 */
+				throw new CKEditorError( 'model-position-path-incorrect', this, { position: this } );
 			}
 		}
 
 		if ( parent.is( '$text' ) ) {
-			/**
-			 * The position's path is incorrect. This means that a position does not point to
-			 * a correct place in the tree and hence, some of its methods and getters cannot work correctly.
-			 *
-			 * **Note**: Unlike DOM and view positions, in the model, the
-			 * {@link module:engine/model/position~Position#parent position's parent} is always an element or a document fragment.
-			 * The last offset in the {@link module:engine/model/position~Position#path position's path} is the point in this element where
-			 * this position points.
-			 *
-			 * Read more about model positions and offsets in
-			 * the {@glink framework/guides/architecture/editing-engine#indexes-and-offsets Editing engine architecture guide}.
-			 *
-			 * @error position-incorrect-path
-			 * @param {module:engine/model/position~Position} position The incorrect position.
-			 */
-			throw new CKEditorError( 'model-position-path-incorrect: The position\'s path is incorrect.', this, { position: this } );
+			throw new CKEditorError( 'model-position-path-incorrect', this, { position: this } );
 		}
 
 		return parent;
@@ -923,13 +923,9 @@ export default class Position {
 				 * {@link module:engine/model/model~Model#createPositionAt `Model#createPositionAt()`}
 				 * requires the offset to be specified when the first parameter is a model item.
 				 *
-				 * @error model-createPositionAt-offset-required
+				 * @error model-createpositionat-offset-required
 				 */
-				throw new CKEditorError(
-					'model-createPositionAt-offset-required: ' +
-					'Model#createPositionAt() requires the offset when the first parameter is a model item.',
-					[ this, itemOrPosition ]
-				);
+				throw new CKEditorError( 'model-createpositionat-offset-required', [ this, itemOrPosition ] );
 			}
 
 			if ( !node.is( 'element' ) && !node.is( 'documentFragment' ) ) {
@@ -939,7 +935,7 @@ export default class Position {
 				 * @error model-position-parent-incorrect
 				 */
 				throw new CKEditorError(
-					'model-position-parent-incorrect: Position parent have to be a element or document fragment.',
+					'model-position-parent-incorrect',
 					[ this, itemOrPosition ]
 				);
 			}
@@ -969,7 +965,7 @@ export default class Position {
 			 * @param {module:engine/model/item~Item} root
 			 */
 			throw new CKEditorError(
-				'model-position-after-root: You cannot make a position after root.',
+				'model-position-after-root',
 				[ this, item ],
 				{ root: item }
 			);
@@ -995,7 +991,7 @@ export default class Position {
 			 * @param {module:engine/model/item~Item} root
 			 */
 			throw new CKEditorError(
-				'model-position-before-root: You cannot make a position before root.',
+				'model-position-before-root',
 				item,
 				{ root: item }
 			);
@@ -1027,7 +1023,7 @@ export default class Position {
 			 * @param {String} rootName
 			 */
 			throw new CKEditorError(
-				'model-position-fromjson-no-root: Cannot create position for document. Root with specified name does not exist.',
+				'model-position-fromjson-no-root',
 				doc,
 				{ rootName: json.root }
 			);

+ 1 - 1
packages/ckeditor5-engine/src/model/range.js

@@ -974,7 +974,7 @@ export default class Range {
 			 * @error range-create-from-ranges-empty-array
 			 */
 			throw new CKEditorError(
-				'range-create-from-ranges-empty-array: At least one range has to be passed.',
+				'range-create-from-ranges-empty-array',
 				null
 			);
 		} else if ( ranges.length == 1 ) {

+ 4 - 4
packages/ckeditor5-engine/src/model/schema.js

@@ -92,7 +92,7 @@ export default class Schema {
 			 * @error schema-cannot-register-item-twice
 			 */
 			throw new CKEditorError(
-				'schema-cannot-register-item-twice: A single item cannot be registered twice in the schema.',
+				'schema-cannot-register-item-twice',
 				this,
 				{
 					itemName
@@ -142,7 +142,7 @@ export default class Schema {
 			 * @param itemName The name of the model element which is being extended.
 			 * @error schema-cannot-extend-missing-item
 			 */
-			throw new CKEditorError( 'schema-cannot-extend-missing-item: Cannot extend an item which was not registered yet.', this, {
+			throw new CKEditorError( 'schema-cannot-extend-missing-item', this, {
 				itemName
 			} );
 		}
@@ -447,7 +447,7 @@ export default class Schema {
 				 * @error schema-check-merge-no-element-before
 				 */
 				throw new CKEditorError(
-					'schema-check-merge-no-element-before: The node before the merge position must be an element.',
+					'schema-check-merge-no-element-before',
 					this
 				);
 			}
@@ -459,7 +459,7 @@ export default class Schema {
 				 * @error schema-check-merge-no-element-after
 				 */
 				throw new CKEditorError(
-					'schema-check-merge-no-element-after: The node after the merge position must be an element.',
+					'schema-check-merge-no-element-after',
 					this
 				);
 			}

+ 8 - 19
packages/ckeditor5-engine/src/model/selection.js

@@ -390,13 +390,9 @@ export default class Selection {
 				/**
 				 * selection.setTo requires the second parameter when the first parameter is a node.
 				 *
-				 * @error model-selection-setTo-required-second-parameter
+				 * @error model-selection-setto-required-second-parameter
 				 */
-				throw new CKEditorError(
-					'model-selection-setTo-required-second-parameter: ' +
-					'selection.setTo requires the second parameter when the first parameter is a node.',
-					[ this, selectable ]
-				);
+				throw new CKEditorError( 'model-selection-setto-required-second-parameter', [ this, selectable ] );
 			}
 
 			this._setRanges( [ range ], backward );
@@ -414,12 +410,9 @@ export default class Selection {
 			 * * View nodes were passed instead of model nodes.
 			 * * `null`/`undefined` was passed.
 			 *
-			 * @error model-selection-setTo-not-selectable
+			 * @error model-selection-setto-not-selectable
 			 */
-			throw new CKEditorError(
-				'model-selection-setTo-not-selectable: Cannot set the selection to the given place.',
-				[ this, selectable ]
-			);
+			throw new CKEditorError( 'model-selection-setto-not-selectable', [ this, selectable ] );
 		}
 	}
 
@@ -452,8 +445,7 @@ export default class Selection {
 				 * @error model-selection-set-ranges-not-range
 				 */
 				throw new CKEditorError(
-					'model-selection-set-ranges-not-range: ' +
-					'Selection range set to an object that is not an instance of model.Range.',
+					'model-selection-set-ranges-not-range',
 					[ this, newRanges ]
 				);
 			}
@@ -495,12 +487,9 @@ export default class Selection {
 			/**
 			 * Cannot set selection focus if there are no ranges in selection.
 			 *
-			 * @error model-selection-setFocus-no-ranges
+			 * @error model-selection-setfocus-no-ranges
 			 */
-			throw new CKEditorError(
-				'model-selection-setFocus-no-ranges: Cannot set selection focus if there are no ranges in selection.',
-				[ this, itemOrPosition ]
-			);
+			throw new CKEditorError( 'model-selection-setfocus-no-ranges', [ this, itemOrPosition ] );
 		}
 
 		const newFocus = Position._createAt( itemOrPosition, offset );
@@ -756,7 +745,7 @@ export default class Selection {
 				 * @param {module:engine/model/range~Range} intersectingRange Range in the selection that intersects with `addedRange`.
 				 */
 				throw new CKEditorError(
-					'model-selection-range-intersects: Trying to add a range that intersects with another range in the selection.',
+					'model-selection-range-intersects',
 					[ this, range ],
 					{ addedRange: range, intersectingRange: this._ranges[ i ] }
 				);

+ 2 - 2
packages/ckeditor5-engine/src/model/textproxy.js

@@ -66,7 +66,7 @@ export default class TextProxy {
 			 *
 			 * @error model-textproxy-wrong-offsetintext
 			 */
-			throw new CKEditorError( 'model-textproxy-wrong-offsetintext: Given offsetInText value is incorrect.', this );
+			throw new CKEditorError( 'model-textproxy-wrong-offsetintext', this );
 		}
 
 		if ( length < 0 || offsetInText + length > textNode.offsetSize ) {
@@ -75,7 +75,7 @@ export default class TextProxy {
 			 *
 			 * @error model-textproxy-wrong-length
 			 */
-			throw new CKEditorError( 'model-textproxy-wrong-length: Given length value is incorrect.', this );
+			throw new CKEditorError( 'model-textproxy-wrong-length', this );
 		}
 
 		/**

+ 7 - 6
packages/ckeditor5-engine/src/model/treewalker.js

@@ -48,7 +48,7 @@ export default class TreeWalker {
 			 * @error model-tree-walker-no-start-position
 			 */
 			throw new CKEditorError(
-				'model-tree-walker-no-start-position: Neither boundaries nor starting position have been defined.',
+				'model-tree-walker-no-start-position',
 				null
 			);
 		}
@@ -56,11 +56,12 @@ export default class TreeWalker {
 		const direction = options.direction || 'forward';
 
 		if ( direction != 'forward' && direction != 'backward' ) {
-			throw new CKEditorError(
-				'model-tree-walker-unknown-direction: Only `backward` and `forward` direction allowed.',
-				options,
-				{ direction }
-			);
+			/**
+			 * Only `backward` and `forward` direction allowed.
+			 *
+			 * @error model-tree-walker-unknown-direction
+			 */
+			throw new CKEditorError( 'model-tree-walker-unknown-direction', options, { direction } );
 		}
 
 		/**

+ 2 - 3
packages/ckeditor5-engine/src/model/utils/insertcontent.js

@@ -324,7 +324,7 @@ class Insertion {
 			 * @param {module:engine/model/position~Position} position Position to insert the node at.
 			 */
 			throw new CKEditorError(
-				'insertcontent-wrong-position: Given node cannot be inserted on the given position.',
+				'insertcontent-wrong-position',
 				this,
 				{ node, position: this.position }
 			);
@@ -451,8 +451,7 @@ class Insertion {
 				 *
 				 * @error insertcontent-invalid-insertion-position
 				 */
-				throw new CKEditorError( 'insertcontent-invalid-insertion-position: ' +
-					'An internal error occurred during insertContent().', this );
+				throw new CKEditorError( 'insertcontent-invalid-insertion-position', this );
 			}
 
 			// Move the position to the previous node, so it isn't moved to the graveyard on merge.

+ 31 - 37
packages/ckeditor5-engine/src/model/writer.js

@@ -196,9 +196,7 @@ export default class Writer {
 					 * @error model-writer-insert-forbidden-move
 					 */
 					throw new CKEditorError(
-						'model-writer-insert-forbidden-move: ' +
-						'Cannot move a node from a document to a different tree. ' +
-						'It is forbidden to move a node that was already in a document outside of it.',
+						'model-writer-insert-forbidden-move',
 						this
 					);
 				} else {
@@ -484,7 +482,7 @@ export default class Writer {
 			 *
 			 * @error writer-move-invalid-range
 			 */
-			throw new CKEditorError( 'writer-move-invalid-range: Invalid range to move.', this );
+			throw new CKEditorError( 'writer-move-invalid-range', this );
 		}
 
 		if ( !range.isFlat ) {
@@ -493,7 +491,7 @@ export default class Writer {
 			 *
 			 * @error writer-move-range-not-flat
 			 */
-			throw new CKEditorError( 'writer-move-range-not-flat: Range to move is not flat.', this );
+			throw new CKEditorError( 'writer-move-range-not-flat', this );
 		}
 
 		const position = Position._createAt( itemOrPosition, offset );
@@ -513,7 +511,7 @@ export default class Writer {
 			 *
 			 * @error writer-move-different-document
 			 */
-			throw new CKEditorError( 'writer-move-different-document: Range is going to be moved between different documents.', this );
+			throw new CKEditorError( 'writer-move-different-document', this );
 		}
 
 		const version = range.root.document ? range.root.document.version : null;
@@ -565,7 +563,7 @@ export default class Writer {
 			 *
 			 * @error writer-merge-no-element-before
 			 */
-			throw new CKEditorError( 'writer-merge-no-element-before: Node before merge position must be an element.', this );
+			throw new CKEditorError( 'writer-merge-no-element-before', this );
 		}
 
 		if ( !( nodeAfter instanceof Element ) ) {
@@ -574,7 +572,7 @@ export default class Writer {
 			 *
 			 * @error writer-merge-no-element-after
 			 */
-			throw new CKEditorError( 'writer-merge-no-element-after: Node after merge position must be an element.', this );
+			throw new CKEditorError( 'writer-merge-no-element-after', this );
 		}
 
 		if ( !position.root.document ) {
@@ -724,7 +722,7 @@ export default class Writer {
 			 * @error writer-rename-not-element-instance
 			 */
 			throw new CKEditorError(
-				'writer-rename-not-element-instance: Trying to rename an object which is not an instance of Element.',
+				'writer-rename-not-element-instance',
 				this
 			);
 		}
@@ -761,7 +759,7 @@ export default class Writer {
 			 *
 			 * @error writer-split-element-no-parent
 			 */
-			throw new CKEditorError( 'writer-split-element-no-parent: Element with no parent can not be split.', this );
+			throw new CKEditorError( 'writer-split-element-no-parent', this );
 		}
 
 		// When limit element is not defined lets set splitElement parent as limit.
@@ -770,7 +768,12 @@ export default class Writer {
 		}
 
 		if ( !position.parent.getAncestors( { includeSelf: true } ).includes( limitElement ) ) {
-			throw new CKEditorError( 'writer-split-invalid-limit-element: Limit element is not a position ancestor.', this );
+			/**
+			 * Limit element is not a position ancestor.
+			 *
+			 * @error writer-split-invalid-limit-element
+			 */
+			throw new CKEditorError( 'writer-split-invalid-limit-element', this );
 		}
 
 		// We need to cache elements that will be created as a result of the first split because
@@ -820,7 +823,7 @@ export default class Writer {
 			 *
 			 * @error writer-wrap-range-not-flat
 			 */
-			throw new CKEditorError( 'writer-wrap-range-not-flat: Range to wrap is not flat.', this );
+			throw new CKEditorError( 'writer-wrap-range-not-flat', this );
 		}
 
 		const element = elementOrString instanceof Element ? elementOrString : new Element( elementOrString );
@@ -831,7 +834,7 @@ export default class Writer {
 			 *
 			 * @error writer-wrap-element-not-empty
 			 */
-			throw new CKEditorError( 'writer-wrap-element-not-empty: Element to wrap with is not empty.', this );
+			throw new CKEditorError( 'writer-wrap-element-not-empty', this );
 		}
 
 		if ( element.parent !== null ) {
@@ -840,7 +843,7 @@ export default class Writer {
 			 *
 			 * @error writer-wrap-element-attached
 			 */
-			throw new CKEditorError( 'writer-wrap-element-attached: Element to wrap with is already attached to tree model.', this );
+			throw new CKEditorError( 'writer-wrap-element-attached', this );
 		}
 
 		this.insert( element, range.start );
@@ -866,7 +869,7 @@ export default class Writer {
 			 *
 			 * @error writer-unwrap-element-no-parent
 			 */
-			throw new CKEditorError( 'writer-unwrap-element-no-parent: Trying to unwrap an element which has no parent.', this );
+			throw new CKEditorError( 'writer-unwrap-element-no-parent', this );
 		}
 
 		this.move( Range._createIn( element ), this.createPositionAfter( element ) );
@@ -919,12 +922,9 @@ export default class Writer {
 			/**
 			 * The `options.usingOperation` parameter is required when adding a new marker.
 			 *
-			 * @error writer-addMarker-no-usingOperation
+			 * @error writer-addmarker-no-usingoperation
 			 */
-			throw new CKEditorError(
-				'writer-addMarker-no-usingOperation: The options.usingOperation parameter is required when adding a new marker.',
-				this
-			);
+			throw new CKEditorError( 'writer-addmarker-no-usingoperation', this );
 		}
 
 		const usingOperation = options.usingOperation;
@@ -935,21 +935,18 @@ export default class Writer {
 			/**
 			 * Marker with provided name already exists.
 			 *
-			 * @error writer-addMarker-marker-exists
+			 * @error writer-addmarker-marker-exists
 			 */
-			throw new CKEditorError( 'writer-addMarker-marker-exists: Marker with provided name already exists.', this );
+			throw new CKEditorError( 'writer-addmarker-marker-exists', this );
 		}
 
 		if ( !range ) {
 			/**
 			 * Range parameter is required when adding a new marker.
 			 *
-			 * @error writer-addMarker-no-range
+			 * @error writer-addmarker-no-range
 			 */
-			throw new CKEditorError(
-				'writer-addMarker-no-range: Range parameter is required when adding a new marker.',
-				this
-			);
+			throw new CKEditorError( 'writer-addmarker-no-range', this );
 		}
 
 		if ( !usingOperation ) {
@@ -1040,9 +1037,9 @@ export default class Writer {
 			/**
 			 * Marker with provided name does not exists.
 			 *
-			 * @error writer-updateMarker-marker-not-exists
+			 * @error writer-updatemarker-marker-not-exists
 			 */
-			throw new CKEditorError( 'writer-updateMarker-marker-not-exists: Marker with provided name does not exists.', this );
+			throw new CKEditorError( 'writer-updatemarker-marker-not-exists', this );
 		}
 
 		if ( !options ) {
@@ -1061,12 +1058,9 @@ export default class Writer {
 			/**
 			 * One of the options is required - provide range, usingOperations or affectsData.
 			 *
-			 * @error writer-updateMarker-wrong-options
+			 * @error writer-updatemarker-wrong-options
 			 */
-			throw new CKEditorError(
-				'writer-updateMarker-wrong-options: One of the options is required - provide range, usingOperations or affectsData.',
-				this
-			);
+			throw new CKEditorError( 'writer-updatemarker-wrong-options', this );
 		}
 
 		const currentRange = currentMarker.getRange();
@@ -1114,9 +1108,9 @@ export default class Writer {
 			/**
 			 * Trying to remove marker which does not exist.
 			 *
-			 * @error writer-removeMarker-no-marker
+			 * @error writer-removemarker-no-marker
 			 */
-			throw new CKEditorError( 'writer-removeMarker-no-marker: Trying to remove marker which does not exist.', this );
+			throw new CKEditorError( 'writer-removemarker-no-marker', this );
 		}
 
 		const marker = this.model.markers.get( name );
@@ -1349,7 +1343,7 @@ export default class Writer {
 		 * @error writer-incorrect-use
 		 */
 		if ( this.model._currentWriter !== this ) {
-			throw new CKEditorError( 'writer-incorrect-use: Trying to use a writer outside the change() block.', this );
+			throw new CKEditorError( 'writer-incorrect-use', this );
 		}
 	}
 

+ 1 - 2
packages/ckeditor5-engine/src/view/attributeelement.js

@@ -120,8 +120,7 @@ export default class AttributeElement extends Element {
 			 * @error attribute-element-get-elements-with-same-id-no-id
 			 */
 			throw new CKEditorError(
-				'attribute-element-get-elements-with-same-id-no-id: ' +
-				'Cannot get elements with the same id for an attribute element without id.',
+				'attribute-element-get-elements-with-same-id-no-id',
 				this
 			);
 		}

+ 11 - 18
packages/ckeditor5-engine/src/view/downcastwriter.js

@@ -503,10 +503,7 @@ export default class DowncastWriter {
 			 *
 			 * @error view-writer-break-non-container-element
 			 */
-			throw new CKEditorError(
-				'view-writer-break-non-container-element: Trying to break an element which is not a container element.',
-				this.document
-			);
+			throw new CKEditorError( 'view-writer-break-non-container-element', this.document );
 		}
 
 		if ( !element.parent ) {
@@ -515,7 +512,7 @@ export default class DowncastWriter {
 			 *
 			 * @error view-writer-break-root
 			 */
-			throw new CKEditorError( 'view-writer-break-root: Trying to break a root element.', this.document );
+			throw new CKEditorError( 'view-writer-break-root', this.document );
 		}
 
 		if ( position.isAtStart ) {
@@ -637,8 +634,7 @@ export default class DowncastWriter {
 			 *
 			 * @error view-writer-merge-containers-invalid-position
 			 */
-			throw new CKEditorError( 'view-writer-merge-containers-invalid-position: ' +
-				'Element before and after given position cannot be merged.', this.document );
+			throw new CKEditorError( 'view-writer-merge-containers-invalid-position', this.document );
 		}
 
 		const lastChild = prev.getChild( prev.childCount - 1 );
@@ -684,7 +680,7 @@ export default class DowncastWriter {
 			 * @error view-writer-invalid-position-container
 			 */
 			throw new CKEditorError(
-				'view-writer-invalid-position-container: Position\'s parent container cannot be found.',
+				'view-writer-invalid-position-container',
 				this.document
 			);
 		}
@@ -874,7 +870,7 @@ export default class DowncastWriter {
 	wrap( range, attribute ) {
 		if ( !( attribute instanceof AttributeElement ) ) {
 			throw new CKEditorError(
-				'view-writer-wrap-invalid-attribute: DowncastWriter#wrap() must be called with an attribute element.',
+				'view-writer-wrap-invalid-attribute',
 				this.document
 			);
 		}
@@ -923,7 +919,7 @@ export default class DowncastWriter {
 			 * @error view-writer-unwrap-invalid-attribute
 			 */
 			throw new CKEditorError(
-				'view-writer-unwrap-invalid-attribute: DowncastWriter#unwrap() must be called with an attribute element.',
+				'view-writer-unwrap-invalid-attribute',
 				this.document
 			);
 		}
@@ -1609,7 +1605,7 @@ export default class DowncastWriter {
 			 *
 			 * @error view-writer-cannot-break-empty-element
 			 */
-			throw new CKEditorError( 'view-writer-cannot-break-empty-element: Cannot break an EmptyElement instance.', this.document );
+			throw new CKEditorError( 'view-writer-cannot-break-empty-element', this.document );
 		}
 
 		// If position is placed inside UIElement - throw an exception as we cannot break inside.
@@ -1623,7 +1619,7 @@ export default class DowncastWriter {
 			 *
 			 * @error view-writer-cannot-break-ui-element
 			 */
-			throw new CKEditorError( 'view-writer-cannot-break-ui-element: Cannot break a UIElement instance.', this.document );
+			throw new CKEditorError( 'view-writer-cannot-break-ui-element', this.document );
 		}
 
 		// If position is placed inside RawElement - throw an exception as we cannot break inside.
@@ -1637,7 +1633,7 @@ export default class DowncastWriter {
 			 *
 			 * @error view-writer-cannot-break-raw-element
 			 */
-			throw new CKEditorError( 'view-writer-cannot-break-raw-element: Cannot break a RawElement instance.', this.document );
+			throw new CKEditorError( 'view-writer-cannot-break-raw-element', this.document );
 		}
 
 		// There are no attributes to break and text nodes breaking is not forced.
@@ -1939,10 +1935,7 @@ function validateNodesToInsert( nodes, errorContext ) {
 			 *
 			 * @error view-writer-insert-invalid-node-type
 			 */
-			throw new CKEditorError(
-				'view-writer-insert-invalid-node-type: One of the nodes to be inserted is of an invalid type.',
-				errorContext
-			);
+			throw new CKEditorError( 'view-writer-insert-invalid-node-type', errorContext );
 		}
 
 		if ( !node.is( '$text' ) ) {
@@ -1988,7 +1981,7 @@ function validateRangeContainer( range, errorContext ) {
 		 *
 		 * @error view-writer-invalid-range-container
 		 */
-		throw new CKEditorError( 'view-writer-invalid-range-container: The container of the given range is invalid.', errorContext );
+		throw new CKEditorError( 'view-writer-invalid-range-container', errorContext );
 	}
 }
 

+ 1 - 1
packages/ckeditor5-engine/src/view/emptyelement.js

@@ -101,7 +101,7 @@ export default class EmptyElement extends Element {
 			 * @error view-emptyelement-cannot-add
 			 */
 			throw new CKEditorError(
-				'view-emptyelement-cannot-add: Cannot add child nodes to EmptyElement instance.',
+				'view-emptyelement-cannot-add',
 				[ this, nodes ]
 			);
 		}

+ 1 - 1
packages/ckeditor5-engine/src/view/node.js

@@ -73,7 +73,7 @@ export default class Node {
 			 *
 			 * @error view-node-not-found-in-parent
 			 */
-			throw new CKEditorError( 'view-node-not-found-in-parent: The node\'s parent does not contain this node.', this );
+			throw new CKEditorError( 'view-node-not-found-in-parent', this );
 		}
 
 		return pos;

+ 4 - 8
packages/ckeditor5-engine/src/view/position.js

@@ -356,13 +356,9 @@ export default class Position {
 				 * {@link module:engine/view/view~View#createPositionAt `View#createPositionAt()`}
 				 * requires the offset to be specified when the first parameter is a view item.
 				 *
-				 * @error view-createPositionAt-offset-required
+				 * @error view-createpositionat-offset-required
 				 */
-				throw new CKEditorError(
-					'view-createPositionAt-offset-required: ' +
-					'View#createPositionAt() requires the offset when the first parameter is a view item.',
-					node
-				);
+				throw new CKEditorError( 'view-createpositionat-offset-required', node );
 			}
 
 			return new Position( node, offset );
@@ -389,7 +385,7 @@ export default class Position {
 			 * @error view-position-after-root
 			 * @param {module:engine/view/node~Node} root
 			 */
-			throw new CKEditorError( 'view-position-after-root: You can not make position after root.', item, { root: item } );
+			throw new CKEditorError( 'view-position-after-root', item, { root: item } );
 		}
 
 		return new Position( item.parent, item.index + 1 );
@@ -415,7 +411,7 @@ export default class Position {
 			 * @error view-position-before-root
 			 * @param {module:engine/view/node~Node} root
 			 */
-			throw new CKEditorError( 'view-position-before-root: You can not make position before root.', item, { root: item } );
+			throw new CKEditorError( 'view-position-before-root', item, { root: item } );
 		}
 
 		return new Position( item.parent, item.index );

+ 1 - 1
packages/ckeditor5-engine/src/view/rawelement.js

@@ -113,7 +113,7 @@ export default class RawElement extends Element {
 			 * @error view-rawelement-cannot-add
 			 */
 			throw new CKEditorError(
-				'view-rawelement-cannot-add: Cannot add child nodes to a RawElement instance.',
+				'view-rawelement-cannot-add',
 				[ this, nodes ]
 			);
 		}

+ 3 - 3
packages/ckeditor5-engine/src/view/renderer.js

@@ -150,9 +150,9 @@ export default class Renderer {
 				/**
 				 * Unknown type passed to Renderer.markToSync.
 				 *
-				 * @error renderer-unknown-type
+				 * @error view-renderer-unknown-type
 				 */
-				throw new CKEditorError( 'view-renderer-unknown-type: Unknown type passed to Renderer.markToSync.', this );
+				throw new CKEditorError( 'view-renderer-unknown-type', this );
 			}
 		}
 	}
@@ -387,7 +387,7 @@ export default class Renderer {
 			 *
 			 * @error view-renderer-filler-was-lost
 			 */
-			throw new CKEditorError( 'view-renderer-filler-was-lost: The inline filler node was lost.', this );
+			throw new CKEditorError( 'view-renderer-filler-was-lost', this );
 		}
 
 		if ( isInlineFiller( domFillerNode ) ) {

+ 8 - 16
packages/ckeditor5-engine/src/view/selection.js

@@ -497,13 +497,9 @@ export default class Selection {
 				/**
 				 * selection.setTo requires the second parameter when the first parameter is a node.
 				 *
-				 * @error view-selection-setTo-required-second-parameter
+				 * @error view-selection-setto-required-second-parameter
 				 */
-				throw new CKEditorError(
-					'view-selection-setTo-required-second-parameter: ' +
-					'selection.setTo requires the second parameter when the first parameter is a node.',
-					this
-				);
+				throw new CKEditorError( 'view-selection-setto-required-second-parameter', this );
 			} else if ( placeOrOffset == 'in' ) {
 				range = Range._createIn( selectable );
 			} else if ( placeOrOffset == 'on' ) {
@@ -523,9 +519,9 @@ export default class Selection {
 			/**
 			 * Cannot set selection to given place.
 			 *
-			 * @error view-selection-setTo-not-selectable
+			 * @error view-selection-setto-not-selectable
 			 */
-			throw new CKEditorError( 'view-selection-setTo-not-selectable: Cannot set selection to given place.', this );
+			throw new CKEditorError( 'view-selection-setto-not-selectable', this );
 		}
 
 		this.fire( 'change' );
@@ -547,12 +543,9 @@ export default class Selection {
 			/**
 			 * Cannot set selection focus if there are no ranges in selection.
 			 *
-			 * @error view-selection-setFocus-no-ranges
+			 * @error view-selection-setfocus-no-ranges
 			 */
-			throw new CKEditorError(
-				'view-selection-setFocus-no-ranges: Cannot set selection focus if there are no ranges in selection.',
-				this
-			);
+			throw new CKEditorError( 'view-selection-setfocus-no-ranges', this );
 		}
 
 		const newFocus = Position._createAt( itemOrPosition, offset );
@@ -660,8 +653,7 @@ export default class Selection {
 			 * @error view-selection-add-range-not-range
 			 */
 			throw new CKEditorError(
-				'view-selection-add-range-not-range: ' +
-				'Selection range set to an object that is not an instance of view.Range',
+				'view-selection-add-range-not-range',
 				this
 			);
 		}
@@ -690,7 +682,7 @@ export default class Selection {
 				 * @param {module:engine/view/range~Range} intersectingRange Range from selection that intersects with `addedRange`.
 				 */
 				throw new CKEditorError(
-					'view-selection-range-intersects: Trying to add a range that intersects with another range from selection.',
+					'view-selection-range-intersects',
 					this,
 					{ addedRange: range, intersectingRange: storedRange }
 				);

+ 2 - 2
packages/ckeditor5-engine/src/view/textproxy.js

@@ -55,7 +55,7 @@ export default class TextProxy {
 			 *
 			 * @error view-textproxy-wrong-offsetintext
 			 */
-			throw new CKEditorError( 'view-textproxy-wrong-offsetintext: Given offsetInText value is incorrect.', this );
+			throw new CKEditorError( 'view-textproxy-wrong-offsetintext', this );
 		}
 
 		if ( length < 0 || offsetInText + length > textNode.data.length ) {
@@ -64,7 +64,7 @@ export default class TextProxy {
 			 *
 			 * @error view-textproxy-wrong-length
 			 */
-			throw new CKEditorError( 'view-textproxy-wrong-length: Given length value is incorrect.', this );
+			throw new CKEditorError( 'view-textproxy-wrong-length', this );
 		}
 
 		/**

+ 7 - 6
packages/ckeditor5-engine/src/view/treewalker.js

@@ -43,17 +43,18 @@ export default class TreeWalker {
 			 * @error view-tree-walker-no-start-position
 			 */
 			throw new CKEditorError(
-				'view-tree-walker-no-start-position: Neither boundaries nor starting position have been defined.',
+				'view-tree-walker-no-start-position',
 				null
 			);
 		}
 
 		if ( options.direction && options.direction != 'forward' && options.direction != 'backward' ) {
-			throw new CKEditorError(
-				'view-tree-walker-unknown-direction: Only `backward` and `forward` direction allowed.',
-				options.startPosition,
-				{ direction: options.direction }
-			);
+			/**
+			 * Only `backward` and `forward` direction allowed.
+			 *
+			 * @error view-tree-walker-unknown-direction
+			 */
+			throw new CKEditorError( 'view-tree-walker-unknown-direction', options.startPosition, { direction: options.direction } );
 		}
 
 		/**

+ 1 - 1
packages/ckeditor5-engine/src/view/uielement.js

@@ -113,7 +113,7 @@ export default class UIElement extends Element {
 			 *
 			 * @error view-uielement-cannot-add
 			 */
-			throw new CKEditorError( 'view-uielement-cannot-add: Cannot add child nodes to UIElement instance.', this );
+			throw new CKEditorError( 'view-uielement-cannot-add', this );
 		}
 	}
 

+ 1 - 3
packages/ckeditor5-engine/src/view/view.js

@@ -460,9 +460,7 @@ export default class View {
 			 * @error cannot-change-view-tree
 			 */
 			throw new CKEditorError(
-				'cannot-change-view-tree: ' +
-				'Attempting to make changes to the view when it is in an incorrect state: rendering or post-fixers are in progress. ' +
-				'This may cause some unexpected behavior and inconsistency between the DOM and the view.',
+				'cannot-change-view-tree',
 				this
 			);
 		}

+ 6 - 6
packages/ckeditor5-engine/tests/controller/datacontroller.js

@@ -189,7 +189,7 @@ describe( 'DataController', () => {
 
 			expectToThrowCKEditorError( () => {
 				data.init( '<p>Bar</p>' );
-			}, /datacontroller-init-document-not-empty:/, model );
+			}, /datacontroller-init-document-not-empty/, model );
 		} );
 
 		it( 'should set data to default main root', () => {
@@ -243,7 +243,7 @@ describe( 'DataController', () => {
 		it( 'should throw an error when non-existent root is used (single)', () => {
 			expectToThrowCKEditorError( () => {
 				data.init( { nonexistent: '<p>Bar</p>' } );
-			}, /^datacontroller-init-non-existent-root:/ );
+			}, 'datacontroller-init-non-existent-root' );
 		} );
 
 		it( 'should throw an error when non-existent root is used (one of many)', () => {
@@ -251,7 +251,7 @@ describe( 'DataController', () => {
 
 			expectToThrowCKEditorError( () => {
 				data.init( { main: 'bar', nonexistent: '<p>Bar</p>' } );
-			}, /^datacontroller-init-non-existent-root:/, model );
+			}, /^datacontroller-init-non-existent-root/, model );
 
 			expect( getData( model, { withoutSelection: true } ) ).to.equal( '' );
 		} );
@@ -332,7 +332,7 @@ describe( 'DataController', () => {
 		it( 'should throw an error when non-existent root is used (single)', () => {
 			expectToThrowCKEditorError( () => {
 				data.set( { nonexistent: '<p>Bar</p>' } );
-			}, /datacontroller-set-non-existent-root:/, model );
+			}, /datacontroller-set-non-existent-root/, model );
 		} );
 
 		it( 'should throw an error when non-existent root is used (one of many) without touching any roots data', () => {
@@ -341,7 +341,7 @@ describe( 'DataController', () => {
 
 			expectToThrowCKEditorError( () => {
 				data.set( { main: 'bar', nonexistent: '<p>Bar</p>' } );
-			}, /datacontroller-set-non-existent-root:/, model );
+			}, /datacontroller-set-non-existent-root/, model );
 
 			expect( getData( model, { withoutSelection: true } ) ).to.equal( 'foo' );
 		} );
@@ -452,7 +452,7 @@ describe( 'DataController', () => {
 		it( 'should throw an error when non-existent root is used', () => {
 			expectToThrowCKEditorError( () => {
 				data.get( { rootName: 'nonexistent' } );
-			}, /datacontroller-get-non-existent-root:/ );
+			}, 'datacontroller-get-non-existent-root' );
 		} );
 
 		it( 'should allow to provide additional options for retrieving data - insert conversion', () => {

+ 1 - 1
packages/ckeditor5-engine/tests/dev-utils/operationreplayer.js

@@ -148,7 +148,7 @@ describe( 'OperationReplayer', () => {
 				.then( () => {
 					throw new Error( 'It should throw an error' );
 				}, err => {
-					expect( err.message ).to.match( /^model-document-applyOperation-wrong-version/ );
+					expect( err.message ).to.match( /model-document-applyoperation-wrong-version/ );
 				} );
 		} );
 	} );

+ 2 - 2
packages/ckeditor5-engine/tests/model/document.js

@@ -87,7 +87,7 @@ describe( 'Document', () => {
 
 			expectToThrowCKEditorError( () => {
 				model.applyOperation( operation );
-			}, /^model-document-applyOperation-wrong-version/, model );
+			}, 'model-document-applyoperation-wrong-version', model );
 		} );
 	} );
 
@@ -130,7 +130,7 @@ describe( 'Document', () => {
 
 			expectToThrowCKEditorError( () => {
 				doc.createRoot( '$root', 'rootName' );
-			}, /model-document-createRoot-name-exists/, model );
+			}, 'model-document-createroot-name-exists', model );
 		} );
 	} );
 

+ 2 - 2
packages/ckeditor5-engine/tests/model/markercollection.js

@@ -127,7 +127,7 @@ describe( 'MarkerCollection', () => {
 		it( 'should throw if marker name with "," is added', () => {
 			expectToThrowCKEditorError( () => {
 				markers._set( 'foo,bar', range );
-			}, /^markercollection-incorrect-marker-name:/, markers );
+			}, 'markercollection-incorrect-marker-name', markers );
 		} );
 	} );
 
@@ -215,7 +215,7 @@ describe( 'MarkerCollection', () => {
 		it( 'should throw if marker does not exist', () => {
 			expectToThrowCKEditorError( () => {
 				markers._refresh( 'name' );
-			}, /^markercollection-refresh-marker-not-exists:/, markers );
+			}, 'markercollection-refresh-marker-not-exists', markers );
 		} );
 	} );
 

+ 2 - 0
packages/ckeditor5-engine/tests/model/model.js

@@ -339,6 +339,7 @@ describe( 'Model', () => {
 		it( 'should throw the original CKEditorError error if it was thrown inside the `change()` block', () => {
 			expectToThrowCKEditorError( () => {
 				model.change( () => {
+					// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
 					throw new CKEditorError( 'foo', null, { foo: 1 } );
 				} );
 			}, /foo/, null, { foo: 1 } );
@@ -355,6 +356,7 @@ describe( 'Model', () => {
 		} );
 
 		it( 'should throw the original CKEditorError error if it was thrown inside the `enqueueChange()` block', () => {
+			// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
 			const err = new CKEditorError( 'foo', null, { foo: 1 } );
 
 			expectToThrowCKEditorError( () => {

+ 1 - 1
packages/ckeditor5-engine/tests/model/nodelist.js

@@ -160,7 +160,7 @@ describe( 'NodeList', () => {
 		it( 'should throw if not a Node is inserted', () => {
 			expectToThrowCKEditorError( () => {
 				nodes._insertNodes( 0, [ 'foo' ] );
-			}, /nodelist-insertNodes-not-node/, nodes );
+			}, 'nodelist-insertnodes-not-node', nodes );
 		} );
 	} );
 

+ 1 - 1
packages/ckeditor5-engine/tests/model/operation/operation.js

@@ -39,7 +39,7 @@ describe( 'Operation', () => {
 			} );
 		} );
 
-		it( 'should create proper json object #1', () => {
+		it( 'should create proper json object #2', () => {
 			const op = new Operation( 4 );
 			const batch = new Batch();
 			batch.addOperation( op );

+ 0 - 39
packages/ckeditor5-engine/tests/model/operation/transform.js

@@ -1771,45 +1771,6 @@ describe( 'transform', () => {
 				expectOperation( transOp[ 2 ], expected );
 			} );
 
-			it( 'range intersects on right side of transforming range and is important: shrink range', () => {
-				const transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 5 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					0
-				);
-
-				const transOp = transform( op, transformBy );
-
-				expected.howMany = 1;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range intersects on right side of transforming range and is less important: split into two operations', () => {
-				const transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 5 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					0
-				);
-
-				const transOp = transform( op, transformBy, strongContext );
-
-				expect( transOp.length ).to.equal( 2 );
-
-				expected.sourcePosition = sourcePosition;
-				expected.howMany = 1;
-
-				expectOperation( transOp[ 0 ], expected );
-
-				expected.sourcePosition = new Position( root, [ 4, 1, 0 ] );
-				expected.targetPosition = targetPosition.getShiftedBy( 1 );
-
-				expectOperation( transOp[ 1 ], expected );
-			} );
-
 			it( 'range intersects, target inside transforming range and is important: split into two operations', () => {
 				op.targetPosition.path = [ 2, 2, 7 ];
 

+ 12 - 12
packages/ckeditor5-engine/tests/model/position.js

@@ -158,7 +158,7 @@ describe( 'Position', () => {
 			it( 'should throw if no offset is passed', () => {
 				expectToThrowCKEditorError( () => {
 					Position._createAt( ul );
-				}, /model-createPositionAt-offset-required/, model );
+				}, 'model-createpositionat-offset-required', model );
 			} );
 
 			it( 'should create positions from positions', () => {
@@ -321,7 +321,7 @@ describe( 'Position', () => {
 
 			expectToThrowCKEditorError( () => {
 				position.parent;
-			}, /^model-position-path-incorrect:/, position, { position } );
+			}, 'model-position-path-incorrect', position, { position } );
 		} );
 
 		it( 'should throw when based on a path, the parent would be a text node', () => {
@@ -330,7 +330,7 @@ describe( 'Position', () => {
 
 			expectToThrowCKEditorError( () => {
 				position.parent;
-			}, /^model-position-path-incorrect:/, position, { position } );
+			}, 'model-position-path-incorrect', position, { position } );
 		} );
 	} );
 
@@ -388,7 +388,7 @@ describe( 'Position', () => {
 
 			expectToThrowCKEditorError( () => {
 				position.index;
-			}, /^model-position-path-incorrect:/, position, { position } );
+			}, 'model-position-path-incorrect', position, { position } );
 		} );
 	} );
 
@@ -419,7 +419,7 @@ describe( 'Position', () => {
 
 			expectToThrowCKEditorError( () => {
 				position.nodeBefore;
-			}, /^model-nodelist-offset-out-of-bounds:/, position );
+			}, 'model-nodelist-offset-out-of-bounds', position );
 		} );
 	} );
 
@@ -450,7 +450,7 @@ describe( 'Position', () => {
 
 			expectToThrowCKEditorError( () => {
 				position.nodeAfter;
-			}, /^model-nodelist-offset-out-of-bounds:/, position );
+			}, 'model-nodelist-offset-out-of-bounds', position );
 		} );
 	} );
 
@@ -486,7 +486,7 @@ describe( 'Position', () => {
 
 			expectToThrowCKEditorError( () => {
 				position.textNode;
-			}, /^model-nodelist-offset-out-of-bounds:/, position );
+			}, 'model-nodelist-offset-out-of-bounds', position );
 		} );
 	} );
 
@@ -615,7 +615,7 @@ describe( 'Position', () => {
 			expect( positionB.isTouching( positionA ) ).to.be.false;
 		} );
 
-		it( 'should return false if there are whole nodes between positions', () => {
+		it( 'should return false if there are whole nodes between positions (same depth, but deeper)', () => {
 			const positionA = new Position( root, [ 1, 0, 3 ] );
 			const positionB = new Position( root, [ 1, 1, 1 ] );
 
@@ -1255,9 +1255,9 @@ describe( 'Position', () => {
 
 			root._appendChild( p );
 
-			const postion = new Position( root, [ 0, 3 ] ); // <p>foo^bar</p>
+			const position = new Position( root, [ 0, 3 ] ); // <p>foo^bar</p>
 
-			testAncestor( postion, postion, p );
+			testAncestor( position, position, p );
 		} );
 
 		it( 'for two positions in the same element returns the element', () => {
@@ -1284,9 +1284,9 @@ describe( 'Position', () => {
 
 			root._appendChild( p );
 
-			const postion = new Position( root, [ 0, 0 ] ); // <p>^<a></a></p>
+			const position = new Position( root, [ 0, 0 ] ); // <p>^<a></a></p>
 
-			testAncestor( postion, postion, p );
+			testAncestor( position, position, p );
 		} );
 
 		it( 'works fine with positions located in DocumentFragment', () => {

+ 32 - 34
packages/ckeditor5-engine/tests/model/schema.js

@@ -62,7 +62,7 @@ describe( 'Schema', () => {
 
 			expectToThrowCKEditorError( () => {
 				schema.register( 'foo' );
-			}, /^schema-cannot-register-item-twice:/, schema );
+			}, 'schema-cannot-register-item-twice', schema );
 		} );
 	} );
 
@@ -91,7 +91,7 @@ describe( 'Schema', () => {
 		it( 'throws when trying to extend a not yet registered item', () => {
 			expectToThrowCKEditorError( () => {
 				schema.extend( 'foo' );
-			}, /^schema-cannot-extend-missing-item:/, schema );
+			}, 'schema-cannot-extend-missing-item', schema );
 		} );
 	} );
 
@@ -960,7 +960,7 @@ describe( 'Schema', () => {
 
 			expectToThrowCKEditorError( () => {
 				expect( schema.checkMerge( position ) );
-			}, /^schema-check-merge-no-element-before:/, schema );
+			}, 'schema-check-merge-no-element-before', schema );
 		} );
 
 		it( 'throws an error if the node before the position is not the element', () => {
@@ -978,7 +978,7 @@ describe( 'Schema', () => {
 
 			expectToThrowCKEditorError( () => {
 				expect( schema.checkMerge( position ) );
-			}, /^schema-check-merge-no-element-before:/, schema );
+			}, 'schema-check-merge-no-element-before', schema );
 		} );
 
 		it( 'throws an error if there is no element after the position', () => {
@@ -995,7 +995,7 @@ describe( 'Schema', () => {
 
 			expectToThrowCKEditorError( () => {
 				expect( schema.checkMerge( position ) );
-			}, /^schema-check-merge-no-element-after:/, schema );
+			}, 'schema-check-merge-no-element-after', schema );
 		} );
 
 		it( 'throws an error if the node after the position is not the element', () => {
@@ -1013,7 +1013,7 @@ describe( 'Schema', () => {
 
 			expectToThrowCKEditorError( () => {
 				expect( schema.checkMerge( position ) );
-			}, /^schema-check-merge-no-element-before:/, schema );
+			}, 'schema-check-merge-no-element-before', schema );
 		} );
 
 		// This is an invalid case by definition – the baseElement should not contain disallowed elements
@@ -2509,7 +2509,7 @@ describe( 'Schema', () => {
 				expect( schema.checkChild( root1, r1p1 ) ).to.be.true;
 			} );
 
-			it( 'passes $root>paragraph>$text – paragraph inherits allowIn from $block through $block\'s allowWhere', () => {
+			it( 'passes $root>paragraph>$text – paragraph inherits allowed content from $block through $block\'s allowContentOf', () => {
 				schema.register( '$root' );
 				schema.register( '$blockProto' );
 				schema.register( '$block', {
@@ -2525,6 +2525,31 @@ describe( 'Schema', () => {
 
 				expect( schema.checkChild( r1p1, r1p1.getChild( 0 ) ) ).to.be.true;
 			} );
+
+			it( 'passes paragraph[align] – paragraph inherits attributes of $block', () => {
+				schema.register( '$block', {
+					allowAttributes: 'align'
+				} );
+				schema.register( 'paragraph', {
+					inheritAllFrom: '$block'
+				} );
+
+				expect( schema.checkAttribute( r1p1, 'align' ) ).to.be.true;
+			} );
+
+			it( 'passes paragraph[align] – paragraph inherits attributes of $block through allowAttributesOf', () => {
+				schema.register( '$blockProto', {
+					allowAttributes: 'align'
+				} );
+				schema.register( '$block', {
+					allowAttributesOf: '$blockProto'
+				} );
+				schema.register( 'paragraph', {
+					inheritAllFrom: '$block'
+				} );
+
+				expect( schema.checkAttribute( r1p1, 'align' ) ).to.be.true;
+			} );
 		} );
 
 		// We need to handle cases where some independent features registered definitions which might use
@@ -2669,33 +2694,6 @@ describe( 'Schema', () => {
 			// However, those situations are rather theoretical, so we're not going to waste time on them now.
 		} );
 
-		describe( 'inheritAllFrom', () => {
-			it( 'passes paragraph[align] – paragraph inherits attributes of $block', () => {
-				schema.register( '$block', {
-					allowAttributes: 'align'
-				} );
-				schema.register( 'paragraph', {
-					inheritAllFrom: '$block'
-				} );
-
-				expect( schema.checkAttribute( r1p1, 'align' ) ).to.be.true;
-			} );
-
-			it( 'passes paragraph[align] – paragraph inherits attributes of $block through allowAttributesOf', () => {
-				schema.register( '$blockProto', {
-					allowAttributes: 'align'
-				} );
-				schema.register( '$block', {
-					allowAttributesOf: '$blockProto'
-				} );
-				schema.register( 'paragraph', {
-					inheritAllFrom: '$block'
-				} );
-
-				expect( schema.checkAttribute( r1p1, 'align' ) ).to.be.true;
-			} );
-		} );
-
 		describe( 'missing attribute definitions', () => {
 			it( 'does not crash when checking an attribute of a non-registered element', () => {
 				expect( schema.checkAttribute( r1p1, 'align' ) ).to.be.false;

+ 10 - 20
packages/ckeditor5-engine/tests/model/selection.js

@@ -123,7 +123,7 @@ describe( 'Selection', () => {
 			expectToThrowCKEditorError( () => {
 				// eslint-disable-next-line no-new
 				new Selection( {} );
-			}, /model-selection-setTo-not-selectable/ );
+			}, 'model-selection-setto-not-selectable' );
 		} );
 	} );
 
@@ -143,7 +143,12 @@ describe( 'Selection', () => {
 			expect( selection.is( 'model' ) ).to.be.false;
 			expect( selection.is( 'model:node' ) ).to.be.false;
 			expect( selection.is( '$text' ) ).to.be.false;
+			expect( selection.is( '$textProxy' ) ).to.be.false;
+			expect( selection.is( 'element' ) ).to.be.false;
 			expect( selection.is( 'element', 'paragraph' ) ).to.be.false;
+			expect( selection.is( 'documentSelection' ) ).to.be.false;
+			expect( selection.is( 'node' ) ).to.be.false;
+			expect( selection.is( 'rootElement' ) ).to.be.false;
 		} );
 	} );
 
@@ -302,13 +307,13 @@ describe( 'Selection', () => {
 		it( 'should throw an error when trying to set selection to not selectable', () => {
 			expectToThrowCKEditorError( () => {
 				selection.setTo( {} );
-			}, /model-selection-setTo-not-selectable/ );
+			}, 'model-selection-setto-not-selectable' );
 		} );
 
 		it( 'should throw an error when trying to set selection to not selectable #2', () => {
 			expectToThrowCKEditorError( () => {
 				selection.setTo();
-			}, /model-selection-setTo-not-selectable/ );
+			}, 'model-selection-setto-not-selectable' );
 		} );
 
 		it( 'should allow setting selection inside an element', () => {
@@ -374,7 +379,7 @@ describe( 'Selection', () => {
 			it( 'should throw if second parameter is not passed', () => {
 				expectToThrowCKEditorError( () => {
 					selection.setTo( root );
-				}, /model-selection-setTo-required-second-parameter/, model );
+				}, 'model-selection-setto-required-second-parameter', model );
 			} );
 
 			it( 'should set selection at given offset in given parent', () => {
@@ -460,7 +465,7 @@ describe( 'Selection', () => {
 
 			expectToThrowCKEditorError( () => {
 				selection.setFocus( endPos );
-			}, /model-selection-setFocus-no-ranges/, model );
+			}, 'model-selection-setfocus-no-ranges', model );
 		} );
 
 		it( 'modifies existing collapsed selection', () => {
@@ -826,21 +831,6 @@ describe( 'Selection', () => {
 		} );
 	} );
 
-	describe( 'is()', () => {
-		it( 'should return true for selection', () => {
-			expect( selection.is( 'selection' ) ).to.be.true;
-		} );
-
-		it( 'should return false for other values', () => {
-			expect( selection.is( 'documentSelection' ) ).to.be.false;
-			expect( selection.is( 'node' ) ).to.be.false;
-			expect( selection.is( '$text' ) ).to.be.false;
-			expect( selection.is( '$textProxy' ) ).to.be.false;
-			expect( selection.is( 'element' ) ).to.be.false;
-			expect( selection.is( 'rootElement' ) ).to.be.false;
-		} );
-	} );
-
 	describe( 'setTo - used to collapse at start', () => {
 		it( 'should collapse to start position and fire change event', () => {
 			selection.setTo( [ range2, range1, range3 ] );

+ 8 - 8
packages/ckeditor5-engine/tests/model/writer.js

@@ -2157,13 +2157,13 @@ describe( 'Writer', () => {
 		it( 'should throw if options.usingOperation is not defined', () => {
 			expectToThrowCKEditorError( () => {
 				addMarker( 'name' );
-			}, /^writer-addMarker-no-usingOperation/, model );
+			}, '^writer-addmarker-no-usingoperation', model );
 		} );
 
 		it( 'should throw if name and range is defined but options.usingOperation is not defined', () => {
 			expectToThrowCKEditorError( () => {
 				addMarker( 'name', { range } );
-			}, /^writer-addMarker-no-usingOperation/, model );
+			}, '^writer-addmarker-no-usingoperation', model );
 		} );
 
 		it( 'should add marker to the document marker collection', () => {
@@ -2215,7 +2215,7 @@ describe( 'Writer', () => {
 
 			expectToThrowCKEditorError( () => {
 				addMarker( 'name', { range: range2, usingOperation: false } );
-			}, /^writer-addMarker-marker-exists/, model );
+			}, 'writer-addmarker-marker-exists', model );
 		} );
 
 		it( 'should use operations when having set usingOperation to true', () => {
@@ -2235,13 +2235,13 @@ describe( 'Writer', () => {
 		it( 'should throw if marker with given name does not exist and range is not passed', () => {
 			expectToThrowCKEditorError( () => {
 				addMarker( 'name', { usingOperation: true } );
-			}, /^writer-addMarker-no-range/, model );
+			}, 'writer-addmarker-no-range', model );
 		} );
 
 		it( 'should throw if marker is set directly and range is not passed', () => {
 			expectToThrowCKEditorError( () => {
 				addMarker( 'name', { usingOperation: false } );
-			}, /^writer-addMarker-no-range/, model );
+			}, 'writer-addmarker-no-range', model );
 		} );
 
 		it( 'should throw when trying to use detached writer', () => {
@@ -2487,13 +2487,13 @@ describe( 'Writer', () => {
 			expectToThrowCKEditorError( () => {
 				addMarker( 'name', { range, usingOperation: false } );
 				updateMarker( 'name', {} );
-			}, /^writer-updateMarker-wrong-options/, model );
+			}, 'writer-updatemarker-wrong-options', model );
 		} );
 
 		it( 'should throw when marker provided by name does not exists', () => {
 			expectToThrowCKEditorError( () => {
 				updateMarker( 'name', { usingOperation: false } );
-			}, /^writer-updateMarker-marker-not-exists/, model );
+			}, 'writer-updatemarker-marker-not-exists', model );
 		} );
 
 		it( 'should only refresh the marker when there is no provided options to update', () => {
@@ -2540,7 +2540,7 @@ describe( 'Writer', () => {
 		it( 'should throw when trying to remove non existing marker', () => {
 			expectToThrowCKEditorError( () => {
 				removeMarker( 'name' );
-			}, /^writer-removeMarker-no-marker/, model );
+			}, 'writer-removemarker-no-marker', model );
 		} );
 
 		it( 'should throw when trying to use detached writer', () => {

+ 2 - 2
packages/ckeditor5-engine/tests/tickets/ckeditor5-692.js

@@ -41,7 +41,7 @@ describe( 'Bug ckeditor5#692', () => {
 
 	describe( 'DomConverter', () => {
 		// https://github.com/ckeditor/ckeditor5/issues/692 Scenario 1.
-		it( 'should handle space after inline filler at the end of container', () => {
+		it( 'should handle space after inline filler at the end of container (scenario 1)', () => {
 			setModelData( editor.model, '<paragraph>foo[]</paragraph>' );
 
 			// Create Bold attribute at the end of paragraph.
@@ -63,7 +63,7 @@ describe( 'Bug ckeditor5#692', () => {
 		} );
 
 		// https://github.com/ckeditor/ckeditor5/issues/692 Scenario 2.
-		it( 'should handle space after inline filler at the end of container', () => {
+		it( 'should handle space after inline filler at the end of container (scenario 2)', () => {
 			setModelData( editor.model, '<paragraph>[]foo</paragraph>' );
 
 			// Create Bold attribute at the end of paragraph.

+ 5 - 21
packages/ckeditor5-engine/tests/view/documentselection.js

@@ -80,16 +80,6 @@ describe( 'DocumentSelection', () => {
 			expect( selection.isBackward ).to.be.false;
 		} );
 
-		it( 'should be able to create a collapsed selection at the given position', () => {
-			const position = range1.start;
-			const selection = new DocumentSelection( position );
-
-			expect( Array.from( selection.getRanges() ).length ).to.equal( 1 );
-			expect( selection.getFirstRange().start ).to.deep.equal( position );
-			expect( selection.getFirstRange().end ).to.deep.equal( position );
-			expect( selection.isBackward ).to.be.false;
-		} );
-
 		it( 'should be able to create a selection from the other document selection', () => {
 			const otherSelection = new DocumentSelection( [ range2, range3 ], { backward: true } );
 			const selection = new DocumentSelection( otherSelection );
@@ -135,7 +125,7 @@ describe( 'DocumentSelection', () => {
 			expectToThrowCKEditorError( () => {
 				// eslint-disable-next-line no-new
 				new DocumentSelection( {} );
-			}, /view-selection-setTo-not-selectable/ );
+			}, 'view-selection-setto-not-selectable' );
 		} );
 	} );
 
@@ -207,7 +197,7 @@ describe( 'DocumentSelection', () => {
 
 			expectToThrowCKEditorError( () => {
 				documentSelection._setFocus( endPos );
-			}, /view-selection-setFocus-no-ranges/, documentSelection );
+			}, 'view-selection-setfocus-no-ranges', documentSelection );
 		} );
 
 		it( 'modifies existing collapsed selection', () => {
@@ -553,12 +543,6 @@ describe( 'DocumentSelection', () => {
 			expect( documentSelection.isEqual( otherSelection ) ).to.be.false;
 		} );
 
-		it( 'should return false if one selection is fake', () => {
-			const otherSelection = new DocumentSelection( null, { fake: true } );
-
-			expect( documentSelection.isEqual( otherSelection ) ).to.be.false;
-		} );
-
 		it( 'should return true if both selection are fake - DocumentSelection and Selection', () => {
 			const otherSelection = new Selection( range1, { fake: true } );
 			documentSelection._setTo( range1, { fake: true } );
@@ -818,7 +802,7 @@ describe( 'DocumentSelection', () => {
 
 				expectToThrowCKEditorError( () => {
 					otherSelection._setTo( {} );
-				}, /view-selection-setTo-not-selectable/ );
+				}, 'view-selection-setto-not-selectable' );
 			} );
 
 			it( 'should throw an error when trying to set to not selectable #2', () => {
@@ -826,7 +810,7 @@ describe( 'DocumentSelection', () => {
 
 				expectToThrowCKEditorError( () => {
 					otherSelection._setTo();
-				}, /view-selection-setTo-not-selectable/ );
+				}, 'view-selection-setto-not-selectable' );
 			} );
 		} );
 
@@ -870,7 +854,7 @@ describe( 'DocumentSelection', () => {
 
 				expectToThrowCKEditorError( () => {
 					documentSelection._setTo( foo );
-				}, /view-selection-setTo-required-second-parameter/, documentSelection );
+				}, 'view-selection-setto-required-second-parameter', documentSelection );
 			} );
 
 			it( 'should collapse selection at node and flag', () => {

+ 58 - 58
packages/ckeditor5-engine/tests/view/domconverter/dom-to-view.js

@@ -421,7 +421,7 @@ describe( 'DomConverter', () => {
 				expect( viewDiv.getChild( 0 ).getChild( 0 ).data ).to.equal( 'f o o' );
 			} );
 
-			function test( inputTexts, output ) {
+			function testTexts( inputTexts, output ) {
 				if ( typeof inputTexts == 'string' ) {
 					inputTexts = [ inputTexts ];
 				}
@@ -446,75 +446,75 @@ describe( 'DomConverter', () => {
 			}
 
 			// At the beginning.
-			test( '_x', ' x' );
-			test( '_ x', '  x' );
-			test( '_ _x', '   x' );
-			test( '_ _ x', '    x' );
+			testTexts( '_x', ' x' );
+			testTexts( '_ x', '  x' );
+			testTexts( '_ _x', '   x' );
+			testTexts( '_ _ x', '    x' );
 
 			// At the end.
-			test( 'x_', 'x ' );
-			test( 'x _', 'x  ' );
-			test( 'x __', 'x   ' );
-			test( 'x _ _', 'x    ' );
+			testTexts( 'x_', 'x ' );
+			testTexts( 'x _', 'x  ' );
+			testTexts( 'x __', 'x   ' );
+			testTexts( 'x _ _', 'x    ' );
 
 			// In the middle.
-			test( 'x x', 'x x' );
-			test( 'x _x', 'x  x' );
-			test( 'x _ x', 'x   x' );
-			test( 'x _ _x', 'x    x' );
+			testTexts( 'x x', 'x x' );
+			testTexts( 'x _x', 'x  x' );
+			testTexts( 'x _ x', 'x   x' );
+			testTexts( 'x _ _x', 'x    x' );
 
 			// Complex.
-			test( '_x_', ' x ' );
-			test( '_ x _x _', '  x  x  ' );
-			test( '_ _x x _', '   x x  ' );
-			test( '_ _x x __', '   x x   ' );
-			test( '_ _x _ _x_', '   x    x ' );
-			test( '_', ' ' );
+			testTexts( '_x_', ' x ' );
+			testTexts( '_ x _x _', '  x  x  ' );
+			testTexts( '_ _x x _', '   x x  ' );
+			testTexts( '_ _x x __', '   x x   ' );
+			testTexts( '_ _x _ _x_', '   x    x ' );
+			testTexts( '_', ' ' );
 
 			// With hard &nbsp;
-			test( '_x', ' x' );
-			test( '__x', ' _x' );
-			test( '___x', ' __x' );
-			test( '__ x', ' _ x' );
-
-			test( 'x_', 'x ' );
-			test( 'x__', 'x_ ' );
-			test( 'x___', 'x__ ' );
-
-			test( 'x_x', 'x_x' );
-			test( 'x___x', 'x___x' );
-			test( 'x____x', 'x____x' );
-			test( 'x__ x', 'x__ x' );
-			test( 'x___ x', 'x___ x' );
-			test( 'x_ _x', 'x_  x' );
-			test( 'x __x', 'x  _x' );
-			test( 'x _ x', 'x   x' );
-			test( 'x __ _x', 'x  _  x' );
+			testTexts( '_x', ' x' );
+			testTexts( '__x', ' _x' );
+			testTexts( '___x', ' __x' );
+			testTexts( '__ x', ' _ x' );
+
+			testTexts( 'x_', 'x ' );
+			testTexts( 'x__', 'x_ ' );
+			testTexts( 'x___', 'x__ ' );
+
+			testTexts( 'x_x', 'x_x' );
+			testTexts( 'x___x', 'x___x' );
+			testTexts( 'x____x', 'x____x' );
+			testTexts( 'x__ x', 'x__ x' );
+			testTexts( 'x___ x', 'x___ x' );
+			testTexts( 'x_ _x', 'x_  x' );
+			testTexts( 'x __x', 'x  _x' );
+			testTexts( 'x _ x', 'x   x' );
+			testTexts( 'x __ _x', 'x  _  x' );
 
 			// Two text nodes.
-			test( [ 'x', 'y' ], 'xy' );
-			test( [ 'x ', 'y' ], 'x y' );
-			test( [ 'x _', 'y' ], 'x  y' );
-			test( [ 'x __', 'y' ], 'x   y' );
-			test( [ 'x _  _', 'y' ], 'x    y' );
-
-			test( [ 'x', ' y' ], 'x y' );
-			test( [ 'x_', ' y' ], 'x  y' );
-			test( [ 'x _', ' y' ], 'x   y' );
-			test( [ 'x __', ' y' ], 'x    y' );
-			test( [ 'x _ _', ' y' ], 'x     y' );
-
-			test( [ 'x', ' _y' ], 'x  y' );
-			test( [ 'x_', ' _y' ], 'x   y' );
-			test( [ 'x _', ' _y' ], 'x    y' );
-			test( [ 'x __', ' _y' ], 'x     y' );
-			test( [ 'x _ _', ' _y' ], 'x      y' );
+			testTexts( [ 'x', 'y' ], 'xy' );
+			testTexts( [ 'x ', 'y' ], 'x y' );
+			testTexts( [ 'x _', 'y' ], 'x  y' );
+			testTexts( [ 'x __', 'y' ], 'x   y' );
+			testTexts( [ 'x _  _', 'y' ], 'x    y' );
+
+			testTexts( [ 'x', ' y' ], 'x y' );
+			testTexts( [ 'x_', ' y' ], 'x  y' );
+			testTexts( [ 'x _', ' y' ], 'x   y' );
+			testTexts( [ 'x __', ' y' ], 'x    y' );
+			testTexts( [ 'x _ _', ' y' ], 'x     y' );
+
+			testTexts( [ 'x', ' _y' ], 'x  y' );
+			testTexts( [ 'x_', ' _y' ], 'x   y' );
+			testTexts( [ 'x _', ' _y' ], 'x    y' );
+			testTexts( [ 'x __', ' _y' ], 'x     y' );
+			testTexts( [ 'x _ _', ' _y' ], 'x      y' );
 
 			// Some tests with hard &nbsp;
-			test( [ 'x', '_y' ], 'x_y' );
-			test( [ 'x_', 'y' ], 'x_y' );
-			test( [ 'x__', ' y' ], 'x_  y' );
-			test( [ 'x_ _', ' y' ], 'x_   y' );
+			testTexts( [ 'x', '_y' ], 'x_y' );
+			testTexts( [ 'x_', 'y' ], 'x_y' );
+			testTexts( [ 'x__', ' y' ], 'x_  y' );
+			testTexts( [ 'x_ _', ' y' ], 'x_   y' );
 
 			it( 'not in preformatted blocks', () => {
 				const domDiv = createElement( document, 'div', {}, [

+ 3 - 3
packages/ckeditor5-engine/tests/view/emptyelement.js

@@ -66,14 +66,14 @@ describe( 'EmptyElement', () => {
 
 		expectToThrowCKEditorError( () => {
 			new EmptyElement( document, 'img', null, [ el ] ); // eslint-disable-line no-new
-		}, 'view-emptyelement-cannot-add: Cannot add child nodes to EmptyElement instance.', el );
+		}, 'view-emptyelement-cannot-add', el );
 	} );
 
 	describe( '_appendChild', () => {
 		it( 'should throw when try to append new child element', () => {
 			expectToThrowCKEditorError( () => {
 				emptyElement._appendChild( element );
-			}, 'view-emptyelement-cannot-add: Cannot add child nodes to EmptyElement instance.', element );
+			}, 'view-emptyelement-cannot-add', element );
 		} );
 	} );
 
@@ -81,7 +81,7 @@ describe( 'EmptyElement', () => {
 		it( 'should throw when try to insert new child element', () => {
 			expectToThrowCKEditorError( () => {
 				emptyElement._insertChild( 0, element );
-			}, 'view-emptyelement-cannot-add: Cannot add child nodes to EmptyElement instance.', element );
+			}, 'view-emptyelement-cannot-add', element );
 		} );
 	} );
 

+ 1 - 1
packages/ckeditor5-engine/tests/view/node.js

@@ -214,7 +214,7 @@ describe( 'Node', () => {
 		} );
 	} );
 
-	describe( 'getIndex()', () => {
+	describe( '#index getter', () => {
 		it( 'should return null if the parent is null', () => {
 			expect( root.index ).to.be.null;
 		} );

+ 1 - 1
packages/ckeditor5-engine/tests/view/position.js

@@ -417,7 +417,7 @@ describe( 'Position', () => {
 
 				expectToThrowCKEditorError( () => {
 					Position._createAt( element );
-				}, /view-createPositionAt-offset-required/ );
+				}, 'view-createpositionat-offset-required' );
 			} );
 
 			it( 'should create positions from positions', () => {

+ 3 - 3
packages/ckeditor5-engine/tests/view/rawelement.js

@@ -35,7 +35,7 @@ describe( 'RawElement', () => {
 		it( 'should throw if child elements are passed to constructor', () => {
 			expectToThrowCKEditorError( () => {
 				new RawElement( doc, 'img', null, [ new Element( doc, 'i' ) ] ); // eslint-disable-line no-new
-			}, 'view-rawelement-cannot-add: Cannot add child nodes to a RawElement instance.' );
+			}, 'view-rawelement-cannot-add' );
 		} );
 	} );
 
@@ -85,7 +85,7 @@ describe( 'RawElement', () => {
 		it( 'should throw when try to append new child element', () => {
 			expectToThrowCKEditorError( () => {
 				rawElement._appendChild( new Element( doc, 'i' ) );
-			}, 'view-rawelement-cannot-add: Cannot add child nodes to a RawElement instance.' );
+			}, 'view-rawelement-cannot-add' );
 		} );
 	} );
 
@@ -93,7 +93,7 @@ describe( 'RawElement', () => {
 		it( 'should throw when try to insert new child element', () => {
 			expectToThrowCKEditorError( () => {
 				rawElement._insertChild( 0, new Element( doc, 'i' ) );
-			}, 'view-rawelement-cannot-add: Cannot add child nodes to a RawElement instance.' );
+			}, 'view-rawelement-cannot-add' );
 		} );
 	} );
 

+ 5 - 15
packages/ckeditor5-engine/tests/view/selection.js

@@ -82,16 +82,6 @@ describe( 'Selection', () => {
 			expect( selection.isBackward ).to.be.false;
 		} );
 
-		it( 'should be able to create a collapsed selection at the given position', () => {
-			const position = range1.start;
-			const selection = new Selection( position );
-
-			expect( Array.from( selection.getRanges() ).length ).to.equal( 1 );
-			expect( selection.getFirstRange().start ).to.deep.equal( position );
-			expect( selection.getFirstRange().end ).to.deep.equal( position );
-			expect( selection.isBackward ).to.be.false;
-		} );
-
 		it( 'should be able to create a selection from the other selection', () => {
 			const otherSelection = new Selection( [ range2, range3 ], { backward: true } );
 			const selection = new Selection( otherSelection );
@@ -137,7 +127,7 @@ describe( 'Selection', () => {
 			expectToThrowCKEditorError( () => {
 				// eslint-disable-next-line no-new
 				new Selection( {} );
-			}, /view-selection-setTo-not-selectable/ );
+			}, 'view-selection-setto-not-selectable' );
 		} );
 	} );
 
@@ -209,7 +199,7 @@ describe( 'Selection', () => {
 
 			expectToThrowCKEditorError( () => {
 				selection.setFocus( endPos );
-			}, /view-selection-setFocus-no-ranges/ );
+			}, 'view-selection-setfocus-no-ranges' );
 		} );
 
 		it( 'modifies existing collapsed selection', () => {
@@ -688,7 +678,7 @@ describe( 'Selection', () => {
 
 				expectToThrowCKEditorError( () => {
 					otherSelection.setTo( {} );
-				}, /view-selection-setTo-not-selectable/ );
+				}, 'view-selection-setto-not-selectable' );
 			} );
 
 			it( 'should throw an error when trying to set to not selectable #2', () => {
@@ -696,7 +686,7 @@ describe( 'Selection', () => {
 
 				expectToThrowCKEditorError( () => {
 					otherSelection.setTo();
-				}, /view-selection-setTo-not-selectable/ );
+				}, 'view-selection-setto-not-selectable' );
 			} );
 		} );
 
@@ -740,7 +730,7 @@ describe( 'Selection', () => {
 
 				expectToThrowCKEditorError( () => {
 					selection.setTo( foo );
-				}, /view-selection-setTo-required-second-parameter/ );
+				}, 'view-selection-setto-required-second-parameter' );
 			} );
 
 			it( 'should collapse selection at node and flag', () => {

+ 0 - 9
packages/ckeditor5-engine/tests/view/styles/utils.js

@@ -232,15 +232,6 @@ describe( 'Styles utils', () => {
 			} );
 		} );
 
-		it( 'should parse one value', () => {
-			expect( getBoxSidesValues( 'foo' ) ).to.deep.equal( {
-				top: 'foo',
-				right: 'foo',
-				bottom: 'foo',
-				left: 'foo'
-			} );
-		} );
-
 		it( 'should parse two value', () => {
 			expect( getBoxSidesValues( 'foo bar' ) ).to.deep.equal( {
 				top: 'foo',

+ 3 - 3
packages/ckeditor5-engine/tests/view/uielement.js

@@ -37,7 +37,7 @@ describe( 'UIElement', () => {
 		it( 'should throw if child elements are passed to constructor', () => {
 			expectToThrowCKEditorError( () => {
 				new UIElement( doc, 'img', null, [ new Element( doc, 'i' ) ] ); // eslint-disable-line no-new
-			}, 'view-uielement-cannot-add: Cannot add child nodes to UIElement instance.' );
+			}, 'view-uielement-cannot-add' );
 		} );
 	} );
 
@@ -87,7 +87,7 @@ describe( 'UIElement', () => {
 		it( 'should throw when try to append new child element', () => {
 			expectToThrowCKEditorError( () => {
 				uiElement._appendChild( new Element( doc, 'i' ) );
-			}, 'view-uielement-cannot-add: Cannot add child nodes to UIElement instance.' );
+			}, 'view-uielement-cannot-add' );
 		} );
 	} );
 
@@ -95,7 +95,7 @@ describe( 'UIElement', () => {
 		it( 'should throw when try to insert new child element', () => {
 			expectToThrowCKEditorError( () => {
 				uiElement._insertChild( 0, new Element( doc, 'i' ) );
-			}, 'view-uielement-cannot-add: Cannot add child nodes to UIElement instance.' );
+			}, 'view-uielement-cannot-add' );
 		} );
 	} );
 

+ 1 - 0
packages/ckeditor5-engine/tests/view/view/view.js

@@ -904,6 +904,7 @@ describe( 'view', () => {
 		it( 'should rethrow custom CKEditorError errors', () => {
 			expectToThrowCKEditorError( () => {
 				view.change( () => {
+					// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
 					throw new CKEditorError( 'foo', view );
 				} );
 			}, /foo/, view );

+ 1 - 2
packages/ckeditor5-font/src/fontsize/fontsizeediting.js

@@ -109,8 +109,7 @@ export default class FontSizeEditing extends Plugin {
 			 * @param {Array.<String>} presets Invalid values.
 			 */
 			throw new CKEditorError(
-				'font-size-invalid-use-of-named-presets: ' +
-				'If config.fontSize.supportAllValues is set to true, you need to use numerical values as font size options.',
+				'font-size-invalid-use-of-named-presets',
 				null, { presets }
 			);
 		}

Некоторые файлы не были показаны из-за большого количества измененных файлов