def test_multiple_runs(self): document_xml = ''' <p> <hyperlink id="foobar"> <r> <t>l</t> <t>i</t> <t>n</t> <t>k</t> </r> </hyperlink> <r> <t>.</t> </r> </p> ''' document = WordprocessingDocumentFactory() document_rels = document.relationship_format.format( id='foobar', type='foo/hyperlink', target='http://google.com', target_mode='External', ) document.add(MainDocumentPart, document_xml, document_rels) expected_html = '<p><a href="http://google.com">link</a>.</p>' self.assert_document_generates_html(document, expected_html)
def test_styles_are_ignored(self): style_xml = ''' <style styleId="heading1" type="paragraph"> <name val="Heading 1"/> <rPr> <b val="on"/> <caps val="on"/> <smallCaps val="on"/> <strike val="on"/> <dstrike val="on"/> </rPr> </style> ''' document_xml = ''' <p> <pPr> <pStyle val="heading1"/> </pPr> <fldSimple instr="FOO bar"> <r> <t>AAA</t> </r> </fldSimple> </p> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, style_xml) document.add(MainDocumentPart, document_xml) expected_html = ''' <h1>AAA</h1> ''' self.assert_document_generates_html(document, expected_html)
def test_multiple_runs(self): document_xml = ''' <p> <fldSimple instr="HYPERLINK http://www.google.com"> <r> <rPr> <b /> </rPr> <t>AAA</t> </r> <r> <rPr> <i /> </rPr> <t>BBB</t> </r> </fldSimple> </p> ''' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = ''' <p> <a href="http://www.google.com"> <strong>AAA</strong> <em>BBB</em> </a> </p> ''' self.assert_document_generates_html(document, expected_html)
def test_character_style_referenced_by_paragraph_is_ignored(self): style_xml = ''' <style styleId="foo" type="character"> <rPr> <b val="on"/> </rPr> </style> ''' document_xml = ''' <p> <pPr> <pStyle val="foo"/> </pPr> <r> <t>aaa</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, style_xml) document.add(MainDocumentPart, document_xml) expected_html = '<p>aaa</p>' self.assert_document_generates_html(document, expected_html)
def test_entity_blowup(self): try: import defusedxml except ImportError: defusedxml = None if defusedxml is None: raise SkipTest('This test case only applies when using defusedxml') document_xml = ''' <p> <r> <t>&a;</t> </r> </p> ''' xml_header = '''<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xml [ <!ENTITY a "123"> ]> ''' document = WordprocessingDocumentFactory(xml_header=xml_header) document.add(MainDocumentPart, document_xml) expected_html = '<p>123</p>' try: self.assert_document_generates_html(document, expected_html) raise AssertionError( 'Expected "EntitiesForbidden" exception did not occur', ) except defusedxml.EntitiesForbidden: pass
def test_textbox_with_content(self): document_xml = ''' <p> <r> <pict> <shape> <textbox> <txbxContent> <p> <r> <t>AAA</t> </r> </p> </txbxContent> </textbox> </shape> </pict> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = ''' <p> <p> AAA </p> </p> ''' self.assert_document_generates_html(document, expected_html)
def test_no_sub_detected_because_local_size_larger_than_pStyle_size(self): document_xml = ''' <p> <pPr> <pStyle val="faked_subscript"/> </pPr> <r> <t>H</t> </r> <r> <rPr> <position val="-8"/> <sz val="30"/> </rPr> <t>2</t> </r> <r> <t>O</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, self.style_xml) document.add(MainDocumentPart, document_xml) expected_html = '<p>H2O</p>' self.assert_document_generates_html(document, expected_html)
def test_basedon_ignored_for_character_based_on_paragraph(self): # character styles may only be based on other character styles # otherwise, the based on specification should be ignored style_xml = ''' <style styleId="one" type="paragraph"> <rPr> <b val="on"/> </rPr> </style> <style styleId="two" type="character"> <basedOn val="one"/> <rPr> <i val="on"/> </rPr> </style> ''' document_xml = ''' <p> <r> <rPr> <rStyle val="two"/> </rPr> <t>aaa</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, style_xml) document.add(MainDocumentPart, document_xml) expected_html = '<p><em>aaa</em></p>' self.assert_document_generates_html(document, expected_html)
def test_instr_missing_target(self): document_xml = ''' <p> <r><t>Link: </t></r> <r> <fldChar fldCharType="begin"/> </r> <r> <instrText> HYPERLINK </instrText> </r> <r> <fldChar fldCharType="separate"/> </r> <r> <t>AAA</t> </r> <r> <fldChar fldCharType="end"/> </r> <r><t>.</t></r> </p> ''' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = '<p>Link: AAA.</p>' self.assert_document_generates_html(document, expected_html)
def test_no_sup_detected_for_size_set_in_rPrChange(self): # Test for issue #116 document_xml = ''' <p> <pPr> <pStyle val="faked_superscript"/> </pPr> <r> <t>n</t> </r> <r> <rPr> <position val="8"/> <rPrChange id="1" author="john" date="2015-02-10T14:33:00Z"> <sz val="19"/> </rPrChange> </rPr> <t>th</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, self.style_xml) document.add(MainDocumentPart, document_xml) expected_html = '<p>nth</p>' self.assert_document_generates_html(document, expected_html)
def test_spanning_single_paragraph(self): document_xml = ''' <p> <r><t>Link: </t></r> <r> <fldChar fldCharType="begin"/> </r> <r> <instrText> HYPERLINK "http://www.google.com/"</instrText> </r> <r> <fldChar fldCharType="separate"/> </r> <r> <t>AAA</t> </r> <r> <fldChar fldCharType="end"/> </r> <r><t>.</t></r> </p> ''' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = '<p>Link: <a href="http://www.google.com/">AAA</a>.</p>' self.assert_document_generates_html(document, expected_html)
def test_missing_fld_char_end(self): # According to 17.16.18, "If a complex field is not closed before the # end of a document story, then no field shall be generated and each # individual run shall be processed as if the field characters did not # exist" document_xml = ''' <p> <r><t>Link: </t></r> <r> <fldChar fldCharType="begin"/> </r> <r> <instrText> HYPERLINK "http://www.google.com/"</instrText> </r> <r> <fldChar fldCharType="separate"/> </r> <r> <t>AAA</t> </r> <r><t>.</t></r> </p> ''' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = '<p>Link: AAA.</p>' self.assert_document_generates_html(document, expected_html)
def test_choice_is_ignored(self): document_xml = ''' <AlternateContent> <Choice> <p> <r> <t>Ignored</t> </r> </p> </Choice> <Fallback> <p> <r> <t>AAA</t> </r> </p> </Fallback> </AlternateContent> ''' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = ''' <p>AAA</p> ''' self.assert_document_generates_html(document, expected_html)
def test_global_run_paragraph_and_character_styles(self): style_xml = ''' <style styleId="foo" type="paragraph"> <rPr> <b val="on"/> </rPr> </style> <style styleId="bar" type="character"> <rPr> <i val="on"/> </rPr> </style> ''' document_xml = ''' <p> <pPr> <pStyle val="foo"/> </pPr> <r> <rPr> <rStyle val="bar"/> </rPr> <t>aaa</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, style_xml) document.add(MainDocumentPart, document_xml) expected_html = '<p><em><strong>aaa</strong></em></p>' self.assert_document_generates_html(document, expected_html)
def test_run_paragraph_mark_style_is_not_used_as_run_style(self): style_xml = ''' <style styleId="foo" type="paragraph"> <pPr> <rPr> <b val="on"/> </rPr> </pPr> </style> ''' document_xml = ''' <p> <pPr> <pStyle val="foo"/> </pPr> <r> <t>aaa</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, style_xml) document.add(MainDocumentPart, document_xml) expected_html = '<p>aaa</p>' self.assert_document_generates_html(document, expected_html)
def test_sup_detected_pStyle_has_larger_size_and_positive_position(self): document_xml = ''' <p> <pPr> <pStyle val="faked_superscript"/> </pPr> <r> <t>n</t> </r> <r> <rPr> <position val="8"/> <sz val="19"/> </rPr> <t>th</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, self.style_xml) document.add(MainDocumentPart, document_xml) expected_html = '<p>n<sup>th</sup></p>' self.assert_document_generates_html(document, expected_html)
def test_with_bookmark_option(self): document_xml = ''' <p> <r><t>Link: </t></r> <r> <fldChar fldCharType="begin"/> </r> <r> <instrText> HYPERLINK "http://www.google.com/" \\l awesome</instrText> </r> <r> <fldChar fldCharType="separate"/> </r> <r> <t>AAA</t> </r> <r> <fldChar fldCharType="end"/> </r> <r><t>.</t></r> </p> ''' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = '<p>Link: <a href="http://www.google.com/#awesome">AAA</a>.</p>' self.assert_document_generates_html(document, expected_html)
def test_no_sup_because_position_is_zero(self): document_xml = ''' <p> <pPr> <pStyle val="faked_superscript"/> </pPr> <r> <t>n</t> </r> <r> <rPr> <position val="0"/> <sz val="19"/> </rPr> <t>th</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, self.style_xml) document.add(MainDocumentPart, document_xml) expected_html = '<p>nth</p>' self.assert_document_generates_html(document, expected_html)
def test_unsupported_instr_content_is_not_ignored(self): document_xml = ''' <p> <r><t>AAA</t></r> <r> <fldChar fldCharType="begin"/> </r> <r> <instrText> FOOBAR baz</instrText> </r> <r> <fldChar fldCharType="separate"/> </r> <r> <t>BBB</t> </r> <r> <fldChar fldCharType="end"/> </r> <r><t>CCC</t></r> </p> ''' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = '<p>AAABBBCCC</p>' self.assert_document_generates_html(document, expected_html)
def test_sub_detected_pStyle_has_smaller_size_and_negative_position(self): document_xml = ''' <p> <pPr> <pStyle val="faked_subscript"/> </pPr> <r> <t>H</t> </r> <r> <rPr> <position val="-8"/> <sz val="19"/> </rPr> <t>2</t> </r> <r> <t>O</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, self.style_xml) document.add(MainDocumentPart, document_xml) expected_html = '<p>H<sub>2</sub>O</p>' self.assert_document_generates_html(document, expected_html)
def test_multiple_runs_with_styles(self): document_xml = ''' <p> <r> <rPr> <b /> </rPr> <t>Foo-</t> </r> <r> <rPr> <b /> </rPr> <t>Bar</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = ''' <p> <strong>Foo-</strong> <strong>Bar</strong> </p> ''' self.assert_document_generates_html(document, expected_html)
def test_style_chain_ends_when_loop_is_detected(self): style_xml = ''' <style styleId="one"> <basedOn val="three"/> <rPr> <b val="on"/> </rPr> </style> <style styleId="two"> <basedOn val="one"/> </style> <style styleId="three"> <basedOn val="two"/> </style> ''' document_xml = ''' <p> <pPr> <pStyle val="three"/> </pPr> <r> <t>aaa</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, style_xml) document.add(MainDocumentPart, document_xml) expected_html = '<p><strong>aaa</strong></p>' self.assert_document_generates_html(document, expected_html)
def test_no_runs_no_text(self): document_xml = '<p></p>' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = '' self.assert_document_generates_html(document, expected_html)
def test_invalid_vals_do_not_create_strong(self): vals = [ 'foo', 'bar', ] paragraph_template = ''' <p> <r> <rPr> <b val="%s" /> </rPr> <t>foo</t> </r> </p> ''' document_xml = ''.join( paragraph_template % val for val in vals ) document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = ''' <p>foo</p> <p>foo</p> ''' self.assert_document_generates_html(document, expected_html)
def test_single_multi_styled_whitespace_in_text_run_is_preserved(self): document_xml = ''' <p> <r> <t>Foo</t> </r> <r> <rPr> <b /> <i /> <u val="single"/> <caps /> <smallCaps /> <dstrike /> <strike /> <webHidden /> <vanish /> </rPr> <t> </t> </r> <r> <t>Bar</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = '<p>Foo Bar</p>' self.assert_document_generates_html(document, expected_html)
def test_blip_embed_refers_to_undefined_image_relationship(self): # Ensure that if a blip embed refers to an undefined image # relationshipp, the image rendering is skipped document_xml = ''' <p> <r> <t>Foo</t> <drawing> <anchor> <graphic> <graphicData> <pic> <blipFill> <blip embed="foobar" /> </blipFill> </pic> </graphicData> </graphic> </anchor> </drawing> <t>Bar</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = '<p>FooBar</p>' self.assert_document_generates_html(document, expected_html)
def test_heading_with_bookmark(self): document_xml = ''' <p> <pPr> <pStyle val="heading1"/> </pPr> <bookmarkStart name="testing"/> <bookmarkEnd/> <r> <t>aaa</t> </r> </p> ''' style_xml = ''' <style styleId="heading1" type="paragraph"> <name val="Heading 1"/> </style> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, style_xml) document.add(MainDocumentPart, document_xml) expected_html = '<h1 id="testing">aaa</h1>' self.assert_document_generates_html(document, expected_html)
def test_empty_head(self): document_xml = '<p><r><t>Foo</t></r></p>' document = WordprocessingDocumentFactory() document.add(MainDocumentPart, document_xml) expected_html = '<html><body><p>Foo</p></body></html>' self.assert_document_generates_html(document, expected_html)
def test_each_heading_level(self): style_template = ''' <style styleId="heading%s" type="paragraph"> <name val="Heading %s"/> </style> ''' style_xml = ''.join( style_template % (i, i) for i in range(1, 11) ) paragraph_template = ''' <p> <pPr> <pStyle val="%s"/> </pPr> <r> <t>%s</t> </r> </p> ''' style_to_text = [ ('heading1', 'aaa'), ('heading2', 'bbb'), ('heading3', 'ccc'), ('heading4', 'ddd'), ('heading5', 'eee'), ('heading6', 'fff'), ('heading7', 'ggg'), ('heading8', 'hhh'), ('heading9', 'iii'), ('heading10', 'jjj'), ] document_xml = ''.join( paragraph_template % entry for entry in style_to_text ) document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, style_xml) document.add(MainDocumentPart, document_xml) expected_html = ''' <h1>aaa</h1> <h2>bbb</h2> <h3>ccc</h3> <h4>ddd</h4> <h5>eee</h5> <h6>fff</h6> <h6>ggg</h6> <h6>hhh</h6> <h6>iii</h6> <h6>jjj</h6> ''' self.assert_document_generates_html(document, expected_html)
def test_heading_as_list_following_bare_paragraph_plus_list(self): style_xml = ''' <style styleId="heading1" type="paragraph"> <name val="Heading 1"/> </style> ''' numbering_xml = ''' <num numId="1"> <abstractNumId val="1"/> </num> <abstractNum abstractNumId="1"> <lvl ilvl="0"> <numFmt val="decimal"/> </lvl> </abstractNum> ''' document_xml = ''' <p> <pPr> <numPr> <ilvl val="0" /> <numId val="1" /> </numPr> </pPr> <r> <t>foo</t> </r> </p> <p><r><t>bare paragraph</t></r></p> <p> <pPr> <pStyle val="heading1"/> <numPr> <ilvl val="0" /> <numId val="1" /> </numPr> </pPr> <r> <t>bar</t> </r> </p> ''' document = WordprocessingDocumentFactory() document.add(StyleDefinitionsPart, style_xml) document.add(NumberingDefinitionsPart, numbering_xml) document.add(MainDocumentPart, document_xml) expected_html = ''' <ol class="pydocx-list-style-type-decimal"> <li>foo<br />bare paragraph</li> <li><strong>bar</strong></li> </ol> ''' self.assert_document_generates_html(document, expected_html)