diff options
Diffstat (limited to 'src/main/java')
4 files changed, 87 insertions, 13 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 1254747..b22742c 100644 --- a/src/main/java/org/zwobble/mammoth/internal/conversion/DocumentToHtml.java +++ b/src/main/java/org/zwobble/mammoth/internal/conversion/DocumentToHtml.java @@ -8,17 +8,19 @@ import org.zwobble.mammoth.internal.styles.HtmlPath; import org.zwobble.mammoth.internal.styles.StyleMap; import org.zwobble.mammoth.internal.util.Base64Encoding; import org.zwobble.mammoth.internal.util.Lists; +import org.zwobble.mammoth.internal.util.Maps; import java.io.IOException; import java.util.*; import java.util.function.Supplier; 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; public class DocumentToHtml { public static InternalResult<List<HtmlNode>> convertToHtml(Document document, DocumentToHtmlOptions options) { - DocumentToHtml documentConverter = new DocumentToHtml(options); + DocumentToHtml documentConverter = new DocumentToHtml(options, document.getComments()); return new InternalResult<>( documentConverter.convertToHtml(document), documentConverter.warnings); @@ -32,36 +34,51 @@ public class DocumentToHtml { } public static InternalResult<List<HtmlNode>> convertToHtml(DocumentElement element, DocumentToHtmlOptions options) { - DocumentToHtml documentConverter = new DocumentToHtml(options); + DocumentToHtml documentConverter = new DocumentToHtml(options, list()); return new InternalResult<>( documentConverter.convertToHtml(element), documentConverter.warnings); } + private static class ReferencedComment { + private final String label; + private final Comment comment; + + private ReferencedComment(String label, Comment comment) { + this.label = label; + this.comment = comment; + } + } + private final String idPrefix; private final boolean preserveEmptyParagraphs; private final StyleMap styleMap; + private final Map<String, Comment> comments; private final List<NoteReference> noteReferences = new ArrayList<>(); + private final List<ReferencedComment> referencedComments = new ArrayList<>(); private final Set<String> warnings = new HashSet<>(); - private DocumentToHtml(DocumentToHtmlOptions options) { + private DocumentToHtml(DocumentToHtmlOptions options, List<Comment> comments) { this.idPrefix = options.idPrefix(); this.preserveEmptyParagraphs = options.shouldPreserveEmptyParagraphs(); this.styleMap = options.styleMap(); + this.comments = Maps.toMapWithKey(comments, Comment::getCommentId); } private List<HtmlNode> convertToHtml(Document document) { List<HtmlNode> mainBody = convertChildrenToHtml(document); // TODO: can you have note references inside a note? List<Note> notes = findNotes(document, noteReferences); - if (notes.isEmpty()) { - return mainBody; - } else { - HtmlNode noteNode = Html.element("ol", - eagerMap(notes, this::convertToHtml)); - return eagerConcat(mainBody, list(noteNode)); - } + List<HtmlNode> noteNodes = notes.isEmpty() + ? list() + : list(Html.element("ol", eagerMap(notes, this::convertToHtml))); + + List<HtmlNode> commentNodes = referencedComments.isEmpty() + ? list() + : list(Html.element("dl", eagerFlatMap(referencedComments, this::convertToHtml))); + + return eagerConcat(mainBody, noteNodes, commentNodes); } private HtmlNode convertToHtml(Note note) { @@ -76,6 +93,25 @@ public class DocumentToHtml { return Html.element("li", map("id", id), eagerConcat(noteBody, list(backLink))); } + private List<HtmlNode> convertToHtml(ReferencedComment referencedComment) { + // TODO: remove duplication with notes + String commentId = referencedComment.comment.getCommentId(); + List<HtmlNode> body = convertToHtml(referencedComment.comment.getBody()); + // 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( + Html.text(" "), + Html.element("a", map("href", "#" + generateReferenceHtmlId("comment", commentId)), list(Html.text("↑"))))); + + return list( + Html.element( + "dt", + map("id", generateReferentHtmlId("comment", commentId)), + list(Html.text("Comment " + referencedComment.label))), + Html.element("dd", + eagerConcat(body, list(backLink)))); + } + private List<HtmlNode> convertToHtml(List<DocumentElement> elements) { return eagerFlatMap( elements, @@ -210,7 +246,21 @@ public class DocumentToHtml { @Override public List<HtmlNode> visit(CommentReference commentReference) { - return list(); + return styleMap.getCommentReference().orElse(HtmlPath.IGNORE).wrap(() -> { + String commentId = commentReference.getCommentId(); + Comment comment = lookup(comments, commentId) + .orElseThrow(() -> new RuntimeException("Referenced comment could not be found, id: " + commentId)); + String label = "[" + comment.getAuthorInitials().orElse("") + (referencedComments.size() + 1) + "]"; + referencedComments.add(new ReferencedComment(label, comment)); + + // TODO: Remove duplication with note references + return list(Html.element( + "a", + map( + "href", "#" + generateReferentHtmlId("comment", commentId), + "id", generateReferenceHtmlId("comment", commentId)), + list(Html.text(label)))); + }).get(); } @Override @@ -240,11 +290,19 @@ public class DocumentToHtml { } private String generateNoteHtmlId(NoteType noteType, String noteId) { - return generateId(noteTypeToIdFragment(noteType) + "-" + noteId); + return generateReferentHtmlId(noteTypeToIdFragment(noteType), noteId); } private String generateNoteRefHtmlId(NoteType noteType, String noteId) { - return generateId(noteTypeToIdFragment(noteType) + "-ref-" + noteId); + return generateReferenceHtmlId(noteTypeToIdFragment(noteType), noteId); + } + + private String generateReferentHtmlId(String referenceType, String referenceId) { + return generateId(referenceType + "-" + referenceId); + } + + private String generateReferenceHtmlId(String referenceType, String referenceId) { + return generateId(referenceType + "-ref-" + referenceId); } private String noteTypeToIdFragment(NoteType noteType) { diff --git a/src/main/java/org/zwobble/mammoth/internal/documents/Document.java b/src/main/java/org/zwobble/mammoth/internal/documents/Document.java index 77d5580..5adc50d 100644 --- a/src/main/java/org/zwobble/mammoth/internal/documents/Document.java +++ b/src/main/java/org/zwobble/mammoth/internal/documents/Document.java @@ -20,4 +20,8 @@ public class Document implements HasChildren { public Notes getNotes() { return notes; } + + public List<Comment> getComments() { + return comments; + } } diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/StyleMap.java b/src/main/java/org/zwobble/mammoth/internal/styles/StyleMap.java index eb810aa..c587483 100644 --- a/src/main/java/org/zwobble/mammoth/internal/styles/StyleMap.java +++ b/src/main/java/org/zwobble/mammoth/internal/styles/StyleMap.java @@ -71,6 +71,10 @@ public class StyleMap { return strikethrough; } + public Optional<HtmlPath> getCommentReference() { + return commentReference; + } + public Optional<HtmlPath> getParagraphHtmlPath(Paragraph paragraph) { return tryFind(paragraphStyles, styleMapping -> styleMapping.matches(paragraph)) .map(StyleMapping::getHtmlPath); diff --git a/src/main/java/org/zwobble/mammoth/internal/util/Lists.java b/src/main/java/org/zwobble/mammoth/internal/util/Lists.java index 0fb53c1..3fbb5dd 100644 --- a/src/main/java/org/zwobble/mammoth/internal/util/Lists.java +++ b/src/main/java/org/zwobble/mammoth/internal/util/Lists.java @@ -40,6 +40,14 @@ public class Lists { return Stream.concat(stream(first), stream(second)).collect(Collectors.toList()); } + public static <T> List<T> eagerConcat(Collection<T> first, Collection<T> second, Collection<T> third) { + List<T> result = new ArrayList<>(first.size() + second.size() + third.size()); + result.addAll(first); + result.addAll(second); + result.addAll(third); + return result; + } + public static <T> List<T> eagerFilter(Iterable<T> iterable, Predicate<T> predicate) { return stream(iterable).filter(predicate).collect(Collectors.toList()); } |
