diff --git a/.gitignore b/.gitignore index a00625a9..f7036520 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ target .settings .classpath **/content/mojo +.sdkmanrc +generated diff --git a/asciidoc-java/src/main/java/io/yupiik/asciidoc/parser/Parser.java b/asciidoc-java/src/main/java/io/yupiik/asciidoc/parser/Parser.java index 3eeb7da3..c5c10782 100644 --- a/asciidoc-java/src/main/java/io/yupiik/asciidoc/parser/Parser.java +++ b/asciidoc-java/src/main/java/io/yupiik/asciidoc/parser/Parser.java @@ -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)); } diff --git a/asciidoc-java/src/main/java/io/yupiik/asciidoc/renderer/html/SimpleHtmlRenderer.java b/asciidoc-java/src/main/java/io/yupiik/asciidoc/renderer/html/SimpleHtmlRenderer.java index c370544c..deb76650 100644 --- a/asciidoc-java/src/main/java/io/yupiik/asciidoc/renderer/html/SimpleHtmlRenderer.java +++ b/asciidoc-java/src/main/java/io/yupiik/asciidoc/renderer/html/SimpleHtmlRenderer.java @@ -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; /** @@ -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("
\n"); + builder.append(""" + + + \n") + .append(" \n") + .append(" \n") + .append("
+ """) + .append(element.level().name()).append(":").append("\n") + .append(" \n"); + visitElement(element.content()); + builder.append("
\n") + .append("
\n"); + } + + @Override + public void visitParagraph(final Paragraph element) { + builder.append("
"); + element.children().forEach(this::visitElement); + builder.append("
"); + } + @Override public void visitHeader(final Header header) { if (header.attributes().get("notitle") == null && !header.title().isBlank()) { @@ -158,6 +194,79 @@ public void visitSection(final Section element) { builder.append(" \n"); } + @Override + public void visitLineBreak(final LineBreak element) { + builder.append("
\n"); + } + + @Override + public void visitLink(final Link element) { + builder.append(" ").append(escape(element.label())).append("\n"); + } + + @Override + public void visitDescriptionList(final DescriptionList element) { + if (element.children().isEmpty()) { + return; + } + builder.append("
\n"); + for (final var elt : element.children().entrySet()) { + builder.append("
").append(escape(elt.getKey())).append("
\n"); + builder.append("
\n"); + visitElement(elt.getValue()); + builder.append("
\n"); + } + builder.append("
\n"); + } + + @Override + public void visitUnOrderedList(final UnOrderedList element) { + if (element.children().isEmpty()) { + return; + } + builder.append(" \n"); + } + + + @Override + public void visitOrderedList(final OrderedList element) { + if (element.children().isEmpty()) { + return; + } + builder.append("
    \n"); + visitListElements(element.children()); + builder.append("
\n"); + } + + private void visitListElements(final List element) { + for (final var elt : element) { + builder.append("
  • \n"); + visitElement(elt); + builder.append("
  • \n"); + } + } + @Override public void visitText(final Text element) { final var wrap = element.options().get("nowrap") == null && element.style().size() != 1; diff --git a/asciidoc-java/src/test/java/io/yupiik/asciidoc/renderer/html/SimpleHtmlRendererTest.java b/asciidoc-java/src/test/java/io/yupiik/asciidoc/renderer/html/SimpleHtmlRendererTest.java index 858f0386..78fce19a 100644 --- a/asciidoc-java/src/test/java/io/yupiik/asciidoc/renderer/html/SimpleHtmlRendererTest.java +++ b/asciidoc-java/src/test/java/io/yupiik/asciidoc/renderer/html/SimpleHtmlRendererTest.java @@ -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() {} + ---- + """, """ @@ -70,7 +68,114 @@ public record Foo() {} - """, - renderer.result()); + """); + } + + @Test + void ol() { + assertRenderingContent(""" + . first + . second + . third""", """ +
      +
    1. + + first + +
    2. +
    3. + + second + +
    4. +
    5. + + third + +
    6. +
    + """); + } + + @Test + void ul() { + assertRenderingContent(""" + * first + * second + * third""", """ + + """); + } + + @Test + void dl() { + assertRenderingContent(""" + first:: one + second:: two""", """ +
    +
    first
    +
    + + one + +
    +
    second
    +
    + + two + +
    +
    + """); + } + + @Test + void admonition() { + assertRenderingContent("NOTE: this is an important note.", """ +
    + + + + + +
    + NOTE: + + + this is an important note. + +
    +
    + """); + } + + 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()); } }