Index: trunk/extensions/VisualEditor/modules/parser/mediawiki.DOMConverter.js |
— | — | @@ -7,24 +7,34 @@ |
8 | 8 | function DOMConverter () { |
9 | 9 | } |
10 | 10 | |
11 | | -// Quick HACK: define Node constants |
12 | | -// https://developer.mozilla.org/en/nodeType |
13 | | -var Node = { |
14 | | - ELEMENT_NODE: 1, |
15 | | - ATTRIBUTE_NODE: 2, |
16 | | - TEXT_NODE: 3, |
17 | | - CDATA_SECTION_NODE: 4, |
18 | | - ENTITY_REFERENCE_NODE: 5, |
19 | | - ENTITY_NODE: 6, |
20 | | - PROCESSING_INSTRUCTION_NODE: 7, |
21 | | - COMMENT_NODE: 8, |
22 | | - DOCUMENT_NODE: 9, |
23 | | - DOCUMENT_TYPE_NODE: 10, |
24 | | - DOCUMENT_FRAGMENT_NODE: 11, |
25 | | - NOTATION_NODE: 12 |
| 11 | +/** |
| 12 | + * Convert a HTML DOM to WikiDom |
| 13 | + * |
| 14 | + * @method |
| 15 | + * @param {Object} root of HTML DOM (usually the body element) |
| 16 | + * @returns {Object} WikiDom representation |
| 17 | + */ |
| 18 | +DOMConverter.prototype.HTMLtoWiki = function ( node ) { |
| 19 | + return this._convertHTMLBranch( node, 'document' ).node; |
26 | 20 | }; |
27 | 21 | |
28 | | -DOMConverter.prototype.getHTMLHandlerInfo = function ( nodeName ) { |
| 22 | + |
| 23 | +/* Private stuff */ |
| 24 | + |
| 25 | +/** |
| 26 | + * Map an HTML node name to (handler, wikiDomName [, attribs]). Only |
| 27 | + * non-annotation html elements are handled here. The conversion should thus |
| 28 | + * use this._getWikiDomAnnotationType first to check if the element is actually |
| 29 | + * an annotation. |
| 30 | + * |
| 31 | + * @static |
| 32 | + * @method |
| 33 | + * @param {String} nodeName, the element's nodeName. |
| 34 | + * @returns {Object} with keys 'handler' (one of the _convertHTMLLeaf and |
| 35 | + * _convertHTMLBranch functions), 'type' (the name of this element in WikiDom) |
| 36 | + * and optionally 'attribs', WikiDom-specific attributes implied by the element name. |
| 37 | + */ |
| 38 | +DOMConverter.prototype._getHTMLtoWikiDomHandlerInfo = function ( nodeName ) { |
29 | 39 | switch ( nodeName.toLowerCase() ) { |
30 | 40 | case 'p': |
31 | 41 | return { |
— | — | @@ -120,7 +130,16 @@ |
121 | 131 | } |
122 | 132 | }; |
123 | 133 | |
124 | | -DOMConverter.prototype.getHTMLAnnotationType = function ( nodeName, warn ) { |
| 134 | +/** |
| 135 | + * Map HTML element names to WikiDom annotation types or undefined. |
| 136 | + * |
| 137 | + * @param {String} nodeName, the HTML element name |
| 138 | + * @param {Boolean} warn (optional), enable warnings for non-annotation |
| 139 | + * element types |
| 140 | + * @returns {String} WikiDom annotation type or undefined if element name does |
| 141 | + * not map to an annotation. |
| 142 | + */ |
| 143 | +DOMConverter.prototype._getWikiDomAnnotationType = function ( nodeName, warn ) { |
125 | 144 | switch ( nodeName.toLowerCase() ) { |
126 | 145 | case 'i': |
127 | 146 | return 'textStyle/italic'; |
— | — | @@ -145,47 +164,6 @@ |
146 | 165 | } |
147 | 166 | }; |
148 | 167 | |
149 | | -/** |
150 | | - * Convert a HTML DOM to WikiDom |
151 | | - * |
152 | | - * @method |
153 | | - * @param {Object} root of HTML DOM (usually the body element) |
154 | | - * @returns {Object} WikiDom version |
155 | | - */ |
156 | | -DOMConverter.prototype.HTMLtoWiki = function ( node ) { |
157 | | - var children = node.childNodes, |
158 | | - out = { |
159 | | - type: 'document', |
160 | | - children: [] |
161 | | - }; |
162 | | - for ( var i = 0, l = children.length; i < l; i++ ) { |
163 | | - var cnode = children[i]; |
164 | | - switch ( cnode.nodeType ) { |
165 | | - case Node.ELEMENT_NODE: |
166 | | - // Call a handler for the particular node type |
167 | | - var hi = this.getHTMLHandlerInfo( cnode.nodeName ); |
168 | | - var res = hi.handler.call(this, cnode, hi.type ); |
169 | | - if ( hi.attribs ) { |
170 | | - $.extend( res.node.attributes, hi.attribs ); |
171 | | - } |
172 | | - out.children.push( res.node ); |
173 | | - break; |
174 | | - case Node.TEXT_NODE: |
175 | | - // Add text as content, and increment offset |
176 | | - // BUT: Should not appear at toplevel! |
177 | | - break; |
178 | | - case Node.COMMENT_NODE: |
179 | | - // Add a comment annotation to which text? Not clear how this |
180 | | - // can be represented in WikiDom. |
181 | | - break; |
182 | | - default: |
183 | | - console.log( "HTML to Wiki DOM conversion error. Unhandled node type " + |
184 | | - cnode.innerHTML ); |
185 | | - break; |
186 | | - } |
187 | | - } |
188 | | - return out; |
189 | | -}; |
190 | 168 | |
191 | 169 | /** |
192 | 170 | * Private HTML branch node handler |
— | — | @@ -223,7 +201,7 @@ |
224 | 202 | switch ( cnode.nodeType ) { |
225 | 203 | case Node.ELEMENT_NODE: |
226 | 204 | // Check if element type is an annotation |
227 | | - var annotationtype = this.getHTMLAnnotationType( cnode.nodeName ); |
| 205 | + var annotationtype = this._getWikiDomAnnotationType( cnode.nodeName ); |
228 | 206 | if ( annotationtype ) { |
229 | 207 | if ( !parNode ) { |
230 | 208 | newPara(); |
— | — | @@ -240,7 +218,7 @@ |
241 | 219 | // Close last paragraph, if still open. |
242 | 220 | parNode = null; |
243 | 221 | // Call a handler for the particular node type |
244 | | - var hi = this.getHTMLHandlerInfo( cnode.nodeName ); |
| 222 | + var hi = this._getHTMLtoWikiDomHandlerInfo( cnode.nodeName ); |
245 | 223 | res = hi.handler.call(this, cnode, hi.type ); |
246 | 224 | if ( hi.attribs ) { |
247 | 225 | $.extend( res.node.attributes, hi.attribs ); |
— | — | @@ -296,7 +274,7 @@ |
297 | 275 | switch ( cnode.nodeType ) { |
298 | 276 | case Node.ELEMENT_NODE: |
299 | 277 | // Call a handler for the particular annotation node type |
300 | | - var annotationtype = this.getHTMLAnnotationType( cnode.nodeName, true ); |
| 278 | + var annotationtype = this._getWikiDomAnnotationType( cnode.nodeName, true ); |
301 | 279 | if ( annotationtype ) { |
302 | 280 | var res = this._convertHTMLAnnotation( cnode, offset, annotationtype ); |
303 | 281 | //console.log( 'res leaf: ' + JSON.stringify(res, null, 2)); |
— | — | @@ -327,6 +305,15 @@ |
328 | 306 | }; |
329 | 307 | }; |
330 | 308 | |
| 309 | +/** |
| 310 | + * Private: Convert an HTML element to an annotation |
| 311 | + * |
| 312 | + * @param {Object} HTML element node |
| 313 | + * @offset {Int} plain-text offset within leaf node |
| 314 | + * @type {String} type of annotation returned by _getWikiDomAnnotationType |
| 315 | + * @return {Object} {text: extracted plain text, annotations: {Array} of |
| 316 | + * annotation nodes} |
| 317 | + */ |
331 | 318 | DOMConverter.prototype._convertHTMLAnnotation = function ( node, offset, type ) { |
332 | 319 | var children = node.childNodes, |
333 | 320 | text = '', |
— | — | @@ -345,7 +332,7 @@ |
346 | 333 | switch ( cnode.nodeType ) { |
347 | 334 | case Node.ELEMENT_NODE: |
348 | 335 | // Call a handler for the particular annotation node type |
349 | | - var annotationtype = this.getHTMLAnnotationType(cnode.nodeName, true); |
| 336 | + var annotationtype = this._getWikiDomAnnotationType(cnode.nodeName, true); |
350 | 337 | if ( annotationtype ) { |
351 | 338 | var res = this._convertHTMLAnnotation( cnode, offset, annotationtype ); |
352 | 339 | //console.log( 'res annotations 2: ' + JSON.stringify(res, null, 2)); |
— | — | @@ -421,7 +408,24 @@ |
422 | 409 | return out; |
423 | 410 | }; |
424 | 411 | |
| 412 | +// Quick HACK: define Node constants |
| 413 | +// https://developer.mozilla.org/en/nodeType |
| 414 | +var Node = { |
| 415 | + ELEMENT_NODE: 1, |
| 416 | + ATTRIBUTE_NODE: 2, |
| 417 | + TEXT_NODE: 3, |
| 418 | + CDATA_SECTION_NODE: 4, |
| 419 | + ENTITY_REFERENCE_NODE: 5, |
| 420 | + ENTITY_NODE: 6, |
| 421 | + PROCESSING_INSTRUCTION_NODE: 7, |
| 422 | + COMMENT_NODE: 8, |
| 423 | + DOCUMENT_NODE: 9, |
| 424 | + DOCUMENT_TYPE_NODE: 10, |
| 425 | + DOCUMENT_FRAGMENT_NODE: 11, |
| 426 | + NOTATION_NODE: 12 |
| 427 | +}; |
425 | 428 | |
| 429 | + |
426 | 430 | if (typeof module == "object") { |
427 | 431 | module.exports.DOMConverter = DOMConverter; |
428 | 432 | } |