mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-12-01 17:36:35 +00:00
4854d644ee
Us grouping the inheritable static properties that way is an implementation detail that is polluting the index and makes it harder to refer to individual identifiers. It also causes problems under JSDuck 5 because that version is more strict about defining properties (Foo.static.bar) of which the parent is not defined in the index (Foo.static), we'd have to add a sea of `@static @property {Object} this.static` all over the place. Might as well hide this implementation detail and just consider them static properties (just like we already do for "private" properties). Change-Id: Ibf2ebf7752aabc2b75b6ac6fa00e2284a181a600
176 lines
5.6 KiB
JavaScript
176 lines
5.6 KiB
JavaScript
/*!
|
|
* VisualEditor DataModel Annotation class.
|
|
*
|
|
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
*/
|
|
|
|
/**
|
|
* Generic DataModel annotation.
|
|
*
|
|
* This is an abstract class, annotations should extend this and call this constructor from their
|
|
* constructor. You should not instantiate this class directly.
|
|
*
|
|
* Annotations in the linear model are instances of subclasses of this class. Subclasses should
|
|
* only override static properties and functions.
|
|
*
|
|
* @class
|
|
* @extends {ve.dm.Model}
|
|
* @constructor
|
|
* @param {Object} element Linear model annotation
|
|
*/
|
|
ve.dm.Annotation = function VeDmAnnotation( element ) {
|
|
// Parent constructor
|
|
ve.dm.Model.call( this, element );
|
|
// Properties
|
|
this.name = this.constructor.static.name; // For ease of filtering
|
|
};
|
|
|
|
/* Inheritance */
|
|
|
|
OO.inheritClass( ve.dm.Annotation, ve.dm.Model );
|
|
|
|
/* Static properties */
|
|
|
|
/**
|
|
* About grouping is not supported for annotations; setting this to true has no effect.
|
|
*
|
|
* @static
|
|
* @property {boolean}
|
|
* @inheritable
|
|
*/
|
|
ve.dm.Annotation.static.enableAboutGrouping = false;
|
|
|
|
/**
|
|
* Automatically apply annotation to content inserted after it.
|
|
*
|
|
* @property {boolean}
|
|
*/
|
|
ve.dm.Annotation.static.applyToAppendedContent = true;
|
|
|
|
/**
|
|
* Abandon continuation when a wordbreak is generated
|
|
*
|
|
* @type {boolean}
|
|
*/
|
|
ve.dm.Annotation.static.splitOnWordbreak = false;
|
|
|
|
/**
|
|
* Static function to convert a linear model data element for this annotation type back to
|
|
* a DOM element.
|
|
*
|
|
* As special facilities for annotations, the annotated content that the returned element will
|
|
* wrap around is passed in as childDomElements, and this function may return an empty array to
|
|
* indicate that the annotation should produce no output. In that case, the child DOM elements will
|
|
* not be wrapped in anything and will be inserted directly into this annotation's parent.
|
|
*
|
|
* @static
|
|
* @inheritable
|
|
* @method
|
|
* @param {Object|Array} dataElement Linear model element or array of linear model data
|
|
* @param {HTMLDocument} doc HTML document for creating elements
|
|
* @param {ve.dm.Converter} converter Converter object to optionally call .getDomSubtreeFromData() on
|
|
* @param {HTMLElement[]} childDomElements Children that will be appended to the returned element
|
|
* @returns {HTMLElement[]} Array of DOM elements; only the first element is used; may be empty
|
|
*/
|
|
ve.dm.Annotation.static.toDomElements = function ( /*dataElement, doc, converter, childDomElements*/ ) {
|
|
throw new Error( 've.dm.Annotation subclass must implement toDomElements' );
|
|
};
|
|
|
|
/* Methods */
|
|
|
|
/**
|
|
* Convenience wrapper for .toDomElements() on the current annotation
|
|
* @method
|
|
* @param {HTMLDocument} [doc] HTML document to use to create elements
|
|
* @see ve.dm.Model#toDomElements
|
|
*/
|
|
ve.dm.Annotation.prototype.getDomElements = function ( doc ) {
|
|
return this.constructor.static.toDomElements( this.element, doc || document );
|
|
};
|
|
|
|
/**
|
|
* Get an object containing comparable annotation properties.
|
|
*
|
|
* This is used by the converter to merge adjacent annotations.
|
|
*
|
|
* @returns {Object} An object containing a subset of the annotation's properties
|
|
*/
|
|
ve.dm.Annotation.prototype.getComparableObject = function () {
|
|
var hashObject = this.getHashObject();
|
|
delete hashObject.htmlAttributes;
|
|
return hashObject;
|
|
};
|
|
|
|
/**
|
|
* HACK: This method strips data-parsoid from HTML attributes for comparisons.
|
|
*
|
|
* This should be removed once similar annotation merging is handled correctly
|
|
* by Parsoid.
|
|
*
|
|
* @returns {Object} An object all HTML attributes except data-parsoid
|
|
*/
|
|
ve.dm.Annotation.prototype.getComparableHtmlAttributes = function () {
|
|
var comparableAttributes, attributes = this.getHtmlAttributes();
|
|
|
|
if ( attributes[0] ) {
|
|
comparableAttributes = ve.copy( attributes[0].values );
|
|
delete comparableAttributes['data-parsoid'];
|
|
return comparableAttributes;
|
|
} else {
|
|
return {};
|
|
}
|
|
};
|
|
|
|
/**
|
|
* HACK: This method adds in HTML attributes so comparable objects aren't serialized
|
|
* together if they have different HTML attributes.
|
|
*
|
|
* This method needs to be different from getComparableObject which is
|
|
* still used for editing annotations.
|
|
*
|
|
* @returns {Object} An object containing a subset of the annotation's properties and HTML attributes
|
|
*/
|
|
ve.dm.Annotation.prototype.getComparableObjectForSerialization = function () {
|
|
var object = this.getComparableObject(),
|
|
htmlAttributes = this.getComparableHtmlAttributes();
|
|
|
|
if ( !ve.isEmptyObject( htmlAttributes ) ) {
|
|
object.htmlAttributes = htmlAttributes;
|
|
}
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* HACK: Check if the annotation was generated by the converter
|
|
*
|
|
* Used by compareToForSerialization to avoid merging generated annotations.
|
|
*
|
|
* @returns {boolean} The annotation was generated
|
|
*/
|
|
ve.dm.Annotation.prototype.isGenerated = function () {
|
|
var attributes = this.getHtmlAttributes();
|
|
return attributes[0] && attributes[0].values && attributes[0].values['data-parsoid'];
|
|
};
|
|
|
|
/**
|
|
* HACK: Compare to another annotation for serialization
|
|
*
|
|
* Compares two annotations using getComparableObjectForSerialization, unless
|
|
* they are both generated annotations, in which case they must be identical.
|
|
*
|
|
* @param {ve.dm.Annotation} annotation Annotation to compare to
|
|
* @returns {boolean} The other annotation is similar to this one
|
|
*/
|
|
ve.dm.Annotation.prototype.compareToForSerialization = function ( annotation ) {
|
|
// If both annotations were generated
|
|
if ( this.isGenerated() && annotation.isGenerated() ) {
|
|
return ve.compare( this.getHashObject(), annotation.getHashObject() );
|
|
}
|
|
|
|
return ve.compare(
|
|
this.getComparableObjectForSerialization(),
|
|
annotation.getComparableObjectForSerialization()
|
|
);
|
|
};
|