diff --git a/docs/asciidoc/packaging/packaging.adoc b/docs/asciidoc/packaging/packaging.adoc index a10da7d83b..d8165bf2cd 100644 --- a/docs/asciidoc/packaging/packaging.adoc +++ b/docs/asciidoc/packaging/packaging.adoc @@ -9,7 +9,7 @@ application. [TIP] ==== -The https://jooby.io/#getting-started[jooby-cli] takes care of configures everything for single jar +The link:/#getting-started[jooby-cli] takes care of configures everything for single jar distribution. Next example shows how to do it in case you created your application manually. ==== diff --git a/docs/src/main/java/io/jooby/adoc/DocGenerator.java b/docs/src/main/java/io/jooby/adoc/DocGenerator.java index 4667f78a31..ec7ad8d68c 100644 --- a/docs/src/main/java/io/jooby/adoc/DocGenerator.java +++ b/docs/src/main/java/io/jooby/adoc/DocGenerator.java @@ -10,7 +10,6 @@ import java.io.File; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -19,11 +18,8 @@ import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.Collection; -import java.util.LinkedHashSet; import java.util.List; import java.util.UUID; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.io.FileUtils; @@ -35,9 +31,7 @@ import org.asciidoctor.SafeMode; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import me.tongfei.progressbar.ProgressBar; import me.tongfei.progressbar.ProgressBarBuilder; import me.tongfei.progressbar.ProgressBarStyle; @@ -53,9 +47,9 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d Path asciidoc = basedir.resolve("asciidoc"); - /** - * Tree dir. The .adoc file became a directory - * modules/hikari.adoc => modules/hikari/index.html + /* + Tree dir. The .adoc file became a directory + modules/hikari.adoc => modules/hikari/index.html */ String[] treeDirs = {"modules", "packaging", "usage", "migration"}; @@ -63,7 +57,7 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d Stream.of(treeDirs) .map(throwingFunction(dir -> countAdoc(asciidoc.resolve(dir)))) .reduce(1, Integer::sum); - int steps = 7 + (doAscii ? adocCount : 0); + int steps = 6 + (doAscii ? adocCount : 0); ProgressBarBuilder pbb = new ProgressBarBuilder() @@ -79,11 +73,11 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d } pb.step(); - /** Wipe out directory: */ + /* Wipe out directory: */ FileUtils.cleanDirectory(outdir.toFile()); pb.step(); - /** Copy /images and /js: */ + /* Copy /images and /js: */ copyFile( outdir, // images @@ -100,7 +94,6 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d createOptions(asciidoc, outdir, version, null)); pb.step(); - AtomicInteger m = new AtomicInteger(); Stream.of(treeDirs) .forEach( throwingConsumer( @@ -113,21 +106,10 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d module -> { processModule(asciidoctor, asciidoc, module, outdir, name, version); pb.step(); - m.incrementAndGet(); }); })); } - // post process - Files.walk(outdir) - .filter(it -> it.getFileName().toString().endsWith("index.html")) - .forEach( - throwingConsumer( - it -> { - Files.write(it, document(it).getBytes(StandardCharsets.UTF_8)); - })); - pb.step(); - // LICENSE Files.copy( basedir.getParent().resolve("LICENSE"), @@ -149,7 +131,7 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d Git git = new Git("jooby-project", "jooby.io", website); git.clone(); - /** Clean: */ + /* Clean: */ FileUtils.deleteDirectory(website.resolve("images").toFile()); FileUtils.deleteDirectory(website.resolve("js").toFile()); FileUtils.deleteQuietly(website.resolve("index.html").toFile()); @@ -239,11 +221,10 @@ private static void processModule( indexlike = indexlike.resolve("index.html"); Files.createDirectories(indexlike.getParent()); Files.move(output, indexlike); - String content = - new String(Files.readAllBytes(indexlike), StandardCharsets.UTF_8) + String content = Files.readString(indexlike) .replace("js/", "../../js/") .replace("images/", "../../images/"); - Files.write(indexlike, content.getBytes(StandardCharsets.UTF_8)); + Files.writeString(indexlike, content); } catch (IOException x) { throw new IllegalStateException(x); } @@ -321,122 +302,6 @@ private static String toJavaName(String tagName) { return name.toString(); } - private static String document(Path index) { - try { - Document doc = Jsoup.parse(index.toFile(), "UTF-8"); - tocItems(doc); - languageTab(doc); - clipboard(doc); - externalLink(doc); - Document.OutputSettings settings = new Document.OutputSettings(); - settings.prettyPrint(false); - settings.indentAmount(0); - settings.outline(false); - return doc.outputSettings(settings).toString(); - } catch (NullPointerException x) { - throw new IllegalStateException("File: " + index, x); - } catch (IOException x) { - throw new IllegalStateException("File: " + index, x); - } - } - - private static void externalLink(Document doc) { - for (Element a : doc.select("a")) { - String href = a.attr("href"); - if (href.startsWith("http://") || href.startsWith("https://")) { - a.attr("target", "_blank"); - } - } - } - - private static void languageTab(Document doc) { - for (Element primary : doc.select(".listingblock.primary")) { - Element secondary = primary.nextElementSibling(); - String secondaryTitle = secondary.selectFirst(".title").text().trim(); - Element primaryContent = primary.selectFirst(".content"); - Element secondaryContent = secondary.selectFirst(".content"); - secondary.remove(); - secondaryContent.remove(); - - Element title = primary.selectFirst(".title"); - - Element tabs = doc.createElement("div").attr("class", "switch"); - Element tab1 = tabs.appendElement("div"); - tab1.attr("class", "switch--item option-1 selected"); - if (secondaryTitle.equalsIgnoreCase("Kotlin")) { - tab1.text("Java"); - } else { - tab1.text(title.text()); - } - - if (title.text().trim().equalsIgnoreCase(tab1.text().trim())) { - title.remove(); - } - - Element tab2 = tabs.appendElement("div"); - tab2.attr("class", "switch--item option-2"); - tab2.text(secondaryTitle); - tabs.appendTo(primary); - primaryContent.addClass("option-1"); - primaryContent.appendTo(primary); - secondaryContent.appendTo(primary); - secondaryContent.addClass("hidden").addClass("option-2"); - ; - } - } - - private static void tocItems(Document doc) { - tocItems(doc, 2); - tocItems(doc, 3); - tocItems(doc, 4); - } - - private static void tocItems(Document doc, int level) { - doc.select("h" + level) - .forEach( - h -> { - if (!h.hasClass("discrete")) { - String id = h.attr("id"); - LinkedHashSet name = new LinkedHashSet<>(); - int parent = level - 1; - Element p = h.parents().select("h" + parent).first(); - if (p != null && !p.hasClass("discrete")) { - String parentId = p.attr("id"); - if (parentId != null && parentId.length() > 0) { - name.add(parentId); - } - } - name.add(id.replaceAll("([a-zA-Z0-9-]+)-\\d+$", "$1")); - String newId = name.stream().collect(Collectors.joining("-")); - if (!id.equals(newId)) { - h.attr("id", newId); - doc.select("a") - .forEach( - a -> { - if (a.attr("href").equals("#" + id) && a.attr("class").length() > 0) { - a.attr("href", "#" + newId); - } - }); - } - } - }); - } - - private static void clipboard(Document doc) { - for (Element code : doc.select("code.hljs")) { - String id = "x" + Long.toHexString(UUID.randomUUID().getMostSignificantBits()); - code.attr("id", id); - Element button = code.parent().appendElement("button"); - button.addClass("clipboard"); - button.attr("data-clipboard-target", "#" + id); - Element img = button.appendElement("img"); - img.attr("src", "/images/clippy.svg"); - img.attr("class", "clippy"); - img.attr("width", "13"); - img.attr("alt", "Copy to clipboard"); - } - } - public static Path basedir() { Path basedir = Paths.get(System.getProperty("user.dir")); if (!basedir.toString().endsWith("docs")) { @@ -449,8 +314,7 @@ public static Path basedir() { public static String version() { try { Document doc = Jsoup.parse(basedir().getParent().resolve("pom.xml").toFile(), "utf-8"); - String version = doc.selectFirst("version").text().trim(); - return version; + return doc.selectFirst("version").text().trim(); } catch (IOException x) { throw new IllegalStateException(x); } diff --git a/docs/src/main/java/io/jooby/adoc/DocPostprocessor.java b/docs/src/main/java/io/jooby/adoc/DocPostprocessor.java new file mode 100644 index 0000000000..3fcdde8e80 --- /dev/null +++ b/docs/src/main/java/io/jooby/adoc/DocPostprocessor.java @@ -0,0 +1,125 @@ +package io.jooby.adoc; + +import static java.util.function.Predicate.not; + +import java.util.LinkedHashSet; +import java.util.UUID; +import org.asciidoctor.extension.Postprocessor; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Document.OutputSettings; +import org.jsoup.nodes.Element; + +public class DocPostprocessor extends Postprocessor { + + @Override + public String process(org.asciidoctor.ast.Document document, String output) { + try { + Document doc = Jsoup.parse(output, "UTF-8"); + + headerIds(doc); + languageTab(doc); + clipboard(doc); + externalLink(doc); + + OutputSettings settings = new OutputSettings(); + settings.prettyPrint(false); + settings.indentAmount(0); + settings.outline(false); + return doc.outputSettings(settings).outerHtml(); + } catch (NullPointerException x) { + throw new IllegalStateException("File: " + document.getDoctitle(), x); + } + } + + private static void externalLink(Document doc) { + doc.select("a[href^=http://], a[href^=https://]") + .forEach(a -> a.attr("target", "_blank")); + } + + private static void languageTab(Document doc) { + for (Element primary : doc.select(".listingblock.primary")) { + Element secondary = primary.nextElementSibling(); + String secondaryTitle = secondary.selectFirst(".title").text().trim(); + Element primaryContent = primary.selectFirst(".content"); + Element secondaryContent = secondary.selectFirst(".content"); + secondary.remove(); + secondaryContent.remove(); + + Element title = primary.selectFirst(".title"); + + Element tabs = doc.createElement("div").attr("class", "switch"); + Element tab1 = tabs.appendElement("div"); + tab1.attr("class", "switch--item option-1 selected"); + if (secondaryTitle.equalsIgnoreCase("Kotlin")) { + tab1.text("Java"); + } else { + tab1.text(title.text()); + } + + if (title.text().trim().equalsIgnoreCase(tab1.text().trim())) { + title.remove(); + } + + Element tab2 = tabs.appendElement("div"); + tab2.attr("class", "switch--item option-2"); + tab2.text(secondaryTitle); + tabs.appendTo(primary); + primaryContent.addClass("option-1"); + primaryContent.appendTo(primary); + secondaryContent.appendTo(primary); + secondaryContent.addClass("hidden").addClass("option-2"); + } + } + + private static void headerIds(Document doc) { + headerIds(doc, 2); + headerIds(doc, 3); + headerIds(doc, 4); + headerIds(doc, 5); + } + + private static void headerIds(Document doc, int level) { + doc.select("h" + level).stream() + .filter(not(DocPostprocessor::isDiscrete)) + .forEach(h -> { + String id = h.attr("id"); + LinkedHashSet name = new LinkedHashSet<>(); + int parent = level - 1; + Element p = h.parents().select("h" + parent).first(); + if (p != null && !isDiscrete(p)) { + String parentId = p.attr("id"); + if (!parentId.isEmpty()) { + name.add(parentId); + } + } + name.add(id.replaceAll("([a-zA-Z0-9-]+)-\\d+$", "$1")); + String newId = String.join("-", name); + if (!id.equals(newId)) { + h.attr("id", newId); + h.select("a").stream() + .filter(a -> a.attr("href").equals("#" + id) && !a.attr("class").isEmpty()) + .forEach(a -> a.attr("href", "#" + newId)); + } + }); + } + + private static boolean isDiscrete(Element e) { + return e.hasClass("discrete"); + } + + private static void clipboard(Document doc) { + for (Element code : doc.select("code.hljs")) { + String id = "x" + Long.toHexString(UUID.randomUUID().getMostSignificantBits()); + code.attr("id", id); + Element button = code.parent().appendElement("button"); + button.addClass("clipboard"); + button.attr("data-clipboard-target", "#" + id); + Element img = button.appendElement("img"); + img.attr("src", "/images/clippy.svg"); + img.attr("class", "clippy"); + img.attr("width", "13"); + img.attr("alt", "Copy to clipboard"); + } + } +} diff --git a/docs/src/main/java/io/jooby/adoc/JoobyExtensionRegistry.java b/docs/src/main/java/io/jooby/adoc/JoobyExtensionRegistry.java index 3a38ac4012..6cab63c2a9 100644 --- a/docs/src/main/java/io/jooby/adoc/JoobyExtensionRegistry.java +++ b/docs/src/main/java/io/jooby/adoc/JoobyExtensionRegistry.java @@ -13,5 +13,6 @@ public class JoobyExtensionRegistry implements ExtensionRegistry { public void register(Asciidoctor asciidoctor) { asciidoctor.javaExtensionRegistry().block("dependency", DependencyProcessor.class); asciidoctor.javaExtensionRegistry().inlineMacro("javadoc", JavadocProcessor.class); + asciidoctor.javaExtensionRegistry().postprocessor(DocPostprocessor.class); } }