-
-
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; | |
} |
Licenced as ISC. License follows:
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
HI, I want to convert Html to Json using TOJSON() function but it doesn't capture special attributes like data-glide_el.
<div class="glide" id="glide_1" >
<div class="glide__track" data-glide-el="track">
<div class="hero__center">
<div class="hero__left">
<span class="">New Inspiration 2020</span>
</div>
<div class="hero__right">
<div class="hero__img-container">
<img class="banner_01" src="./images/banner_01.jpg" alt="banner2" />
</div>
</div>
</div>
</div>
</div>
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?
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?
@sstur could you add a license?