class HtmlTextExtractor implements DocumentTransformer {

    private final String cssSelector;
    private final Map<String, String> metadataCssSelectors;
    private final boolean includeLinks;

    /**
     * Constructs an instance of HtmlToTextTransformer that extracts all text from a given Document containing HTML.
     */
    public HtmlTextExtractor() {
        this(null, null, false);
    }

    /**
     * Constructs an instance of HtmlToTextTransformer that extracts text from HTML elements matching the provided CSS selector.
     *
     * @param cssSelector          A CSS selector.
     *                             For example, "#page-content" will extract text from the HTML element with the id "page-content".
     * @param metadataCssSelectors A mapping from metadata keys to CSS selectors.
     *                             For example, Mep.of("title", "#page-title") will extract all text from the HTML element
     *                             with id "title" and store it in {@link Metadata} under the key "title".
     * @param includeLinks         Specifies whether links should be included in the extracted text.
     */
    public HtmlTextExtractor(String cssSelector, Map<String, String> metadataCssSelectors, boolean includeLinks) {
        this.cssSelector = cssSelector;
        this.metadataCssSelectors = metadataCssSelectors;
        this.includeLinks = includeLinks;
    }

    @Override
    public Document transform(Document document) {<FILL_FUNCTION_BODY>}

    private static String extractText(org.jsoup.nodes.Document jsoupDocument, String cssSelector, boolean includeLinks) {
        return jsoupDocument.select(cssSelector).stream()
                .map(element -> extractText(element, includeLinks))
                .collect(joining("\n\n"));
    }

    private static String extractText(Element element, boolean includeLinks) {
        NodeVisitor visitor = new TextExtractingVisitor(includeLinks);
        traverse(visitor, element);
        return visitor.toString().trim();
    }

    // taken from https://github.com/jhy/jsoup/blob/master/src/main/java/org/jsoup/examples/HtmlToPlainText.java
    private static class TextExtractingVisitor implements NodeVisitor {

        private final StringBuilder textBuilder = new StringBuilder();
        private final boolean includeLinks;

        private TextExtractingVisitor(boolean includeLinks) {
            this.includeLinks = includeLinks;
        }

        @Override
        public void head(Node node, int depth) { // hit when the node is first seen
            String name = node.nodeName();
            if (node instanceof TextNode)
                textBuilder.append(((TextNode) node).text());
            else if (name.equals("li"))
                textBuilder.append("\n * ");
            else if (name.equals("dt"))
                textBuilder.append("  ");
            else if (in(name, "p", "h1", "h2", "h3", "h4", "h5", "h6", "tr"))
                textBuilder.append("\n");
        }

        @Override
        public void tail(Node node, int depth) { // hit when all the node's children (if any) have been visited
            String name = node.nodeName();
            if (in(name, "br", "dd", "dt", "p", "h1", "h2", "h3", "h4", "h5", "h6"))
                textBuilder.append("\n");
            else if (includeLinks && name.equals("a"))
                textBuilder.append(format(" <%s>", node.absUrl("href")));
        }

        @Override
        public String toString() {
            return textBuilder.toString();
        }
    }
}

        String html = document.text();
        org.jsoup.nodes.Document jsoupDocument = Jsoup.parse(html);

        String text;
        if (cssSelector != null) {
            text = extractText(jsoupDocument, cssSelector, includeLinks);
        } else {
            text = extractText(jsoupDocument, includeLinks);
        }

        Metadata metadata = document.metadata().copy();
        if (metadataCssSelectors != null) {
            metadataCssSelectors.forEach((metadataKey, cssSelector) ->
                    metadata.add(metadataKey, jsoupDocument.select(cssSelector).text()));
        }

        return Document.from(text, metadata);
    
<no_super_class>