Created
December 1, 2024 21:04
-
-
Save JorianWoltjer/3b3ee6d0f70e776bb94c3eac7d9c3ad2 to your computer and use it in GitHub Desktop.
Convert an HTML/XML snippet to JavaScript `createDocument` and `setAttribute` recursively
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { JSDOM } from 'jsdom'; | |
const dom = new JSDOM(` | |
<h1 id="title">Hello, World!</h1> | |
<p>This is a paragraph.</p> | |
<ul> | |
<li>Item 1</li> | |
<li>Item 2</li> | |
<li>Item 3</li> | |
</ul> | |
`); | |
const { Node } = dom.window; | |
function getUniqueName(name, existingNames) { | |
if (!existingNames.has(name)) { | |
existingNames.add(name); | |
return name; | |
} | |
let i = 2; | |
while (existingNames.has(`${name}${i}`)) { | |
i++; | |
} | |
const varName = `${name}${i}`; | |
existingNames.add(varName); | |
return varName; | |
} | |
function getCode(node, indent = 0, existingNames = new Set()) { | |
const padding = " ".repeat(indent); | |
let code = ""; | |
if (node.nodeType === Node.TEXT_NODE) { | |
const text = node.textContent.trim(); | |
let varName; | |
if (text) { | |
varName = getUniqueName("text", existingNames); | |
code += `${padding}const ${varName} = document.createTextNode(${JSON.stringify(node.textContent)});\n`; | |
} | |
return { code, varName }; | |
} | |
const tagName = node.tagName.toLowerCase(); | |
const varName = getUniqueName(tagName.match(/(\w+)$/)[1], existingNames); | |
code += `${padding}const ${varName} = document.createElement(${JSON.stringify(tagName)});\n`; | |
for (const { name, value } of node.attributes) { | |
code += `${padding}${varName}.setAttribute(${JSON.stringify(name)}, ${JSON.stringify(value)});\n`; | |
} | |
let listOfChilds = Array.from(node.childNodes).map((child) => getCode(child, indent + 1, existingNames)); | |
listOfChilds = listOfChilds.filter((child) => child.code !== ""); | |
if (listOfChilds.length > 0) { | |
code += `${padding}{\n`; | |
for (const { code: childCode, varName: childVarName } of listOfChilds) { | |
code += childCode; | |
code += `${padding} ${varName}.appendChild(${childVarName});\n`; | |
} | |
code += `${padding}}\n`; | |
listOfChilds.forEach(({ varName }) => existingNames.delete(varName)); | |
} | |
return { code, varName }; | |
} | |
for (const node of dom.window.document.body.childNodes) { | |
console.log(getCode(node).code.trim()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Setup:
Example output: