From 7cd8a43f1008f1f006570a41f586b5db8a861b20 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 28 Mar 2019 12:10:20 +0100 Subject: [PATCH 1/5] Feature: Introduced schema#setAttributeProperties() and schema#getAttributeProperties() methods. --- src/model/schema.js | 38 ++++++++++++++++++++++++++++++++++++++ tests/model/schema.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/model/schema.js b/src/model/schema.js index f1fdc4ad5..ddce81285 100644 --- a/src/model/schema.js +++ b/src/model/schema.js @@ -39,6 +39,14 @@ export default class Schema { constructor() { this._sourceDefinitions = {}; + /** + * A map containing attribute's properties. + * + * @private + * @member {Map.} + */ + this._attributeProperties = {}; + this.decorate( 'checkChild' ); this.decorate( 'checkAttribute' ); @@ -140,6 +148,36 @@ export default class Schema { this._clearCache(); } + /** + * Registers custom properties to a given attribute. + * + * // Mark blockQuote as a formatting attribute. + * schema.setAttributeProperties( 'blockQuote', { + * isFormatting: true + * } ); + * + * // Override code not to be considered a formatting markup. + * schema.setAttributeProperties( 'code', { + * isFormatting: false + * } ); + * + * @param {String} attributeName Name of the attribute to receive properties. + * @param {Map.} properties Dictionary of properties. + */ + setAttributeProperties( attributeName, properties ) { + this._attributeProperties[ attributeName ] = Object.assign( this._attributeProperties[ attributeName ] || {}, properties ); + } + + /** + * Returns properties assigned to a given attribute. + * + * @param {String} attributeName Name of the attribute. + * @returns {Map.} + */ + getAttributeProperties( attributeName ) { + return this._attributeProperties[ attributeName ]; + } + /** * Returns all registered items. * diff --git a/tests/model/schema.js b/tests/model/schema.js index a01a6e54b..ee54e0682 100644 --- a/tests/model/schema.js +++ b/tests/model/schema.js @@ -96,6 +96,49 @@ describe( 'Schema', () => { } ); } ); + describe( 'setAttributeProperties()', () => { + beforeEach( () => { + schema.register( '$root' ); + schema.register( 'paragraph', { + allowIn: '$root' + } ); + schema.register( '$text', { + allowIn: 'paragraph' + } ); + } ); + + it( 'allows registering new properties', () => { + schema.extend( '$text', { allowAttributes: 'testAttribute' } ); + + schema.setAttributeProperties( 'testAttribute', { + foo: 'bar', + baz: 'bom' + } ); + + expect( schema.getAttributeProperties( 'testAttribute' ) ).to.deep.equal( { + foo: 'bar', + baz: 'bom' + } ); + } ); + + it( 'support adding properties in subsequent calls', () => { + schema.extend( '$text', { allowAttributes: 'testAttribute' } ); + + schema.setAttributeProperties( 'testAttribute', { + first: 'foo' + } ); + + schema.setAttributeProperties( 'testAttribute', { + second: 'bar' + } ); + + expect( schema.getAttributeProperties( 'testAttribute' ) ).to.deep.equal( { + first: 'foo', + second: 'bar' + } ); + } ); + } ); + describe( 'getDefinitions()', () => { it( 'returns compiled definitions', () => { schema.register( '$root' ); From 5b0ce2dd5664cc8434cd159491ebfcb666153089 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 28 Mar 2019 15:06:26 +0100 Subject: [PATCH 2/5] Docs: Improved docs for setAttributeProperties and added a custom typedef describing known properties. --- src/model/schema.js | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/model/schema.js b/src/model/schema.js index ddce81285..2f11642b1 100644 --- a/src/model/schema.js +++ b/src/model/schema.js @@ -151,6 +151,8 @@ export default class Schema { /** * Registers custom properties to a given attribute. * + * It can be used to mark the attributes relation and handle them in a common way. + * * // Mark blockQuote as a formatting attribute. * schema.setAttributeProperties( 'blockQuote', { * isFormatting: true @@ -161,8 +163,27 @@ export default class Schema { * isFormatting: false * } ); * + * You can also use custom attributes: + * + * schema.setAttributeProperties( 'blockQuote', { + * customAttribute: 'value' + * } ); + * + * Subsequent calls to the same attributes will add up the value: + * + * schema.setAttributeProperties( 'blockQuote', { + * one: 1 + * } ); + * + * schema.setAttributeProperties( 'blockQuote', { + * two: 2 + * } ); + * + * console.log( schema.getAttributeProperties( 'blockQuote' ) ); + * // Logs: {one: 1, two: 2} + * * @param {String} attributeName Name of the attribute to receive properties. - * @param {Map.} properties Dictionary of properties. + * @param {module:engine/model/schema~AttributeProperties} properties A dictionary of properties. */ setAttributeProperties( attributeName, properties ) { this._attributeProperties[ attributeName ] = Object.assign( this._attributeProperties[ attributeName ] || {}, properties ); @@ -172,7 +193,7 @@ export default class Schema { * Returns properties assigned to a given attribute. * * @param {String} attributeName Name of the attribute. - * @returns {Map.} + * @returns {module:engine/model/schema~AttributeProperties} */ getAttributeProperties( attributeName ) { return this._attributeProperties[ attributeName ]; @@ -1323,6 +1344,15 @@ export class SchemaContext { * @typedef {Object} module:engine/model/schema~SchemaContextItem */ +/** + * A structure containing additional metadata describing the attribute. + * + * See {@link module:engine/schema~setAttributeProperties} for usage examples. + * + * @typedef {Object} module:engine/model/schema~AttributeProperties + * @property {Boolean} [isFormatting] Indicates that the attribute should be considered as a visual formatting. + */ + function compileBaseItemRule( sourceItemRules, itemName ) { const itemRule = { name: itemName, From 72604d5980f60c68aca35d3a07a61cf1d011e807 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 28 Mar 2019 15:09:55 +0100 Subject: [PATCH 3/5] Code style: Moved schema#getAttributeProperties and schema#setAttributeProperties to a more proper place. --- src/model/schema.js | 128 ++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/src/model/schema.js b/src/model/schema.js index 2f11642b1..033d84e5b 100644 --- a/src/model/schema.js +++ b/src/model/schema.js @@ -148,70 +148,6 @@ export default class Schema { this._clearCache(); } - /** - * Registers custom properties to a given attribute. - * - * It can be used to mark the attributes relation and handle them in a common way. - * - * // Mark blockQuote as a formatting attribute. - * schema.setAttributeProperties( 'blockQuote', { - * isFormatting: true - * } ); - * - * // Override code not to be considered a formatting markup. - * schema.setAttributeProperties( 'code', { - * isFormatting: false - * } ); - * - * You can also use custom attributes: - * - * schema.setAttributeProperties( 'blockQuote', { - * customAttribute: 'value' - * } ); - * - * Subsequent calls to the same attributes will add up the value: - * - * schema.setAttributeProperties( 'blockQuote', { - * one: 1 - * } ); - * - * schema.setAttributeProperties( 'blockQuote', { - * two: 2 - * } ); - * - * console.log( schema.getAttributeProperties( 'blockQuote' ) ); - * // Logs: {one: 1, two: 2} - * - * @param {String} attributeName Name of the attribute to receive properties. - * @param {module:engine/model/schema~AttributeProperties} properties A dictionary of properties. - */ - setAttributeProperties( attributeName, properties ) { - this._attributeProperties[ attributeName ] = Object.assign( this._attributeProperties[ attributeName ] || {}, properties ); - } - - /** - * Returns properties assigned to a given attribute. - * - * @param {String} attributeName Name of the attribute. - * @returns {module:engine/model/schema~AttributeProperties} - */ - getAttributeProperties( attributeName ) { - return this._attributeProperties[ attributeName ]; - } - - /** - * Returns all registered items. - * - * @returns {Object.} - */ - getDefinitions() { - if ( !this._compiledDefinitions ) { - this._compile(); - } - - return this._compiledDefinitions; - } - /** * Returns a definition of the given item or `undefined` if item is not registered. * @@ -534,6 +470,70 @@ export default class Schema { }, { priority: 'high' } ); } + /** + * Registers custom properties to a given attribute. + * + * It can be used to mark the attributes relation and handle them in a common way. + * + * // Mark blockQuote as a formatting attribute. + * schema.setAttributeProperties( 'blockQuote', { + * isFormatting: true + * } ); + * + * // Override code not to be considered a formatting markup. + * schema.setAttributeProperties( 'code', { + * isFormatting: false + * } ); + * + * You can also use custom attributes: + * + * schema.setAttributeProperties( 'blockQuote', { + * customAttribute: 'value' + * } ); + * + * Subsequent calls to the same attributes will add up the value: + * + * schema.setAttributeProperties( 'blockQuote', { + * one: 1 + * } ); + * + * schema.setAttributeProperties( 'blockQuote', { + * two: 2 + * } ); + * + * console.log( schema.getAttributeProperties( 'blockQuote' ) ); + * // Logs: {one: 1, two: 2} + * + * @param {String} attributeName Name of the attribute to receive properties. + * @param {module:engine/model/schema~AttributeProperties} properties A dictionary of properties. + */ + setAttributeProperties( attributeName, properties ) { + this._attributeProperties[ attributeName ] = Object.assign( this._attributeProperties[ attributeName ] || {}, properties ); + } + + /** + * Returns properties assigned to a given attribute. + * + * @param {String} attributeName Name of the attribute. + * @returns {module:engine/model/schema~AttributeProperties} + */ + getAttributeProperties( attributeName ) { + return this._attributeProperties[ attributeName ]; + } + + /** + * Returns all registered items. + * + * @returns {Object.} + */ + getDefinitions() { + if ( !this._compiledDefinitions ) { + this._compile(); + } + + return this._compiledDefinitions; + } + /** * Returns the lowest {@link module:engine/model/schema~Schema#isLimit limit element} containing the entire * selection/range/position or the root otherwise. From 0495b386364e46c1775ca25ec181ed8f0842b850 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 28 Mar 2019 15:20:31 +0100 Subject: [PATCH 4/5] Docs: Fixed API reference link. --- src/model/schema.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/model/schema.js b/src/model/schema.js index 033d84e5b..cb990057d 100644 --- a/src/model/schema.js +++ b/src/model/schema.js @@ -1347,7 +1347,7 @@ export class SchemaContext { /** * A structure containing additional metadata describing the attribute. * - * See {@link module:engine/schema~setAttributeProperties} for usage examples. + * See {@link module:engine/model/schema~Schema#setAttributeProperties `Schema#setAttributeProperties()`} for usage examples. * * @typedef {Object} module:engine/model/schema~AttributeProperties * @property {Boolean} [isFormatting] Indicates that the attribute should be considered as a visual formatting. From 118b34cbf7833642d79bedf1d812bb39ff72ece8 Mon Sep 17 00:00:00 2001 From: Marek Lewandowski Date: Thu, 28 Mar 2019 15:33:12 +0100 Subject: [PATCH 5/5] Tests: Simplified common code. --- tests/model/schema.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/model/schema.js b/tests/model/schema.js index ee54e0682..883112705 100644 --- a/tests/model/schema.js +++ b/tests/model/schema.js @@ -105,11 +105,10 @@ describe( 'Schema', () => { schema.register( '$text', { allowIn: 'paragraph' } ); + schema.extend( '$text', { allowAttributes: 'testAttribute' } ); } ); it( 'allows registering new properties', () => { - schema.extend( '$text', { allowAttributes: 'testAttribute' } ); - schema.setAttributeProperties( 'testAttribute', { foo: 'bar', baz: 'bom' @@ -122,8 +121,6 @@ describe( 'Schema', () => { } ); it( 'support adding properties in subsequent calls', () => { - schema.extend( '$text', { allowAttributes: 'testAttribute' } ); - schema.setAttributeProperties( 'testAttribute', { first: 'foo' } );