Помогите улучшить парсер html

Возможно, вопрос задан не совсем корректно, так что поясню. Я написал класс для редактирования html. Он еще не закончен, но не суть. В нем есть метод, который делает из строки html массив объектов с иерархической структурой, как в этом считанном html отрывке. Прошу помощи у более опытных разработчиков в улучшении этого парсера. Приму любые комментарии, отвечу на все вопросы. Пишу чисто в учебных целях, так что пояснения будут большим плюсом. Заранее спасибо всем откликнувшимся.

class HTMLEditor {
    constructor(html) {
        this.html = html;
        this.obj = [];

        this.tag = '';
        this.paramKey = '';
        this.paramVal = '';
        this.paramFlag = true;
        this.text = '';

        this.state = '';
        this.depth = 0;

        this.elem = {};
        this.directory = [
            'area',
            'base',
            'br',
            'col',
            'hr',
            'img',
            'input',
            'link',
            'meta',
            'param',
        ]
    }
    reset (html) {
        this.html = html;
        this.tag = '';
        this.paramKey = '';
        this.paramVal = '';
        this.paramFlag = true; // true значит читаем ключ иначе читаем значение
        this.text = '';

        this.state = '';
        this.depth = 0;

        this.elem = {};
    }
    HTMLPrinter () {
        const printChild = (child) => {
            child.forEach(ch => {
                for (let param in ch.params) {
                    ch.self.setAttribute(param, ch.params[param]);
                }
                ch.parent.self.append(ch.self);
                if (ch.children) {
                    printChild (ch.children);
                }
            });
        }
        try {
            if (!document.querySelector('debug')) {
                const div = document.createElement('div');
                div.classList = 'debug';
                document.querySelector('body').append(div);
            }
            this.obj.forEach((item) => {
                for (let param in item.params) {
                    item.self.setAttribute(param, item.params[param]);
                    console.log(item.self[param]);
                }

                if (item.parent) {
                    item.parent.self.append(item.self);
                } else {
                    document.querySelector('.debug').append(item.self);
                }
                printChild(item.children);
                console.log(item);
            });
        } catch (e) {
            console.log(e);
        }
    }
    HTMLParser () {
        let parents = [];
        let quote  = '';

        for (var i = 0; i < this.html.length; i++) {
            if (this.html[i] === '<') {
                this.text = this.text.replace('\\n').trim();
                if (this.text) {
                    this.elem = {
                        'parent': parents[this.depth - 1],
                        'children': null,
                        'params': {},
                        'self' : this.text,
                    };
                    if (parents[this.depth - 1]) {
                        parents[this.depth - 1].children.push(this.elem);
                    }
                }

                this.state = 'rTag';
                this.tag = '';
            } else if (this.html[i] === '>') {
                if (this.state === 'rTag') {
                    try {
                        this.elem = {
                            'parent': null,
                            'children': [],
                            'params': {
                            },
                            'self' : null,
                        };

                        this.elem.self = document.createElement(this.tag);
                        parents[this.depth] = this.elem;

                        if (this.depth === 0) {
                            this.obj.push(this.elem);
                        } else {

                            this.elem.parent = parents[this.depth - 1];
                            this.elem.parent.children.push(this.elem);
                        }

                        let flag = this.directory.some((el) => {
                            return this.tag === el;
                        });
                        if (!flag) this.depth++;


                    } catch (e) {
                        console.log("error, maybe the depth was -1", e);
                    }
                }
                this.state = 'rTex';
                this.text = '';
                this.paramVal = this.paramVal || true;
                if (this.paramKey) {
                    this.elem.params[this.paramKey] = this.paramVal;
                }
                this.paramKey = '';
                this.paramVal = '';
                this.paramFlag = true;
            } else if (this.html[i] === ' ') {
                if (this.state === 'rTex') {

                    this.text += this.html[i];
                }
                if (this.state === 'rPar') {

                    if (this.paramFlag) {
                        this.paramVal = this.paramVal || true;
                        if (this.paramKey) {
                            this.elem.params[this.paramKey] = this.paramVal;
                        }
                        this.paramKey = '';
                        this.paramVal = '';
                        this.paramFlag = true;
                    } else {
                        this.paramVal += this.html[i];
                    }
                }
                if (this.state === 'rTag') {
                    try {
                        this.elem = {
                            'parent': null,
                            'children': [],
                            'params': {
                            },
                            'self' : null,
                        };

                        this.elem.self = document.createElement(this.tag);
                        parents[this.depth] = this.elem;

                        if (this.depth === 0) {
                            this.obj.push(this.elem);
                        } else {

                            this.elem.parent = parents[this.depth - 1];
                            this.elem.parent.children.push(this.elem);
                        }

                        this.state = 'rPar';
                        this.param = '';
                        let flag = this.directory.some((el) => {
                            return this.tag === el;
                        });
                        if (!flag) this.depth++;


                    } catch (e) {
                        console.log("error, maybe the depth was -1", e);
                    }
                }
            } else if (this.paramFlag && this.html[i] === '/') {
                this.state = 'cTag';
                this.depth--;
                parents.pop();
            } else {
                switch (this.state) {
                    case 'rTag':
                        this.tag += this.html[i];
                        break;
                    case 'rPar':
                        try {
                            if (this.paramFlag && this.html[i] === "=") {
                                i++;
                                if (this.html[i] === "\"" || this.html[i] === "\'" || this.html[i] === "\`") {
                                    this.paramFlag = !this.paramFlag;
                                    quote = this.html[i];
                                } else {
                                    throw "unexpected space, quote was expected";
                                }
                            } else if (!this.paramFlag && this.html[i] === quote) {
                                this.paramFlag = !this.paramFlag;
                            } else {
                                if (this.paramFlag) {
                                    this.paramKey += this.html[i];
                                } else {
                                    this.paramVal += this.html[i];
                                }
                            }
                        } catch (e) {
                            console.log(e);
                        }
                        break;
                    case 'rTex':
                        this.text += this.html[i];
                        break;
                }
            }
        }
    }
}
const str = `
<section class="popUp hide put">
    <form class="TaskGen f f_col f_c" >
        <textarea class="input" name="task" rows="8" cols="80">Разобрать входящие</textarea>
        <input class="input" type="text" name="processig" value="Бессрочно">
        <input class="input" type="text" name="complite" value="Бессрочно">
        <input class="input" type="hidden" name="CreateTime" value="">
        <button class="button" type="button" name="sendTask">Создать</button>
    </form>
</section>
`;
const editor = new HTMLEditor(str);
editor.HTMLParser();
editor.HTMLPrinter();

Ответы (0 шт):