Luke Plant avatar Luke Plant committed 82579db

Added BadStructure for badly formed columns

Comments (0)

Files changed (2)

semanticeditor/tests.py

         html = "<h1>1</h1><p>para 1</p><h1>2</h1><h1>3</h1>"
         self.assertRaises(BadStructure, format_html, html, {'2':[NEWCOL]})
 
+    def test_columns_nested_newcols(self):
+        """
+        Check that attempting to add columns at a different level
+        will generate an error
+        """
+        html = "<h1>1</h1><h2>1.1</h2><h1>2</h1>"
+        self.assertRaises(BadStructure, format_html, html, {'1':[NEWROW],
+                                                            '1.1':[NEWCOL]})
+    def test_columns_nested_newrow(self):
+        """
+        Check that attempting to add new row at a different level
+        will generate an error
+        """
+        html = "<h1>1</h1><h2>1.1</h2>"
+        self.assertRaises(BadStructure, format_html, html, {'1':[NEWROW],
+                                                            '1.1':[NEWROW]})
+
 
 class TestElementTreeUtils(TestCase):
     def test_get_parent(self):

semanticeditor/utils/presentation.py

 <p>Use this command to start a new row.</p>
 
 <p>This must be used in conjunction with 'New column'
-to create a column layout.</p>.
+to create a column layout.</p>
 
 <p>Please note that new rows and columns cannot be started at any
 point in the document.  Within a given row, new columns can only be
 is required and subsequent headings of the same level may be given
 a 'New column' command.</p>
 
+<p>If you wish to stop an existing column layout for a section, then you will
+need to apply a 'New row' command to that section, creating a row with
+just one column in it.</p>
+
 """)
 
 NEWCOL = PresentationCommand('newcol',
     # TODO: due to HTML/CSS quirks, we may need to add an empty <div
     # class="rowclear"> after every <div class="row">
 
+def _assert_no_column_structure(node, known_nodes, styleinfo, current_level):
+    # Check that no NEWROW/NEWCOL commands are found in the *children*
+    # of node
+    for n in node.getiterator():
+        if n == node:
+            continue
+        name = known_nodes.get(n)
+        if name is not None:
+            commands = styleinfo[name]
+            if NEWROW in commands or NEWCOL in commands:
+                raise BadStructure("Heading '%(heading)s' has a 'New row' or 'New column' command applied to "
+                                   "it, but it is at a section level %(level)s, which is lower than current "
+                                   "column structure, which is defined at level %(curlevel)s." %
+                                   dict(heading=name, level=n[0].tag, curlevel=current_level))
+
+
 def _add_rows_and_columns(topnode, known_nodes, styleinfo):
     cur_row_start = None
     cur_col = None
             else:
                 columns.append((idx + idx_offset, name))
 
-        if not cur_row_start:
-            # Rows/columns can only be added within the same level of nesting
-            # of the HTML document.  This means we do not need to recurse if
-            # we have started adding rows/columns.
+        if cur_row_start:
+            # Rows/columns can only be added within the same level of
+            # nesting of the HTML document.  This means we do not need
+            # to recurse if we have started adding rows/columns.
+            # However, it is helpful to recurse and check that no
+            # NEWROW/COL commands were found, and complain to the user
+            # if they are.
+            _assert_no_column_structure(node, known_nodes, styleinfo,
+                                        cur_row_start[0].tag)
+        else:
             _add_rows_and_columns(node, known_nodes, styleinfo)
-            # However, it would be good to recurse and check that no
-            # NEWROW/COL commands were found, and warn the user if
-            # they are.
 
         # If we are at last node, and are still in a row, there won't
         # be a NEWROW command, so we have to close implicitly,
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.