diff --git a/src/parser/model/ParserHtml.js b/src/parser/model/ParserHtml.js index 4cfc7974a..f2e99aa7d 100644 --- a/src/parser/model/ParserHtml.js +++ b/src/parser/model/ParserHtml.js @@ -53,95 +53,92 @@ module.exports = config => { }, /** - * Fetch data from node - * @param {HTMLElement} el DOM + * Get data from the node element + * @param {HTMLElement} el DOM element to traverse * @return {Array} */ parseNode(el) { - var result = []; - var nodes = el.childNodes; + const result = []; + const nodes = el.childNodes; for (var i = 0, len = nodes.length; i < len; i++) { - var node = nodes[i]; - var model = {}; - var attrs = node.attributes || []; - var attrsLen = attrs.length; - var prevI = result.length - 1; - var prevSib = result[prevI]; - var ct = this.compTypes; - - if(ct){ - var obj = ''; - /* - for (var cType in ct) { - var component = ct[cType].model; - obj = component.isComponent(node); - if(obj) - break; - }*/ - for (var it = 0; it < ct.length; it++) { - var component = ct[it].model; - obj = component.isComponent(node); - if(obj) - break; + const node = nodes[i]; + const attrs = node.attributes || []; + const attrsLen = attrs.length; + const nodePrev = result[result.length - 1]; + const nodeChild = node.childNodes.length; + const ct = this.compTypes; + let model = {}; + + // Start with understanding what kind of component it is + if (ct) { + let obj = ''; + + // Iterate over all available Component Types and + // the first with a valid result will be that component + for (let it = 0; it < ct.length; it++) { + obj = ct[it].model.isComponent(node); + if (obj) break; } model = obj; } - if(!model.tagName) + // Set tag name if not yet done + if (!model.tagName) { model.tagName = node.tagName ? node.tagName.toLowerCase() : ''; + } - if(attrsLen) + if (attrsLen) { model.attributes = {}; + } - // Store attributes - for (var j = 0; j < attrsLen; j++){ - var nodeName = attrs[j].nodeName; - var nodeValue = attrs[j].nodeValue; + // Parse attributes + for (let j = 0; j < attrsLen; j++) { + const nodeName = attrs[j].nodeName; + let nodeValue = attrs[j].nodeValue; - //Isolate few attributes - if(nodeName == 'style') + // Isolate attributes + if (nodeName == 'style') { model.style = this.parseStyle(nodeValue); - else if(nodeName == 'class') + } else if (nodeName == 'class') { model.classes = this.parseClass(nodeValue); - else if (nodeName == 'contenteditable') + } else if (nodeName == 'contenteditable') { continue; - else if (nodeName.indexOf(modelAttrStart) === 0) { + } else if (nodeName.indexOf(modelAttrStart) === 0) { const modelAttr = nodeName.replace(modelAttrStart, ''); const valueLen = nodeValue.length; const firstChar = nodeValue && nodeValue.substr(0, 1); const lastChar = nodeValue && nodeValue.substr(valueLen - 1); nodeValue = nodeValue === 'true' ? true : nodeValue; nodeValue = nodeValue === 'false' ? false : nodeValue; - // Try to json parse where is possible + + // Try to parse JSON where it's possible // I can get false positive here (eg. a selector '[data-attr]') // so put it under try/catch and let fail silently try { nodeValue = (firstChar == '{' && lastChar == '}') || (firstChar == '[' && lastChar == ']') ? JSON.parse(nodeValue) : nodeValue; } catch (e) {} + model[modelAttr] = nodeValue; } else { model.attributes[nodeName] = nodeValue; } } + // Check for nested elements but avoid it if already provided + if (nodeChild && !model.components) { + // Avoid infinite nested text nodes + const firstChild = node.childNodes[0]; - var nodeChild = node.childNodes.length; - - // Check for nested elements and avoid them if an array - // was already given - if(nodeChild && !model.components){ - // Avoid infinite text nodes nesting - var firstChild = node.childNodes[0]; - if(nodeChild === 1 && firstChild.nodeType === 3){ - if(!model.type){ - model.type = 'text'; - } + // If there is only one child and it's a TEXTNODE + // just make it content of the current node + if (nodeChild === 1 && firstChild.nodeType === 3) { + !model.type && (model.type = 'text'); model.content = firstChild.nodeValue; - }else{ - var parsed = this.parseNode(node); + } else { + const parsed = this.parseNode(node); // From:
TEST
<-- span is text type // TO:
TEST
<-- div become text type if(parsed.length == 1 && parsed[0].type == 'text' && @@ -155,9 +152,9 @@ module.exports = config => { // Check if it's a text node and if could be moved to the prevous model if(model.type == 'textnode'){ - var prevIsText = prevSib && prevSib.type == 'textnode'; + var prevIsText = nodePrev && nodePrev.type == 'textnode'; if(prevIsText){ - prevSib.content += model.content; + nodePrev.content += model.content; continue; } // Throw away empty nodes (keep spaces)