Change the HTML attribute prefix from html/ to html/0/

This means that <p data-foo="bar"> will now be converted to a paragraph
with attributes {"html/0/data-foo":"bar"} rather than {"html/foo":"bar"}

This paves the way for multi-element node (about group) handling in the
node API: nodes representing multiple DOM elements will have html/i/attr
to represent an attribute of the i'th DOM element.

Change-Id: Iea52bdccd721942ca708c8f9f47e934524809845
This commit is contained in:
Catrope 2013-02-06 11:47:52 -08:00
parent edd0baf4fe
commit 591f2e7396
6 changed files with 34 additions and 34 deletions

View file

@ -33,7 +33,7 @@ ve.ce.Node = function VeCeNode( type, model, $element ) {
this.$.data( 'node', this );
ve.setDomAttributes(
this.$[0],
this.model.getAttributes( 'html/' ),
this.model.getAttributes( 'html/0/' ),
this.constructor.static.domAttributeWhitelist
);
};
@ -117,9 +117,9 @@ ve.ce.Node.static.$shieldTemplate = $( '<img>' )
* @param {string} to New value
*/
ve.ce.Node.prototype.onAttributeChange = function ( key, from, to ) {
var htmlKey = key.substr( 5 ).toLowerCase();
var htmlKey = key.substr( 7 ).toLowerCase();
if (
key.indexOf( 'html/' ) === 0 &&
key.indexOf( 'html/0/' ) === 0 &&
htmlKey.length &&
this.constructor.static.domAttributeWhitelist.indexOf( htmlKey ) !== -1
) {

View file

@ -128,9 +128,9 @@ ve.dm.Converter.prototype.getDomElementFromDataElement = function ( dataElement
dataElementAttributes = dataElement.attributes;
if ( dataElementAttributes ) {
for ( key in dataElementAttributes ) {
// Only include 'html/*' attributes and strip the 'html/' from the beginning of the name
if ( key.indexOf( 'html/' ) === 0 ) {
domElement.setAttribute( key.substr( 5 ), dataElementAttributes[key] );
// Only include 'html/0/*' attributes and strip the 'html/0/' from the beginning of the name
if ( key.indexOf( 'html/0/' ) === 0 ) {
domElement.setAttribute( key.substr( 7 ), dataElementAttributes[key] );
}
}
}
@ -172,10 +172,10 @@ ve.dm.Converter.prototype.getDataElementFromDomElement = function ( domElement,
domElementAttributes = domElement.attributes;
if ( domElementAttributes.length ) {
dataElementAttributes = dataElement.attributes = dataElement.attributes || {};
// Include all attributes and prepend 'html/' to each attribute name
// Include all attributes and prepend 'html/0/' to each attribute name
for ( i = 0; i < domElementAttributes.length; i++ ) {
domElementAttribute = domElementAttributes[i];
dataElementAttributes['html/' + domElementAttribute.name] = domElementAttribute.value;
dataElementAttributes['html/0/' + domElementAttribute.name] = domElementAttribute.value;
}
}
if ( this.nodeFactory.isNodeContent( dataElement.type ) && !annotations.isEmpty() ) {
@ -434,7 +434,7 @@ ve.dm.Converter.prototype.getDataFromDom = function ( domElement, annotations, d
}
// Preserve HTML attributes
// FIXME the following is duplicated from getDataElementFromDomElement()
// Include all attributes and prepend 'html/' to each attribute name
// Include all attributes and prepend 'html/0/' to each attribute name
for ( j = 0; j < childDomElement.attributes.length; j++ ) {
// ..but exclude attributes we've already processed,
// because they'll be overwritten otherwise *sigh*
@ -443,7 +443,7 @@ ve.dm.Converter.prototype.getDataFromDom = function ( domElement, annotations, d
childDomElement.attributes[j].name !== ( isLink ? 'rel' : 'property' ) &&
childDomElement.attributes[j].name !== ( isLink ? 'href' : 'content' )
) {
childDataElement.attributes['html/' + childDomElement.attributes[j].name] = childDomElement.attributes[j].value;
childDataElement.attributes['html/0/' + childDomElement.attributes[j].name] = childDomElement.attributes[j].value;
}
}
data.push( childDataElement );

View file

@ -218,7 +218,7 @@ QUnit.test( 'getRenderedContents', function ( assert ) {
['b', [ { 'type': 'textStyle/bold' } ]],
{
'type': 'MWentity',
'attributes': { 'character': 'c', 'html/typeof': 'mw:Entity' },
'attributes': { 'character': 'c', 'html/0/typeof': 'mw:Entity' },
'annotations': [ { 'type': 'textStyle/bold' } ]
},
{ 'type': '/MWentity' },

View file

@ -274,7 +274,7 @@ QUnit.test( 'newFromRemoval', 15, function ( assert ) {
'type': 'replace',
'remove': [
'h',
{ 'type': 'image', 'attributes': { 'html/src': 'image.png' } },
{ 'type': 'image', 'attributes': { 'html/0/src': 'image.png' } },
{ 'type': '/image' },
'i'
],

View file

@ -142,13 +142,13 @@ QUnit.test( 'commit/rollback', 66, function ( assert ) {
['pushReplaceElementAttribute', 'style', 'bullet', 'number'],
['pushReplaceElementAttribute', 'test', undefined, 'abcd'],
['pushRetain', 27],
['pushReplaceElementAttribute', 'html/src', 'image.png', undefined]
['pushReplaceElementAttribute', 'html/0/src', 'image.png', undefined]
],
'expected': function ( data ) {
data[0].attributes.level = 2;
data[12].attributes.style = 'number';
data[12].attributes.test = 'abcd';
delete data[39].attributes['html/src'];
delete data[39].attributes['html/0/src'];
ve.setProp( data[0], 'internal', 'changed', 'attributes', 1 );
ve.setProp( data[12], 'internal', 'changed', 'attributes', 2 );
ve.setProp( data[39], 'internal', 'changed', 'attributes', 1 );

View file

@ -218,7 +218,7 @@ ve.dm.example.data = [
// 38 - Plain "h"
'h',
// 39 - Beginning of inline image
{ 'type': 'image', 'attributes': { 'html/src': 'image.png' } },
{ 'type': 'image', 'attributes': { 'html/0/src': 'image.png' } },
// 40 - End of inline image
{ 'type': '/image' },
// 41 - Plain "i"
@ -374,8 +374,8 @@ ve.dm.example.withMeta = [
'attributes': {
'style': 'meta',
'key': null,
'html/typeof': 'mw:Placeholder',
'html/data-parsoid': 'foobar'
'html/0/typeof': 'mw:Placeholder',
'html/0/data-parsoid': 'foobar'
}
},
{ 'type': '/metaBlock' }
@ -477,8 +477,8 @@ ve.dm.example.withMetaMetaData = [
'attributes': {
'style': 'meta',
'key': null,
'html/typeof': 'mw:Placeholder',
'html/data-parsoid': 'foobar'
'html/0/typeof': 'mw:Placeholder',
'html/0/data-parsoid': 'foobar',
}
}
]
@ -639,13 +639,13 @@ ve.dm.example.conversions = {
'domElement': ve.example.createDomElement( 'tr' ),
'dataElement': { 'type': 'tableRow' }
},
'paragraph with mw-data attribute': {
'paragraph with data-mw attribute': {
'domElement': ve.example.createDomElement( 'p', { 'data-mw': '{"test":1234}' } ),
'dataElement': { 'type': 'paragraph', 'attributes': { 'html/data-mw': '{"test":1234}' } }
'dataElement': { 'type': 'paragraph', 'attributes': { 'html/0/data-mw': '{"test":1234}' } }
},
'paragraph with style attribute': {
'domElement': ve.example.createDomElement( 'p', { 'style': 'color:blue' } ),
'dataElement': { 'type': 'paragraph', 'attributes': { 'html/style': 'color:blue' } }
'dataElement': { 'type': 'paragraph', 'attributes': { 'html/0/style': 'color:blue' } }
}
};
@ -674,7 +674,7 @@ ve.dm.example.domToDataCases = {
'html': '<img src="image.png">',
'data': [
{ 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } },
{ 'type': 'image', 'attributes' : { 'html/src' : 'image.png' } },
{ 'type': 'image', 'attributes' : { 'html/0/src' : 'image.png' } },
{ 'type' : '/image' },
{ 'type': '/paragraph' }
]
@ -724,7 +724,7 @@ ve.dm.example.domToDataCases = {
{ 'type': '/alienInline' },
{
'type': 'MWentity',
'attributes': { 'character': 'c', 'html/typeof': 'mw:Entity' },
'attributes': { 'character': 'c', 'html/0/typeof': 'mw:Entity' },
'annotations': [ ve.dm.example.bold, ve.dm.example.italic ]
},
{ 'type': '/MWentity' },
@ -763,7 +763,7 @@ ve.dm.example.domToDataCases = {
'html': '<img src="foo.jpg">12',
'data': [
{ 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } },
{ 'type': 'image', 'attributes': { 'html/src': 'foo.jpg' } },
{ 'type': 'image', 'attributes': { 'html/0/src': 'foo.jpg' } },
{ 'type': '/image' },
'1',
'2',
@ -1839,12 +1839,12 @@ ve.dm.example.domToDataCases = {
'data': [
{ 'type': 'paragraph' },
'a',
{ 'type': 'MWentity', 'attributes': { 'character': '¢', 'html/typeof': 'mw:Entity' } },
{ 'type': 'MWentity', 'attributes': { 'character': '¢', 'html/0/typeof': 'mw:Entity' } },
{ 'type': '/MWentity' },
'b',
{ 'type': 'MWentity', 'attributes': { 'character': '¥', 'html/typeof': 'mw:Entity' } },
{ 'type': 'MWentity', 'attributes': { 'character': '¥', 'html/0/typeof': 'mw:Entity' } },
{ 'type': '/MWentity' },
{ 'type': 'MWentity', 'attributes': { 'character': '™', 'html/typeof': 'mw:Entity' } },
{ 'type': 'MWentity', 'attributes': { 'character': '™', 'html/0/typeof': 'mw:Entity' } },
{ 'type': '/MWentity' },
{ 'type': '/paragraph' }
]
@ -1854,12 +1854,12 @@ ve.dm.example.domToDataCases = {
'data': [
{ 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } },
'a',
{ 'type': 'MWentity', 'attributes': { 'character': '¢', 'html/typeof': 'mw:Entity' } },
{ 'type': 'MWentity', 'attributes': { 'character': '¢', 'html/0/typeof': 'mw:Entity' } },
{ 'type': '/MWentity' },
'b',
{ 'type': 'MWentity', 'attributes': { 'character': '¥', 'html/typeof': 'mw:Entity' } },
{ 'type': 'MWentity', 'attributes': { 'character': '¥', 'html/0/typeof': 'mw:Entity' } },
{ 'type': '/MWentity' },
{ 'type': 'MWentity', 'attributes': { 'character': '™', 'html/typeof': 'mw:Entity' } },
{ 'type': 'MWentity', 'attributes': { 'character': '™', 'html/0/typeof': 'mw:Entity' } },
{ 'type': '/MWentity' },
{ 'type': '/paragraph' }
]
@ -1871,7 +1871,7 @@ ve.dm.example.domToDataCases = {
'a',
' ',
' ',
{ 'type': 'MWentity', 'attributes': { 'character': ' ', 'html/typeof': 'mw:Entity' } },
{ 'type': 'MWentity', 'attributes': { 'character': ' ', 'html/0/typeof': 'mw:Entity' } },
{ 'type': '/MWentity' },
' ',
' ',
@ -1881,10 +1881,10 @@ ve.dm.example.domToDataCases = {
' ',
' ',
' ',
{ 'type': 'MWentity', 'attributes': { 'character': '¥', 'html/typeof': 'mw:Entity' } },
{ 'type': 'MWentity', 'attributes': { 'character': '¥', 'html/0/typeof': 'mw:Entity' } },
{ 'type': '/MWentity' },
'\t',
{ 'type': 'MWentity', 'attributes': { 'character': '™', 'html/typeof': 'mw:Entity' } },
{ 'type': 'MWentity', 'attributes': { 'character': '™', 'html/0/typeof': 'mw:Entity' } },
{ 'type': '/MWentity' },
{ 'type': '/paragraph' }
]