diff options
| author | Michael Williamson <mike@zwobble.org> | 2015-01-21 19:38:48 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2015-01-21 19:38:48 +0000 |
| commit | 72e5c9810f9ec8f88d62491f37a68abd9927e6fd (patch) | |
| tree | c814868592a084917b8c1e820ba03e9943e59b71 | |
| parent | e3884f135f15a506fd33338c4f127dd706936679 (diff) | |
Operate over a more generic notion of note
| -rw-r--r-- | mammoth/conversion.py | 52 | ||||
| -rw-r--r-- | mammoth/documents.py | 38 | ||||
| -rw-r--r-- | mammoth/docx/document_xml.py | 31 | ||||
| -rw-r--r-- | tests/conversion_tests.py | 10 | ||||
| -rw-r--r-- | tests/docx/document_xml_tests.py | 4 |
5 files changed, 72 insertions, 63 deletions
diff --git a/mammoth/conversion.py b/mammoth/conversion.py index 9eaa3d2..6ef13c8 100644 --- a/mammoth/conversion.py +++ b/mammoth/conversion.py @@ -35,7 +35,7 @@ class DocumentConverter(object): self.messages = [] self._style_map = style_map self._uniquifier = generate_uniquifier() - self._footnote_ids = [] + self._note_references = [] self._converters = { documents.Document: self._convert_document, documents.Paragraph: self._convert_paragraph, @@ -48,8 +48,8 @@ class DocumentConverter(object): documents.TableCell: self._convert_table_cell, documents.LineBreak: self._line_break, documents.Image: convert_image or images.inline(self._convert_image), - documents.FootnoteReference: self._convert_footnote_reference, - documents.Footnote: self._convert_footnote, + documents.NoteReference: self._convert_note_reference, + documents.Note: self._convert_note, } self._convert_underline = convert_underline @@ -62,11 +62,11 @@ class DocumentConverter(object): self._convert_elements_to_html(document.children, html_generator) html_generator.end_all() html_generator.start("ol") - footnotes = [ - document.footnotes.find_footnote_by_id(footnote_id) - for footnote_id in self._footnote_ids + notes = [ + document.notes.resolve(reference) + for reference in self._note_references ] - self._convert_elements_to_html(footnotes, html_generator) + self._convert_elements_to_html(notes, html_generator) html_generator.end() @@ -146,29 +146,29 @@ class DocumentConverter(object): "src": "data:{0};base64,{1}".format(image.content_type, encoded_src) } - def _convert_footnote_reference(self, footnote_reference, html_generator): - uid = self._footnote_uid(footnote_reference.footnote_id) + def _convert_note_reference(self, note_reference, html_generator): + uid = self._note_uid(note_reference.note_id) html_generator.start("sup") html_generator.start("a", { - "href": "#footnote-" + uid, - "id": "footnote-ref-" + uid + "href": "#{0}-{1}".format(note_reference.note_type, uid), + "id": "{0}-ref-{1}".format(note_reference.note_type, uid), }) - self._footnote_ids.append(footnote_reference.footnote_id); - footnote_number = len(self._footnote_ids) - html_generator.text("[{0}]".format(footnote_number)) + self._note_references.append(note_reference); + note_number = len(self._note_references) + html_generator.text("[{0}]".format(note_number)) html_generator.end() html_generator.end() - def _convert_footnote(self, footnote, html_generator): - uid = self._footnote_uid(footnote.id) - html_generator.start("li", {"id": "footnote-{0}".format(uid)}) - footnote_generator = HtmlGenerator() - self._convert_elements_to_html(footnote.body, footnote_generator) - footnote_generator.text(" ") - footnote_generator.start("a", {"href": "#footnote-ref-{0}".format(uid)}) - footnote_generator.text(_up_arrow) - footnote_generator.end_all() - html_generator.append(footnote_generator) + def _convert_note(self, note, html_generator): + uid = self._note_uid(note.id) + html_generator.start("li", {"id": "{0}-{1}".format(note.note_type, uid)}) + note_generator = HtmlGenerator() + self._convert_elements_to_html(note.body, note_generator) + note_generator.text(" ") + note_generator.start("a", {"href": "#{0}-ref-{1}".format(note.note_type, uid)}) + note_generator.text(_up_arrow) + note_generator.end_all() + html_generator.append(note_generator) html_generator.end() @@ -200,8 +200,8 @@ class DocumentConverter(object): return default - def _footnote_uid(self, footnote_id): - return "{0}-{1}".format(self._uniquifier, footnote_id) + def _note_uid(self, note_id): + return "{0}-{1}".format(self._uniquifier, note_id) def _document_matcher_matches(matcher, element, element_type): diff --git a/mammoth/documents.py b/mammoth/documents.py index e7a46c4..9effce8 100644 --- a/mammoth/documents.py +++ b/mammoth/documents.py @@ -1,7 +1,7 @@ import dodge -Document = dodge.data_class("Document", ["children", "footnotes"]) +Document = dodge.data_class("Document", ["children", "notes"]) Paragraph = dodge.data_class("Paragraph", ["children", "style_id", "style_name", "numbering"]) Run = dodge.data_class("Run", [ "children", "style_id", "style_name", "is_bold", "is_italic", @@ -25,10 +25,10 @@ class Image(object): self.open = open -def document(children, footnotes=None): - if footnotes is None: - footnotes = Footnotes({}) - return Document(children, footnotes) +def document(children, notes=None): + if notes is None: + notes = Notes({}) + return Document(children, notes) def paragraph(children, style_id=None, style_name=None, numbering=None): return Paragraph(children, style_id, style_name, numbering) @@ -67,22 +67,32 @@ def numbering_level(level_index, is_ordered): _NumberingLevel = dodge.data_class("NumberingLevel", ["level_index", "is_ordered"]) -footnote = Footnote = dodge.data_class("Footnote", ["id", "body"]) +note = Note = dodge.data_class("Note", ["note_type", "id", "body"]) -class Footnotes(object): - def __init__(self, footnotes): - self._footnotes = footnotes +class Notes(object): + def __init__(self, notes): + self._notes = notes - def find_footnote_by_id(self, id): - return self._footnotes[id] + def find_note(self, note_type, note_id): + return self._notes[(note_type, note_id)] + + def resolve(self, reference): + return self.find_note(reference.note_type, reference.note_id) def __eq__(self, other): - return isinstance(other, Footnotes) and self._footnotes == other._footnotes + return isinstance(other, Notes) and self._notes == other._notes def __ne__(self, other): return not (self == other) -footnotes = Footnotes +def notes(notes_list): + return Notes(dict( + (_note_key(note), note) + for note in notes_list + )) + +def _note_key(note): + return (note.note_type, note.id) -footnote_reference = FootnoteReference = dodge.data_class("FootnoteReference", ["footnote_id"]) +note_reference = NoteReference = dodge.data_class("NoteReference", ["note_type", "note_id"]) diff --git a/mammoth/docx/document_xml.py b/mammoth/docx/document_xml.py index d82dec4..ce035ad 100644 --- a/mammoth/docx/document_xml.py +++ b/mammoth/docx/document_xml.py @@ -23,12 +23,12 @@ def read_document_xml_element(element, content_types=content_types, relationships=relationships, styles=styles, - footnote_elements=footnote_elements, + note_elements=footnote_elements, docx_file=docx_file, ) return reader(element) -def _create_reader(numbering, content_types, relationships, styles, footnote_elements, docx_file): +def _create_reader(numbering, content_types, relationships, styles, note_elements, docx_file): _handlers = {} _ignored_elements = set([ "w:bookmarkStart", @@ -134,20 +134,13 @@ def _create_reader(numbering, content_types, relationships, styles, footnote_ele def document(element): body_element = _find_child(element, "w:body") children_result = _read_xml_elements(body_element.children) - footnotes_result = results.combine(map(_read_footnote, footnote_elements)) - - return results.map( - lambda children, footnotes: documents.document( - children, - documents.footnotes(dict((footnote.id, footnote) for footnote in footnotes)) - ), - children_result, footnotes_result - ) + notes_result = results.combine(map(_read_note, note_elements)).map(documents.notes) + return results.map(documents.document, children_result, notes_result) - def _read_footnote(element): + def _read_note(element): return _read_xml_elements(element.body).map( - lambda body: documents.footnote(element.id, body)) + lambda body: documents.note(element.note_type, element.id, body)) @handler("w:tab") @@ -228,9 +221,15 @@ def _create_reader(numbering, content_types, relationships, styles, footnote_ele image = documents.image(alt_text=alt_text, content_type=content_type, open=open_image) return results.success(image) - @handler("w:footnoteReference") - def footnote_reference(element): - return results.success(documents.footnote_reference(element.attributes["w:id"])) + def note_reference_reader(note_type): + @handler("w:{0}Reference".format(note_type)) + def note_reference(element): + return results.success(documents.note_reference(note_type, element.attributes["w:id"])) + + return note_reference + + note_reference_reader("footnote") + note_reference_reader("endnote") def read(element): handler = _handlers.get(element.name) diff --git a/tests/conversion_tests.py b/tests/conversion_tests.py index 246671d..39c57cd 100644 --- a/tests/conversion_tests.py +++ b/tests/conversion_tests.py @@ -286,7 +286,7 @@ def can_define_custom_conversion_for_images(): @istest def footnote_reference_is_converted_to_superscript_intra_page_link(): - footnote_reference = documents.footnote_reference("4") + footnote_reference = documents.note_reference("footnote", "4") result = convert_document_element_to_html( footnote_reference, generate_uniquifier=lambda: 42 @@ -296,15 +296,15 @@ def footnote_reference_is_converted_to_superscript_intra_page_link(): @istest def footnotes_are_included_after_the_main_body(): - footnote_reference = documents.footnote_reference("4") + footnote_reference = documents.note_reference("footnote", "4") document = documents.document( [documents.paragraph([ _run_with_text("Knock knock"), documents.run([footnote_reference]) ])], - footnotes=documents.Footnotes({ - "4": documents.Footnote("4", [_paragraph_with_text("Who's there?")]) - }) + notes=documents.notes([ + documents.note("footnote", "4", [_paragraph_with_text("Who's there?")]) + ]) ) result = convert_document_element_to_html( document, diff --git a/tests/docx/document_xml_tests.py b/tests/docx/document_xml_tests.py index 8e2cb8d..a0d29b9 100644 --- a/tests/docx/document_xml_tests.py +++ b/tests/docx/document_xml_tests.py @@ -321,7 +321,7 @@ class ReadXmlElementTests(object): document_xml = xml_element("w:document", {}, [body_xml]) document = _read_and_get_document_xml_element(document_xml, footnote_elements=footnotes) - footnote = document.footnotes.find_footnote_by_id("4") + footnote = document.notes.find_note("footnote", "4") assert_equal("4", footnote.id) assert isinstance(footnote.body[0], documents.Paragraph) @@ -329,7 +329,7 @@ class ReadXmlElementTests(object): def footnote_reference_has_id_read(self): footnote_xml = xml_element("w:footnoteReference", {"w:id": "4"}) footnote = _read_and_get_document_xml_element(footnote_xml) - assert_equal("4", footnote.footnote_id) + assert_equal("4", footnote.note_id) @istest def ignored_elements_are_ignored_without_message(self): |
