Merge "Rename fringeWhitespace to internal"

This commit is contained in:
Trevor Parscal 2012-08-17 17:40:36 +00:00 committed by Gerrit Code Review
commit 467c80fb44
24 changed files with 106 additions and 100 deletions

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.LeafNode}
* @param {Integer} [length] Length of content data in document
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.AlienBlockNode = function ( length, attributes ) {
ve.dm.AlienBlockNode = function ( length, attributes, internal ) {
// Inheritance
ve.dm.LeafNode.call( this, 'alienBlock', 0, attributes );
ve.dm.LeafNode.call( this, 'alienBlock', 0, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.LeafNode}
* @param {Integer} [length] Length of content data in document
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.AlienInlineNode = function ( length, attributes ) {
ve.dm.AlienInlineNode = function ( length, attributes, internal ) {
// Inheritance
ve.dm.LeafNode.call( this, 'alienInline', 0, attributes );
ve.dm.LeafNode.call( this, 'alienInline', 0, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.LeafNode}
* @param {Integer} [length] Length of content data in document
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.BreakNode = function ( length, attributes ) {
ve.dm.BreakNode = function ( length, attributes, internal ) {
// Inheritance
ve.dm.LeafNode.call( this, 'break', 0, attributes );
ve.dm.LeafNode.call( this, 'break', 0, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.BranchNode}
* @param {ve.dm.BranchNode[]} [children] Child nodes to attach
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.DefinitionListItemNode = function ( children, attributes ) {
ve.dm.DefinitionListItemNode = function ( children, attributes, internal ) {
// Inheritance
ve.dm.BranchNode.call( this, 'definitionListItem', children, attributes );
ve.dm.BranchNode.call( this, 'definitionListItem', children, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.BranchNode}
* @param {ve.dm.BranchNode[]} [children] Child nodes to attach
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.DefinitionListNode = function ( children, attributes ) {
ve.dm.DefinitionListNode = function ( children, attributes, internal ) {
// Inheritance
ve.dm.BranchNode.call( this, 'definitionList', children, attributes );
ve.dm.BranchNode.call( this, 'definitionList', children, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.BranchNode}
* @param {ve.dm.LeafNode[]} [children] Child nodes to attach
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.HeadingNode = function ( children, attributes ) {
ve.dm.HeadingNode = function ( children, attributes, internal ) {
// Inheritance
ve.dm.BranchNode.call( this, 'heading', children, attributes );
ve.dm.BranchNode.call( this, 'heading', children, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.LeafNode}
* @param {Integer} [length] Length of content data in document
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.ImageNode = function ( length, attributes ) {
ve.dm.ImageNode = function ( length, attributes, internal ) {
// Inheritance
ve.dm.LeafNode.call( this, 'image', 0, attributes );
ve.dm.LeafNode.call( this, 'image', 0, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.BranchNode}
* @param {ve.dm.BranchNode[]} [children] Child nodes to attach
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.ListItemNode = function ( children, attributes ) {
ve.dm.ListItemNode = function ( children, attributes, internal ) {
// Inheritance
ve.dm.BranchNode.call( this, 'listItem', children, attributes );
ve.dm.BranchNode.call( this, 'listItem', children, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.BranchNode}
* @param {ve.dm.BranchNode[]} [children] Child nodes to attach
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.ListNode = function ( children, attributes ) {
ve.dm.ListNode = function ( children, attributes, internal ) {
// Inheritance
ve.dm.BranchNode.call( this, 'list', children, attributes );
ve.dm.BranchNode.call( this, 'list', children, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.BranchNode}
* @param {ve.dm.LeafNode[]} [children] Child nodes to attach
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.ParagraphNode = function ( children, attributes ) {
ve.dm.ParagraphNode = function ( children, attributes, internal ) {
// Inheritance
ve.dm.BranchNode.call( this, 'paragraph', children, attributes );
ve.dm.BranchNode.call( this, 'paragraph', children, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.BranchNode}
* @param {ve.dm.LeafNode[]} [children] Child nodes to attach
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.PreformattedNode = function ( children, attributes ) {
ve.dm.PreformattedNode = function ( children, attributes, internal ) {
// Inheritance
ve.dm.BranchNode.call( this, 'preformatted', children, attributes );
ve.dm.BranchNode.call( this, 'preformatted', children, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.BranchNode}
* @param {ve.dm.BranchNode[]} [children] Child nodes to attach
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.TableCellNode = function ( children, attributes ) {
ve.dm.TableCellNode = function ( children, attributes, internal ) {
// Inheritance
ve.dm.BranchNode.call( this, 'tableCell', children, attributes );
ve.dm.BranchNode.call( this, 'tableCell', children, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.BranchNode}
* @param {ve.dm.BranchNode[]} [children] Child nodes to attach
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.TableNode = function ( children, attributes ) {
ve.dm.TableNode = function ( children, attributes, internal ) {
// Inheritance
ve.dm.BranchNode.call( this, 'table', children, attributes );
ve.dm.BranchNode.call( this, 'table', children, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.BranchNode}
* @param {ve.dm.BranchNode[]} [children] Child nodes to attach
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.TableRowNode = function ( children, attributes ) {
ve.dm.TableRowNode = function ( children, attributes, internal ) {
// Inheritance
ve.dm.BranchNode.call( this, 'tableRow', children, attributes );
ve.dm.BranchNode.call( this, 'tableRow', children, attributes, internal );
};
/* Static Members */

View file

@ -13,10 +13,11 @@
* @extends {ve.dm.BranchNode}
* @param {ve.dm.BranchNode[]} [children] Child nodes to attach
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.TableSectionNode = function ( children, attributes ) {
ve.dm.TableSectionNode = function ( children, attributes, internal ) {
// Inheritance
ve.dm.BranchNode.call( this, 'tableSection', children, attributes );
ve.dm.BranchNode.call( this, 'tableSection', children, attributes, internal );
};
/* Static Members */

View file

@ -16,10 +16,11 @@
* @param {String} type Symbolic name of node type
* @param {ve.dm.Node[]} [children] Child nodes to attach
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.BranchNode = function ( type, children, attributes ) {
ve.dm.BranchNode = function ( type, children, attributes, internal ) {
// Inheritance
ve.dm.Node.call( this, type, 0, attributes );
ve.dm.Node.call( this, type, 0, attributes, internal );
ve.BranchNode.call( this );
if ( ve.isArray( children ) && children.length ) {

View file

@ -335,15 +335,23 @@ ve.dm.Converter.prototype.getDataFromDom = function ( domElement, annotations, d
}
// Strip leading and trailing whitespace
// but only in non-annotation nodes
// (but only in non-annotation nodes)
// and store it so it can be restored later.
// whitespace = [ outerPre, innerPre, innerPost, outerPost ]
// <tag> text </tag> <nextTag>
// ^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^
// outerPre innerPre innerPost outerPost
if ( annotations.length === 0 && i === 0 && wrapperElement ) {
// Strip leading whitespace from the first child
matches = text.match( /^\s+/ );
if ( matches && matches[0] !== '' ) {
if ( !wrapperElement.fringeWhitespace ) {
wrapperElement.fringeWhitespace = {};
if ( !wrapperElement.internal ) {
wrapperElement.internal = {};
}
wrapperElement.fringeWhitespace.innerPre = matches[0];
if ( !wrapperElement.internal.whitespace ) {
wrapperElement.internal.whitespace = [];
}
wrapperElement.internal.whitespace[1] = matches[0];
text = text.substring( matches[0].length );
}
}
@ -355,10 +363,13 @@ ve.dm.Converter.prototype.getDataFromDom = function ( domElement, annotations, d
// Strip trailing whitespace from the last child
matches = text.match( /\s+$/ );
if ( matches && matches[0] !== '' ) {
if ( !wrapperElement.fringeWhitespace ) {
wrapperElement.fringeWhitespace = {};
if ( !wrapperElement.internal ) {
wrapperElement.internal = {};
}
wrapperElement.fringeWhitespace.innerPost = matches[0];
if ( !wrapperElement.internal.whitespace ) {
wrapperElement.internal.whitespace = [];
}
wrapperElement.internal.whitespace[2] = matches[0];
text = text.substring( 0,
text.length - matches[0].length );
}
@ -532,9 +543,10 @@ ve.dm.Converter.prototype.getDomFromData = function ( data ) {
// Make sure the alien closing is skipped
i++;
} else if ( dataElement.type.charAt( 0 ) === '/' ) {
// Process whitespace
if ( domElement.veWhitespace ) {
pre = domElement.veWhitespace.innerPre;
// Process inner whitespace
// whitespace = [ outerPre, innerPre, innerPost, outerPost ]
if ( domElement.veInternal && domElement.veInternal.whitespace ) {
pre = domElement.veInternal.whitespace[1];
if ( pre ) {
if ( domElement.firstChild.nodeType === 3 ) {
// First child is a TextNode, prepend to it
@ -547,7 +559,7 @@ ve.dm.Converter.prototype.getDomFromData = function ( data ) {
);
}
}
post = domElement.veWhitespace.innerPost;
post = domElement.veInternal.whitespace[2];
if ( post ) {
if ( domElement.lastChild.nodeType === 3 ) {
// Last child is a TextNode, append to it
@ -559,16 +571,16 @@ ve.dm.Converter.prototype.getDomFromData = function ( data ) {
);
}
}
delete domElement.veWhitespace;
}
delete domElement.veInternal;
// Ascend to parent node
domElement = domElement.parentNode;
} else {
// Create node from data
childDomElement = this.getDomElementFromDataElement( dataElement );
// Add whitespace info
if ( dataElement.fringeWhitespace ) {
childDomElement.veWhitespace = dataElement.fringeWhitespace;
// Add reference to internal data to propagate whitespace info
if ( dataElement.internal ) {
childDomElement.veInternal = dataElement.internal;
}
// Add element
domElement.appendChild( childDomElement );

View file

@ -71,10 +71,9 @@ ve.dm.Document = function ( data, parentDocument ) {
if ( this.data[i].type.charAt( 0 ) !== '/' ) {
// Branch or leaf node opening
// Create a childless node
node = ve.dm.nodeFactory.create( this.data[i].type, [], this.data[i].attributes );
if ( this.data[i].fringeWhitespace ) {
node.setFringeWhitespace( this.data[i].fringeWhitespace );
}
node = ve.dm.nodeFactory.create( this.data[i].type, [],
this.data[i].attributes, this.data[i].internal
);
// Set the root pointer now, to prevent cascading updates
node.setRoot( root );
// Put the childless node on the current inner stack

View file

@ -16,10 +16,11 @@
* @param {String} type Symbolic name of node type
* @param {Integer} [length] Length of content data in document
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Reference to internal data object
*/
ve.dm.LeafNode = function ( type, length, attributes ) {
ve.dm.LeafNode = function ( type, length, attributes, internal ) {
// Inheritance
ve.dm.Node.call( this, type, length, attributes );
ve.dm.Node.call( this, type, length, attributes, internal );
ve.LeafNode.call( this );
};

View file

@ -15,15 +15,16 @@
* @param {String} type Symbolic name of node type
* @param {Integer} [length] Length of content data in document
* @param {Object} [attributes] Reference to map of attribute key/value pairs
* @param {Object} [internal] Object with internal data to store for this node
*/
ve.dm.Node = function ( type, length, attributes ) {
ve.dm.Node = function ( type, length, attributes, internal ) {
// Inheritance
ve.Node.call( this, type );
// Properties
this.length = length || 0;
this.attributes = attributes || {};
this.fringeWhitespace = {};
this.internal = internal || {};
this.doc = undefined;
};
@ -225,8 +226,8 @@ ve.dm.Node.prototype.getClonedElement = function () {
if ( !ve.isEmptyObject( this.attributes ) ) {
retval.attributes = ve.copyObject( this.attributes );
}
if ( !ve.isEmptyObject( this.fringeWhitespace ) ) {
retval.fringeWhitespace = ve.copyObject( this.fringeWhitespace );
if ( !ve.isEmptyObject( this.internal ) ) {
retval.internal = ve.copyObject( this.internal );
}
return retval;
};
@ -263,29 +264,6 @@ ve.dm.Node.prototype.canBeMergedWith = function ( node ) {
return true;
};
/**
* Store whitespace that was stripped from the fringes of this node, so it can be restored when
* converting back to HTML.
*
* This function can be passed an object with multiple position-value pairs:
* setFringeWhitespace( { 'innerPre': ' ', 'outerPost': '\n' } ) is equivalent to:
* setFringeWhitespace( 'innerPre', ' ' ); setFringeWhitespace( 'outerPost', '\n' );
*
* @param {String} position Position where the whitespace occurred:
* 'innerPre', 'innerPost', 'outerPre' or 'outerPost'
* @param {String} value The whitespace
*/
ve.dm.Node.prototype.setFringeWhitespace = function ( position, value ) {
var k;
if ( typeof position === 'object' ) {
for ( k in position ) {
this.fringeWhitespace[k] = position[k];
}
} else {
this.fringeWhitespace[position] = value;
}
};
/* Inheritance */
ve.extendClass( ve.dm.Node, ve.Node );

View file

@ -442,7 +442,7 @@ ve.dm.example.domToDataCases = {
'data': [
{ 'type': 'list', 'attributes': { 'style': 'bullet' } },
{ 'type': 'listItem' },
{ 'type': 'paragraph', 'fringeWhitespace': { 'innerPre': ' ' } },
{ 'type': 'paragraph', 'internal': { 'whitespace': [ undefined, ' ' ] } },
[
'b',
{
@ -649,7 +649,7 @@ ve.dm.example.domToDataCases = {
{
'type': 'heading',
'attributes': { 'level': 2 },
'fringeWhitespace': { 'innerPre': ' ' }
'internal': { 'whitespace': [ undefined, ' ' ] }
},
'B',
'a',
@ -658,7 +658,7 @@ ve.dm.example.domToDataCases = {
{
'type': 'heading',
'attributes': { 'level': 2 },
'fringeWhitespace': { 'innerPost': ' ' }
'internal': { 'whitespace': [ undefined, undefined, ' ' ] }
},
'B',
'a',
@ -667,7 +667,7 @@ ve.dm.example.domToDataCases = {
{
'type': 'heading',
'attributes': { 'level': 2 },
'fringeWhitespace': { 'innerPre': ' ', 'innerPost': ' ' }
'internal': { 'whitespace': [ undefined, ' ', ' ' ] }
},
'Q',
'u',
@ -689,16 +689,14 @@ ve.dm.example.domToDataCases = {
{ 'type': '/paragraph' },
{ 'type': '/listItem' },
{ 'type': 'listItem' },
{ 'type': 'paragraph', 'fringeWhitespace': { 'innerPre': ' ' }
},
{ 'type': 'paragraph', 'internal': { 'whitespace': [ undefined, ' ' ] } },
'B',
'a',
'r',
{ 'type': '/paragraph' },
{ 'type': '/listItem' },
{ 'type': 'listItem' },
{ 'type': 'paragraph', 'fringeWhitespace': { 'innerPost': ' ' }
},
{ 'type': 'paragraph', 'internal': { 'whitespace': [ undefined, undefined, ' ' ] } },
'B',
'a',
'z',
@ -707,7 +705,7 @@ ve.dm.example.domToDataCases = {
{ 'type': 'listItem' },
{
'type': 'paragraph',
'fringeWhitespace': { 'innerPre': ' ', 'innerPost': ' ' }
'internal': { 'whitespace': [ undefined, ' ', ' ' ] }
},
'Q',
'u',
@ -723,7 +721,7 @@ ve.dm.example.domToDataCases = {
'data': [
{
'type': 'paragraph',
'fringeWhitespace': { 'innerPre': ' ', 'innerPost': ' '}
'internal': { 'whitespace': [ undefined, ' ', ' ' ] }
},
[ ' ', { '{"type":"textStyle/italic"}': { 'type': 'textStyle/italic' } } ],
[ ' ', { '{"type":"textStyle/italic"}': { 'type': 'textStyle/italic' } } ],

View file

@ -9,9 +9,10 @@ QUnit.module( 've.Factory' );
/* Stubs */
ve.FactoryObjectStub = function ( a, b ) {
ve.FactoryObjectStub = function ( a, b, c ) {
this.a = a;
this.b = b;
this.c = c;
};
/* Tests */
@ -31,15 +32,15 @@ QUnit.test( 'create', 2, function ( assert ) {
var factory = new ve.Factory();
assert.throws(
function () {
factory.create( 'factory-object-stub', 23, { 'bar': 'baz' } );
factory.create( 'factory-object-stub', 23, 'foo', { 'bar': 'baz' } );
},
Error,
'throws an exception when trying to create a object of an unregistered type'
);
factory.register( 'factory-object-stub', ve.FactoryObjectStub );
assert.deepEqual(
factory.create( 'factory-object-stub', 16, { 'baz': 'quux' } ),
new ve.FactoryObjectStub( 16, { 'baz': 'quux' } ),
factory.create( 'factory-object-stub', 16, 'foo', { 'baz': 'quux' } ),
new ve.FactoryObjectStub( 16, 'foo', { 'baz': 'quux' } ),
'creates objects of a registered type and passes through arguments'
);
} );

View file

@ -4,7 +4,7 @@
* Builds a summary of a node tree.
*
* Generated summaries contain node types, lengths, outer lengths, attributes and summaries for
* each child recusively. It's simple and fast to use deepEqual on this.
* each child recursively. It's simple and fast to use deepEqual on this.
*
* @method
* @param {ve.Node} node Node tree to summarize
@ -17,7 +17,8 @@ function getNodeTreeSummary( node, shallow ) {
'getType': node.getType(),
'getLength': node.getLength(),
'getOuterLength': node.getOuterLength(),
'attributes': node.attributes
'attributes': node.attributes,
'internal': node.internal
};
if ( node.children !== undefined ) {
summary['children.length'] = node.children.length;

View file

@ -48,20 +48,20 @@ ve.Factory.prototype.register = function ( type, constructor ) {
* Type is used to look up the constructor to use, while all additional arguments are passed to the
* constructor directly, so leaving one out will pass an undefined to the constructor.
*
* WARNING: JavaScript does not allow using new and .apply together, so we just pass through 2
* WARNING: JavaScript does not allow using new and .apply together, so we just pass through 3
* arguments here since we know we only need that many at this time. If we need more in the future
* we should change this to suit that use case. Because of undefined pass through, there's no harm
* in adding more.
*
* @method
* @param {String} type Object type
* @param {Mixed} [...] Up to 2 additional arguments to pass through to the constructor
* @param {Mixed} [...] Up to 3 additional arguments to pass through to the constructor
* @returns {Object} The new object
* @throws 'Unknown object type'
*/
ve.Factory.prototype.create = function ( type, a, b ) {
ve.Factory.prototype.create = function ( type, a, b, c ) {
if ( type in this.registry ) {
return new this.registry[type]( a, b );
return new this.registry[type]( a, b, c );
}
throw new Error( 'Unknown object type: ' + type );
};