private static function buildHtml(&$html, $tag_object, $options, $tab = 0)
    {
        self::checkBuildOptions($options);

        $tag_is_special = in_array($tag_object->getTag(), self::$special_tags);
        $tag_is_ignored = in_array($tag_object->getTag(), array_get($options, 'ignore_tags', []));

        $ignore_tag = true;
        if (!isset($options['ignore_tags']) || !$tag_is_ignored) {
            $ignore_tag = false;
        } elseif (isset($options['ignore_tags']) && $tag_is_ignored) {
            $tab--;
        }

        $pad = '';
        if ($tab > 0) {
            $pad = str_pad($pad, $tab * 2, ' ', STR_PAD_LEFT);
        }

        if (!$ignore_tag) {
            if ($tag_is_special) {
                $html .= $pad.trim((string) $tag_object)."\n";
            } elseif (!$tag_is_special) {
                $html .= $pad;
                $html .= '<'.$tag_object->tag.''.self::buildHtmlAttribute($tag_object->getAttributes()).'>';
                $html .= ($tag_object->use_whitespace) ? "\n" : '';
                if (strlen($tag_object->getText())) {
                    $html .= ($tag_object->use_whitespace) ? $pad.'  ' : '';
                    $html .= $tag_object->getText();
                }
                $html .= ($tag_object->use_whitespace && strlen($tag_object->getText())) ? "\n" : '';
            }
        }

        if (!$tag_is_special && $tag_object->hasChildNodes()) {
            foreach ($tag_object->getChildNodes() as $child_tag_object) {
                self::buildHtml($html, $child_tag_object, $options, $tab + 1);
            }
        }

        $pad = '';
        if ($tab > 0) {
            $pad = str_pad($pad, $tab * 2, ' ', STR_PAD_LEFT);
        }

        if (!$ignore_tag && !$tag_is_special) {
            $html .= ($tag_object->use_whitespace) ? $pad : '';
            $html .= '</'.$tag_object->tag.'>'."\n";
        }
    }