prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  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."
  
  </issue>
  <code>
  [start of bookwyrm/sanitize_html.py]
  1 ''' html parser to clean up incoming text from unknown sources '''
  2 from html.parser import HTMLParser
  3 
  4 class InputHtmlParser(HTMLParser):#pylint: disable=abstract-method
  5     ''' Removes any html that isn't allowed_tagsed from a block '''
  6 
  7     def __init__(self):
  8         HTMLParser.__init__(self)
  9         self.allowed_tags = [
  10             'p', 'br',
  11             'b', 'i', 'strong', 'em', 'pre',
  12             'a', 'span', 'ul', 'ol', 'li'
  13         ]
  14         self.tag_stack = []
  15         self.output = []
  16         # if the html appears invalid, we just won't allow any at all
  17         self.allow_html = True
  18 
  19 
  20     def handle_starttag(self, tag, attrs):
  21         ''' check if the tag is valid '''
  22         if self.allow_html and tag in self.allowed_tags:
  23             self.output.append(('tag', self.get_starttag_text()))
  24             self.tag_stack.append(tag)
  25         else:
  26             self.output.append(('data', ''))
  27 
  28 
  29     def handle_endtag(self, tag):
  30         ''' keep the close tag '''
  31         if not self.allow_html or tag not in self.allowed_tags:
  32             self.output.append(('data', ''))
  33             return
  34 
  35         if not self.tag_stack or self.tag_stack[-1] != tag:
  36             # the end tag doesn't match the most recent start tag
  37             self.allow_html = False
  38             self.output.append(('data', ''))
  39             return
  40 
  41         self.tag_stack = self.tag_stack[:-1]
  42         self.output.append(('tag', '</%s>' % tag))
  43 
  44 
  45     def handle_data(self, data):
  46         ''' extract the answer, if we're in an answer tag '''
  47         self.output.append(('data', data))
  48 
  49 
  50     def get_output(self):
  51         ''' convert the output from a list of tuples to a string '''
  52         if self.tag_stack:
  53             self.allow_html = False
  54         if not self.allow_html:
  55             return ''.join(v for (k, v) in self.output if k == 'data')
  56         return ''.join(v for (k, v) in self.output)
  57
  [end of bookwyrm/sanitize_html.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/bookwyrm/sanitize_html.py b/bookwyrm/sanitize_html.py
  --- a/bookwyrm/sanitize_html.py
  +++ b/bookwyrm/sanitize_html.py
  @@ -7,7 +7,7 @@
       def __init__(self):
           HTMLParser.__init__(self)
           self.allowed_tags = [
  -            'p', 'br',
  +            'p', 'blockquote', 'br',
               'b', 'i', 'strong', 'em', 'pre',
               'a', 'span', 'ul', 'ol', 'li'
           ]
  
verification_info: {"golden_diff": "diff --git a/bookwyrm/sanitize_html.py b/bookwyrm/sanitize_html.py\n--- a/bookwyrm/sanitize_html.py\n+++ b/bookwyrm/sanitize_html.py\n@@ -7,7 +7,7 @@\n     def __init__(self):\n         HTMLParser.__init__(self)\n         self.allowed_tags = [\n-            'p', 'br',\n+            'p', 'blockquote', 'br',\n             'b', 'i', 'strong', 'em', 'pre',\n             'a', 'span', 'ul', 'ol', 'li'\n         ]\n", "issue": "Feature request - block quote formatting in reviews\nI 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:\r\n\r\n```\r\n> \"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.\"\r\n```\r\n\r\nBut 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!\r\n\r\nI would expect it to render more like it does here on Github:\r\n\r\n> \"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.\"\n", "before_files": [{"content": "''' html parser to clean up incoming text from unknown sources '''\nfrom html.parser import HTMLParser\n\nclass InputHtmlParser(HTMLParser):#pylint: disable=abstract-method\n    ''' Removes any html that isn't allowed_tagsed from a block '''\n\n    def __init__(self):\n        HTMLParser.__init__(self)\n        self.allowed_tags = [\n            'p', 'br',\n            'b', 'i', 'strong', 'em', 'pre',\n            'a', 'span', 'ul', 'ol', 'li'\n        ]\n        self.tag_stack = []\n        self.output = []\n        # if the html appears invalid, we just won't allow any at all\n        self.allow_html = True\n\n\n    def handle_starttag(self, tag, attrs):\n        ''' check if the tag is valid '''\n        if self.allow_html and tag in self.allowed_tags:\n            self.output.append(('tag', self.get_starttag_text()))\n            self.tag_stack.append(tag)\n        else:\n            self.output.append(('data', ''))\n\n\n    def handle_endtag(self, tag):\n        ''' keep the close tag '''\n        if not self.allow_html or tag not in self.allowed_tags:\n            self.output.append(('data', ''))\n            return\n\n        if not self.tag_stack or self.tag_stack[-1] != tag:\n            # the end tag doesn't match the most recent start tag\n            self.allow_html = False\n            self.output.append(('data', ''))\n            return\n\n        self.tag_stack = self.tag_stack[:-1]\n        self.output.append(('tag', '</%s>' % tag))\n\n\n    def handle_data(self, data):\n        ''' extract the answer, if we're in an answer tag '''\n        self.output.append(('data', data))\n\n\n    def get_output(self):\n        ''' convert the output from a list of tuples to a string '''\n        if self.tag_stack:\n            self.allow_html = False\n        if not self.allow_html:\n            return ''.join(v for (k, v) in self.output if k == 'data')\n        return ''.join(v for (k, v) in self.output)\n", "path": "bookwyrm/sanitize_html.py"}]}