aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2017-05-24 23:01:19 +0100
committerMichael Williamson <mike@zwobble.org>2017-05-24 23:01:19 +0100
commitebb527596ec4dad842232cf8b30cb1d48f34244d (patch)
tree3f04a5513c13632c8c0f7755f4bd763002e03442 /src
parent370df4d36053736446e9334008d012ebda5f86bb (diff)
Write thead and th for headers in table
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/conversion/DocumentToHtml.java122
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/Bookmark.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/Break.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/CommentReference.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/DocumentElement.java2
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/DocumentElementVisitor.java28
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/Hyperlink.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/Image.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/NoteReference.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/Paragraph.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/Run.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/Tab.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/Table.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/TableCell.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/TableRow.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/documents/Text.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/util/Optionals.java13
-rw-r--r--src/test/java/org/zwobble/mammoth/tests/conversion/DocumentToHtmlTests.java36
-rw-r--r--src/test/java/org/zwobble/mammoth/tests/documents/DocumentElementMakers.java10
20 files changed, 185 insertions, 82 deletions
diff --git a/src/main/java/org/zwobble/mammoth/internal/conversion/DocumentToHtml.java b/src/main/java/org/zwobble/mammoth/internal/conversion/DocumentToHtml.java
index bdb3d01..9de8224 100644
--- a/src/main/java/org/zwobble/mammoth/internal/conversion/DocumentToHtml.java
+++ b/src/main/java/org/zwobble/mammoth/internal/conversion/DocumentToHtml.java
@@ -15,6 +15,8 @@ import java.io.InputStream;
import java.util.*;
import java.util.function.Supplier;
+import static org.zwobble.mammoth.internal.util.Casts.tryCast;
+import static org.zwobble.mammoth.internal.util.Iterables.findIndex;
import static org.zwobble.mammoth.internal.util.Lists.*;
import static org.zwobble.mammoth.internal.util.Maps.lookup;
import static org.zwobble.mammoth.internal.util.Maps.map;
@@ -23,7 +25,7 @@ public class DocumentToHtml {
public static InternalResult<List<HtmlNode>> convertToHtml(Document document, DocumentToHtmlOptions options) {
DocumentToHtml documentConverter = new DocumentToHtml(options, document.getComments());
return new InternalResult<>(
- documentConverter.convertToHtml(document),
+ documentConverter.convertToHtml(document, new Context()),
documentConverter.warnings);
}
@@ -37,7 +39,7 @@ public class DocumentToHtml {
public static InternalResult<List<HtmlNode>> convertToHtml(DocumentElement element, DocumentToHtmlOptions options) {
DocumentToHtml documentConverter = new DocumentToHtml(options, list());
return new InternalResult<>(
- documentConverter.convertToHtml(element),
+ documentConverter.convertToHtml(element, new Context()),
documentConverter.warnings);
}
@@ -60,6 +62,22 @@ public class DocumentToHtml {
private final List<ReferencedComment> referencedComments = new ArrayList<>();
private final Set<String> warnings = new HashSet<>();
+ private static class Context {
+ private final boolean isHeader;
+
+ Context() {
+ this(false);
+ }
+
+ Context(boolean isHeader) {
+ this.isHeader = isHeader;
+ }
+
+ Context isHeader(boolean isHeader) {
+ return new Context(isHeader);
+ }
+ }
+
private DocumentToHtml(DocumentToHtmlOptions options, List<Comment> comments) {
this.idPrefix = options.idPrefix();
this.preserveEmptyParagraphs = options.shouldPreserveEmptyParagraphs();
@@ -68,26 +86,26 @@ public class DocumentToHtml {
this.comments = Maps.toMapWithKey(comments, Comment::getCommentId);
}
- private List<HtmlNode> convertToHtml(Document document) {
- List<HtmlNode> mainBody = convertChildrenToHtml(document);
+ private List<HtmlNode> convertToHtml(Document document, Context context) {
+ List<HtmlNode> mainBody = convertChildrenToHtml(document, context);
// TODO: can you have note references inside a note?
List<Note> notes = findNotes(document, noteReferences);
List<HtmlNode> noteNodes = notes.isEmpty()
? list()
- : list(Html.element("ol", eagerMap(notes, this::convertToHtml)));
+ : list(Html.element("ol", eagerMap(notes, note -> convertToHtml(note, context))));
List<HtmlNode> commentNodes = referencedComments.isEmpty()
? list()
- : list(Html.element("dl", eagerFlatMap(referencedComments, this::convertToHtml)));
+ : list(Html.element("dl", eagerFlatMap(referencedComments, comment -> convertToHtml(comment, context))));
return eagerConcat(mainBody, noteNodes, commentNodes);
}
- private HtmlNode convertToHtml(Note note) {
+ private HtmlNode convertToHtml(Note note, Context context) {
String id = generateNoteHtmlId(note.getNoteType(), note.getId());
String referenceId = generateNoteRefHtmlId(note.getNoteType(), note.getId());
- List<HtmlNode> noteBody = convertToHtml(note.getBody());
+ List<HtmlNode> noteBody = convertToHtml(note.getBody(), context);
// TODO: we probably want this to collapse more eagerly than other collapsible elements
// -- for instance, any paragraph will probably do, regardless of attributes. (Possible other elements will do too.)
HtmlNode backLink = Html.collapsibleElement("p", list(
@@ -96,10 +114,10 @@ public class DocumentToHtml {
return Html.element("li", map("id", id), eagerConcat(noteBody, list(backLink)));
}
- private List<HtmlNode> convertToHtml(ReferencedComment referencedComment) {
+ private List<HtmlNode> convertToHtml(ReferencedComment referencedComment, Context context) {
// TODO: remove duplication with notes
String commentId = referencedComment.comment.getCommentId();
- List<HtmlNode> body = convertToHtml(referencedComment.comment.getBody());
+ List<HtmlNode> body = convertToHtml(referencedComment.comment.getBody(), context);
// TODO: we probably want this to collapse more eagerly than other collapsible elements
// -- for instance, any paragraph will probably do, regardless of attributes. (Possible other elements will do too.)
HtmlNode backLink = Html.collapsibleElement("p", list(
@@ -115,22 +133,23 @@ public class DocumentToHtml {
eagerConcat(body, list(backLink))));
}
- private List<HtmlNode> convertToHtml(List<DocumentElement> elements) {
+ private List<HtmlNode> convertToHtml(List<DocumentElement> elements, Context context) {
return eagerFlatMap(
elements,
- this::convertToHtml);
+ element -> convertToHtml(element, context)
+ );
}
- private List<HtmlNode> convertChildrenToHtml(HasChildren element) {
- return convertToHtml(element.getChildren());
+ private List<HtmlNode> convertChildrenToHtml(HasChildren element, Context context) {
+ return convertToHtml(element.getChildren(), context);
}
- private List<HtmlNode> convertToHtml(DocumentElement element) {
- return element.accept(new DocumentElementVisitor<List<HtmlNode>>() {
+ private List<HtmlNode> convertToHtml(DocumentElement element, Context context) {
+ return element.accept(new DocumentElementVisitor<List<HtmlNode>, Context>() {
@Override
- public List<HtmlNode> visit(Paragraph paragraph) {
+ public List<HtmlNode> visit(Paragraph paragraph, Context context) {
Supplier<List<HtmlNode>> children = () -> {
- List<HtmlNode> content = convertChildrenToHtml(paragraph);
+ List<HtmlNode> content = convertChildrenToHtml(paragraph, context);
return preserveEmptyParagraphs ? cons(Html.FORCE_WRITE, content) : content;
};
HtmlPath mapping = styleMap.getParagraphHtmlPath(paragraph)
@@ -144,8 +163,8 @@ public class DocumentToHtml {
}
@Override
- public List<HtmlNode> visit(Run run) {
- Supplier<List<HtmlNode>> nodes = () -> convertChildrenToHtml(run);
+ public List<HtmlNode> visit(Run run, Context context) {
+ Supplier<List<HtmlNode>> nodes = () -> convertChildrenToHtml(run, context);
if (run.isStrikethrough()) {
nodes = styleMap.getStrikethrough().orElse(HtmlPath.collapsibleElement("s")).wrap(nodes);
}
@@ -175,7 +194,7 @@ public class DocumentToHtml {
}
@Override
- public List<HtmlNode> visit(Text text) {
+ public List<HtmlNode> visit(Text text, Context context) {
if (text.getValue().isEmpty()) {
return list();
} else {
@@ -184,12 +203,12 @@ public class DocumentToHtml {
}
@Override
- public List<HtmlNode> visit(Tab tab) {
+ public List<HtmlNode> visit(Tab tab, Context context) {
return list(Html.text("\t"));
}
@Override
- public List<HtmlNode> visit(Break breakElement) {
+ public List<HtmlNode> visit(Break breakElement, Context context) {
HtmlPath mapping = styleMap.getBreakHtmlPath(breakElement)
.orElseGet(() -> {
if (breakElement.getType() == Break.Type.LINE) {
@@ -202,17 +221,46 @@ public class DocumentToHtml {
}
@Override
- public List<HtmlNode> visit(Table table) {
- return list(Html.element("table", convertChildrenToHtml(table)));
+ public List<HtmlNode> visit(Table table, Context context) {
+ List<HtmlNode> children = generateTableChildren(table, context);
+ return list(Html.element("table", children));
+ }
+
+ private List<HtmlNode> generateTableChildren(Table table, Context context) {
+ int bodyIndex = findIndex(table.getChildren(), child -> !isHeader(child))
+ .orElse(table.getChildren().size());
+ if (bodyIndex == 0) {
+ return convertToHtml(table.getChildren(), context.isHeader(false));
+ } else {
+ List<HtmlNode> headRows = convertToHtml(
+ table.getChildren().subList(0, bodyIndex),
+ context.isHeader(true)
+ );
+ List<HtmlNode> bodyRows = convertToHtml(
+ table.getChildren().subList(bodyIndex, table.getChildren().size()),
+ context.isHeader(false)
+ );
+ return list(
+ Html.element("thead", headRows),
+ Html.element("tbody", bodyRows)
+ );
+ }
+ }
+
+ private boolean isHeader(DocumentElement child) {
+ return tryCast(TableRow.class, child)
+ .map(TableRow::isHeader)
+ .orElse(false);
}
@Override
- public List<HtmlNode> visit(TableRow tableRow) {
- return list(Html.element("tr", convertChildrenToHtml(tableRow)));
+ public List<HtmlNode> visit(TableRow tableRow, Context context) {
+ return list(Html.element("tr", convertChildrenToHtml(tableRow, context)));
}
@Override
- public List<HtmlNode> visit(TableCell tableCell) {
+ public List<HtmlNode> visit(TableCell tableCell, Context context) {
+ String tagName = context.isHeader ? "th" : "td";
Map<String, String> attributes = new HashMap<>();
if (tableCell.getColspan() != 1) {
attributes.put("colspan", Integer.toString(tableCell.getColspan()));
@@ -220,14 +268,14 @@ public class DocumentToHtml {
if (tableCell.getRowspan() != 1) {
attributes.put("rowspan", Integer.toString(tableCell.getRowspan()));
}
- return list(Html.element("td", attributes,
- Lists.cons(Html.FORCE_WRITE, convertChildrenToHtml(tableCell))));
+ return list(Html.element(tagName, attributes,
+ Lists.cons(Html.FORCE_WRITE, convertChildrenToHtml(tableCell, context))));
}
@Override
- public List<HtmlNode> visit(Hyperlink hyperlink) {
+ public List<HtmlNode> visit(Hyperlink hyperlink, Context context) {
Map<String, String> attributes = map("href", generateHref(hyperlink));
- return list(Html.collapsibleElement("a", attributes, convertChildrenToHtml(hyperlink)));
+ return list(Html.collapsibleElement("a", attributes, convertChildrenToHtml(hyperlink, context)));
}
private String generateHref(Hyperlink hyperlink) {
@@ -241,12 +289,12 @@ public class DocumentToHtml {
}
@Override
- public List<HtmlNode> visit(Bookmark bookmark) {
+ public List<HtmlNode> visit(Bookmark bookmark, Context context) {
return list(Html.element("a", map("id", generateId(bookmark.getName())), list(Html.FORCE_WRITE)));
}
@Override
- public List<HtmlNode> visit(NoteReference noteReference) {
+ public List<HtmlNode> visit(NoteReference noteReference, Context context) {
noteReferences.add(noteReference);
String noteAnchor = generateNoteHtmlId(noteReference.getNoteType(), noteReference.getNoteId());
String noteReferenceAnchor = generateNoteRefHtmlId(noteReference.getNoteType(), noteReference.getNoteId());
@@ -256,7 +304,7 @@ public class DocumentToHtml {
}
@Override
- public List<HtmlNode> visit(CommentReference commentReference) {
+ public List<HtmlNode> visit(CommentReference commentReference, Context context) {
return styleMap.getCommentReference().orElse(HtmlPath.IGNORE).wrap(() -> {
String commentId = commentReference.getCommentId();
Comment comment = lookup(comments, commentId)
@@ -275,7 +323,7 @@ public class DocumentToHtml {
}
@Override
- public List<HtmlNode> visit(Image image) {
+ public List<HtmlNode> visit(Image image, Context context) {
// TODO: custom image handlers
// TODO: handle empty content type
return image.getContentType()
@@ -306,7 +354,7 @@ public class DocumentToHtml {
})
.orElse(list());
}
- });
+ }, context);
}
private String generateNoteHtmlId(NoteType noteType, String noteId) {
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/Bookmark.java b/src/main/java/org/zwobble/mammoth/internal/documents/Bookmark.java
index cca6317..a2890c4 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/Bookmark.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/Bookmark.java
@@ -12,7 +12,7 @@ public class Bookmark implements DocumentElement {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/Break.java b/src/main/java/org/zwobble/mammoth/internal/documents/Break.java
index 0764221..71e129d 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/Break.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/Break.java
@@ -22,7 +22,7 @@ public class Break implements DocumentElement {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/CommentReference.java b/src/main/java/org/zwobble/mammoth/internal/documents/CommentReference.java
index cea65f4..7db9343 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/CommentReference.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/CommentReference.java
@@ -12,7 +12,7 @@ public class CommentReference implements DocumentElement {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/DocumentElement.java b/src/main/java/org/zwobble/mammoth/internal/documents/DocumentElement.java
index b3360ed..7b440cf 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/DocumentElement.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/DocumentElement.java
@@ -1,5 +1,5 @@
package org.zwobble.mammoth.internal.documents;
public interface DocumentElement {
- <T> T accept(DocumentElementVisitor<T> visitor);
+ <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context);
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/DocumentElementVisitor.java b/src/main/java/org/zwobble/mammoth/internal/documents/DocumentElementVisitor.java
index c83e3c5..908a9b7 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/DocumentElementVisitor.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/DocumentElementVisitor.java
@@ -1,22 +1,22 @@
package org.zwobble.mammoth.internal.documents;
-public interface DocumentElementVisitor<T> {
- T visit(Paragraph paragraph);
- T visit(Run run);
- T visit(Text text);
+public interface DocumentElementVisitor<T, U> {
+ T visit(Paragraph paragraph, U context);
+ T visit(Run run, U context);
+ T visit(Text text, U context);
- T visit(Tab tab);
- T visit(Break lineBreak);
+ T visit(Tab tab, U context);
+ T visit(Break lineBreak, U context);
- T visit(Table table);
- T visit(TableRow tableRow);
- T visit(TableCell tableCell);
+ T visit(Table table, U context);
+ T visit(TableRow tableRow, U context);
+ T visit(TableCell tableCell, U context);
- T visit(Hyperlink hyperlink);
- T visit(Bookmark bookmark);
- T visit(NoteReference noteReference);
- T visit(CommentReference commentReference);
+ T visit(Hyperlink hyperlink, U context);
+ T visit(Bookmark bookmark, U context);
+ T visit(NoteReference noteReference, U context);
+ T visit(CommentReference commentReference, U context);
- T visit(Image image);
+ T visit(Image image, U context);
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/Hyperlink.java b/src/main/java/org/zwobble/mammoth/internal/documents/Hyperlink.java
index ceb558f..f78b7fe 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/Hyperlink.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/Hyperlink.java
@@ -36,7 +36,7 @@ public class Hyperlink implements DocumentElement, HasChildren {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/Image.java b/src/main/java/org/zwobble/mammoth/internal/documents/Image.java
index 8ceee7c..f112eed 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/Image.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/Image.java
@@ -31,7 +31,7 @@ public class Image implements DocumentElement {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/NoteReference.java b/src/main/java/org/zwobble/mammoth/internal/documents/NoteReference.java
index 7d0beb2..3a5047e 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/NoteReference.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/NoteReference.java
@@ -26,7 +26,7 @@ public class NoteReference implements DocumentElement {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/Paragraph.java b/src/main/java/org/zwobble/mammoth/internal/documents/Paragraph.java
index 66ea009..a404ae6 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/Paragraph.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/Paragraph.java
@@ -27,7 +27,7 @@ public class Paragraph implements DocumentElement, HasChildren {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/Run.java b/src/main/java/org/zwobble/mammoth/internal/documents/Run.java
index 61f865f..29415c7 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/Run.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/Run.java
@@ -59,7 +59,7 @@ public class Run implements DocumentElement, HasChildren {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/Tab.java b/src/main/java/org/zwobble/mammoth/internal/documents/Tab.java
index b977d12..a9a59c8 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/Tab.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/Tab.java
@@ -7,7 +7,7 @@ public class Tab implements DocumentElement {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/Table.java b/src/main/java/org/zwobble/mammoth/internal/documents/Table.java
index 7381c7d..031b382 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/Table.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/Table.java
@@ -15,7 +15,7 @@ public class Table implements DocumentElement, HasChildren {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/TableCell.java b/src/main/java/org/zwobble/mammoth/internal/documents/TableCell.java
index 0874109..2837725 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/TableCell.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/TableCell.java
@@ -27,7 +27,7 @@ public class TableCell implements DocumentElement, HasChildren {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/TableRow.java b/src/main/java/org/zwobble/mammoth/internal/documents/TableRow.java
index f00ec58..0b5721d 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/TableRow.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/TableRow.java
@@ -17,8 +17,8 @@ public class TableRow implements DocumentElement, HasChildren {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
public boolean isHeader() {
diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/Text.java b/src/main/java/org/zwobble/mammoth/internal/documents/Text.java
index 64123e9..cf1ab6c 100644
--- a/src/main/java/org/zwobble/mammoth/internal/documents/Text.java
+++ b/src/main/java/org/zwobble/mammoth/internal/documents/Text.java
@@ -12,7 +12,7 @@ public class Text implements DocumentElement {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(this);
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(this, context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java b/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java
index 76ea8ea..f4eda9e 100644
--- a/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java
+++ b/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java
@@ -434,8 +434,8 @@ class StatefulBodyXmlReader {
}
@Override
- public <T> T accept(DocumentElementVisitor<T> visitor) {
- return visitor.visit(new TableCell(1, colspan, children));
+ public <T, U> T accept(DocumentElementVisitor<T, U> visitor, U context) {
+ return visitor.visit(new TableCell(1, colspan, children), context);
}
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/util/Optionals.java b/src/main/java/org/zwobble/mammoth/internal/util/Optionals.java
index d98b579..d0ca67e 100644
--- a/src/main/java/org/zwobble/mammoth/internal/util/Optionals.java
+++ b/src/main/java/org/zwobble/mammoth/internal/util/Optionals.java
@@ -1,7 +1,9 @@
package org.zwobble.mammoth.internal.util;
import java.util.Optional;
+import java.util.OptionalInt;
import java.util.function.BiFunction;
+import java.util.function.IntFunction;
public class Optionals {
public static <T> Optional<T> first(Optional<T> first, Optional<T> second) {
@@ -35,4 +37,15 @@ public class Optionals {
return Optional.empty();
}
}
+
+ public static <R> Optional<R> map(
+ OptionalInt first,
+ IntFunction<R> function)
+ {
+ if (first.isPresent()) {
+ return Optional.of(function.apply(first.getAsInt()));
+ } else {
+ return Optional.empty();
+ }
+ }
}
diff --git a/src/test/java/org/zwobble/mammoth/tests/conversion/DocumentToHtmlTests.java b/src/test/java/org/zwobble/mammoth/tests/conversion/DocumentToHtmlTests.java
index 038056c..3c4af09 100644
--- a/src/test/java/org/zwobble/mammoth/tests/conversion/DocumentToHtmlTests.java
+++ b/src/test/java/org/zwobble/mammoth/tests/conversion/DocumentToHtmlTests.java
@@ -241,6 +241,42 @@ public class DocumentToHtmlTests {
}
@Test
+ public void headerRowsAreWrappedInThead() {
+ assertThat(
+ convertToHtml(new Table(list(
+ tableRow(list(tableCell()), withIsHeader(true)),
+ tableRow(list(tableCell()), withIsHeader(true)),
+ tableRow(list(tableCell()), withIsHeader(false))
+ ))),
+
+ deepEquals(list(Html.element("table", list(
+ Html.element("thead", list(
+ Html.element("tr", list(Html.element("th", list(Html.FORCE_WRITE)))),
+ Html.element("tr", list(Html.element("th", list(Html.FORCE_WRITE))))
+ )),
+ Html.element("tbody", list(
+ Html.element("tr", list(Html.element("td", list(Html.FORCE_WRITE))))
+ ))
+ ))))
+ );
+ }
+
+ @Test
+ public void tbodyIsOmittedIfAllRowsAreHeaders() {
+ assertThat(
+ Html.stripEmpty(convertToHtml(new Table(list(
+ tableRow(list(tableCell()), withIsHeader(true))
+ )))),
+
+ deepEquals(list(Html.element("table", list(
+ Html.element("thead", list(
+ Html.element("tr", list(Html.element("th", list(Html.FORCE_WRITE))))
+ ))
+ ))))
+ );
+ }
+
+ @Test
public void tableCellsAreWrittenWithColspanIfNotEqualToOne() {
assertThat(
convertToHtml(new Table(list(
diff --git a/src/test/java/org/zwobble/mammoth/tests/documents/DocumentElementMakers.java b/src/test/java/org/zwobble/mammoth/tests/documents/DocumentElementMakers.java
index 560eb54..a3595ae 100644
--- a/src/test/java/org/zwobble/mammoth/tests/documents/DocumentElementMakers.java
+++ b/src/test/java/org/zwobble/mammoth/tests/documents/DocumentElementMakers.java
@@ -21,6 +21,7 @@ public class DocumentElementMakers {
private static final ArgumentKey<Boolean> STRIKETHROUGH = new ArgumentKey<>("strikethrough");
private static final ArgumentKey<VerticalAlignment> VERTICAL_ALIGNMENT = new ArgumentKey<>("verticalAlignment");
private static final ArgumentKey<List<DocumentElement>> CHILDREN = new ArgumentKey<>("children");
+ private static final ArgumentKey<Boolean> IS_HEADER = new ArgumentKey<>("isHeader");
private static final ArgumentKey<Integer> COLSPAN = new ArgumentKey<>("colspan");
private static final ArgumentKey<Integer> ROWSPAN = new ArgumentKey<>("rowspan");
private static final ArgumentKey<List<Comment>> COMMENTS = new ArgumentKey<>("comments");
@@ -57,6 +58,10 @@ public class DocumentElementMakers {
return arg(CHILDREN, asList(children));
}
+ public static Argument<Boolean> withIsHeader(boolean isHeader) {
+ return arg(IS_HEADER, isHeader);
+ }
+
public static Argument<Integer> withRowspan(Integer rowspan) {
return arg(ROWSPAN, rowspan);
}
@@ -108,8 +113,9 @@ public class DocumentElementMakers {
return run(withChildren(new Text(text)));
}
- public static TableRow tableRow(List<DocumentElement> cells) {
- return new TableRow(cells, false);
+ public static TableRow tableRow(List<DocumentElement> cells, Object... args) {
+ Arguments arguments = new Arguments(args);
+ return new TableRow(cells, arguments.get(IS_HEADER, false));
}
public static TableCell tableCell(Object... args) {