Skip to content

Instantly share code, notes, and snippets.

@qb20nh
Last active December 17, 2021 06:38
Show Gist options
  • Save qb20nh/63e0c3112832a966c70b8dfd7378f1ee to your computer and use it in GitHub Desktop.
Save qb20nh/63e0c3112832a966c70b8dfd7378f1ee to your computer and use it in GitHub Desktop.
Populate jstl-el-like expressions with JS
const iterateNode = (rootNode, [attrVisitor, textVisitor]) => {
if (rootNode instanceof Node) {
for(const node of rootNode.childNodes) {
if (node instanceof Element) {
for (const attr of node.attributes) {
attrVisitor.call(null, attr)
}
iterateNode(node, [attrVisitor, textVisitor])
} else if (node instanceof Text) {
textVisitor.call(null, node)
}
}
}
}
const nodes = []
const populateData = (template, data) => {
if (template instanceof HTMLTemplateElement) {
iterateNode(template.content, [
attr => {
const constructionIndicator = 'foreach:constructing'
if (attr.name.startsWith('foreach:') && !attr.ownerElement.hasAttribute(constructionIndicator)) {
attr.ownerElement.setAttribute(constructionIndicator, '')
return
}
attr.value = replaceExpr(data, attr.value)
},
text => {
nodes.push(text)
text.textContent = replaceExpr(data, text.textContent)
}
])
}
}
const cloneAndPopulateData = (node, data) => {
if (node instanceof Element) {
const clone = node.cloneNode(true)
populateData(clone, data)
node.parentNode.appendChild(clone)
}
}
const nullString = s => {
return (s !== undefined && String(s).length > 0) ? s : ''
}
const replaceExpr = (data, text) =>
text.replace(/(.)?\\$\{\s*([^\}\.\s]+(\.[^\}\.\s]+)*)\s*\}/g, (match, escapeChar, expr) => {
if (escapeChar === '\\') {
return match
} else {
const value = findProperty(data, expr.split('.'))
return nullString(escapeChar) + nullString(value)
}
})
const findProperty = (data, [...path]) => {
let ref = data
for(const part of path) {
if (part in ref) {
ref = ref[part]
} else {
return
}
}
return typeof ref === 'function' ? ref() : ref
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment