Repository: matthewwithanm/python-markdownify (python)

Issue:
Custom converter functions are not recognized for heading tags
When creating custom converters with MarkdownConverter for specific tags, all converters for `h1`-`h6` headings are ignored, and headings are processed according to the standard converter options.

```html
<h1>This is a heading</h1>
<p>This is a paragraph</p>
```

```python
class FixMarkup(MarkdownConverter):
    def convert_h1(self, el, text, parent_tags):
        return 'Heading override'

def md(html, **options):
    return FixMarkup(**options).convert(html)

markdown = md(html, heading_style='ATX')
```

**Expected output:**

```markdown
Heading override

This is a paragraph
```

**Actual output:**

```markdown
# This is a heading

This is a paragraph
```

Pull request:
Ensure that explicitly provided heading conversion functions are used (#212)
Fixes #212.

The precedence of conversion function lookup is modified so that explicitly defined heading conversion functions (such as `convert_h3()`) take precedence over general heading conversion functions (processed by `convert_hN()`).

Unit tests are added for both cases.

Patch:
diff --git a/markdownify/__init__.py b/markdownify/__init__.py
index 780761c..c732711 100644
--- a/markdownify/__init__.py
+++ b/markdownify/__init__.py
@@ -363,16 +363,20 @@ class MarkdownConverter(object):
         if not self.should_convert_tag(tag_name):
             return None
 
-        # Handle headings with convert_hN() function
+        # Look for an explicitly defined conversion function by tag name first
+        convert_fn_name = "convert_%s" % re_make_convert_fn_name.sub("_", tag_name)
+        convert_fn = getattr(self, convert_fn_name, None)
+        if convert_fn:
+            return convert_fn
+
+        # If tag is any heading, handle with convert_hN() function
         match = re_html_heading.match(tag_name)
         if match:
-            n = int(match.group(1))
+            n = int(match.group(1))  # get value of N from <hN>
             return lambda el, text, parent_tags: self.convert_hN(n, el, text, parent_tags)
 
-        # For other tags, look up their conversion function by tag name
-        convert_fn_name = "convert_%s" % re_make_convert_fn_name.sub('_', tag_name)
-        convert_fn = getattr(self, convert_fn_name, None)
-        return convert_fn
+        # No conversion function was found
+        return None
 
     def should_convert_tag(self, tag):
         """Given a tag name, return whether to convert based on strip/convert options."""
@@ -650,6 +654,9 @@ class MarkdownConverter(object):
 
         return '\n\n```%s\n%s\n```\n\n' % (code_language, text)
 
+    def convert_q(self, el, text, parent_tags):
+        return '"' + text + '"'
+
     def convert_script(self, el, text, parent_tags):
         return ''
 


Test patch:
diff --git a/tests/test_conversions.py b/tests/test_conversions.py
index 27951ee..6145411 100644
--- a/tests/test_conversions.py
+++ b/tests/test_conversions.py
@@ -305,6 +305,11 @@ def test_pre():
     assert md("<p>foo</p>\n<pre>bar</pre>\n</p>baz</p>", sub_symbol="^") == "\n\nfoo\n\n```\nbar\n```\n\nbaz"
 
 
+def test_q():
+    assert md('foo <q>quote</q> bar') == 'foo "quote" bar'
+    assert md('foo <q cite="https://example.com">quote</q> bar') == 'foo "quote" bar'
+
+
 def test_script():
     assert md('foo <script>var foo=42;</script> bar') == 'foo  bar'
 
diff --git a/tests/test_custom_converter.py b/tests/test_custom_converter.py
index 26faf90..00a83fc 100644
--- a/tests/test_custom_converter.py
+++ b/tests/test_custom_converter.py
@@ -14,8 +14,12 @@ class UnitTestConverter(MarkdownConverter):
         """Ensure conversion function is found for tags with special characters in name"""
         return "convert_custom_tag(): %s" % text
 
+    def convert_h1(self, el, text, parent_tags):
+        """Ensure explicit heading conversion function is used"""
+        return "convert_h1: %s" % (text)
+
     def convert_hN(self, n, el, text, parent_tags):
-        """Ensure conversion function is found for headings"""
+        """Ensure general heading conversion function is used"""
         return "convert_hN(%d): %s" % (n, text)
 
 
@@ -29,6 +33,8 @@ def test_custom_conversion_functions():
 
     assert md("<custom-tag>text</custom-tag>") == "convert_custom_tag(): text"
 
+    assert md("<h1>text</h1>") == "convert_h1: text"
+
     assert md("<h3>text</h3>") == "convert_hN(3): text"