import type { Arg, Directive, Nullable, Renderer } from "../engine/mod.ts"
import { format } from "./format.ts"
export function filter(renderer: Renderer, node: Nullable<Element>, { format: _format = true, comments = true, directives = ["*warn", "*id"], clean = "" } = {} as FilterOptions): string {
if (!node) {
return ""
}
let html = _filter(renderer, node.cloneNode(true) as Element, { comments, directives, clean }).innerHTML
if (_format) {
html = format(html)
}
return html.trim()
}
export type FilterOptions = {
format?: boolean
comments?: boolean
directives?: Array<Directive["name"]>
clean?: string
}
function _filter(renderer: Renderer, node: Element, { comments, directives, clean } = {} as Arg<typeof filter, 2, true>): Element {
if ((node.nodeType === renderer.window.Node.COMMENT_NODE) && (!comments)) {
node.remove()
return node
}
if ((node.nodeType === renderer.window.Node.ELEMENT_NODE) && clean) {
const pattern = new RegExp(clean)
Array.from(node.attributes).forEach((attribute) => pattern.test(attribute.name) && node.removeAttribute(attribute.name))
}
if ((node.nodeType === renderer.window.Node.ELEMENT_NODE) && (node.hasAttribute("style")) && (!node.getAttribute("style")!.endsWith(";"))) {
node.setAttribute("style", `${node.getAttribute("style")};`)
}
if ((node.nodeType === renderer.window.Node.ELEMENT_NODE) && (Array.isArray(directives)) && (!directives.includes("*"))) {
renderer.directives.forEach((directive) => {
if (directives.includes(`${directive.name}`)) {
return
}
renderer.getAttributes(node as HTMLElement, directive.name).forEach((attribute) => {
node.removeAttribute(attribute.name)
})
})
}
if ((node.nodeType === renderer.window.Node.ELEMENT_NODE) && (node.hasAttribute("filter-remove"))) {
node.remove()
}
Array.from(node.childNodes).forEach((child) => _filter(renderer, child as Element, arguments[2]))
return node
}
|