"""
GLAMWalk -- Volume 4: Libraries & Archives
03_html_to_text_converter.py

A complete, stdlib-only HTML-to-plain-text converter built by subclassing HTMLParser -- no third-party library required.

Source: Volume Four, Section 1.3 -- Converting HTML to Plain Text
Targets Python 3.11.4 -- see Volume One, Chapter 1.5/1.6.
"""

from html.parser import HTMLParser
import re

class TextExtractor(HTMLParser):
    BLOCK_TAGS = {"p", "div", "br", "h1", "h2", "h3", "li", "blockquote"}
    SKIP_TAGS = {"script", "style", "head"}

    def __init__(self):
        super().__init__()          # let the real HTMLParser set itself up first
        self._skip_depth = 0
        self.parts = []

    def handle_starttag(self, tag, attrs):
        if tag in self.SKIP_TAGS:
            self._skip_depth += 1
        elif tag in self.BLOCK_TAGS:
            self.parts.append("\n")  # a paragraph/heading/etc. starts a new line

    def handle_endtag(self, tag):
        if tag in self.SKIP_TAGS and self._skip_depth > 0:
            self._skip_depth -= 1

    def handle_data(self, data):
        if self._skip_depth == 0:    # ignore text inside <script>/<style>
            self.parts.append(data)

def html_to_text(html_str):
    parser = TextExtractor()
    parser.feed(html_str)
    text = "".join(parser.parts)
    return re.sub(r"\n{3,}", "\n\n", text).strip()   # collapse excess blank lines
