import * as htmlparser from "htmlparser2" export interface HTMLTag extends ElementStructure { name: string attrs: { [index: string]: string } type: "element" } export interface HTMLText extends ElementStructure { content: string type: "text" } export interface ElementStructure { type: "element" | "text" | "style" | "script" children: ElementStructure[] } export function parseHTMLStructure(content: string): ElementStructure[] { let root: HTMLTag = { type: "element", children: [], attrs: {}, name: "root" } let stack = [] let cur: ElementStructure = root let parser = new htmlparser.Parser({ onopentag: (name, attrs) => { let el: HTMLTag el = { type: "element", attrs, children: [], name } as HTMLTag cur.children.push(el) stack.push(cur) cur = el }, ontext: (text: string) => { cur.children.push({ type: "text", content: text, children: null } as ElementStructure) }, onclosetag: () => { cur = stack.pop() } }, { decodeEntities: true }) parser.end(content) return root.children } export function structureToString(s: ElementStructure) { if (s.type === "text") return s["content"] let result = "" for (let child of s["children"] || []) { result += structureToString(child) } return result }