Skip to content

Commit

Permalink
[asciidoctor-java] few more html block implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
rmannibucau committed Dec 9, 2023
1 parent eceb4c0 commit 9e3f18a
Show file tree
Hide file tree
Showing 4 changed files with 244 additions and 20 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ target
.settings
.classpath
**/content/mojo
.sdkmanrc
generated
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ public Header parseHeader(final Reader reader) {
return new Header(title, author, revision, attributes);
}

public Body parseBody(final String reader, final ParserContext context) {
return parseBody(new Reader(List.of(reader.split("\n"))), context.resolver());
}

public Body parseBody(final BufferedReader reader, final ParserContext context) {
return parseBody(new Reader(reader.lines().toList()), context.resolver());
}

public Body parseBody(final Reader reader, final ContentResolver resolver) {
return new Body(doParse(reader, line -> true, resolver));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,28 @@
*/
package io.yupiik.asciidoc.renderer.html;

import io.yupiik.asciidoc.model.Admonition;
import io.yupiik.asciidoc.model.Code;
import io.yupiik.asciidoc.model.ConditionalBlock;
import io.yupiik.asciidoc.model.DescriptionList;
import io.yupiik.asciidoc.model.Document;
import io.yupiik.asciidoc.model.Element;
import io.yupiik.asciidoc.model.Header;
import io.yupiik.asciidoc.model.LineBreak;
import io.yupiik.asciidoc.model.Link;
import io.yupiik.asciidoc.model.OrderedList;
import io.yupiik.asciidoc.model.Paragraph;
import io.yupiik.asciidoc.model.Section;
import io.yupiik.asciidoc.model.Text;
import io.yupiik.asciidoc.model.UnOrderedList;
import io.yupiik.asciidoc.renderer.Visitor;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import static java.util.Locale.ROOT;
import static java.util.stream.Collectors.joining;

/**
Expand Down Expand Up @@ -105,6 +115,32 @@ public void visit(final Document document) {
}
}

@Override
public void visitAdmonition(final Admonition element) {
// todo: here we need to assume we have icons to render it more elegantly
builder.append(" <div class=\"admonitionblock ").append(element.level().name().toLowerCase(ROOT)).append("\">\n");
builder.append("""
<table>
<tr>
<td class="icon">
""")
.append(element.level().name()).append(":").append("\n")
.append(" </td>\n")
.append(" <td class=\"content\">\n");
visitElement(element.content());
builder.append(" </td>\n")
.append(" </tr>\n")
.append(" </table>\n")
.append(" </div>\n");
}

@Override
public void visitParagraph(final Paragraph element) {
builder.append(" <div class=\"paragraph\">");
element.children().forEach(this::visitElement);
builder.append(" </div>");
}

@Override
public void visitHeader(final Header header) {
if (header.attributes().get("notitle") == null && !header.title().isBlank()) {
Expand Down Expand Up @@ -158,6 +194,79 @@ public void visitSection(final Section element) {
builder.append(" </div>\n");
}

@Override
public void visitLineBreak(final LineBreak element) {
builder.append(" <br>\n");
}

@Override
public void visitLink(final Link element) {
builder.append(" <a href=\"").append(element.url()).append("\"");

final var window = element.options().get("window");
if (window != null) {
builder.append(" target=\"").append(window).append("\"");
}

final var nofollow = element.options().get("nofollow");
final boolean noopener = "_blank".equals(window) || element.options().get("noopener") != null;
if (nofollow != null) {
builder.append(" rel=\"nofollow");
if (noopener) {
builder.append(" noopener");
}
builder.append("\"");
} else if (noopener) {
builder.append(" rel=\"noopener\"");
}

builder.append(">").append(escape(element.label())).append("</a>\n");
}

@Override
public void visitDescriptionList(final DescriptionList element) {
if (element.children().isEmpty()) {
return;
}
builder.append(" <dl>\n");
for (final var elt : element.children().entrySet()) {
builder.append(" <dt>").append(escape(elt.getKey())).append("</dt>\n");
builder.append(" <dd>\n");
visitElement(elt.getValue());
builder.append("</dd>\n");
}
builder.append(" </dl>\n");
}

@Override
public void visitUnOrderedList(final UnOrderedList element) {
if (element.children().isEmpty()) {
return;
}
builder.append(" <ul>\n");
visitListElements(element.children());
builder.append(" </ul>\n");
}


@Override
public void visitOrderedList(final OrderedList element) {
if (element.children().isEmpty()) {
return;
}
builder.append(" <ol>\n");
visitListElements(element.children());
builder.append(" </ol>\n");
}

private void visitListElements(final List<Element> element) {
for (final var elt : element) {
builder.append(" <li>\n");
visitElement(elt);
builder.append(" </li>\n");
}
}

@Override
public void visitText(final Text element) {
final var wrap = element.options().get("nowrap") == null && element.style().size() != 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,31 @@
package io.yupiik.asciidoc.renderer.html;

import io.yupiik.asciidoc.parser.Parser;
import io.yupiik.asciidoc.parser.internal.LocalContextResolver;
import io.yupiik.asciidoc.parser.resolver.ContentResolver;
import org.junit.jupiter.api.Test;

import java.nio.file.Path;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;

class SimpleHtmlRendererTest {
@Test
void renderHtml() {
final var doc = new Parser().parse("""
= Main title
Some text.
== Second part
This is a snippet:
[source,java]
----
public record Foo() {}
----
""", new Parser.ParserContext(new LocalContextResolver(Path.of("target/missing"))));
final var renderer = new SimpleHtmlRenderer();
renderer.visit(doc);
assertEquals(
assertRendering("""
= Main title
Some text.
== Second part
This is a snippet:
[source,java]
----
public record Foo() {}
----
""",
"""
<!DOCTYPE html>
<html lang="en">
Expand Down Expand Up @@ -70,7 +68,114 @@ public record Foo() {}
</div>
</body>
</html>
""",
renderer.result());
""");
}

@Test
void ol() {
assertRenderingContent("""
. first
. second
. third""", """
<ol>
<li>
<span>
first
</span>
</li>
<li>
<span>
second
</span>
</li>
<li>
<span>
third
</span>
</li>
</ol>
""");
}

@Test
void ul() {
assertRenderingContent("""
* first
* second
* third""", """
<ul>
<li>
<span>
first
</span>
</li>
<li>
<span>
second
</span>
</li>
<li>
<span>
third
</span>
</li>
</ul>
""");
}

@Test
void dl() {
assertRenderingContent("""
first:: one
second:: two""", """
<dl>
<dt>first</dt>
<dd>
<span>
one
</span>
</dd>
<dt>second</dt>
<dd>
<span>
two
</span>
</dd>
</dl>
""");
}

@Test
void admonition() {
assertRenderingContent("NOTE: this is an important note.", """
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
NOTE:
</td>
<td class="content">
<span>
this is an important note.
</span>
</td>
</tr>
</table>
</div>
""");
}

private void assertRendering(final String adoc, final String html) {
final var doc = new Parser().parse(adoc, new Parser.ParserContext(ContentResolver.of(Path.of("target/missing"))));
final var renderer = new SimpleHtmlRenderer();
renderer.visit(doc);
assertEquals(html, renderer.result());
}

private void assertRenderingContent(final String adoc, final String html) {
final var doc = new Parser().parseBody(adoc, new Parser.ParserContext(ContentResolver.of(Path.of("target/missing"))));
final var renderer = new SimpleHtmlRenderer(Map.of("noheader", "true"));
renderer.visitBody(doc);
assertEquals(html, renderer.result());
}
}

0 comments on commit 9e3f18a

Please sign in to comment.