Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
Release 4.2.0 - unreleased

* The docx parser wraps OMML equations (m:oMath) in <span class="math">; their
text was previously emitted as unmarked body text (TIKA-4968).

* The docx parser links REF, PAGEREF and NOTEREF fields, and in-document
HYPERLINK \l fields, to their bookmarks (<a href="#bookmark">). Fields are now
tracked as a stack, so a field nested in a HYPERLINK field no longer ends the
enclosing link early. Simple fields (w:fldSimple) are now parsed as well, so
HYPERLINK, INCLUDEPICTURE and similar fields written that way are linked or
reported like their complex-field equivalents (TIKA-4967).

* The docx parser now applies bold and italics set by a run's character style
(e.g. Word's built-in Strong and Emphasis), following basedOn chains; previously
only direct formatting was emitted. The new OfficeParserConfig option
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ class FormattingTagManager {

private final XHTMLContentHandler xhtml;

// Outermost to innermost: hyperlink > span > bold > italic > strike > underline
// Outermost to innermost: hyperlink > math > span > bold > italic > strike > underline
private String currentHyperlink = null;
private boolean isMath = false;
private String currentSpanClass = null;
private boolean wrapperHyperlinkActive = false;
private boolean isBold = false;
Expand Down Expand Up @@ -123,7 +124,7 @@ void applyFormatting(RunProperties runProperties, String spanClass) throws SAXEx
}

if (!Objects.equals(spanClass, currentSpanClass)) {
closeInlineTags();
closeStyledTags();
if (spanClass != null) {
xhtml.startElement("span", "class", spanClass);
}
Expand Down Expand Up @@ -195,6 +196,27 @@ void applyFormatting(RunProperties runProperties, String spanClass) throws SAXEx
}
}

/**
* Opens {@code <span class="math">} for an OMML equation. A hyperlink change inside
* the equation closes it.
Comment on lines +200 to +201
*/
void openMath() throws SAXException {
if (isMath) {
return;
}
closeStyledTags();
xhtml.startElement("span", "class", "math");
isMath = true;
}

void closeMath() throws SAXException {
if (isMath) {
closeStyledTags();
xhtml.endElement("span");
isMath = false;
}
}

/**
* Closes all currently open tags in proper nesting order.
*/
Expand All @@ -208,6 +230,11 @@ void closeAll() throws SAXException {
}

private void closeInlineTags() throws SAXException {
closeStyledTags();
closeMath();
}

private void closeStyledTags() throws SAXException {
closeFormattingTags();
if (currentSpanClass != null) {
xhtml.endElement("span");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,16 @@ public void hyperlinkEnd() throws SAXException {
formattingTags.closeHyperlink();
}

@Override
public void startMath() throws SAXException {
formattingTags.openMath();
}

@Override
public void endMath() throws SAXException {
formattingTags.closeMath();
}

@Override
public void startParagraph(ParagraphProperties paragraphProperties) throws SAXException {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ public class OOXMLWordAndPowerPointTextHandler extends DefaultHandler {
"http://schemas.openxmlformats.org/drawingml/2006/main";
private final static String V_NS = "urn:schemas-microsoft-com:vml";
private final static String C_NS = "http://schemas.openxmlformats.org/drawingml/2006/chart";
private final static String M_NS =
"http://schemas.openxmlformats.org/officeDocument/2006/math";
private final static String O_MATH = "oMath";
private final static String OFFICE_DOC_RELATIONSHIP_NS =
"http://schemas.openxmlformats.org/officeDocument/2006/relationships";
private final static char[] TAB_CHAR = new char[]{'\t'};
Expand Down Expand Up @@ -178,6 +181,7 @@ public class OOXMLWordAndPowerPointTextHandler extends DefaultHandler {
private final Deque<FieldFrame> fieldStack = new ArrayDeque<>();
private int hyperlinkElementDepth = 0;
private boolean inInstrText = false;
private int mathDepth = 0;
private EditType editType =
EditType.NONE;

Expand Down Expand Up @@ -273,6 +277,10 @@ public void startElement(String uri, String localName, String qName, Attributes
//yes, I know, likely premature optimization...
if (RPR.equals(localName)) {
inRPr = true;
} else if (O_MATH.equals(localName) && M_NS.equals(uri)) {
if (mathDepth++ == 0) {
bodyContentsHandler.startMath();
}
} else if (R.equals(localName)) {
inR = true;
} else if (T.equals(localName)) {
Expand Down Expand Up @@ -554,6 +562,10 @@ public void endElement(String uri, String localName, String qName) throws SAXExc
return;
} else if (RPR.equals(localName)) {
inRPr = false;
} else if (O_MATH.equals(localName) && M_NS.equals(uri)) {
if (mathDepth > 0 && --mathDepth == 0) {
bodyContentsHandler.endMath();
}
} else if (R.equals(localName)) {
handleEndOfRun();
} else if (T.equals(localName)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ default void fieldCodeHyperlinkStart(String link) throws SAXException {

void hyperlinkEnd() throws SAXException;

/**
* Called at the start of an OMML equation ({@code m:oMath}); its runs follow.
*/
default void startMath() throws SAXException {
}

default void endMath() throws SAXException {
}

void startParagraph(ParagraphProperties paragraphProperties) throws SAXException;

void endParagraph() throws SAXException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@ public void testMissingText() throws Exception {
assertContains("Rich_text_in_cell", xmlResult.xml);
}

@Test
public void testOmmlMath() throws Exception {
String xml = getXML("testWORD_omml.docx").xml;
assertContains("<p>area <span class=\"math\">A=<b>π</b>rr2</span> done</p>", xml);
assertContains("<p><span class=\"math\">x+y</span></p>", xml);
assertContains("<p><b>bold </b><span class=\"math\">z</span><b> after</b></p>", xml);
}

@Test
public void testBoldHyperlink() throws Exception {
String xml = getXML("testWORD_boldHyperlink.docx").xml;
Expand Down
Binary file not shown.
Loading