121 lines
4.1 KiB
JavaScript
121 lines
4.1 KiB
JavaScript
function extractSchemaDetails(str) {
|
|
// Regular expression with named capture groups for name and optional placeholder
|
|
const regex = /{{(?<name>[^:}]+)(?::(?<placeholder>[^:}]+))?}}/g
|
|
const results = []
|
|
let match
|
|
|
|
while ((match = regex.exec(str)) !== null) {
|
|
|
|
// check if the match is already in the results array
|
|
if (results.some((result) => result.name === match.groups.name)) {
|
|
continue
|
|
}
|
|
|
|
results.push({
|
|
name: match.groups.name,
|
|
placeholder: match.groups.placeholder || null, // If placeholder is undefined, null
|
|
input: null
|
|
})
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
function replaceDivTextExceptSpan(div, newTextBefore) {
|
|
|
|
// Iterate over child nodes of the div
|
|
for (const node of div.childNodes) {
|
|
// Check if the node is a text node
|
|
if (node.nodeType === Node.TEXT_NODE) {
|
|
// Check the position of the text node to determine if it's before or after the span
|
|
if (node.nextSibling && node.nextSibling.tagName === 'SPAN') {
|
|
// Text node before the span
|
|
node.nodeValue = newTextBefore;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
const main = () => {
|
|
// select every code block with class language-template
|
|
document.querySelectorAll('code.language-template').forEach((codeElement) => {
|
|
// get the code inside the block
|
|
const codeInnerText = codeElement.innerText
|
|
const id = Math.random().toString(36).substring(7)
|
|
|
|
const templateContainer = document.createElement('div')
|
|
templateContainer.id = id;
|
|
templateContainer.className = "template-container"
|
|
|
|
const title = document.createElement('div')
|
|
title.className = "template-title"
|
|
title.innerText = "Template"
|
|
templateContainer.appendChild(title)
|
|
|
|
const templateVars = extractSchemaDetails(codeInnerText)
|
|
|
|
const renderInputs = () => {
|
|
let newCode = codeInnerText
|
|
|
|
templateVars.forEach((variable) => {
|
|
const escapedPlaceholder = variable.name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
const regexPattern = `{{${escapedPlaceholder}(?::[^}]+)?}}`; // Matches {{name}} or {{name:anything}}
|
|
const regex = new RegExp(regexPattern, 'g');
|
|
|
|
if (variable.input !== null && variable.input !== "") {
|
|
newCode = newCode.replace(regex, variable.input)
|
|
}
|
|
})
|
|
|
|
replaceDivTextExceptSpan(codeElement, newCode)
|
|
}
|
|
|
|
// create input elements
|
|
templateVars.forEach((variable) => {
|
|
const inputDiv = document.createElement('div')
|
|
inputDiv.className = "template-input-div"
|
|
|
|
const label = document.createElement('label')
|
|
label.for = `${id}-${variable.name}`
|
|
label.innerText = variable.name
|
|
|
|
const input = document.createElement('input')
|
|
input.id = `${id}-${variable.name}`
|
|
input.placeholder = variable.placeholder || variable.name
|
|
input.value = null
|
|
input.className = "template-input"
|
|
|
|
input.addEventListener('input', e => {
|
|
variable.input = e.target.value
|
|
renderInputs()
|
|
})
|
|
|
|
inputDiv.appendChild(label)
|
|
inputDiv.appendChild(input)
|
|
templateContainer.appendChild(inputDiv)
|
|
})
|
|
|
|
const copyButton = document.createElement('button')
|
|
copyButton.className = "template-copy-button"
|
|
copyButton.innerText = "Copy"
|
|
copyButton.addEventListener('click', () => {
|
|
navigator.clipboard.writeText(codeElement.innerText.trim())
|
|
})
|
|
templateContainer.appendChild(copyButton)
|
|
|
|
// get parent element
|
|
const outerDiv = codeElement.parentElement.parentElement.parentElement
|
|
const codeBlock = codeElement.parentElement.parentElement
|
|
|
|
|
|
// insert the template container before the code block
|
|
outerDiv.insertBefore(templateContainer, codeElement.parentElement.parentElement)
|
|
|
|
templateContainer.appendChild(codeBlock)
|
|
})
|
|
}
|
|
|
|
window.boot.register("page-ready", () => {
|
|
main()
|
|
}) |