Commits

Luke Plant committed 4aa46d7

Return StructureItem objects in extract_structure instead of tuples

Includes client side changes - using objects instead of arrays,
and using StructureItem.sect_id instead of .name

  • Participants
  • Parent commits d03643a

Comments (0)

Files changed (4)

File semanticeditor/media/semanticeditor/javascript/wymeditor/plugins/semantic/wymeditor.semantic.js

     this.name = wym._element.get(0).name;
     // available_styles: an array of dictionaries corresponding to PresentationInfo objects
     this.available_styles = new Array();
-    // stored_headings: an array of 2 elements arrays, [heading level, heading name]
+    // stored_headings: array of StructureItem objects (attributes .level, .name, .sect_id, .tag)
     this.stored_headings = new Array();
     // active_heading_list - a possibly filtered version of stored_headings
     this.active_heading_list = new Array();
-    // presentation_info: a dictionary of { heading name : [PresentationInfo] }
+    // presentation_info: a dictionary of { sect_id : [PresentationInfo] }
     this.presentation_info = {};
 
     this.setup_controls(jQuery(wym._box).find(".wym_area_bottom"));
 	return;
     }
     var headingIndex = parseInt(selected, 10);
-    var heading = this.active_heading_list[headingIndex][1];
-    var styles = this.presentation_info[heading];
+    var sect_id = this.active_heading_list[headingIndex].sect_id;
+    var styles = this.presentation_info[sect_id];
     if (styles == null) {
 	styles = new Array();
-	this.presentation_info[heading] = styles;
+	this.presentation_info[sect_id] = styles;
     }
     this.optsbox.find("input").each(
 	function(i, input) {
 	    jQuery(this).change(function(event) {
 				    var style = expandPresStyle(input.value);
 				    if (input.checked) {
-					self.add_style(heading, style);
+					self.add_style(sect_id, style);
 				    } else {
-					self.remove_style(heading, style);
+					self.remove_style(sect_id, style);
 				    }
 				    self.headingscontrol.get(0).focus();
 			 });
     return false;
 };
 
-PresentationControls.prototype.add_style = function(heading, presinfo) {
-    var styles = this.presentation_info[heading];
+PresentationControls.prototype.add_style = function(sect_id, presinfo) {
+    var styles = this.presentation_info[sect_id];
     styles.push(presinfo);
-    this.presentation_info[heading] = jQuery.unique(styles);
+    this.presentation_info[sect_id] = jQuery.unique(styles);
 };
 
-PresentationControls.prototype.remove_style = function(heading, presinfo) {
-    var styles = this.presentation_info[heading];
+PresentationControls.prototype.remove_style = function(sect_id, presinfo) {
+    var styles = this.presentation_info[sect_id];
     styles = jQuery.grep(styles, function(item, i) {
 			     return !(item.prestype == presinfo.prestype
 				      && item.name == presinfo.name);
 			 });
-    this.presentation_info[heading] = styles;
+    this.presentation_info[sect_id] = styles;
 };
 
 // If data contains an error message, display to the user,
     if (this.headingsfilter.get(0).checked) {
 	items = jQuery.grep(self.stored_headings,
                             function(item, idx) {
-				return (item[2].toUpperCase()).match(/H\d/);
+				return (item.tag.toUpperCase()).match(/H\d/);
 			    });
     } else {
 	items = self.stored_headings;
     this.unbind_optsbox();
     this.headingscontrol.empty();
     jQuery.each(this.active_heading_list, function(i, item) {
-		    // item[0] is the heading level,
-		    // item[1] is the heading name
-		    var spaces = (new Array((item[0]-1)*3)).join(" ");
-		    self.headingscontrol.append("<option value='" + i.toString() + "'>" + spaces + item[2].toLowerCase() + ": " + escapeHtml(item[1]) + "</option>");
+		    var spaces = (new Array((item.level - 1)*3)).join("&nbsp;");
+		    self.headingscontrol.append("<option value='" + i.toString() + "'>" + spaces + item.tag.toLowerCase() + ": " + escapeHtml(item.name) + "</option>");
     });
 };
 

File semanticeditor/tests.py

 
 from django.test import TestCase
 from semanticeditor.utils import extract_structure, InvalidHtml, IncorrectHeadings, format_html, parse, get_parent, get_index, BadStructure, TooManyColumns, NEWROW, NEWCOL, extract_presentation, get_structure
-from semanticeditor.utils.presentation import PresentationInfo, PresentationClass
+from semanticeditor.utils.presentation import PresentationInfo, PresentationClass, StructureItem
 
 PC = PresentationClass
 
-class TestStructure(TestCase):
-    """
-    Tests for how the structure is extracted and labelled
-    """
-    def test_use_existing_sect_ids(self):
-        html = "<h1 id='h1_10'>Hi</h1><h1>There</h1>"
-        structure = get_structure(parse(html))
-        self.assertEqual(structure[0].sect_id, "h1_10")
-        self.assertEqual(structure[1].sect_id, "h1_1")
-
 class TestExtractStructure(TestCase):
     def test_extract_structure(self):
-        self.assertEqual(extract_structure("""
+        self.assertEqual([(s.level, s.sect_id, s.name, s.tag) for s in extract_structure("""
 <h1>Heading <b>with </b><i>embedded <em>stuff</em> in</i> it</h1> Hmm
 <p>A long paragraph with some actual content</p>
 <h2>A sub heading</h2>
 <p>nasty  éééééééééééééééééééééééééé</p>
 <h6>level 6</h6>
 <h1>Heading two</h1>
-"""), [(1, u"Heading with embedded stuff in it", u"H1"),
-       (2, u"A long paragraph wit...", u"P"),
-       (2, u"A sub heading", u"H2"),
-       (3, u"Another para...", u"P"),
-       (3, u"level 3", u"H3"),
-       (4, u"A long paragraph wit...2", u"P"),
-       (4, u"level 4", u"H4"),
-       (5, u"Another para...2", u"P"),
-       (5, u"level 5", u"H5"),
-       (6, u"nasty  ééééééééééééé...", u"P"),
-       (6, u"level 6", u"H6"),
-       (1, u"Heading two", u"H1"),
-       ])
+""")],
+        [(1, "h1_1", u"Heading with embedded stuff in it", u"H1"),
+         (2, "p_1", u"A long paragraph wit...", u"P"),
+         (2, "h2_1", u"A sub heading", u"H2"),
+         (3, "p_2", u"Another para...", u"P"),
+         (3, "h3_1", u"level 3", u"H3"),
+         (4, "p_3", u"A long paragraph wit...2", u"P"),
+         (4, "h4_1", u"level 4", u"H4"),
+         (5, "p_4", u"Another para...2", u"P"),
+         (5, "h5_1", u"level 5", u"H5"),
+         (6, "p_5", u"nasty  ééééééééééééé...", u"P"),
+         (6, "h6_1", u"level 6", u"H6"),
+         (1, "h1_2", u"Heading two", u"H1"),
+         ])
 
     def test_extract_structure_missing(self):
         self.assertEqual(extract_structure("Hello"), [])
     def test_rejects_duplicate_headings(self):
         self.assertRaises(IncorrectHeadings, extract_structure, "<h1>Hello</h1><h2>Hello</h2>")
 
+    def test_use_existing_sect_ids(self):
+        html = "<h1 id='h1_10'>Hi</h1><h1>There</h1>"
+        structure = get_structure(parse(html))
+        self.assertEqual(structure[0].sect_id, "h1_10")
+        self.assertEqual(structure[1].sect_id, "h1_1")
+
 class TestPresentationInfo(TestCase):
     def test_equality(self):
         p1 = PresentationInfo(prestype="command", name="foo", verbose_name="blah")

File semanticeditor/utils/presentation.py

     # Parse
     tree = parse(content)
     structure = get_structure(tree, assert_structure=True)
-    return [(s.level, s.name, s.tag) for s in structure]
+    return structure
 
 # == Formatting HTML ==
 #

File semanticeditor/views.py

         return failure(e.args[0])
     return success(val)
 
+def SI_to_dict(si):
+    """
+    Convert a StructureItem to dictionary for use client side
+    """
+    return dict((k,v) for k,v in si.__dict__.items() if k != 'node')
+
 @json_view
 def extract_structure_view(request):
     data = request.POST.get('html','').encode("utf-8")
-    return graceful_errors(AllUserErrors, lambda: extract_structure(data))
+    def _handled():
+        return map(SI_to_dict, extract_structure(data))
+    return graceful_errors(AllUserErrors, _handled)
 
 def PI_to_dict(pi):
     """
     return pi.__dict__
 
 def dict_to_PI(d):
+    """
+    Convert a dictionary to a PresentationInfo
+    """
     return PresentationInfo(prestype=d['prestype'], name=d['name'])
 
 @json_view