-
-
Save sstur/7379870 to your computer and use it in GitHub Desktop.
function toJSON(node) { | |
let propFix = { for: 'htmlFor', class: 'className' }; | |
let specialGetters = { | |
style: (node) => node.style.cssText, | |
}; | |
let attrDefaultValues = { style: '' }; | |
let obj = { | |
nodeType: node.nodeType, | |
}; | |
if (node.tagName) { | |
obj.tagName = node.tagName.toLowerCase(); | |
} else if (node.nodeName) { | |
obj.nodeName = node.nodeName; | |
} | |
if (node.nodeValue) { | |
obj.nodeValue = node.nodeValue; | |
} | |
let attrs = node.attributes; | |
if (attrs) { | |
let defaultValues = new Map(); | |
for (let i = 0; i < attrs.length; i++) { | |
let name = attrs[i].nodeName; | |
defaultValues.set(name, attrDefaultValues[name]); | |
} | |
// Add some special cases that might not be included by enumerating | |
// attributes above. Note: this list is probably not exhaustive. | |
switch (obj.tagName) { | |
case 'input': { | |
if (node.type === 'checkbox' || node.type === 'radio') { | |
defaultValues.set('checked', false); | |
} else if (node.type !== 'file') { | |
// Don't store the value for a file input. | |
defaultValues.set('value', ''); | |
} | |
break; | |
} | |
case 'option': { | |
defaultValues.set('selected', false); | |
break; | |
} | |
case 'textarea': { | |
defaultValues.set('value', ''); | |
break; | |
} | |
} | |
let arr = []; | |
for (let [name, defaultValue] of defaultValues) { | |
let propName = propFix[name] || name; | |
let specialGetter = specialGetters[propName]; | |
let value = specialGetter ? specialGetter(node) : node[propName]; | |
if (value !== defaultValue) { | |
arr.push([name, value]); | |
} | |
} | |
if (arr.length) { | |
obj.attributes = arr; | |
} | |
} | |
let childNodes = node.childNodes; | |
// Don't process children for a textarea since we used `value` above. | |
if (obj.tagName !== 'textarea' && childNodes && childNodes.length) { | |
let arr = (obj.childNodes = []); | |
for (let i = 0; i < childNodes.length; i++) { | |
arr[i] = toJSON(childNodes[i]); | |
} | |
} | |
return obj; | |
} | |
function toDOM(input) { | |
let obj = typeof input === 'string' ? JSON.parse(input) : input; | |
let propFix = { for: 'htmlFor', class: 'className' }; | |
let node; | |
let nodeType = obj.nodeType; | |
switch (nodeType) { | |
// ELEMENT_NODE | |
case 1: { | |
node = document.createElement(obj.tagName); | |
if (obj.attributes) { | |
for (let [attrName, value] of obj.attributes) { | |
let propName = propFix[attrName] || attrName; | |
// Note: this will throw if setting the value of an input[type=file] | |
node[propName] = value; | |
} | |
} | |
break; | |
} | |
// TEXT_NODE | |
case 3: { | |
return document.createTextNode(obj.nodeValue); | |
} | |
// COMMENT_NODE | |
case 8: { | |
return document.createComment(obj.nodeValue); | |
} | |
// DOCUMENT_FRAGMENT_NODE | |
case 11: { | |
node = document.createDocumentFragment(); | |
break; | |
} | |
default: { | |
// Default to an empty fragment node. | |
return document.createDocumentFragment(); | |
} | |
} | |
if (obj.childNodes && obj.childNodes.length) { | |
for (let childNode of obj.childNodes) { | |
node.appendChild(toDOM(childNode)); | |
} | |
} | |
return node; | |
} |
it doesn't capture special attributes like data-glide-el
True. The reason is that data attributes don't change the way the static HTML displays, so it doesn't make sense to capture them for the original goals of this script.
In most cases, the purpose of data attributes is for JavaScript to do something with the data, but toJSON() also doesn't capture JavaScript or JS-related attributes (like onclick
).
So I'd say data attributes are out of scope for this, but I'd be open to hear if there's a good use for adding support.
don't know how to generate the same HTML from JSON
If you need HTML output, I'd suggest you first create DOM and then convert that to HTML using innerHTML
or something similar.
where can I provide my root node in toDOM()
toDOM()
doesn't require a root node, instead it returns a node. You can attach that node to your document using something like document.body.appendChild(node)
.
Can we support SVG too?
HI, I want to convert Html to Json using TOJSON() function but it doesn't capture special attributes like data-glide_el.
In the same manner, I am don't know how to generate the same HTML from JSON already created in the above step.
where can I provide my root node in toDOM() function so that it can add the generated code to it?