''' html parser to clean up incoming text from unknown sources '''
from html.parser import HTMLParser

class InputHtmlParser(HTMLParser):#pylint: disable=abstract-method
    ''' Removes any html that isn't allowed_tagsed from a block '''

    def __init__(self):
        HTMLParser.__init__(self)
        self.allowed_tags = [
            'p', 'br',
            'b', 'i', 'strong', 'em', 'pre',
            'a', 'span', 'ul', 'ol', 'li'
        ]
        self.tag_stack = []
        self.output = []
        # if the html appears invalid, we just won't allow any at all
        self.allow_html = True


    def handle_starttag(self, tag, attrs):
        ''' check if the tag is valid '''
        if self.allow_html and tag in self.allowed_tags:
            self.output.append(('tag', self.get_starttag_text()))
            self.tag_stack.append(tag)
        else:
            self.output.append(('data', ''))


    def handle_endtag(self, tag):
        ''' keep the close tag '''
        if not self.allow_html or tag not in self.allowed_tags:
            self.output.append(('data', ''))
            return

        if not self.tag_stack or self.tag_stack[-1] != tag:
            # the end tag doesn't match the most recent start tag
            self.allow_html = False
            self.output.append(('data', ''))
            return

        self.tag_stack = self.tag_stack[:-1]
        self.output.append(('tag', '</%s>' % tag))


    def handle_data(self, data):
        ''' extract the answer, if we're in an answer tag '''
        self.output.append(('data', data))


    def get_output(self):
        ''' convert the output from a list of tuples to a string '''
        if self.tag_stack:
            self.allow_html = False
        if not self.allow_html:
            return ''.join(v for (k, v) in self.output if k == 'data')
        return ''.join(v for (k, v) in self.output)

bookwyrm/sanitize_html.py
''' html parser to clean up incoming text from unknown sources '''
from html.parser import HTMLParser

class InputHtmlParser(HTMLParser):#pylint: disable=abstract-method
    ''' Removes any html that isn't allowed_tagsed from a block '''

    def __init__(self):
        HTMLParser.__init__(self)
        self.allowed_tags = [
            'p', 'blockquote', 'br',
            'b', 'i', 'strong', 'em', 'pre',
            'a', 'span', 'ul', 'ol', 'li'
        ]
        self.tag_stack = []
        self.output = []
        # if the html appears invalid, we just won't allow any at all
        self.allow_html = True


    def handle_starttag(self, tag, attrs):
        ''' check if the tag is valid '''
        if self.allow_html and tag in self.allowed_tags:
            self.output.append(('tag', self.get_starttag_text()))
            self.tag_stack.append(tag)
        else:
            self.output.append(('data', ''))


    def handle_endtag(self, tag):
        ''' keep the close tag '''
        if not self.allow_html or tag not in self.allowed_tags:
            self.output.append(('data', ''))
            return

        if not self.tag_stack or self.tag_stack[-1] != tag:
            # the end tag doesn't match the most recent start tag
            self.allow_html = False
            self.output.append(('data', ''))
            return

        self.tag_stack = self.tag_stack[:-1]
        self.output.append(('tag', '</%s>' % tag))


    def handle_data(self, data):
        ''' extract the answer, if we're in an answer tag '''
        self.output.append(('data', data))


    def get_output(self):
        ''' convert the output from a list of tuples to a string '''
        if self.tag_stack:
            self.allow_html = False
        if not self.allow_html:
            return ''.join(v for (k, v) in self.output if k == 'data')
        return ''.join(v for (k, v) in self.output)

bookwyrm/sanitize_html.py
diff --git a/bookwyrm/sanitize_html.py b/bookwyrm/sanitize_html.py
index de13ede853..be7fb56fdc 100644
--- a/bookwyrm/sanitize_html.py
+++ b/bookwyrm/sanitize_html.py
@@ -7,7 +7,7 @@ class InputHtmlParser(HTMLParser):#pylint: disable=abstract-method
     def __init__(self):
         HTMLParser.__init__(self)
         self.allowed_tags = [
-            'p', 'br',
+            'p', 'blockquote', 'br',
             'b', 'i', 'strong', 'em', 'pre',
             'a', 'span', 'ul', 'ol', 'li'
         ]

Feature request - block quote formatting in reviews
I published [a review](https://bookwyrm.social/user/darius/review/14497) just now with a markdown-style block quote in it. The second-to-last paragraph is formatted, at least when I wrote it in the dialog box, like this:

```
> "I was expecting to go to prison for the rest of my life," Ellsberg wryly said later, "and Ithiel wanted to know whether I understood that I'd never get another dollar from the federal government."
```

But it renders as regular text. I'm guessing a lot of reviewers will want to excerpt their books, so block quotes seem like a good thing to include!

I would expect it to render more like it does here on Github:

> "I was expecting to go to prison for the rest of my life," Ellsberg wryly said later, "and Ithiel wanted to know whether I understood that I'd never get another dollar from the federal government."
