Commits

Luke Plant  committed 1b630ea

Fixed some bugs with column creation

  • Participants
  • Parent commits 79458b1

Comments (0)

Files changed (2)

File semanticeditor/tests.py

 # -*- coding: utf-8 -*-
 
 from django.test import TestCase
-from semanticeditor.utils import extract_headings, InvalidHtml, IncorrectHeadings, format_html, parse, get_parent, get_index, BadStructure, NEWROW, NEWCOL
+from semanticeditor.utils import extract_headings, InvalidHtml, IncorrectHeadings, format_html, parse, get_parent, get_index, BadStructure, TooManyColumns, NEWROW, NEWCOL
 
 class TestExtract(TestCase):
     def test_extract_headings(self):
         self.assertEqual(outh, format_html(html, {'1':[NEWROW],
                                                   '2':[NEWCOL]}))
 
+    def test_max_cols(self):
+        html = "<h1>1</h1><h1>2</h1><h1>3</h1><h1>4</h1><h1>5</h1>"
+        self.assertRaises(TooManyColumns, format_html, html, {'1':[NEWROW],
+                                                              '2':[NEWCOL],
+                                                              '3':[NEWCOL],
+                                                              '4':[NEWCOL],
+                                                              '5':[NEWCOL]
+                                                            })
+
+    def test_creates_section_divs_2(self):
+        html = \
+            "<h1>1</h1>" \
+            "<h1>2</h1>" \
+            "<h2>2.1</h2>" \
+            "<h2>2.2</h2>" \
+            "<h2>2.3</h2>" \
+            "<h2>2.4</h2>" \
+            "<h1>3</h1>" \
+            "<h1>4</h1>"
+
+        outh = \
+            "<div><h1>1</h1></div>" \
+            "<div><h1>2</h1>" \
+            "<div><h2>2.1</h2></div>" \
+            "<div><h2>2.2</h2></div>" \
+            "<div><h2>2.3</h2></div>" \
+            "<div><h2>2.4</h2></div>" \
+            "</div>" \
+            "<div><h1>3</h1></div>" \
+            "<div><h1>4</h1></div>"
+        self.assertEqual(outh, format_html(html, {}))
+
+
+    def test_columns_2(self):
+        html = \
+            "<h1>1</h1>" \
+            "<h1>2</h1>" \
+            "<h2>2.1</h2>" \
+            "<h2>2.2</h2>" \
+            "<h2>2.3</h2>" \
+            "<h2>2.4</h2>" \
+            "<h1>3</h1>" \
+            "<h1>4</h1>"
+
+        outh = \
+            "<div><h1>1</h1></div>" \
+            "<div><h1>2</h1>" \
+            "<div class=\"row2col\">" \
+            "<div class=\"col\">" \
+            "<div><h2>2.1</h2></div>" \
+            "</div>" \
+            "<div class=\"col\">" \
+            "<div><h2>2.2</h2></div>" \
+            "</div>" \
+            "</div>" \
+            "<div class=\"row2col\">" \
+            "<div class=\"col\">" \
+            "<div><h2>2.3</h2></div>" \
+            "</div>" \
+            "<div class=\"col\">" \
+            "<div><h2>2.4</h2></div>" \
+            "</div>" \
+            "</div>" \
+            "</div>" \
+            "<div class=\"row2col\">" \
+            "<div class=\"col\">" \
+            "<div><h1>3</h1></div>" \
+            "</div>" \
+            "<div class=\"col\">" \
+            "<div><h1>4</h1></div>" \
+            "</div>" \
+            "</div>"
+        self.assertEqual(outh, format_html(html, {'2.1':[NEWROW],
+                                                  '2.2':[NEWCOL],
+                                                  '2.3':[NEWROW],
+                                                  '2.4':[NEWCOL],
+                                                  '3':[NEWROW],
+                                                  '4':[NEWCOL],
+                                                  }))
+
     def test_columns_missing_newrow(self):
         html = "<h1>1</h1><p>para 1</p><h1>2</h1><h1>3</h1>"
         self.assertRaises(BadStructure, format_html, html, {'2':[NEWCOL]})

File semanticeditor/utils.py

 class BadStructure(ValueError):
     pass
 
+class TooManyColumns(BadStructure):
+    pass
+
 headingdef = ['h1','h2','h3','h4','h5','h6']
 NEWROW = 'command:newrow'
 NEWCOL = 'command:newcolumn'
 
+MAXCOLS = 4
+
 def _is_command(x):
     return x.startswith('command:')
 
 def _add_rows_and_columns(topnode, known_nodes, styleinfo):
     cur_row_start = None
     cur_col = None
-    children = topnode.getchildren()
+    children = list(topnode.getchildren())
+    # Offset used to cope with the fact that we are pulling sub-nodes
+    # out of topnode as we go along.
+    idx_offset = 0
     for idx, node in enumerate(children):
         name = known_nodes.get(node)
         if name is None:
         if NEWROW in commands:
             if cur_row_start is not None:
                 # The previous row is finished
-                _apply_row_col_divs(topnode, cur_row_start_idx, idx, columns)
-
+                _apply_row_col_divs(topnode, cur_row_start_idx + idx_offset, idx + idx_offset, columns)
+                # We have removed (idx - cur_row_start_idx) elements,
+                # and added one back
+                idx_offset += -(idx - cur_row_start_idx) + 1
             # start a new row
             cur_row_start = node
             cur_row_start_idx = idx
                                    "'%(name)s' without an appropriate 'new row' "
                                    "command before it. " % dict(name=name))
             else:
-                columns.append((idx, node))
+                columns.append((idx + idx_offset, name))
 
         if not cur_row_start:
             # Rows/columns can only be added within the same level of nesting
         # including the current node in the row (hence idx + 1).
         if idx == len(children) - 1 and cur_row_start is not None \
                 and len(columns) > 0:
-                _apply_row_col_divs(topnode, cur_row_start_idx, idx + 1, columns)
+                _apply_row_col_divs(topnode, cur_row_start_idx + idx_offset, idx + 1 + idx_offset, columns)
 
 
 def _apply_row_col_divs(parent, start_idx, stop_idx, columns):
     newrow.set('class', 'row%dcol' % len(columns))
 
     # Add the columns
+    if len(columns) > MAXCOLS:
+        raise TooManyColumns("The maximum number of columns is %(max)d. "
+                             "Please move section '%(name)s' into a new "
+                             "row." % dict(max=MAXCOLS, name=columns[MAXCOLS][1]))
 
     # The idx in 'columns' are all out now, due to having pulled the
     # nodes out. Fix them up, and add a dummy entry to provide the