Catrope has uploaded a new change for review.
https://gerrit.wikimedia.org/r/50026
Change subject: Support RDFa type regexes in ModelRegistry
......................................................................
Support RDFa type regexes in ModelRegistry
Change-Id: Id19c3a567140f9e27ba732b6e8d9e25bc7a28a4f
---
M modules/ve/dm/ve.dm.Annotation.js
M modules/ve/dm/ve.dm.ModelRegistry.js
M modules/ve/dm/ve.dm.Node.js
M modules/ve/test/dm/ve.dm.ModelRegistry.test.js
4 files changed, 82 insertions(+), 43 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor
refs/changes/26/50026/1
diff --git a/modules/ve/dm/ve.dm.Annotation.js
b/modules/ve/dm/ve.dm.Annotation.js
index 344e351..91fb778 100644
--- a/modules/ve/dm/ve.dm.Annotation.js
+++ b/modules/ve/dm/ve.dm.Annotation.js
@@ -67,7 +67,7 @@
* @see ve.dm.ModelRegistry
*
* @static
- * @property {Array} static.matchTagNames
+ * @property {string[]} static.matchTagNames
* @inheritable
*/
ve.dm.Annotation.static.matchTagNames = null;
@@ -80,7 +80,7 @@
* @see ve.dm.ModelRegistry
*
* @static
- * @property {Array} static.matchRdfaType
+ * @property {Array} static.matchRdfaType Array of strings or regular
expressions
* @inheritable
*/
ve.dm.Annotation.static.matchRdfaTypes = null;
diff --git a/modules/ve/dm/ve.dm.ModelRegistry.js
b/modules/ve/dm/ve.dm.ModelRegistry.js
index 26aa572..f265a1c 100644
--- a/modules/ve/dm/ve.dm.ModelRegistry.js
+++ b/modules/ve/dm/ve.dm.ModelRegistry.js
@@ -17,11 +17,17 @@
ve.dm.ModelRegistry = function VeDmModelRegistry() {
// Parent constructor
ve.Registry.call( this );
+ // Map of func presence and tag names to model names
// [ { tagName: [modelNamesWithoutFunc] }, { tagName:
[modelNamesWithFunc] } ]
this.modelsByTag = [ {}, {} ];
+ // Map of func presence and rdfaTypes to model names; only rdfaTypes
specified as strings are in here
// { matchFunctionPresence: { rdfaType: { tagName: [modelNames] } } }
// [ { rdfaType: { tagName: [modelNamesWithoutFunc] } }, { rdfaType: {
tagName: [modelNamesWithFunc] } ]
this.modelsByTypeAndTag = [];
+ // Map of func presence to array of model names with rdfaType regexps
+ // [ [modelNamesWithoutFunc], [modelNamesWithFunc] ]
+ this.modelsWithTypeRegExps = [ [], [] ];
+ // Map tracking registration order
// { nameA: 0, nameB: 1, ... }
this.registrationOrder = {};
this.nextNumber = 0;
@@ -36,33 +42,27 @@
/**
* Helper function for register(). Adds a value to the front of an array in a
nested object.
- * Objects and arrays are created if needed. You can specify either two or
three keys and a value.
+ * Objects and arrays are created if needed. You can specify one or more keys
and a value.
*
* Specifically:
- * addType( obj, keyA, keyB, keyC, value ) does obj[keyA][keyB][keyC].unshift(
value );
+ * addType( obj, keyA, value ) does obj[keyA].unshift( value );
* addType( obj, keyA, keyB, value ) does obj[keyA][keyB].unshift( value );
+ * etc.
*
* @param {Object} obj Object to add to
- * @param {string} keyA Key into obj
- * @param {string} keyB Key into obj[keyA]
- * @param {string|Mixed} keyC Key into obj[keyA][keyB], or value to add to
array if value not set
- * @param {Mixed} [value] Value to add to the array
*/
-function addType( obj, keyA, keyB, keyC, value ) {
- if ( obj[keyA] === undefined ) {
- obj[keyA] = {};
+function addType( obj /*, ...*/ ) {
+ var i, len, o = obj;
+ for ( i = 1, len = arguments.length - 2; i < len; i++ ) {
+ if ( o[arguments[i]] === undefined ) {
+ o[arguments[i]] = {};
+ }
+ o = o[arguments[i]];
}
- if ( obj[keyA][keyB] === undefined ) {
- obj[keyA][keyB] = value === undefined ? [] : {};
+ if ( o[arguments[i]] === undefined ) {
+ o[arguments[i]] = [];
}
- if ( value !== undefined && obj[keyA][keyB][keyC] === undefined ) {
- obj[keyA][keyB][keyC] = [];
- }
- if ( value === undefined ) {
- obj[keyA][keyB].unshift( keyC );
- } else {
- obj[keyA][keyB][keyC].unshift( value );
- }
+ o[arguments[i]].unshift( arguments[i + 1] );
}
/* Public methods */
@@ -103,10 +103,14 @@
);
}
for ( i = 0; i < types.length; i++ ) {
- for ( j = 0; j < tags.length; j++ ) {
- addType( this.modelsByTypeAndTag,
- +!!constructor.static.matchFunction, types[i],
tags[j], name
- );
+ if ( types[i] instanceof RegExp ) {
+ addType( this.modelsWithTypeRegExps,
+!!constructor.static.matchFunction, name );
+ } else {
+ for ( j = 0; j < tags.length; j++ ) {
+ addType( this.modelsByTypeAndTag,
+ +!!constructor.static.matchFunction,
types[i], tags[j], name
+ );
+ }
}
}
@@ -177,13 +181,31 @@
return reg.registrationOrder[b] - reg.registrationOrder[a];
}
- function matchWithFunc( types, tag ) {
- var i, j, matches, queue = [];
- for ( i = 0; i < types.length; i++ ) {
- matches = ve.getProp( reg.modelsByTypeAndTag, 1,
types[i], tag ) || [];
- for ( j = 0; j < matches.length; j++ ) {
- queue.push( matches[j] );
+ function matchTypeRegExps( type, tag, withFunc ) {
+ var i, j, types, matches = [], models =
reg.modelsWithTypeRegExps[+!!withFunc];
+ for ( i = 0; i < models.length; i++ ) {
+ types = reg.registry[models[i]].static.matchRdfaTypes;
+ for ( j = 0; j < types.length; j++ ) {
+ if (
+ type.match( types[j] ) &&
+ (
+
reg.registry[models[i]].static.matchTagNames === null ||
+ ve.indexOf( tag,
reg.registry[models[i]].static.matchTagNames ) !== -1
+ )
+ ) {
+ matches.push( models[i] );
+ }
}
+ }
+ return matches;
+ }
+
+ function matchWithFunc( types, tag ) {
+ var i, queue = [];
+ for ( i = 0; i < types.length; i++ ) {
+ queue = queue
+ .concat( ve.getProp( reg.modelsByTypeAndTag, 1,
types[i], tag ) || [] )
+ .concat( matchTypeRegExps( types[i], tag, true
) );
}
queue.sort( byRegistrationOrderDesc );
for ( i = 0; i < queue.length; i++ ) {
@@ -195,16 +217,18 @@
}
function matchWithoutFunc( types, tag ) {
- var i, j, matches, winningName = null;
+ var i, queue = [], winningName = null;
for ( i = 0; i < types.length; i++ ) {
- matches = ve.getProp( reg.modelsByTypeAndTag, 0,
types[i], tag ) || [];
- for ( j = 0; j < matches.length; j++ ) {
- if (
- winningName === null ||
- reg.registrationOrder[winningName] <
reg.registrationOrder[matches[j]]
- ) {
- winningName = matches[j];
- }
+ queue = queue
+ .concat( ve.getProp( reg.modelsByTypeAndTag, 0,
types[i], tag ) || [] )
+ .concat( matchTypeRegExps( types[i], tag, false
) );
+ }
+ for ( i = 0; i < queue.length; i++ ) {
+ if (
+ winningName === null ||
+ reg.registrationOrder[winningName] <
reg.registrationOrder[queue[i]]
+ ) {
+ winningName = queue[i];
}
}
return winningName;
diff --git a/modules/ve/dm/ve.dm.Node.js b/modules/ve/dm/ve.dm.Node.js
index 6eb1fa0..634d5ed 100644
--- a/modules/ve/dm/ve.dm.Node.js
+++ b/modules/ve/dm/ve.dm.Node.js
@@ -54,7 +54,7 @@
* Empty array means none, null means any.
* For more information about element matching, see ve.dm.ModelRegistry.
* @static
- * @property {Array} static.matchTagNames
+ * @property {string[]} static.matchTagNames
* @inheritable
*/
ve.dm.Node.static.matchTagNames = null;
@@ -64,7 +64,7 @@
* Empty array means none, null means any.
* For more information about element matching, see ve.dm.ModelRegistry.
* @static
- * @property {Array} static.matchRdfaType
+ * @property {Array} static.matchRdfaType Array of strings or regular
expressions
* @inheritable
*/
ve.dm.Node.static.matchRdfaTypes = null;
diff --git a/modules/ve/test/dm/ve.dm.ModelRegistry.test.js
b/modules/ve/test/dm/ve.dm.ModelRegistry.test.js
index 8dfaa20..379ff45 100644
--- a/modules/ve/test/dm/ve.dm.ModelRegistry.test.js
+++ b/modules/ve/test/dm/ve.dm.ModelRegistry.test.js
@@ -83,9 +83,17 @@
ve.dm.StubBarNode.static.toDataElement = function () {};
ve.dm.StubBarNode.static.toDomElements = function () {};
+ve.dm.StubRegExpNode = function VeDmStubRegExpNode( children, element ) {
+ ve.dm.BranchNode.call( this, 'stub-regexp', children, element );
+};
+ve.inheritClass( ve.dm.StubRegExpNode, ve.dm.BranchNode );
+ve.dm.StubRegExpNode.static.name = 'stub-regexp';
+ve.dm.StubRegExpNode.static.matchTagNames = ['abbr'];
+ve.dm.StubRegExpNode.static.matchRdfaTypes = [ /^mw:/ ];
+
/* Tests */
-QUnit.test( 'matchElement', 16, function ( assert ) {
+QUnit.test( 'matchElement', 18, function ( assert ) {
var registry = new ve.dm.ModelRegistry(), element;
element = document.createElement( 'a' );
assert.deepEqual( registry.matchElement( element ), null,
'matchElement() returns null if registry empty' );
@@ -99,6 +107,7 @@
registry.register( ve.dm.StubSingleTypeAndFuncAnnotation );
registry.register( ve.dm.StubSingleTagAndTypeAndFuncAnnotation );
registry.register( ve.dm.StubBarNode );
+ registry.register( ve.dm.StubRegExpNode );
element = document.createElement( 'b' );
assert.deepEqual( registry.matchElement( element ), 'stubnothingset',
'nothingset matches anything' );
@@ -117,6 +126,9 @@
assert.deepEqual( registry.matchElement( element ), 'stubfunc',
'func-only match' );
element.setAttribute( 'rel', 'mw:foo' );
assert.deepEqual( registry.matchElement( element ),
'stubsingletypeandfunc', 'type and func match' );
+ element = document.createElement( 'abbr' );
+ element.setAttribute( 'rel', 'mw:baz' );
+ assert.deepEqual( registry.matchElement( element ), 'stub-regexp',
'RegExp type match' );
registry.registerExtensionSpecificType( /^mw:/ );
registry.registerExtensionSpecificType( 'foo' );
@@ -135,4 +147,7 @@
assert.deepEqual( registry.matchElement( element ), null,
'extension-specific type matching string prevents type match' );
element.setAttribute( 'rel', 'foo bar mw:bogus' );
assert.deepEqual( registry.matchElement( element ), null, 'two
extension-specific types prevent non-extension-specific type match' );
+ element = document.createElement( 'abbr' );
+ element.setAttribute( 'rel', 'mw:baz' );
+ assert.deepEqual( registry.matchElement( element ), 'stub-regexp',
'RegExp type match for extension-specific type' );
} );
--
To view, visit https://gerrit.wikimedia.org/r/50026
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Id19c3a567140f9e27ba732b6e8d9e25bc7a28a4f
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Catrope <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits