Luke Plant avatar Luke Plant committed bfb23c1

Fixed issue #27 - paragraphs containing only plugins should be auto-converted to divs

Comments (0)

Files changed (2)

semanticeditor/tests.py

 from django.test import TestCase
 from semanticeditor.utils import *
 
+
 PC = PresentationClass
 
 class TestExtractStructure(TestCase):
         structure = get_structure(parse(html))
         self.assertEqual(["h1_1", "h1_4", "h1_2", "h1_3"], [s.sect_id for s in structure])
 
+
 class TestPresentationInfo(TestCase):
     def test_equality(self):
         p1 = PresentationInfo(prestype="command", name="foo", verbose_name="blah")
         self.assertNotEqual(p2, p3)
         self.assertEqual(set([p1]), set([p2]))
 
+
 class TestFormat(TestCase):
     def setUp(self):
         # monkey patch to ensure some assumptions we make about LayoutDetails.
         pres, html3 = extract_presentation(html2)
         self.assertEqual(html, html3)
 
+
 class TestHacks(TestCase):
     def test_div_format_hack(self):
+        """
+        Check that we can convert 'p' tags into 'div' using the 'div' class hack
+        """
         html = '<p>Test</p>'
         outh = '<div class=\"row\"><div><div><div class="div">Test</div></div></div></div>'
         self.assertEqual(outh, format_html(html, {'p_1':[PC('div')]}))
 
     def test_div_extract_hack(self):
+        """
+        Check that a div with class "div" is recognised and turned back into a 'p'
+        when extracting
+        """
         html = '<div class="div">Test</div>'
         pres, html2 = extract_presentation(html)
         self.assertEqual({'p_1':set([PC('div')])}, pres)
         self.assertEqual('<p id="p_1">Test</p>', html2);
 
+    def test_plugin_p_hack(self):
+        """
+        Check that a 'p' with only a plugin object is converted to a 'div'
+        """
+        # NB: current implementation of plugin objects is that they are
+        # represented by an image in the editor.  Our code has to run before
+        # these are converted, so we have to work with this implementation detail.
+        html = '<p> <img src="blah" id="plugin_obj_123"/></p>'
+        outh = '<div class="row"><div><div><div class="div"> <img src="blah" id="plugin_obj_123"/></div></div></div></div>'
+        self.assertEqual(outh, format_html(html, {}))
+
+    def test_plugin_p_hack_empty_only(self):
+        """
+        Check that if 'p' has any text in it, it is not converted
+        """
+        html = '<p>X <img src="blah" id="plugin_obj_123" /></p>'
+        outh = '<div class="row"><div><div><p>X <img src="blah" id="plugin_obj_123"/></p></div></div></div>'
+        self.assertEqual(outh, format_html(html, {}))
+        html2 = '<p> <img src="blah" id="plugin_obj_123" />X</p>'
+        outh2 = '<div class="row"><div><div><p> <img src="blah" id="plugin_obj_123"/>X</p></div></div></div>'
+        self.assertEqual(outh2, format_html(html2, {}))
+
+
 class TestElementTreeUtils(TestCase):
     def test_get_parent(self):
         """
         t = parse("<a><b1></b1><b2></b2></a>")
         n = t.find(".//b2")
         p = get_parent(t, n)
-        self.assertEqual(1, get_index(p,n))
+        self.assertEqual(1, get_index(p, n))
 
     def test_eliminate_tag_1(self):
         t = ET.fromstring("<a>Hello<b>Goodbye</b>End</a>")
         pres2, html2 = extract_presentation(html)
         self.assertEqual(pres, pres2)
 
+
 class TestHtmlCleanup(TestCase):
     safari_example_1 = """
 <p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.8em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-size: 0.9em; line-height: 1.4em; "><strong style="font-weight: bold; ">Formerly: Community Health Sciences Research (CHSR) IRG</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.8em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-size: 0.9em; line-height: 1.4em; ">The Clinical Epidemiology IRG aims to undertake research that makes an important difference to patient care. Our work is divided into two broad research areas:</p><h4 style="color: rgb(153, 0, 51); margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-size: 1.1em; line-height: 1.3em; "><strong style="font-weight: bold; ">Clinical and environmental epidemiology -</strong>&#160;including</h4><ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.5em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.4em; font-size: 0.9em; "><li style="margin-top: 0px; margin-right: 0px;margin-bottom: 0.25em; margin-left: 20px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px;padding-left: 0px; ">mental health</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 20px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">child protection</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 20px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px;">cancer</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 20px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">environmental, economic and social risk factors</li></ul></span>

semanticeditor/utils/presentation.py

         for n in tree.getiterator():
             if n.tag == 'p' and ('div' in _get_classes_for_node(n)):
                 n.tag = 'div'
+            if n.tag == 'p':
+                # If only child element is a plugin object, convert to
+                # a div.
+                # NB: current implementation of plugin objects is that they
+                # are represented by an image in the editor.  Our code has to
+                # run before these are converted, so we have to work with this
+                # implementation detail.
+                children = n.getchildren()
+                if ((n.text is None or n.text.strip() == "")
+                    and len(children) == 1
+                    and children[0].tag == "img"
+                    and (children[0].tail is None or children[0].tail.strip() == "")
+                    and children[0].attrib.get('id', '').startswith("plugin_obj")):
+                        n.tag = 'div'
+                        # Add 'div' to list of classes
+                        # This handles the reverse transform for us:
+                        n.attrib['class'] = ' '.join(n.attrib.get('class', '').split(' ') + ['div']).strip()
         return tree
 
     def extract_post_parse_hacks(self, tree):
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.