Index: trunk/extensions/VisualEditor/modules/es/models/es.DocumentModel.js |
— | — | @@ -492,12 +492,21 @@ |
493 | 493 | var stack = []; |
494 | 494 | // Text and annotations |
495 | 495 | function start( offset, annotation ) { |
496 | | - stack.push( es.extendObject( true, {}, annotation, { 'range': { 'start': offset } } ) ); |
| 496 | + // Make a new verion of the annotation object and push it to the stack |
| 497 | + var obj = { |
| 498 | + 'type': annotation.type, |
| 499 | + 'range': { 'start': offset } |
| 500 | + }; |
| 501 | + if ( annotation.data ) { |
| 502 | + obj.data = es.copyObject( annotation.data ); |
| 503 | + } |
| 504 | + stack.push( obj ); |
497 | 505 | } |
498 | 506 | function end( offset, annotation ) { |
499 | 507 | for ( var i = stack.length - 1; i >= 0; i-- ) { |
500 | 508 | if ( !stack[i].range.end ) { |
501 | 509 | if ( annotation ) { |
| 510 | + // We would just compare hashes, but the stack doesn't contain any |
502 | 511 | if ( stack[i].type === annotation.type && |
503 | 512 | es.compareObjects( stack[i].data, annotation.data ) ) { |
504 | 513 | stack[i].range.end = offset; |
Index: trunk/extensions/VisualEditor/modules/es/serializers/es.HtmlSerializer.js |
— | — | @@ -26,6 +26,18 @@ |
27 | 27 | return ( new es.HtmlSerializer( options ) ).document( data ); |
28 | 28 | }; |
29 | 29 | |
| 30 | +es.HtmlSerializer.getHtmlAttributes = function( attributes ) { |
| 31 | + var htmlAttributes = {}, |
| 32 | + count = 0; |
| 33 | + for ( var key in attributes ) { |
| 34 | + if ( key.indexOf( 'html/' ) === 0 ) { |
| 35 | + htmlAttributes[key.substr( 5 )] = attributes[key]; |
| 36 | + count++; |
| 37 | + } |
| 38 | + } |
| 39 | + return count ? htmlAttributes : null; |
| 40 | +}; |
| 41 | + |
30 | 42 | /* Methods */ |
31 | 43 | |
32 | 44 | es.HtmlSerializer.prototype.document = function( node, rawFirstParagraph ) { |
— | — | @@ -35,7 +47,7 @@ |
36 | 48 | if ( childNode.type in this ) { |
37 | 49 | // Special case for paragraphs which have particular wrapping needs |
38 | 50 | if ( childNode.type === 'paragraph' ) { |
39 | | - lines.push( this.paragraph( childNode, rawFirstParagraph && b === 0 ) ); |
| 51 | + lines.push( this.paragraph( childNode, rawFirstParagraph && i === 0 ) ); |
40 | 52 | } else { |
41 | 53 | lines.push( this[childNode.type].call( this, childNode ) ); |
42 | 54 | } |
— | — | @@ -52,9 +64,9 @@ |
53 | 65 | return es.Html.makeTag( 'hr', {}, false ); |
54 | 66 | }; |
55 | 67 | |
56 | | -es.HtmlSerializer.prototype.heading = function( heading ) { |
| 68 | +es.HtmlSerializer.prototype.heading = function( node ) { |
57 | 69 | return es.Html.makeTag( |
58 | | - 'h' + heading.level, {}, this.serializeLine( heading.content ) |
| 70 | + 'h' + node.attributes.level, {}, this.content( node.content ) |
59 | 71 | ); |
60 | 72 | }; |
61 | 73 | |
— | — | @@ -72,8 +84,9 @@ |
73 | 85 | }; |
74 | 86 | |
75 | 87 | es.HtmlSerializer.prototype.table = function( node ) { |
76 | | - var lines = []; |
77 | | - lines.push( es.Html.makeOpeningTag( 'table', node.attributes ) ); |
| 88 | + var lines = [], |
| 89 | + attributes = es.HtmlSerializer.getHtmlAttributes( node.attributes ); |
| 90 | + lines.push( es.Html.makeOpeningTag( 'table', attributes ) ); |
78 | 91 | for ( var i = 0, length = node.children.length; i < length; i++ ) { |
79 | 92 | lines.push( this.tableRow( node.children[i] ) ); |
80 | 93 | } |
— | — | @@ -82,8 +95,9 @@ |
83 | 96 | }; |
84 | 97 | |
85 | 98 | es.HtmlSerializer.prototype.tableRow = function( node ) { |
86 | | - var lines = []; |
87 | | - lines.push( es.Html.makeOpeningTag( 'tr', node.attributes ) ); |
| 99 | + var lines = [], |
| 100 | + attributes = es.HtmlSerializer.getHtmlAttributes( node.attributes ); |
| 101 | + lines.push( es.Html.makeOpeningTag( 'tr', attributes ) ); |
88 | 102 | for ( var i = 0, length = node.children.length; i < length; i++ ) { |
89 | 103 | lines.push( this.tableCell( node.children[i] ) ); |
90 | 104 | } |
— | — | @@ -93,10 +107,11 @@ |
94 | 108 | |
95 | 109 | es.HtmlSerializer.prototype.tableCell = function( node ) { |
96 | 110 | var symbolTable = { |
97 | | - 'tableHeading': 'th', |
98 | | - 'tableCell': 'td' |
99 | | - }; |
100 | | - return es.Html.makeTag( symbolTable[node.type], node.attributes, this.document( node, true ) ); |
| 111 | + 'tableHeading': 'th', |
| 112 | + 'tableCell': 'td' |
| 113 | + }, |
| 114 | + attributes = es.HtmlSerializer.getHtmlAttributes( node.attributes ); |
| 115 | + return es.Html.makeTag( symbolTable[node.type], attributes, this.document( node, true ) ); |
101 | 116 | }; |
102 | 117 | |
103 | 118 | es.HtmlSerializer.prototype.transclusion = function( node ) { |
Index: trunk/extensions/VisualEditor/modules/es/serializers/es.WikitextSerializer.js |
— | — | @@ -26,6 +26,18 @@ |
27 | 27 | return ( new es.WikitextSerializer( options ) ).document( data ); |
28 | 28 | }; |
29 | 29 | |
| 30 | +es.WikitextSerializer.getHtmlAttributes = function( attributes ) { |
| 31 | + var htmlAttributes = {}, |
| 32 | + count = 0; |
| 33 | + for ( var key in attributes ) { |
| 34 | + if ( key.indexOf( 'html/' ) === 0 ) { |
| 35 | + htmlAttributes[key.substr( 5 )] = attributes[key]; |
| 36 | + count++; |
| 37 | + } |
| 38 | + } |
| 39 | + return count ? htmlAttributes : null; |
| 40 | +}; |
| 41 | + |
30 | 42 | /* Methods */ |
31 | 43 | |
32 | 44 | es.WikitextSerializer.prototype.document = function( node, rawFirstParagraph ) { |
— | — | @@ -56,8 +68,8 @@ |
57 | 69 | }; |
58 | 70 | |
59 | 71 | es.WikitextSerializer.prototype.heading = function( node ) { |
60 | | - var symbols = es.repeatString( '=', node.level ); |
61 | | - return symbols + this.serializeLine( node.line ) + symbols; |
| 72 | + var symbols = es.repeatString( '=', node.attributes.level ); |
| 73 | + return symbols + this.content( node.content ) + symbols; |
62 | 74 | }; |
63 | 75 | |
64 | 76 | es.WikitextSerializer.prototype.paragraph = function( node ) { |
— | — | @@ -80,28 +92,37 @@ |
81 | 93 | for ( var i = 0, length = node.children.length; i < length; i++ ) { |
82 | 94 | var childNode = node.children[i]; |
83 | 95 | lines.push( |
84 | | - convertStyles( childNode.styles ) + ' ' + this.content( childNode.content, path ) |
| 96 | + convertStyles( childNode.attributes.styles ) + ' ' + |
| 97 | + this.content( childNode.content ) |
85 | 98 | ); |
86 | 99 | } |
87 | 100 | return lines.join( '\n' ); |
88 | 101 | }; |
89 | 102 | |
90 | | -es.WikitextSerializer.prototype.table = function( table ) { |
91 | | - var lines = []; |
92 | | - lines.push( '{|' + es.Document.Serializer.buildXmlAttributes( table.attributes ) ); |
| 103 | +es.WikitextSerializer.prototype.table = function( node ) { |
| 104 | + var lines = [], |
| 105 | + attributes = es.WikitextSerializer.getHtmlAttributes( node.attributes ); |
| 106 | + if ( attributes ) { |
| 107 | + attributes = es.Html.makeAttributeList( attributes ); |
| 108 | + } |
| 109 | + lines.push( '{|' + attributes ); |
93 | 110 | for ( var i = 0, length = node.children.length; i < length; i++ ) { |
94 | | - lines.push( this.tableRow( node.children[i] ) ); |
| 111 | + lines.push( this.tableRow( node.children[i], i === 0 ) ); |
95 | 112 | } |
96 | 113 | lines.push( '|}' ); |
97 | 114 | return lines.join( '\n' ); |
98 | 115 | }; |
99 | 116 | |
100 | | -es.WikitextSerializer.prototype.tableRow = function( node ) { |
101 | | - var lines = []; |
| 117 | +es.WikitextSerializer.prototype.tableRow = function( node, first ) { |
| 118 | + var lines = [], |
| 119 | + attributes = es.WikitextSerializer.getHtmlAttributes( node.attributes ); |
| 120 | + if ( attributes ) { |
| 121 | + attributes = es.Html.makeAttributeList( attributes ); |
| 122 | + } |
| 123 | + if ( !first || attributes ) { |
| 124 | + lines.push( '|-' + attributes ); |
| 125 | + } |
102 | 126 | for ( var i = 0, length = node.children.length; i < length; i++ ) { |
103 | | - if ( i > 0 ) { |
104 | | - lines.push( '|-' ); |
105 | | - } |
106 | 127 | lines.push( this.tableCell( node.children[i] ) ); |
107 | 128 | } |
108 | 129 | return lines.join( '\n' ); |
— | — | @@ -110,11 +131,13 @@ |
111 | 132 | es.WikitextSerializer.prototype.tableCell = function( node ) { |
112 | 133 | var symbolTable = { |
113 | 134 | 'tableHeading': '!', |
114 | | - 'tableData': '|' |
| 135 | + 'tableCell': '|' |
115 | 136 | }; |
116 | | - return symbolTable[node.type] + |
117 | | - ( node.attributes ? es.Html.makeAttributeList( cell.attributes ) + '|' : '' ) + |
118 | | - this.document( node, true ); |
| 137 | + var attributes = es.WikitextSerializer.getHtmlAttributes( node.attributes ); |
| 138 | + if ( attributes ) { |
| 139 | + attributes = es.Html.makeAttributeList( attributes ) + '|'; |
| 140 | + } |
| 141 | + return symbolTable[node.type] + attributes + this.document( node, true ); |
119 | 142 | }; |
120 | 143 | |
121 | 144 | es.WikitextSerializer.prototype.transclusion = function( node ) { |