Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/asciidoc/packaging/packaging.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
====

Expand Down
156 changes: 10 additions & 146 deletions docs/src/main/java/io/jooby/adoc/DocGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;

Expand All @@ -53,17 +47,17 @@ 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"};

int adocCount =
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()
Expand All @@ -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
Expand All @@ -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(
Expand All @@ -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"),
Expand All @@ -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());
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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<String> 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")) {
Expand All @@ -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);
}
Expand Down
125 changes: 125 additions & 0 deletions docs/src/main/java/io/jooby/adoc/DocPostprocessor.java
Original file line number Diff line number Diff line change
@@ -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<String> 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");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}