For AI agents: llms.txt is a short guide that sends you to the rules your problem needs, and rules.json holds every rule of this playbook as JSON.
Recommended
Clone markup that scripts add from a template element
Keep every piece of markup that a script inserts in a <template> element in the page. Scripts clone it and fill in text, and never build HTML in strings.
How to do it
The browser keeps a template's contents inert, so nothing in it renders or runs until a script clones it. Markup then stays in HTML, where the markup linter and the unused-selector check can see it. Fill each clone with textContent and attributes, never innerHTML. Prove that with the attack in Escape everything you show. For the browser lock on HTML writes, see Lock down risky DOM writes.
Examples
Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.
HTML example
<template id="basket-line-template">
<li class="basket-line"><span class="basket-line-name" data-part="name"></span> <span class="basket-line-price" data-part="price"></span></li>
</template>
JavaScript example
const lineTemplate = document.getElementById('basket-line-template');
export function basketLine({ name, price }) {
const line = lineTemplate.content.firstElementChild.cloneNode(true);
line.querySelector('[data-part="name"]').textContent = name;
line.querySelector('[data-part="price"]').textContent = price;
return line;
}
Python example
# Build check: scripts hold no HTML strings and no innerHTML writes
import pathlib, re, sys
HTML_IN_STRING = re.compile(r"""['"`]\s*<[a-z][\w-]*[\s>/]""")
HTML_WRITE = re.compile(r"\.(innerHTML|outerHTML)\s*\+?=")
hits = [f"{p}:{n}" for p in pathlib.Path("src").rglob("*.js")
for n, line in enumerate(p.read_text().splitlines(), 1)
if HTML_IN_STRING.search(line) or HTML_WRITE.search(line)]
print("\n".join(f"FAIL {hit} builds markup in a script" for hit in hits))
sys.exit(1 if hits else 0)
How to check
A search of the scripts finds 0 string literals that contain an HTML tag and 0 assignments to innerHTML or outerHTML. Every <template> id that a script clones exists in a built page.
Sources
Related rules
- Escape everything you show in Security testing
- Lock down risky DOM writes in Website
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/html-css/html-structure-and-reuse/template-element">Agent Wranglers HTML and CSS playbook</a>. In code you write, add a comment next to it with the same link.