8
0
Pārlūkot izejas kodu

Docs: Documentation for features-related classes. Updated JSDoc in multiple files.

Szymon Cofalik 9 gadi atpakaļ
vecāks
revīzija
07866bb588

+ 0 - 3
packages/ckeditor5-engine/src/bold/boldfeature.js

@@ -12,10 +12,7 @@ import AttributeCommand from '../command/attributecommand.js';
  * Bold feature.
  *
  * Bold features bring in possibility to mark some of the content (most commonly some text) as "important" ("bold").
- *
- * @class features.Bold
  */
-
 export default class BoldFeature extends Feature {
 	init() {
 		// Create instance of AttributeCommand which will handle bold attribute and add to commands registry.

+ 3 - 3
packages/ckeditor5-engine/src/collection.js

@@ -34,7 +34,7 @@ export default class Collection {
 		 * The internal list of items in the collection.
 		 *
 		 * @private
-		 * @type {Object[]}
+		 * @member {Array.<Object>} core.Collection#_items
 		 */
 		this._items = [];
 
@@ -42,7 +42,7 @@ export default class Collection {
 		 * The internal map of items in the collection.
 		 *
 		 * @private
-		 * @type {Map}
+		 * @member {Map} core.Collection#_itemMap
 		 */
 		this._itemMap = new Map();
 
@@ -50,7 +50,7 @@ export default class Collection {
 		 * The name of the property which is considered to identify an item.
 		 *
 		 * @private
-		 * @type {String}
+		 * @member {String} core.Collection#_idProperty
 		 */
 		this._idProperty = options && options.idProperty || 'id';
 	}

+ 23 - 28
packages/ckeditor5-engine/src/command/attributecommand.js

@@ -11,19 +11,20 @@ import Range from '../treemodel/range.js';
 
 /**
  * An extension of basic {@link core.command.Command} class, which provides utilities for a command that sets a single
- * attribute on a text or element with value `true`. AttributeCommand uses {@link treeModel.Document#selection} to
- * decide which nodes (if any) should be changed, and applies or removes attributes from them. See {@link #execute} for more.
+ * attribute on a text or element with value `true`. AttributeCommand uses {@link core.treeModel.Document#selection} to
+ * decide which nodes (if any) should be changed, and applies or removes attributes from them.
+ * See {@link core.treeView.Converter#execute} for more.
  *
- * The command checks {@link treeModel.Document#schema} to decide if it should be enabled. See {@link #checkSchema} for more.
+ * The command checks {@link core.treeModel.Document#schema} to decide if it should be enabled.
+ * See {@link core.treeView.Converter#checkSchema} for more.
  *
- * @class core.command.AttributeCommand
+ * @memberOf core.command
  */
-
 export default class AttributeCommand extends Command {
 	/**
 	 * @see core.command.Command
-	 * @param editor {core.Editor}
-	 * @param attributeKey {String} Attribute that will be set by the command.
+	 * @param {core.Editor} editor
+	 * @param {String} attributeKey Attribute that will be set by the command.
 	 */
 	constructor( editor, attributeKey ) {
 		super( editor );
@@ -31,7 +32,7 @@ export default class AttributeCommand extends Command {
 		/**
 		 * Attribute that will be set by the command.
 		 *
-		 * @type {String}
+		 * @member {String} core.command.AttributeCommand#attributeKey
 		 */
 		this.attributeKey = attributeKey;
 	}
@@ -47,9 +48,9 @@ export default class AttributeCommand extends Command {
 	}
 
 	/**
-	 * Checks {@link treeModel.Document#schema} to decide if the command should be enabled:
-	 * * if selection is on range, command is enabled if any of nodes in that range can have bold,
-	 * * if selection is collapsed, command is enabled if text with bold is allowed in that node.
+	 * Checks {@link core.treeModel.Document#schema} to decide if the command should be enabled:
+	 * * if selection is on range, the command is enabled if any of nodes in that range can have bold,
+	 * * if selection is collapsed, the command is enabled if text with bold is allowed in that node.
 	 *
 	 * @see core.command.Command#checkSchema
 	 * @returns {Boolean}
@@ -60,7 +61,7 @@ export default class AttributeCommand extends Command {
 
 		if ( selection.isCollapsed ) {
 			// Check whether schema allows for a test with `attributeKey` in caret position.
-			return schema.checkAtPosition( { name: '$text', attribute: this.attributeKey }, selection.getFirstPosition() );
+			return schema.checkAtPosition( selection.getFirstPosition(), '$text', this.attributeKey );
 		} else {
 			const ranges = selection.getRanges();
 
@@ -72,13 +73,10 @@ export default class AttributeCommand extends Command {
 
 				// Walk the range.
 				while ( !step.done ) {
-					const query = {
-						// If returned item does not have name property, it is a treeModel.TextFragment.
-						name: step.value.item.name || '$text',
-						attribute: this.attributeKey
-					};
+					// If returned item does not have name property, it is a treeModel.TextFragment.
+					const name = step.value.item.name || '$text';
 
-					if ( schema.checkAtPosition( query, last ) ) {
+					if ( schema.checkAtPosition( last, name, this.attributeKey ) ) {
 						// If we found a node that is allowed to have the attribute, return true.
 						return true;
 					}
@@ -98,17 +96,17 @@ export default class AttributeCommand extends Command {
 	 *
 	 * If the command is active (`value == true`), it will remove attributes. Otherwise, it will set attributes.
 	 *
-	 * The execution result differs, depending on the {@link treeModel.Document#selection}:
+	 * The execution result differs, depending on the {@link core.treeModel.Document#selection}:
 	 * * if selection is on a range, the command applies the attribute on all nodes in that ranges
-	 * (if they are allowed to have this attribute by the{@link treeModel.Schema schema}),
-	 * * if selection is collapsed in non-empty node, the command applies attribute to the {@link treeModel.Document#selection}
+	 * (if they are allowed to have this attribute by the{@link core.treeModel.Schema schema}),
+	 * * if selection is collapsed in non-empty node, the command applies attribute to the {@link core.treeModel.Document#selection}
 	 * itself (note that typed characters copy attributes from selection),
 	 * * if selection is collapsed in empty node, the command applies attribute to the parent node of selection (note
 	 * that selection inherits all attributes from a node if it is in empty node).
 	 *
 	 * If the command is disabled (`isEnabled == false`) when it is executed, nothing will happen.
 	 *
-	 * @param [forceValue] {Boolean} If set it will force command behavior. If `true`, command will apply attribute,
+	 * @param {Boolean} [forceValue] If set it will force command behavior. If `true`, command will apply attribute,
 	 * otherwise command will remove attribute. If not set, command will look for it's current value to decide what it should do.
 	 */
 	execute( forceValue ) {
@@ -145,7 +143,7 @@ export default class AttributeCommand extends Command {
 	 * Walks through given array of ranges and removes parts of them that are not allowed by schema to have the
 	 * attribute set. This is done by breaking a range in two and omitting the not allowed part.
 	 *
-	 * @param ranges {Array.<treeModel.Range>} Ranges to be validated.
+	 * @param {Array.<core.treeModel.Range>} ranges Ranges to be validated.
 	 * @returns {Array} Ranges without invalid parts.
 	 * @private
 	 */
@@ -161,12 +159,9 @@ export default class AttributeCommand extends Command {
 			let to = range.end;
 
 			while ( !step.done ) {
-				const query = {
-					name: step.value.item.name || '$text',
-					attribute: this.attributeKey
-				};
+				const name = step.value.item.name || '$text';
 
-				if ( !this.editor.document.schema.checkAtPosition( query, last ) ) {
+				if ( !this.editor.document.schema.checkAtPosition( last, name, this.attributeKey ) ) {
 					if ( !from.isEqual( last ) ) {
 						validRanges.push( new Range( from, last ) );
 					}

+ 14 - 6
packages/ckeditor5-engine/src/command/command.js

@@ -18,21 +18,19 @@ import utils from '../utils.js';
  *
  * This is an abstract base class for all commands.
  *
- * @class core.command.Command
+ * @memberOf core.command
  */
-
 export default class Command {
 	/**
 	 * Creates a new Command instance.
 	 *
 	 * @param {core.Editor} editor Editor on which this command will be used.
-	 * @constructor
 	 */
 	constructor( editor ) {
 		/**
 		 * Editor on which this command will be used.
 		 *
-		 * @type {core.Editor}
+		 * @member {core.Editor} core.command.Command#editor
 		 */
 		this.editor = editor;
 
@@ -40,7 +38,7 @@ export default class Command {
 		 * Flag indicating whether a command is enabled or disabled.
 		 * A disabled command should do nothing upon it's execution.
 		 *
-		 * @type {Boolean}
+		 * @member {Boolean} core.command.Command#isEnabled
 		 */
 		this.isEnabled = true;
 
@@ -60,13 +58,15 @@ export default class Command {
 	 * obligatory). If it is defined, it will be added as a callback to `refreshState` event.
 	 *
 	 * @method checkSchema
-	 * @returns {Boolean} `true` if command should be enabled according to {@link treeModel.Document#schema}. `false` otherwise.
+	 * @returns {Boolean} `true` if command should be enabled according to {@link core.treeModel.Document#schema}. `false` otherwise.
 	 */
 
 	/**
 	 * Fires `refreshState` event and checks it's resolve value to decide whether command should be enabled or not.
 	 * Other parts of code might listen to `refreshState` event on this command and add their callbacks. This
 	 * way the responsibility of deciding whether a command should be enabled is shared.
+	 *
+	 * @fires {@link core.command.Command.refreshState refreshState}
 	 */
 	refreshState() {
 		this.isEnabled = this.fire( 'refreshState' ) !== false;
@@ -110,3 +110,11 @@ function disableCallback( evt ) {
 }
 
 utils.mix( Command, EmitterMixin );
+
+/**
+ * Fired whenever command has to have it's {@link core.command.Command#isEnabled} property refreshed. Every feature,
+ * command or other class which should be able to disable command (set `isEnabled` to `false`) should listen to this
+ * event.
+ *
+ * @event core.command.Command.refreshState
+ */

+ 27 - 12
packages/ckeditor5-engine/src/editor.js

@@ -44,7 +44,7 @@ export default class Editor {
 		/**
 		 * Holds all configurations specific to this editor instance.
 		 *
-		 * This instance of the {@link Config} class is customized so its {@link Config#get} method will retrieve
+		 * This instance of the {@link core.Config} class is customized so its {@link core.Config#get} method will retrieve
 		 * global configurations available in {@link CKEDITOR.config} if configurations are not found in the
 		 * instance itself.
 		 *
@@ -61,10 +61,26 @@ export default class Editor {
 		 */
 		this.plugins = new PluginCollection( this );
 
+		/**
+		 * Tree Model document managed by this editor.
+		 *
+		 * @member {core.treeModel.Document} core.Editor#document
+		 */
 		this.document = new Document();
 
+		/**
+		 * Commands registered to the editor.
+		 *
+		 * @member {Map} core.Editor#commands
+		 */
 		this.commands = new Map();
 
+		/**
+		 * Mapper that maps Tree Model into Tree View
+		 * TODO: this should probably be something else, or not here
+		 *
+		 * @member {Mapper} core.Editor#treeMapper
+		 */
 		this.treeMapper = new Mapper();
 
 		/**
@@ -181,7 +197,13 @@ export default class Editor {
 		return this.editable.getData();
 	}
 
-	execute( commandName ) {
+	/**
+	 * Executes specified command with given parameter.
+	 *
+	 * @param {String} commandName Name of command to execute.
+	 * @param {*} [commandParam] If set, command will be executed with this parameter.
+	 */
+	execute( commandName, commandParam ) {
 		let command = this.commands.get( commandName );
 
 		if ( !command ) {
@@ -193,7 +215,7 @@ export default class Editor {
 			throw new CKEditorError( 'editor-command-not-found: Specified command has not been added to the editor.' );
 		}
 
-		command.execute();
+		command.execute( commandParam );
 	}
 }
 
@@ -203,13 +225,6 @@ utils.mix( Editor, ObservableMixin );
  * Fired when this editor instance is destroyed. The editor at this point is not usable and this event should be used to
  * perform the clean-up in any plugin.
  *
- * @event core.Editor#destroy
- */
-
-/**
- * @cfg {String[]} features
- */
-
-/**
- * @cfg {String} creator
+ * @memberOf core.Editor
+ * @event destroy
  */

+ 1 - 0
packages/ckeditor5-engine/src/emittermixin.js

@@ -225,6 +225,7 @@ const EmitterMixin = {
 	 * @param {String} event The name of the event.
 	 * @param {...*} [args] Additional arguments to be passed to the callbacks.
 	 * @method core.EmitterMixin#fire
+	 * @returns {*} Value returned by the last callback processed in the event loop.
 	 */
 	fire( event, args ) {
 		const callbacks = getCallbacksIfAny( this, event );

+ 1 - 2
packages/ckeditor5-engine/src/feature.js

@@ -17,9 +17,8 @@ import Plugin from './plugin.js';
  * * registering converters to editor (if the feature operates on Tree Model),
  * * setting and registering UI components (if the feature uses it).
  *
- * @class core.Feature
+ * @memberOf core
  */
-
 export default class Feature extends Plugin {
 	/**
 	 * Creates a new Plugin instance.

+ 2 - 4
packages/ckeditor5-engine/src/treemodel/batch.js

@@ -40,18 +40,16 @@ export default class Batch {
 		/**
 		 * Document which this Batch changes.
 		 *
-		 * @member core.treeModel.Batch#doc
+		 * @member {core.treeModel.Document} core.treeModel.Batch#doc
 		 * @readonly
-		 * @type {core.treeModel.Document}
 		 */
 		this.doc = doc;
 
 		/**
 		 * Array of deltas which compose Batch.
 		 *
-		 * @member core.treeModel.Batch#deltas
+		 * @member {Array.<core.treeModel.delta.Delta>} core.treeModel.Batch#deltas
 		 * @readonly
-		 * @type {Array.<core.treeModel.delta.Delta>}
 		 */
 		this.deltas = [];
 	}

+ 26 - 13
packages/ckeditor5-engine/src/treemodel/document.js

@@ -58,9 +58,6 @@ export default class Document {
 		 */
 		this.version = 0;
 
-		// Graveyard tree root. Document always have a graveyard root, which stores removed nodes.
-		this.createRoot( graveyardSymbol );
-
 		/**
 		 * Array of pending changes. See: {@link core.treeModel.Document#enqueueChanges}.
 		 *
@@ -77,6 +74,14 @@ export default class Document {
 		 */
 		this.selection = new Selection();
 
+		/**
+		 * Schema for this document.
+		 *
+		 * @member {core.treeModel.Schema} core.treeModel.Document#schema
+		 */
+		this.schema = new Schema();
+
+		// Add events that will update selection attributes.
 		this.selection.on( 'update', () => {
 			this._updateSelectionAttributes();
 		} );
@@ -85,7 +90,8 @@ export default class Document {
 			this._updateSelectionAttributes();
 		} );
 
-		this.schema = new Schema();
+		// Graveyard tree root. Document always have a graveyard root, which stores removed nodes.
+		this.createRoot( graveyardSymbol );
 	}
 
 	/**
@@ -166,13 +172,14 @@ export default class Document {
 	}
 
 	/**
-	 * Enqueue a callback with document changes. Any changes to be done on document (mostly using {@link core.treeModel.Document#batch} should
-	 * be placed in the queued callback. If no other plugin is changing document at the moment, the callback will be
+	 * Enqueue a callback with document changes. Any changes to be done on document (mostly using {@link core.treeModel.Document#batch}
+	 * should be placed in the queued callback. If no other plugin is changing document at the moment, the callback will be
 	 * called immediately. Otherwise it will wait for all previously queued changes to finish happening. This way
 	 * queued callback will not interrupt other callbacks.
 	 *
-	 * When all queued changes are done {@link core.treeModel.Document#changesDone} event is fired.
+	 * When all queued changes are done {@link core.treeModel.Document.changesDone} event is fired.
 	 *
+	 * @fires {@link core.treeModel.Document.changesDone}
 	 * @param {Function} callback Callback to enqueue.
 	 */
 	enqueueChanges( callback ) {
@@ -211,6 +218,12 @@ export default class Document {
 		return this.roots.get( id );
 	}
 
+	/**
+	 * Updates this document's {@link core.treeModel.Document#selection selection} attributes. Should be fired
+	 * whenever selection attributes might have changed (i.e. when selection ranges change or document is changed).
+	 *
+	 * @private
+	 */
 	_updateSelectionAttributes() {
 		if ( !this.selection.hasAnyRange ) {
 			this.selection.clearAttributes();
@@ -289,11 +302,11 @@ export default class Document {
 	 *
 	 * There are 5 types of change:
 	 *
-	 * * `'insert'` when nodes are inserted,
-	 * * `'remove'` when nodes are removed,
-	 * * `'reinsert'` when remove is undone,
-	 * * `'move'` when nodes are moved,
-	 * * `'attribute'` when attributes change. TODO attribute
+	 * * 'insert' when nodes are inserted,
+	 * * 'remove' when nodes are removed,
+	 * * 'reinsert' when remove is undone,
+	 * * 'move' when nodes are moved,
+	 * * 'attribute' when attributes change.
 	 *
 	 * Change event is fired after the change is done. This means that any ranges or positions passed in
 	 * `changeInfo` are referencing nodes and paths in updated tree model.
@@ -310,7 +323,7 @@ export default class Document {
 	 * is `undefined` it means that new attribute was inserted. Otherwise it contains changed or removed attribute value.
 	 * @param {*} [changeInfo.newValue] Only for `'attribute'` type. If the type is `'attribute'` and `newValue`
 	 * is `undefined` it means that attribute was removed. Otherwise it contains changed or inserted attribute value.
-	 * @param {core.treeModel.Batch} batch A {@link core.treeModel.Batch batch} of changes which this change is a part of.
+	 * @param {core.treeModel.Batch} batch A batch of changes which this change is a part of.
 	 */
 
 	/**

+ 2 - 13
packages/ckeditor5-engine/src/treemodel/element.js

@@ -30,7 +30,7 @@ export default class Element extends Node {
 		 * Element name.
 		 *
 		 * @readonly
-		 * @type {String}
+		 * @member {String} core.treeModel.Element#name
 		 */
 		this.name = name;
 
@@ -38,7 +38,7 @@ export default class Element extends Node {
 		 * List of children nodes.
 		 *
 		 * @protected
-		 * @type {core.treeModel.NodeList}
+		 * @member {core.treeModel.NodeList} core.treeModel.Element#_children
 		 */
 		this._children = new NodeList();
 
@@ -50,7 +50,6 @@ export default class Element extends Node {
 	/**
 	 * Gets child at the given index.
 	 *
-	 * @method core.treeModel.Element#getChild
 	 * @param {Number} index Index of child.
 	 * @returns {core.treeModel.Node} Child node.
 	 */
@@ -61,7 +60,6 @@ export default class Element extends Node {
 	/**
 	 * Gets the number of element's children.
 	 *
-	 * @method core.treeModel.Element#getChildCount
 	 * @returns {Number} The number of element's children.
 	 */
 	getChildCount() {
@@ -71,7 +69,6 @@ export default class Element extends Node {
 	/**
 	 * Gets index of the given child node.
 	 *
-	 * @method core.treeModel.Element#getChildIndex
 	 * @param {core.treeModel.Node} node Child node.
 	 * @returns {Number} Index of the child node.
 	 */
@@ -86,7 +83,6 @@ export default class Element extends Node {
 	 * Note that the list of children can be modified only in elements not yet attached to the document.
 	 * All attached nodes should be modified using the {@link core.treeModel.operation.InsertOperation}.
 	 *
-	 * @method core.treeModel.Element#appendChildren
 	 * @param {core.treeModel.NodeSet} nodes The list of nodes to be inserted.
 	 */
 	appendChildren( nodes ) {
@@ -99,7 +95,6 @@ export default class Element extends Node {
 	 * Note that the list of children can be modified only in elements not yet attached to the document.
 	 * All attached nodes should be modified using the {@link core.treeModel.operation.InsertOperation}.
 	 *
-	 * @method core.treeModel.Element#insertChildren
 	 * @param {Number} index Position where nodes should be inserted.
 	 * @param {core.treeModel.NodeSet} nodes The list of nodes to be inserted.
 	 * The list of nodes can be of any type accepted by the {@link core.treeModel.NodeList} constructor.
@@ -120,7 +115,6 @@ export default class Element extends Node {
 	 * Note that the list of children can be modified only in elements not yet attached to the document.
 	 * All attached nodes should be modified using the {@link core.treeModel.operation.RemoveOperation}.
 	 *
-	 * @method core.treeModel.Element#removeChildren
 	 * @param {Number} index Position of the first node to remove.
 	 * @param {Number} number Number of nodes to remove.
 	 * @returns {core.treeModel.NodeList} The list of removed nodes.
@@ -138,7 +132,6 @@ export default class Element extends Node {
 	/**
 	 * Sets attribute on the element. If attribute with the same key already is set, it overwrites its values.
 	 *
-	 * @method core.treeModel.Element#setAttribute
 	 * @param {String} key Key of attribute to set.
 	 * @param {*} value Attribute value.
 	 */
@@ -149,7 +142,6 @@ export default class Element extends Node {
 	/**
 	 * Removes all attributes from the element and sets given attributes.
 	 *
-	 * @method core.treeModel.Element#setAttributesTo
 	 * @param {Iterable|Object} attrs Iterable object containing attributes to be set. See {@link core.treeModel.Node#getAttributes}.
 	 */
 	setAttributesTo( attrs ) {
@@ -159,7 +151,6 @@ export default class Element extends Node {
 	/**
 	 * Removes an attribute with given key from the element.
 	 *
-	 * @method core.treeModel.Element#removeAttribute
 	 * @param {String} key Key of attribute to remove.
 	 * @returns {Boolean} `true` if the attribute was set on the element, `false` otherwise.
 	 */
@@ -169,8 +160,6 @@ export default class Element extends Node {
 
 	/**
 	 * Removes all attributes from the element.
-	 *
-	 * @method core.treeModel.Element#clearAttributes
 	 */
 	clearAttributes() {
 		this._attrs.clear();

+ 0 - 2
packages/ckeditor5-engine/src/treemodel/liveposition.js

@@ -59,8 +59,6 @@ export default class LivePosition extends Position {
 	 * Unbinds all events previously bound by LivePosition. Use it whenever you don't need LivePosition instance
 	 * anymore (i.e. when leaving scope in which it was declared or before re-assigning variable that was
 	 * referring to it).
-	 *
-	 * @method core.treeModel.LivePosition#detach
 	 */
 	detach() {
 		this.stopListening();

+ 2 - 0
packages/ckeditor5-engine/src/treemodel/liverange.js

@@ -12,7 +12,9 @@ import utils from '../utils.js';
 
 /**
  * LiveRange is a Range in the Tree Model that updates itself as the tree changes. It may be used as a bookmark.
+ *
  * **Note:** Constructor creates it's own {@link core.treeModel.LivePosition} instances basing on passed values.
+ *
  * **Note:** Be very careful when dealing with LiveRange. Each LiveRange instance bind events that might
  * have to be unbound. Use {@link core.treeModel.LiveRange#detach detach} whenever you don't need LiveRange anymore.
  *

+ 10 - 15
packages/ckeditor5-engine/src/treemodel/node.js

@@ -10,22 +10,23 @@ import utils from '../utils.js';
 import CKEditorError from '../ckeditorerror.js';
 
 /**
- * Creates a tree node.
+ * Tree model node. This is an abstract class for other classes representing different nodes in Tree Model.
  *
- * This is an abstract class, so this constructor should not be used directly.
- *
- * @param {Iterable|Object} attrs Iterable collection of attributes.
- *
- * @abstract
- * @class core.treeModel.Node
- * @classdesc Abstract document tree node class.
+ * @memberOf core.treeModel
  */
 export default class Node {
+	/**
+	 * Creates a tree node.
+	 *
+	 * This is an abstract class, so this constructor should not be used directly.
+	 *
+	 * @param {Iterable|Object} attrs Iterable collection of attributes.
+	 * @abstract
+	 */
 	constructor( attrs ) {
 		/**
 		 * Parent element. Null by default. Set by {@link core.treeModel.Element#insertChildren}.
 		 *
-		 * @member core.treeModel.Node#parent
 		 * @readonly
 		 * @member {core.treeModel.Element|null} core.treeModel.Node#parent
 		 */
@@ -108,7 +109,6 @@ export default class Node {
 	 *
 	 * Throws error if the parent element does not contain this node.
 	 *
-	 * @method core.treeModel.Node#getIndes
 	 * @returns {Number|Null} Index of the node in the parent element or null if the node has not parent.
 	 */
 	getIndex() {
@@ -134,7 +134,6 @@ export default class Node {
 	 * Gets path to the node. For example if the node is the second child of the first child of the root then the path
 	 * will be `[ 1, 2 ]`. This path can be used as a parameter of {@link core.treeModel.Position}.
 	 *
-	 * @method core.treeModel.Node#getPath
 	 * @returns {Number[]} The path.
 	 */
 	getPath() {
@@ -152,7 +151,6 @@ export default class Node {
 	/**
 	 * Custom toJSON method to solve child-parent circular dependencies.
 	 *
-	 * @method core.treeModel.Node#toJSON
 	 * @returns {Object} Clone of this object with the parent property replaced with its name.
 	 */
 	toJSON() {
@@ -167,7 +165,6 @@ export default class Node {
 	/**
 	 * Checks if the node has an attribute for given key.
 	 *
-	 * @method core.treeModel.Node#hasAttribute
 	 * @param {String} key Key of attribute to check.
 	 * @returns {Boolean} `true` if attribute with given key is set on node, `false` otherwise.
 	 */
@@ -178,7 +175,6 @@ export default class Node {
 	/**
 	 * Gets an attribute value for given key or undefined if that attribute is not set on node.
 	 *
-	 * @method core.treeModel.Node#getAttribute
 	 * @param {String} key Key of attribute to look for.
 	 * @returns {*} Attribute value or null.
 	 */
@@ -189,7 +185,6 @@ export default class Node {
 	/**
 	 * Returns iterator that iterates over this node attributes.
 	 *
-	 * @method core.treeModel.Node#getAttributes
 	 * @returns {Iterable.<*>}
 	 */
 	getAttributes() {

+ 2 - 2
packages/ckeditor5-engine/src/treemodel/nodelist.js

@@ -109,7 +109,7 @@ export default class NodeList {
 		 * Internal array to store nodes.
 		 *
 		 * @protected
-		 * @type {Array}
+		 * @member {Array} core.treeModel.NodeList#_nodes
 		 */
 		this._nodes = [];
 
@@ -119,7 +119,7 @@ export default class NodeList {
 		 * which occupy multiple slots in `_indexMap`.
 		 *
 		 * @private
-		 * @type {Array}
+		 * @member {Array} core.treeModel.NodeList#_indexMap
 		 */
 		this._indexMap = [];
 

+ 4 - 2
packages/ckeditor5-engine/src/treemodel/position.js

@@ -37,7 +37,7 @@ export default class Position {
 		/**
 		 * Root element for the path. Note that this element can not have a parent.
 		 *
-		 * @type {core.treeModel.RootElement}
+		 * @member {core.treeModel.RootElement} core.treeModel.Position#root
 		 */
 		this.root = root;
 
@@ -66,7 +66,7 @@ export default class Position {
 		 *        |- a   Before: [ 1, 1, 1 ] After: [ 1, 1, 2 ]
 		 *        |- r   Before: [ 1, 1, 2 ] After: [ 1, 1, 3 ]
 		 *
-		 * @type {Number[]}
+		 * @member {Array.<Number>} core.treeModel.Position#path
 		 */
 		this.path = path;
 	}
@@ -103,6 +103,8 @@ export default class Position {
 
 	/**
 	 * Sets offset in the parent, which is the last element of the path.
+	 *
+	 * @param {Number} newOffset
 	 */
 	set offset( newOffset ) {
 		this.path[ this.path.length - 1 ] = newOffset;

+ 1 - 1
packages/ckeditor5-engine/src/treemodel/rootelement.js

@@ -17,7 +17,7 @@ export default class RootElement extends Element {
 	/**
 	 * Creates tree root node.
 	 *
-	 * @param {Document} doc {@link Document} that is an owner of the root.
+	 * @param {core.treeModel.Document} doc {@link core.treeModel.Document} that is an owner of the root.
 	 * @param {String} name Node name.
 	 */
 	constructor( doc, name ) {

+ 224 - 10
packages/ckeditor5-engine/src/treemodel/schema.js

@@ -8,21 +8,73 @@
 import clone from '../lib/lodash/clone.js';
 import CKEditorError from '../ckeditorerror.js';
 
+/**
+ * SchemaItem is a singular registry item in {@link core.treeModel.Schema} that groups and holds allow/disallow rules for
+ * one entity. This class is used internally in {@link core.treeModel.Schema} and should not be used outside it.
+ *
+ * @see core.treeModel.Schema
+ * @memberOf core.treeModel
+ */
 export class SchemaItem {
+	/**
+	 * Creates SchemaItem instance.
+	 *
+	 * @param {core.treeModel.Schema} schema Schema instance that owns this item.
+	 */
 	constructor( schema ) {
+		/**
+		 * Schema instance that owns this item.
+		 *
+		 * @member {core.treeModel.Schema} core.treeModel.SchemaItem#_schema
+		 * @private
+		 */
 		this._schema = schema;
+
+		/**
+		 * Paths in which the entity, represented by this item, is allowed.
+		 *
+		 * @member {Array} core.treeModel.SchemaItem#_allowed
+		 * @private
+		 */
 		this._allowed = [];
+
+		/**
+		 * Paths in which the entity, represented by this item, is disallowed.
+		 *
+		 * @member {Array} core.treeModel.SchemaItem#_disallowed
+		 * @private
+		 */
 		this._disallowed = [];
 	}
 
+	/**
+	 * Allows entity, represented by this item, to be in given path.
+	 *
+	 * @param {Array.<String>|String} path Path in which entity is allowed. String with item names separated by spaces may be passed.
+	 * @param {String} [attribute] If set, this path will be used only for entities that have an attribute with this key.
+	 */
 	addAllowed( path, attribute ) {
 		this._addPath( '_allowed', path, attribute );
 	}
 
+	/**
+	 * Disallows entity, represented by this item, to be in given path.
+	 *
+	 * @param {Array.<String>|String} path Path in which entity is disallowed. String with item names separated by spaces may be passed.
+	 * @param {String} [attribute] If set, this path will be used only for entities that have an attribute with this key.
+	 */
 	addDisallowed( path, attribute ) {
 		this._addPath( '_disallowed', path, attribute );
 	}
 
+	/**
+	 * Adds path to the SchemaItem instance.
+	 *
+	 * @param {String} member Name of the array member into which the path will be added. Possible values are `_allowed` or `_disallowed`.
+	 * @param {Array.<String>|String} path Path to be added. String with item names separated by spaces may be passed.
+	 * @param {String} [attribute] If set, this path will be used only for entities that have an attribute with this key.
+	 * @private
+	 */
 	_addPath( member, path, attribute ) {
 		if ( typeof path === 'string' ) {
 			path = path.split( ' ' );
@@ -33,6 +85,14 @@ export class SchemaItem {
 		this[ member ].push( { path, attribute } );
 	}
 
+	/**
+	 * Returns all paths of given type that were previously registered in the item.
+	 *
+	 * @param {String} type Paths' type. Possible values are `ALLOW` or `DISALLOW`.
+	 * @param {String} [attribute] If set, only paths registered for given attribute will be returned.
+	 * @returns {Array} Paths registered in the item.
+	 * @private
+	 */
 	_getPaths( type, attribute ) {
 		let source = type === 'ALLOW' ? this._allowed : this._disallowed;
 		let paths = [];
@@ -46,25 +106,49 @@ export class SchemaItem {
 		return paths;
 	}
 
+	/**
+	 * Checks whether this item has any registered path of given type that matches provided path.
+	 *
+	 * @param {String} type Paths' type. Possible values are `ALLOW` or `DISALLOW`.
+	 * @param {Array.<String>} checkPath Path to check.
+	 * @param {String} [attribute] If set, only paths registered for given attribute will be returned.
+	 * @returns {Boolean} `true` if item has any registered matching path, `false` otherwise.
+	 * @private
+	 */
 	_hasMatchingPath( type, checkPath, attribute ) {
 		const itemPaths = this._getPaths( type, attribute );
 
 		checkPath = checkPath.slice();
 
+		// We check every path registered (possibly with given attribute) in the item.
 		for ( let itemPath of itemPaths ) {
+			// We have one of paths registered in the item.
+
+			// Now we have to check every item name from the path to check.
 			for ( let checkName of checkPath ) {
+				// Every item name is expanded to all names of items that item is extending.
+				// So, if on item path, there is an item that is extended by item from checked path, it will
+				// also be treated as matching.
 				let chain = this._schema._extensionChains.get( checkName );
 
+				// Since our paths have to match in given order, we always check against first item from item path.
+				// So, if item path is: B D E
+				// And checked path is: A B C D E
+				// It will be matching (A won't match, B will match, C won't match, D and E will match)
 				if ( chain.indexOf( itemPath[ 0 ] ) > -1 ) {
+					// Every time we have a match, we remove it from `itemPath` so we can still check against first item.
 					itemPath.shift();
 				}
 			}
 
+			// If `itemPath` has no items it means that we removed all of them, so we matched all of them.
+			// This means that we found a matching path.
 			if ( itemPath.length === 0 ) {
 				return true;
 			}
 		}
 
+		// No matching path found.
 		return false;
 	}
 
@@ -84,29 +168,91 @@ export class SchemaItem {
 }
 
 /**
- * @class core.treeModel.Schema
+ * Schema is a run-time created and modified description of which entity in Tree Model is allowed to be inside another
+ * entity. It is checked to verify whether given action can be preformed on Tree Model or whether Tree Model
+ * is in correct state.
+ *
+ * Schema consist of {@link core.treeModel.SchemaItem schema items}, each describing different entity. Entity can be
+ * either a Tree Model element or an abstract group for similar elements. Entities are represented by names. Names
+ * of special/abstract entities should be prefixed by `$` sign.
+ *
+ * Each entity in Schema may have a set of allow/disallow rules. Every rule describes in which entities given entity
+ * can or cannot be.
+ *
+ * Entities can extend other entities. This mechanism allows for grouping entities under abstract names. Whenever a rule
+ * is applied to entity, it is also true for all other entities that extends that entity. For example, let's assume there is
+ * entity named `$block` and entity `div` extends `$block`. If we add a rule, that entity `$text` with attribute `myAttr`
+ * is allowed in `$block`, it will also be allowed in `div` (and all other entities extending `$block`). It would be
+ * possible to disallow `$text` with `myAttr` in `div` by explicitly adding disallow rule for `$text` with `myAttr` in `$block`.
+ *
+ * @memberOf core.TreeModel
  */
 export default class Schema {
+	/**
+	 * Creates Schema instance.
+	 */
 	constructor() {
+		/**
+		 * Schema items registered in the schema.
+		 *
+		 * @member {Map} core.treeModel.Schema#_items
+		 * @private
+		 */
 		this._items = new Map();
+
+		/**
+		 * Description of what entities are a base for given entity.
+		 *
+		 * @member {Map} core.treeModel.Schema#_extensionChains
+		 * @private
+		 */
 		this._extensionChains = new Map();
 
+		// Register some default abstract entities.
 		this.registerItem( '$inline', null );
 		this.registerItem( '$block', null );
-
 		this.registerItem( '$text', '$inline' );
 
+		// Allow inline elements inside block elements.
 		this.allow( { name: '$inline', inside: '$block' } );
 	}
 
+	/**
+	 * Allows given query in the schema.
+	 *
+	 *		// Allow text with bold attribute in all P elements.
+	 *		schema.registerItem( 'p', '$block' );
+	 *		schema.allow( { name: '$text', attribute: 'bold', inside: 'p' } );
+	 *
+	 *		// Allow header in Ps that are in DIVs
+	 *		schema.registerItem( 'header', '$block' );
+	 *		schema.registerItem( 'div', '$block' );
+	 *		schema.allow( { name: 'header', inside: 'div p' } ); // inside: [ 'div', 'p' ] would also work.
+	 *
+	 * @param {core.treeModel.SchemaQuery} query Allowed query.
+	 */
 	allow( query ) {
 		this._getItem( query.name ).addAllowed( query.inside, query.attribute );
 	}
 
+	/**
+	 * Disallows given query in the schema.
+	 *
+	 * @see {@link core.treeModel.Schema#allow}
+	 * @param {core.treeModel.SchemaQuery} query Disallowed query.
+	 */
 	disallow( query ) {
 		this._getItem( query.name ).addDisallowed( query.inside, query.attribute );
 	}
 
+	/**
+	 * Returns {@link core.treeModel.SchemaItem schema item} that was registered in the schema under given name.
+	 * If item has not been found, throws error.
+	 *
+	 * @param {String} itemName Name to look for in schema.
+	 * @returns {core.treeModel.SchemaItem} Schema item registered under given name.
+	 * @private
+	 */
 	_getItem( itemName ) {
 		if ( !this.hasItem( itemName ) ) {
 			/**
@@ -120,10 +266,25 @@ export default class Schema {
 		return this._items.get( itemName );
 	}
 
+	/**
+	 * Checks whether there is an item registered under given name in schema.
+	 *
+	 * @param itemName
+	 * @returns {boolean}
+	 */
 	hasItem( itemName ) {
 		return this._items.has( itemName );
 	}
 
+	/**
+	 * Registers given item name in schema.
+	 *
+	 *		// Register P element that should be treated like all block elements.
+	 *		schema.registerItem( 'p', '$block' );
+	 *
+	 * @param {String} itemName Name to register.
+	 * @param [isExtending] If set, new item will extend item with given name.
+	 */
 	registerItem( itemName, isExtending ) {
 		if ( this.hasItem( itemName ) ) {
 			/**
@@ -143,29 +304,64 @@ export default class Schema {
 			throw new CKEditorError( 'schema-no-item: Item with specified name does not exist in schema.' );
 		}
 
+		// Create new SchemaItem and add it to the items store.
 		this._items.set( itemName, new SchemaItem( this ) );
 
+		// Create an extension chain.
+		// Extension chain has all item names that should be checked when that item is on path to check.
+		// This simply means, that if item is not extending anything, it should have only itself in it's extension chain.
+		// Since extending is not dynamic, we can simply get extension chain of extended item and expand it with registered name,
+		// if the registered item is extending something.
 		const chain = this.hasItem( isExtending ) ? this._extensionChains.get( isExtending ).concat( itemName ) : [ itemName ];
 		this._extensionChains.set( itemName, chain );
 	}
 
-	checkAtPosition( query, position ) {
-		if ( !this.hasItem( query.name ) ) {
+	/**
+	 * Checks whether entity with given name (and optionally, with given attribute) is allowed at given position.
+	 *
+	 *		// Check whether bold text can be placed at caret position.
+	 *		let caretPos = editor.document.selection.getFirstPosition();
+	 *		if ( schema.checkAtPosition( caretPos, '$text', 'bold' ) ) { ... }
+	 *
+	 * @param {core.treeModel.Position} position Position to check at.
+	 * @param {String} name Entity name to check.
+	 * @param {String} [attribute] If set, schema will check for entity with given attribute.
+	 * @returns {Boolean} `true` if entity is allowed, `false` otherwise
+	 */
+	checkAtPosition( position, name, attribute ) {
+		if ( !this.hasItem( name ) ) {
 			return false;
 		}
 
-		const path = Schema._makeItemsPathFromPosition( position );
-
-		return this.checkForPath( query, path );
+		return this.checkQuery( {
+			name: name,
+			inside: Schema._makeItemsPathFromPosition( position ),
+			attribute: attribute
+		} );
 	}
 
-	checkForPath( query, path ) {
+	/**
+	 * Checks whether given query is allowed in schema.
+	 *
+	 *		// Check whether bold text is allowed in header element.
+	 *		let query = {
+	 *			name: '$text',
+	 *			attribute: 'bold',
+	 *			inside: 'header'
+	 *		};
+	 *		if ( schema.checkQuery( query ) ) { ... }
+	 *
+	 * @param {core.treeModel.SchemaQuery} query Query to check.
+	 * @returns {Boolean} `true` if given query is allowed in schema, `false` otherwise.
+	 */
+	checkQuery( query ) {
 		if ( !this.hasItem( query.name ) ) {
 			return false;
 		}
 
-		path = ( typeof path === 'string' ) ? path.split( ' ' ) : path;
+		const path = ( typeof query.inside === 'string' ) ? query.inside.split( ' ' ) : query.inside;
 
+		// Get extension chain of given item and retrieve all schema items that are extended by given item.
 		const schemaItems = this._extensionChains.get( query.name ).map( ( name ) => {
 			return this._getItem( name );
 		} );
@@ -177,7 +373,7 @@ export default class Schema {
 			}
 		}
 
-		// There are no disallow path that matches query.
+		// At this point, the query is not disallowed.
 		// If there is any allow path that matches query, this query is valid with schema.
 		for ( let schemaItem of schemaItems ) {
 			if ( schemaItem._hasMatchingPath( 'ALLOW', path, query.attribute ) ) {
@@ -189,6 +385,13 @@ export default class Schema {
 		return false;
 	}
 
+	/**
+	 * Gets position and traverses through it's parents to get their names and returns them.
+	 *
+	 * @param {core.treeModel.Position} position Position to start building path from.
+	 * @returns {Array.<String>} Path containing elements names from top-most to the one containing given position.
+	 * @private
+	 */
 	static _makeItemsPathFromPosition( position ) {
 		let path = [];
 		let parent = position.parent;
@@ -198,6 +401,17 @@ export default class Schema {
 			parent = parent.parent;
 		}
 
+		path.reverse();
+
 		return path;
 	}
 }
+
+/**
+ * Object with query used by {@link core.treeModel.Schema} to query schema or add allow/disallow rules to schema.
+ *
+ * @typedef {Object} core.treeModel.SchemaQuery
+ * @property {String} name Entity name.
+ * @property {Array.<String>|String} inside Path inside which the entity is placed.
+ * @property {String} [attribute] If set, the query applies only to entities that has attribute with given key.
+ */

+ 43 - 11
packages/ckeditor5-engine/src/treemodel/selection.js

@@ -50,11 +50,11 @@ export default class Selection {
 
 	/**
 	 * Selection anchor. Anchor may be described as a position where the selection starts.
-	 * Together with {@link #focus} they define the direction of selection, which is important
-	 * when expanding/shrinking selection. When there are no ranges in selection anchor is null.
-	 * Anchor is always a start or end of the most recent added range. It may be a bit unintuitive when
-	 * there are multiple ranges in selection.
+	 * Together with {@link core.treeModel.Selection#focus} they define the direction of selection, which is important
+	 * when expanding/shrinking selection. When there are no ranges in selection anchor is null. Anchor is always
+	 * the start or end of the most recent added range. It may be a bit unintuitive when there are multiple ranges in selection.
 	 *
+	 * @see core.treeModel.Selection#focus
 	 * @type {core.treeModel.LivePosition|null}
 	 */
 	get anchor() {
@@ -68,10 +68,9 @@ export default class Selection {
 	}
 
 	/**
-	 * Selection focus. Focus is a position where the selection ends. When there are no ranges in selection,
-	 * focus is null.
+	 * Selection focus. Focus is a position where the selection ends. When there are no ranges in selection, focus is null.
 	 *
-	 * @link {#anchor}
+	 * @see core.treeModel.Selection#anchor
 	 * @type {core.treeModel.LivePosition|null}
 	 */
 	get focus() {
@@ -84,6 +83,12 @@ export default class Selection {
 		return null;
 	}
 
+	/**
+	 * Flag indicating whether the selection has any range in it.
+	 *
+	 * @readonly
+	 * @type {Boolean}
+	 */
 	get hasAnyRange() {
 		return this._ranges.length > 0;
 	}
@@ -110,11 +115,14 @@ export default class Selection {
 
 	/**
 	 * Adds a range to the selection. Added range is copied and converted to {@link core.treeModel.LiveRange}. This means
-	 * that passed range is not saved in the Selection instance and you can safely operate on it. Accepts a flag
-	 * describing in which way the selection is made - passed range might be selected from {@link core.treeModel.Range#start}
-	 * to {@link core.treeModel.Range#end} or from {@link core.treeModel.Range#start} to {@link core.treeModel.Range#end}. The flag
-	 * is used to set {@link #anchor} and {@link #focus} properties.
+	 * that passed range is not saved in the Selection instance and you can safely operate on it.
 	 *
+	 * Accepts a flag describing in which way the selection is made - passed range might be selected from
+	 * {@link core.treeModel.Range#start} to {@link core.treeModel.Range#end} or from {@link core.treeModel.Range#start}
+	 * to {@link core.treeModel.Range#end}. The flag is used to set {@link core.treeModel.Selection#anchor} and
+	 * {@link core.treeModel.Selection#focus} properties.
+	 *
+	 * @fires {@link core.treeModel.Selection.update update}
 	 * @param {core.treeModel.Range} range Range to add.
 	 * @param {Boolean} [isBackward] Flag describing if added range was selected forward - from start to end (`false`)
 	 * or backward - from end to start (`true`). Defaults to `false`.
@@ -145,6 +153,15 @@ export default class Selection {
 		return this._ranges.slice();
 	}
 
+	/**
+	 * Returns the first range in the selection. First range is the one which {@link core.treeModel.Range#start start} position
+	 * {@link core.treeModel.Position#isBefore is before} start position of all other ranges (not to confuse with the first range
+	 * added to the selection).
+	 *
+	 * If there are no ranges in selection, retruns null instead.
+	 *
+	 * @returns {core.treeModel.Range|null}
+	 */
 	getFirstRange() {
 		let first = null;
 
@@ -159,6 +176,12 @@ export default class Selection {
 		return first && Range.createFromRange( first );
 	}
 
+	/**
+	 * Returns the first position in the selection. First position is the position that {@link core.treeModel.Position#isBefore is before}
+	 * any other position in the selection ranges.
+	 *
+	 * @returns {core.treeModel.Position|null}
+	 */
 	getFirstPosition() {
 		let firstRange = this.getFirstRange();
 
@@ -168,6 +191,7 @@ export default class Selection {
 	/**
 	 * Removes all ranges that were added to the selection. Fires update event.
 	 *
+	 * @fires {@link core.treeModel.Selection.update update}
 	 */
 	removeAllRanges() {
 		this.detach();
@@ -181,6 +205,7 @@ export default class Selection {
 	 * is treated like the last added range and is used to set {@link #anchor} and {@link #focus}. Accepts a flag
 	 * describing in which way the selection is made (see {@link #addRange}).
 	 *
+	 * @fires {@link core.treeModel.Selection.update update}
 	 * @param {Array.<core.treeModel.Range>} newRanges Array of ranges to set.
 	 * @param {Boolean} [isLastBackward] Flag describing if last added range was selected forward - from start to end (`false`)
 	 * or backward - from end to start (`true`). Defaults to `false`.
@@ -294,3 +319,10 @@ function pushRange( range ) {
 }
 
 utils.mix( Selection, EmitterMixin );
+
+/**
+ * Fired whenever selection ranges are changed through {@link core.treeModel.Selection Selection API}. Not fired when
+ * {@link core.treeModel.LiveRange live ranges} inserted in selection change because of Tree Model changes.
+ *
+ * @event core.treeModel.Selection.update
+ */

+ 3 - 3
packages/ckeditor5-engine/src/treemodel/textfragment.js

@@ -33,7 +33,7 @@ export default class TextFragment {
 		 * First character node contained in {@link core.treeModel.TextFragment}.
 		 *
 		 * @readonly
-		 * @type {core.treeModel.CharacterProxy}
+		 * @member {core.treeModel.CharacterProxy} core.treeModel.TextFragment#first
 		 */
 		this.first = firstCharacter;
 
@@ -41,7 +41,7 @@ export default class TextFragment {
 		 * Characters contained in {@link core.treeModel.TextFragment}.
 		 *
 		 * @readonly
-		 * @type {String}
+		 * @member {String} core.treeModel.TextFragment#text
 		 */
 		this.text = firstCharacter._nodeListText.text.substr( this.first._index, length );
 
@@ -49,7 +49,7 @@ export default class TextFragment {
 		 * Last {@link core.treeModel.CharacterProxy character node} contained in {@link core.treeModel.TextFragment}.
 		 *
 		 * @readonly
-		 * @type {core.treeModel.CharacterProxy}
+		 * @member {core.treeModel.CharacterProxy} core.treeModel.TextFragment#last
 		 */
 		this.last = this.getCharAt( this.text.length - 1 );
 	}

+ 1 - 1
packages/ckeditor5-engine/src/treeview/converter.js

@@ -13,7 +13,7 @@ import ViewElement from './element.js';
  * {@link core.treeView.Converter#bindElements binding} these nodes.
  *
  * Converter does not check which nodes should be rendered (use {@link core.treeView.Renderer}), does not keep a state of
- * a tree nor keeps synchronization between tree view and DOM tree (use {@link @core.treeView.TreeView}).
+ * a tree nor keeps synchronization between tree view and DOM tree (use {@link core.treeView.TreeView}).
  *
  * Converter keeps DOM elements to View element bindings, so when the converter will be destroyed, the binding will be
  * lost. Two converters will keep separate binding maps, so one tree view can be bound with two DOM trees.

+ 2 - 4
packages/ckeditor5-engine/src/treeview/position.js

@@ -20,16 +20,14 @@ export default class Position {
 		/**
 		 * Position parent element.
 		 *
-		 * @member core.treeView.Position#parent
-		 * @type {core.treeView.Element}
+		 * @member {core.treeView.Element} core.treeView.Position#parent
 		 */
 		this.parent = parent;
 
 		/**
 		 * Position offset.
 		 *
-		 * @member core.treeView.Position#offset
-		 * @type {Number}
+		 * @member {Number} core.treeView.Position#offset
 		 */
 		this.offset = offset;
 	}

+ 0 - 3
packages/ckeditor5-engine/src/treeview/treeview.js

@@ -81,7 +81,6 @@ export default class TreeView {
 	 * Adds an observer to the set of observers. This method also {@link core.treeView.Observer#init initializes} and
 	 * {@link core.treeView.Observer#attach attaches} the observer.
 	 *
-	 * @method core.treeView.TreeView#addObserver
 	 * @param {core.treeView.Observer} observer Observer to add.
 	 */
 	addObserver( observer ) {
@@ -93,8 +92,6 @@ export default class TreeView {
 	/**
 	 * Renders all changes. In order to avoid triggering the observers (e.g. mutations) all observers all detached
 	 * before rendering and reattached after that.
-	 *
-	 * @method core.treeView.TreeView#render
 	 */
 	render() {
 		for ( let observer of this.observers ) {

+ 30 - 22
packages/ckeditor5-engine/tests/treemodel/schema/schema.js

@@ -31,7 +31,7 @@ describe( 'constructor', () => {
 	} );
 
 	it( 'should allow inline in block', () => {
-		expect( schema.checkForPath( { name: '$inline' }, [ '$block' ] ) ).to.be.true;
+		expect( schema.checkQuery( { name: '$inline', inside: [ '$block' ] } ) ).to.be.true;
 	} );
 } );
 
@@ -57,7 +57,7 @@ describe( 'registerItem', () => {
 	it( 'should make registered item inherit allows from base item', () => {
 		schema.registerItem( 'image', '$inline' );
 
-		expect( schema.checkForPath( { name: 'image' }, [ '$block' ] ) ).to.be.true;
+		expect( schema.checkQuery( { name: 'image', inside: [ '$block' ] } ) ).to.be.true;
 	} );
 
 	it( 'should throw if item with given name has already been registered in schema', () => {
@@ -106,11 +106,11 @@ describe( 'allow', () => {
 		schema.registerItem( 'p', '$block' );
 		schema.registerItem( 'div', '$block' );
 
-		expect( schema.checkForPath( { name: 'p' }, [ 'div' ] ) ).to.be.false;
+		expect( schema.checkQuery( { name: 'p', inside: [ 'div' ] } ) ).to.be.false;
 
 		schema.allow( { name: 'p', inside: 'div' } );
 
-		expect( schema.checkForPath( { name: 'p' }, [ 'div' ] ) ).to.be.true;
+		expect( schema.checkQuery( { name: 'p', inside: [ 'div' ] } ) ).to.be.true;
 	} );
 } );
 
@@ -121,11 +121,11 @@ describe( 'disallow', () => {
 
 		schema.allow( { name: '$block', attribute: 'bold', inside: 'div' } );
 
-		expect( schema.checkForPath( { name: 'p', attribute: 'bold' }, [ 'div' ] ) ).to.be.true;
+		expect( schema.checkQuery( { name: 'p', attribute: 'bold', inside: [ 'div' ] } ) ).to.be.true;
 
 		schema.disallow( { name: 'p', attribute: 'bold', inside: 'div' } );
 
-		expect( schema.checkForPath( { name: 'p', attribute: 'bold' }, [ 'div' ] ) ).to.be.false;
+		expect( schema.checkQuery( { name: 'p', attribute: 'bold', inside: [ 'div' ] } ) ).to.be.false;
 	} );
 } );
 
@@ -154,48 +154,56 @@ describe( 'checkAtPosition', () => {
 
 	it( 'should return true if given element is allowed by schema at given position', () => {
 		// Block should be allowed in root.
-		expect( schema.checkAtPosition( { name: '$block' }, new Position( root, [ 0 ] ) ) ).to.be.true;
+		expect( schema.checkAtPosition( new Position( root, [ 0 ] ), '$block' ) ).to.be.true;
 
 		// P is block and block should be allowed in root.
-		expect( schema.checkAtPosition( { name: 'p' }, new Position( root, [ 0 ] ) ) ).to.be.true;
+		expect( schema.checkAtPosition( new Position( root, [ 0 ] ), 'p' ) ).to.be.true;
 
 		// P is allowed in DIV by the set rule.
-		expect( schema.checkAtPosition( { name: 'p' }, new Position( root, [ 0, 0 ] ) ) ).to.be.true;
+		expect( schema.checkAtPosition( new Position( root, [ 0, 0 ] ), 'p' ) ).to.be.true;
 
 		// Inline is allowed in any block and is allowed with attribute bold.
 		// We do not check if it is allowed in header, because it is disallowed by the set rule.
-		expect( schema.checkAtPosition( { name: '$inline' }, new Position( root, [ 0, 0 ] ) ) ).to.be.true;
-		expect( schema.checkAtPosition( { name: '$inline' }, new Position( root, [ 2, 0 ] ) ) ).to.be.true;
-		expect( schema.checkAtPosition( { name: '$inline', attribute: 'bold' }, new Position( root, [ 0, 0 ] ) ) ).to.be.true;
-		expect( schema.checkAtPosition( { name: '$inline', attribute: 'bold' }, new Position( root, [ 2, 0 ] ) ) ).to.be.true;
+		expect( schema.checkAtPosition( new Position( root, [ 0, 0 ] ), '$inline' ) ).to.be.true;
+		expect( schema.checkAtPosition( new Position( root, [ 2, 0 ] ), '$inline' ) ).to.be.true;
+		expect( schema.checkAtPosition( new Position( root, [ 0, 0 ] ), '$inline', 'bold' ) ).to.be.true;
+		expect( schema.checkAtPosition( new Position( root, [ 2, 0 ] ), '$inline', 'bold' ) ).to.be.true;
 
 		// Header is allowed in DIV.
-		expect( schema.checkAtPosition( { name: 'header' }, new Position( root, [ 0, 0 ] ) ) ).to.be.true;
+		expect( schema.checkAtPosition( new Position( root, [ 0, 0 ] ), 'header' ) ).to.be.true;
 
 		// Inline is allowed in block and root is DIV, which is block.
-		expect( schema.checkAtPosition( { name: '$inline' }, new Position( root, [ 0 ] ) ) ).to.be.true;
+		expect( schema.checkAtPosition( new Position( root, [ 0 ] ), '$inline' ) ).to.be.true;
 	} );
 
 	it( 'should return false if given element is not allowed by schema at given position', () => {
 		// P with attribute is not allowed anywhere.
-		expect( schema.checkAtPosition( { name: 'p', attribute: 'bold' }, new Position( root, [ 0 ] ) ) ).to.be.false;
-		expect( schema.checkAtPosition( { name: 'p', attribute: 'bold' }, new Position( root, [ 0, 0 ] ) ) ).to.be.false;
+		expect( schema.checkAtPosition( new Position( root, [ 0 ] ), 'p', 'bold' ) ).to.be.false;
+		expect( schema.checkAtPosition( new Position( root, [ 0, 0 ] ), 'p', 'bold' ) ).to.be.false;
 
 		// Bold text is not allowed in header
-		expect( schema.checkAtPosition( { name: '$text', attribute: 'bold' }, new Position( root, [ 1, 0 ] ) ) ).to.be.false;
+		expect( schema.checkAtPosition( new Position( root, [ 1, 0 ] ), '$text', 'bold' ) ).to.be.false;
 	} );
 
 	it( 'should return false if given element is not registered in schema', () => {
-		expect( schema.checkAtPosition( { name: 'new' }, new Position( root, [ 0 ] ) ) ).to.be.false;
+		expect( schema.checkAtPosition( new Position( root, [ 0 ] ), 'new' ) ).to.be.false;
 	} );
 } );
 
-describe( 'checkForPath', () => {
+describe( 'checkQuery', () => {
 	it( 'should return false if given element is not registered in schema', () => {
-		expect( schema.checkForPath( { name: 'new' }, 'div header' ) ).to.be.false;
+		expect( schema.checkQuery( { name: 'new', inside: [ 'div', 'header' ] } ) ).to.be.false;
 	} );
 
 	it( 'should handle path given as string', () => {
-		expect( schema.checkForPath( { name: '$inline' }, '$block $block $block' ) ).to.be.true;
+		expect( schema.checkQuery( { name: '$inline', inside: '$block $block $block' } ) ).to.be.true;
+	} );
+
+	it( 'should handle attributes', () => {
+		schema.registerItem( 'p', '$block' );
+		schema.allow( { name: 'p', inside: '$block' } );
+
+		expect( schema.checkQuery( { name: 'p', inside: '$block' } ) ).to.be.true;
+		expect( schema.checkQuery( { name: 'p', attribute: 'bold', inside: '$block' } ) ).to.be.false;
 	} );
 } );