Repository: django-wiki/django-wiki

Issue:
Tables aren't responsive
Bootstrap has a .table-responsive class that tables can be wrapped in to enable horizontal scrolling on small devices for big tables. 

http://getbootstrap.com/css/#tables-responsive



Discussion:
Great find!! That's definitely missing!


Resolving patch:
diff --git a/wiki/core/markdown/__init__.py b/wiki/core/markdown/__init__.py
--- a/wiki/core/markdown/__init__.py
+++ b/wiki/core/markdown/__init__.py
@@ -2,6 +2,7 @@
 
 from wiki.conf import settings
 from wiki.core.markdown.mdx.previewlinks import PreviewLinksExtension
+from wiki.core.markdown.mdx.responsivetable import ResponsiveTableExtension
 from wiki.core.plugins import registry as plugin_registry
 import markdown
 
@@ -17,7 +18,7 @@ def __init__(self, article, preview=False, *args, **kwargs):
 
     def core_extensions(self):
         """List of core extensions found in the mdx folder"""
-        return [PreviewLinksExtension()]
+        return [PreviewLinksExtension(), ResponsiveTableExtension()]
 
     def get_markdown_extensions(self):
         kwargs = settings.MARKDOWN_KWARGS
diff --git a/wiki/core/markdown/mdx/responsivetable.py b/wiki/core/markdown/mdx/responsivetable.py
new file mode 100644
--- /dev/null
+++ b/wiki/core/markdown/mdx/responsivetable.py
@@ -0,0 +1,41 @@
+from __future__ import absolute_import, unicode_literals
+
+import markdown
+from markdown.util import etree
+from markdown.treeprocessors import Treeprocessor
+
+
+class ResponsiveTableExtension(markdown.Extension):
+    """Wraps all tables with Bootstrap's table-responsive class"""
+
+    def extendMarkdown(self, md, md_globals):
+        md.treeprocessors.add('responsivetable', ResponsiveTableTree(md), "_end")
+
+
+class ResponsiveTableTree(Treeprocessor):
+    def run(self, root):
+        for table_wrapper in list(root.getiterator('table')):
+            table_new = self.create_table_element()
+            self.convert_to_wrapper(table_wrapper)
+            self.move_children(table_wrapper, table_new)
+            table_wrapper.append(table_new)
+        return root
+
+    def create_table_element(self):
+        """Create table element with text and tail"""
+        element = etree.Element('table')
+        element.text = '\n'
+        element.tail = '\n'
+        return element
+
+    def move_children(self, element1, element2):
+        """Moves children from element1 to element2"""
+        for child in element1.getchildren():
+            element2.append(child)
+        # reversed is needed to safely remove items while iterating
+        for child in reversed(element1.getchildren()):
+            element1.remove(child)
+
+    def convert_to_wrapper(self, element):
+        element.tag = 'div'
+        element.set('class', 'table-responsive')


Test patch:
diff --git a/wiki/tests/test_markdown.py b/wiki/tests/test_markdown.py
new file mode 100644
--- /dev/null
+++ b/wiki/tests/test_markdown.py
@@ -0,0 +1,18 @@
+from __future__ import absolute_import, unicode_literals
+
+from django.test import TestCase
+import markdown
+from wiki.core.markdown.mdx.responsivetable import ResponsiveTableExtension
+
+class ResponsiveTableTests(TestCase):
+    def setUp(self):
+        self.md = markdown.Markdown(extensions=[
+            'extra',
+            ResponsiveTableExtension()
+        ])
+        self.md_without = markdown.Markdown(extensions=['extra'])
+
+    def test_wrapping(self):
+        text = '|th|th|\n|--|--|\n|td|td|'
+        expected = '<div class="table-responsive">\n' + self.md_without.convert(text) + '\n</div>'
+        self.assertEqual(self.md.convert(text), expected)