Skip to content

Instantly share code, notes, and snippets.

@kmxz
Last active August 29, 2015 14:27
Show Gist options
  • Save kmxz/434034c2d09e87dbf373 to your computer and use it in GitHub Desktop.
Save kmxz/434034c2d09e87dbf373 to your computer and use it in GitHub Desktop.
A tool to convert a HTML fragment to a section of JavaScript to create it using Dom.$
/**
* @param{HTMLElement} root
* @param{number} prettyPrint - indent width; 0 for no pretty-print
* @param{string} func - the name of the function to be called. for example, "Dom.$"
* @param{boolean} allVar - name all elements as variables
* @param{boolean} omitSpace - trim all text nodes
*/
var toDom$ = function (root, prettyPrint, func, allVar, omitSpace) {
var table = [];
var getVariableNameCandidateList = function (el) {
var list = [];
if (el.id) { list.push(el.id); }
var i;
for (i = 0; i < el.classList.length; i++) {
list.push(el.classList[i]);
}
list.push(el.tagName);
return list;
};
var getVariableName = function (el) {
var candidates = getVariableNameCandidateList(el).map(function (str) {
return str.toLowerCase().replace(/[^A-Za-z0-9]/g, '_');
});
var i;
for (i = 0; i < candidates.length; i++) {
if (table.indexOf(candidates[i]) < 0) {
table.push(candidates[i]);
return candidates[i];
}
}
i = 1;
while (table.indexOf(candidates[0] + i) >= 0) {
i++;
}
table.push(candidates[0] + i);
return candidates[0] + i;
};
var quote = function (str) { return JSON.stringify(str); };
var printIndent = function (r) {
return new Array(r + 1).join(' ');
};
var getChildren = function (node, level) {
var cl = Array.prototype.slice.call(node.childNodes);
level += prettyPrint;
var children = cl.map(function (el) { return toDom(el, level); }).filter(function (s) { return s; });
if (!children.length) { return 'null'; }
if (prettyPrint) {
return (children.length === 1) ?
('\n' + printIndent(level) + children[0]) :
('[\n' + printIndent(level) + children.join(',\n' + printIndent(level)) + ']');
} else {
return (children.length === 1) ? children[0] : ('[' + children.join(',') + ']');
}
};
var getProperties = function (el) {
var obj = {};
var attrs = Array.prototype.slice.call(el.attributes);
attrs.forEach(function (attr) {
if (attr.name.toLowerCase() === 'style') { return; }
if (attr.name.toLowerCase() === 'class') { return; }
obj[attr.name]= attr.value;
});
var styles = Array.prototype.slice.call(el.style);
if (styles.length) {
obj['style'] = {};
styles.forEach(function (key) {
obj['style'][key] = el.style[key];
});
}
var classList = (el.classList.length > 1) ? Array.prototype.slice.call(el.classList) : (el.classList.length ? el.classList[0] : null);
if (Object.keys(obj).length) {
obj['class'] = classList;
return quote(obj);
} else {
return quote(classList);
}
};
var toDom = function (node, level) {
var trimmed, toReturn, propertiesStr, childrenStr;
if (node.nodeType === 1) {
toReturn = allVar ? (getVariableName(node) + (prettyPrint ? ' = ' : '=')) : '';
toReturn += func + '(' + quote(node.tagName.toLowerCase());
propertiesStr = getProperties(node);
childrenStr = getChildren(node, level);
if (propertiesStr === 'null' && childrenStr === 'null') {
return toReturn + ')';
}
toReturn += (prettyPrint ? ', ' : ',') + propertiesStr;
if (childrenStr === 'null') {
return toReturn + ')';
}
return toReturn + (prettyPrint ? ', ' : ',') + childrenStr + ')';
} else if (node.nodeType === 3) {
if (omitSpace) {
trimmed = node.textContent.trim();
return trimmed.length ? quote(trimmed) : null;
} else {
return quote(node.textContent);
}
} else {
throw 'Unexpected node.';
}
};
var all = toDom(root, 0);
var pre = '';
if (table.length) {
pre = 'var ' + table.join(prettyPrint ? ', ' : ',') + ';';
}
if (prettyPrint) {
pre += '\n';
}
return pre + all;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment