• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import { html, type TreeAdapter, type TreeAdapterTypeMap, type Token } from 'parse5';
2
3function getSerializedTreeIndent(indent: number): string {
4    return '|'.padEnd(indent + 2, ' ');
5}
6
7function getElementSerializedNamespaceURI<T extends TreeAdapterTypeMap>(
8    element: T['element'],
9    treeAdapter: TreeAdapter<T>
10): string {
11    switch (treeAdapter.getNamespaceURI(element)) {
12        case html.NS.SVG:
13            return 'svg ';
14        case html.NS.MATHML:
15            return 'math ';
16        default:
17            return '';
18    }
19}
20
21function serializeNodeList<T extends TreeAdapterTypeMap>(
22    nodes: T['node'][],
23    indent: number,
24    treeAdapter: TreeAdapter<T>
25): string {
26    let str = '';
27
28    for (let node of nodes) {
29        str += getSerializedTreeIndent(indent);
30
31        if (treeAdapter.isCommentNode(node)) {
32            str += `<!-- ${treeAdapter.getCommentNodeContent(node)} -->\n`;
33        } else if (treeAdapter.isTextNode(node)) {
34            str += `"${treeAdapter.getTextNodeContent(node)}"\n`;
35        } else if (treeAdapter.isDocumentTypeNode(node)) {
36            const publicId = treeAdapter.getDocumentTypeNodePublicId(node);
37            const systemId = treeAdapter.getDocumentTypeNodeSystemId(node);
38
39            str += `<!DOCTYPE ${treeAdapter.getDocumentTypeNodeName(node) || ''}`;
40
41            if (publicId || systemId) {
42                str += ` "${publicId}" "${systemId}"`;
43            }
44
45            str += '>\n';
46        } else {
47            const tn = treeAdapter.getTagName(node);
48
49            str += `<${getElementSerializedNamespaceURI(node, treeAdapter) + tn}>\n`;
50
51            let childrenIndent = indent + 2;
52            const serializedAttrs = treeAdapter.getAttrList(node).map((attr: Token.Attribute) => {
53                let attrStr = getSerializedTreeIndent(childrenIndent);
54
55                if (attr.prefix) {
56                    attrStr += `${attr.prefix} `;
57                }
58
59                attrStr += `${attr.name}="${attr.value}"\n`;
60
61                return attrStr;
62            });
63
64            str += serializedAttrs.sort().join('');
65
66            if (tn === html.TAG_NAMES.TEMPLATE && treeAdapter.getNamespaceURI(node) === html.NS.HTML) {
67                str += `${getSerializedTreeIndent(childrenIndent)}content\n`;
68                childrenIndent += 2;
69                node = treeAdapter.getTemplateContent(node);
70            }
71
72            str += serializeNodeList(treeAdapter.getChildNodes(node), childrenIndent, treeAdapter);
73        }
74    }
75
76    return str;
77}
78
79export function serializeToDatFileFormat<T extends TreeAdapterTypeMap>(
80    rootNode: T['parentNode'],
81    treeAdapter: TreeAdapter<T>
82): string {
83    return serializeNodeList(treeAdapter.getChildNodes(rootNode), 0, treeAdapter);
84}
85