|
|
|
@ -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<Object>} |
|
|
|
*/ |
|
|
|
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: <div> <span>TEST</span> </div> <-- span is text type
|
|
|
|
// TO: <div> TEST </div> <-- 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)
|
|
|
|
|