Skip to content

Commit b48e72b

Browse files
committed
refactor: move post-processing to asciidoc lifecycle
Signed-off-by: Lewis Birks <[email protected]>
1 parent 034580a commit b48e72b

File tree

3 files changed

+135
-141
lines changed

3 files changed

+135
-141
lines changed

docs/src/main/java/io/jooby/adoc/DocGenerator.java

Lines changed: 9 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@
77

88
import static io.jooby.SneakyThrows.throwingConsumer;
99
import static io.jooby.SneakyThrows.throwingFunction;
10-
import static java.util.function.Predicate.not;
1110

1211
import java.io.File;
1312
import java.io.IOException;
14-
import java.nio.charset.StandardCharsets;
1513
import java.nio.file.Files;
1614
import java.nio.file.Path;
1715
import java.nio.file.Paths;
@@ -20,10 +18,8 @@
2018
import java.time.format.DateTimeFormatter;
2119
import java.util.Arrays;
2220
import java.util.Collection;
23-
import java.util.LinkedHashSet;
2421
import java.util.List;
2522
import java.util.UUID;
26-
import java.util.concurrent.atomic.AtomicInteger;
2723
import java.util.stream.Stream;
2824

2925
import org.apache.commons.io.FileUtils;
@@ -35,7 +31,6 @@
3531
import org.asciidoctor.SafeMode;
3632
import org.jsoup.Jsoup;
3733
import org.jsoup.nodes.Document;
38-
import org.jsoup.nodes.Element;
3934

4035
import me.tongfei.progressbar.ProgressBarBuilder;
4136
import me.tongfei.progressbar.ProgressBarStyle;
@@ -52,17 +47,17 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d
5247

5348
Path asciidoc = basedir.resolve("asciidoc");
5449

55-
/**
56-
* Tree dir. The .adoc file became a directory
57-
* modules/hikari.adoc => modules/hikari/index.html
50+
/*
51+
Tree dir. The .adoc file became a directory
52+
modules/hikari.adoc => modules/hikari/index.html
5853
*/
5954
String[] treeDirs = {"modules", "packaging", "usage", "migration"};
6055

6156
int adocCount =
6257
Stream.of(treeDirs)
6358
.map(throwingFunction(dir -> countAdoc(asciidoc.resolve(dir))))
6459
.reduce(1, Integer::sum);
65-
int steps = 7 + (doAscii ? adocCount : 0);
60+
int steps = 6 + (doAscii ? adocCount : 0);
6661

6762
ProgressBarBuilder pbb =
6863
new ProgressBarBuilder()
@@ -78,11 +73,11 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d
7873
}
7974
pb.step();
8075

81-
/** Wipe out directory: */
76+
/* Wipe out directory: */
8277
FileUtils.cleanDirectory(outdir.toFile());
8378
pb.step();
8479

85-
/** Copy /images and /js: */
80+
/* Copy /images and /js: */
8681
copyFile(
8782
outdir,
8883
// images
@@ -99,7 +94,6 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d
9994
createOptions(asciidoc, outdir, version, null));
10095
pb.step();
10196

102-
AtomicInteger m = new AtomicInteger();
10397
Stream.of(treeDirs)
10498
.forEach(
10599
throwingConsumer(
@@ -112,21 +106,10 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d
112106
module -> {
113107
processModule(asciidoctor, asciidoc, module, outdir, name, version);
114108
pb.step();
115-
m.incrementAndGet();
116109
});
117110
}));
118111
}
119112

120-
// post process
121-
Files.walk(outdir)
122-
.filter(it -> it.getFileName().toString().endsWith("index.html"))
123-
.forEach(
124-
throwingConsumer(
125-
it -> {
126-
Files.write(it, document(it).getBytes(StandardCharsets.UTF_8));
127-
}));
128-
pb.step();
129-
130113
// LICENSE
131114
Files.copy(
132115
basedir.getParent().resolve("LICENSE"),
@@ -148,7 +131,7 @@ public static void generate(Path basedir, boolean publish, boolean v1, boolean d
148131
Git git = new Git("jooby-project", "jooby.io", website);
149132
git.clone();
150133

151-
/** Clean: */
134+
/* Clean: */
152135
FileUtils.deleteDirectory(website.resolve("images").toFile());
153136
FileUtils.deleteDirectory(website.resolve("js").toFile());
154137
FileUtils.deleteQuietly(website.resolve("index.html").toFile());
@@ -238,11 +221,10 @@ private static void processModule(
238221
indexlike = indexlike.resolve("index.html");
239222
Files.createDirectories(indexlike.getParent());
240223
Files.move(output, indexlike);
241-
String content =
242-
new String(Files.readAllBytes(indexlike), StandardCharsets.UTF_8)
224+
String content = Files.readString(indexlike)
243225
.replace("js/", "../../js/")
244226
.replace("images/", "../../images/");
245-
Files.write(indexlike, content.getBytes(StandardCharsets.UTF_8));
227+
Files.writeString(indexlike, content);
246228
} catch (IOException x) {
247229
throw new IllegalStateException(x);
248230
}
@@ -320,120 +302,6 @@ private static String toJavaName(String tagName) {
320302
return name.toString();
321303
}
322304

323-
private static String document(Path index) {
324-
try {
325-
Document doc = Jsoup.parse(index.toFile(), "UTF-8");
326-
headerIds(doc);
327-
languageTab(doc);
328-
clipboard(doc);
329-
externalLink(doc);
330-
Document.OutputSettings settings = new Document.OutputSettings();
331-
settings.prettyPrint(false);
332-
settings.indentAmount(0);
333-
settings.outline(false);
334-
return doc.outputSettings(settings).toString();
335-
} catch (NullPointerException x) {
336-
throw new IllegalStateException("File: " + index, x);
337-
} catch (IOException x) {
338-
throw new IllegalStateException("File: " + index, x);
339-
}
340-
}
341-
342-
private static void externalLink(Document doc) {
343-
for (Element a : doc.select("a")) {
344-
String href = a.attr("href");
345-
if (href.startsWith("http://") || href.startsWith("https://")) {
346-
a.attr("target", "_blank");
347-
}
348-
}
349-
}
350-
351-
private static void languageTab(Document doc) {
352-
for (Element primary : doc.select(".listingblock.primary")) {
353-
Element secondary = primary.nextElementSibling();
354-
String secondaryTitle = secondary.selectFirst(".title").text().trim();
355-
Element primaryContent = primary.selectFirst(".content");
356-
Element secondaryContent = secondary.selectFirst(".content");
357-
secondary.remove();
358-
secondaryContent.remove();
359-
360-
Element title = primary.selectFirst(".title");
361-
362-
Element tabs = doc.createElement("div").attr("class", "switch");
363-
Element tab1 = tabs.appendElement("div");
364-
tab1.attr("class", "switch--item option-1 selected");
365-
if (secondaryTitle.equalsIgnoreCase("Kotlin")) {
366-
tab1.text("Java");
367-
} else {
368-
tab1.text(title.text());
369-
}
370-
371-
if (title.text().trim().equalsIgnoreCase(tab1.text().trim())) {
372-
title.remove();
373-
}
374-
375-
Element tab2 = tabs.appendElement("div");
376-
tab2.attr("class", "switch--item option-2");
377-
tab2.text(secondaryTitle);
378-
tabs.appendTo(primary);
379-
primaryContent.addClass("option-1");
380-
primaryContent.appendTo(primary);
381-
secondaryContent.appendTo(primary);
382-
secondaryContent.addClass("hidden").addClass("option-2");
383-
}
384-
}
385-
386-
private static void headerIds(Document doc) {
387-
headerIds(doc, 2);
388-
headerIds(doc, 3);
389-
headerIds(doc, 4);
390-
headerIds(doc, 5);
391-
}
392-
393-
private static void headerIds(Document doc, int level) {
394-
doc.select("h" + level).stream()
395-
.filter(not(DocGenerator::isDiscrete))
396-
.forEach(h -> {
397-
String id = h.attr("id");
398-
LinkedHashSet<String> name = new LinkedHashSet<>();
399-
int parent = level - 1;
400-
Element p = h.parents().select("h" + parent).first();
401-
if (p != null && !isDiscrete(p)) {
402-
String parentId = p.attr("id");
403-
if (!parentId.isEmpty()) {
404-
name.add(parentId);
405-
}
406-
}
407-
name.add(id.replaceAll("([a-zA-Z0-9-]+)-\\d+$", "$1"));
408-
String newId = String.join("-", name);
409-
if (!id.equals(newId)) {
410-
h.attr("id", newId);
411-
h.select("a").stream()
412-
.filter(a -> a.attr("href").equals("#" + id) && !a.attr("class").isEmpty())
413-
.forEach(a -> a.attr("href", "#" + newId));
414-
}
415-
});
416-
}
417-
418-
private static boolean isDiscrete(Element p) {
419-
return p.hasClass("discrete");
420-
}
421-
422-
private static void clipboard(Document doc) {
423-
for (Element code : doc.select("code.hljs")) {
424-
String id = "x" + Long.toHexString(UUID.randomUUID().getMostSignificantBits());
425-
code.attr("id", id);
426-
Element button = code.parent().appendElement("button");
427-
button.addClass("clipboard");
428-
button.attr("data-clipboard-target", "#" + id);
429-
Element img = button.appendElement("img");
430-
img.attr("src", "/images/clippy.svg");
431-
img.attr("class", "clippy");
432-
img.attr("width", "13");
433-
img.attr("alt", "Copy to clipboard");
434-
}
435-
}
436-
437305
public static Path basedir() {
438306
Path basedir = Paths.get(System.getProperty("user.dir"));
439307
if (!basedir.toString().endsWith("docs")) {
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package io.jooby.adoc;
2+
3+
import static java.util.function.Predicate.not;
4+
5+
import java.util.LinkedHashSet;
6+
import java.util.UUID;
7+
import org.asciidoctor.extension.Postprocessor;
8+
import org.jsoup.Jsoup;
9+
import org.jsoup.nodes.Document;
10+
import org.jsoup.nodes.Document.OutputSettings;
11+
import org.jsoup.nodes.Element;
12+
13+
public class DocPostprocessor extends Postprocessor {
14+
15+
@Override
16+
public String process(org.asciidoctor.ast.Document document, String output) {
17+
try {
18+
Document doc = Jsoup.parse(output, "UTF-8");
19+
20+
headerIds(doc);
21+
languageTab(doc);
22+
clipboard(doc);
23+
externalLink(doc);
24+
25+
OutputSettings settings = new OutputSettings();
26+
settings.prettyPrint(false);
27+
settings.indentAmount(0);
28+
settings.outline(false);
29+
return doc.outputSettings(settings).outerHtml();
30+
} catch (NullPointerException x) {
31+
throw new IllegalStateException("File: " + document.getDoctitle(), x);
32+
}
33+
}
34+
35+
private static void externalLink(Document doc) {
36+
doc.select("a[href^=http://], a[href^=https://]")
37+
.forEach(a -> a.attr("target", "_blank"));
38+
}
39+
40+
private static void languageTab(Document doc) {
41+
for (Element primary : doc.select(".listingblock.primary")) {
42+
Element secondary = primary.nextElementSibling();
43+
String secondaryTitle = secondary.selectFirst(".title").text().trim();
44+
Element primaryContent = primary.selectFirst(".content");
45+
Element secondaryContent = secondary.selectFirst(".content");
46+
secondary.remove();
47+
secondaryContent.remove();
48+
49+
Element title = primary.selectFirst(".title");
50+
51+
Element tabs = doc.createElement("div").attr("class", "switch");
52+
Element tab1 = tabs.appendElement("div");
53+
tab1.attr("class", "switch--item option-1 selected");
54+
if (secondaryTitle.equalsIgnoreCase("Kotlin")) {
55+
tab1.text("Java");
56+
} else {
57+
tab1.text(title.text());
58+
}
59+
60+
if (title.text().trim().equalsIgnoreCase(tab1.text().trim())) {
61+
title.remove();
62+
}
63+
64+
Element tab2 = tabs.appendElement("div");
65+
tab2.attr("class", "switch--item option-2");
66+
tab2.text(secondaryTitle);
67+
tabs.appendTo(primary);
68+
primaryContent.addClass("option-1");
69+
primaryContent.appendTo(primary);
70+
secondaryContent.appendTo(primary);
71+
secondaryContent.addClass("hidden").addClass("option-2");
72+
}
73+
}
74+
75+
private static void headerIds(Document doc) {
76+
headerIds(doc, 2);
77+
headerIds(doc, 3);
78+
headerIds(doc, 4);
79+
headerIds(doc, 5);
80+
}
81+
82+
private static void headerIds(Document doc, int level) {
83+
doc.select("h" + level).stream()
84+
.filter(not(DocPostprocessor::isDiscrete))
85+
.forEach(h -> {
86+
String id = h.attr("id");
87+
LinkedHashSet<String> name = new LinkedHashSet<>();
88+
int parent = level - 1;
89+
Element p = h.parents().select("h" + parent).first();
90+
if (p != null && !isDiscrete(p)) {
91+
String parentId = p.attr("id");
92+
if (!parentId.isEmpty()) {
93+
name.add(parentId);
94+
}
95+
}
96+
name.add(id.replaceAll("([a-zA-Z0-9-]+)-\\d+$", "$1"));
97+
String newId = String.join("-", name);
98+
if (!id.equals(newId)) {
99+
h.attr("id", newId);
100+
h.select("a").stream()
101+
.filter(a -> a.attr("href").equals("#" + id) && !a.attr("class").isEmpty())
102+
.forEach(a -> a.attr("href", "#" + newId));
103+
}
104+
});
105+
}
106+
107+
private static boolean isDiscrete(Element e) {
108+
return e.hasClass("discrete");
109+
}
110+
111+
private static void clipboard(Document doc) {
112+
for (Element code : doc.select("code.hljs")) {
113+
String id = "x" + Long.toHexString(UUID.randomUUID().getMostSignificantBits());
114+
code.attr("id", id);
115+
Element button = code.parent().appendElement("button");
116+
button.addClass("clipboard");
117+
button.attr("data-clipboard-target", "#" + id);
118+
Element img = button.appendElement("img");
119+
img.attr("src", "/images/clippy.svg");
120+
img.attr("class", "clippy");
121+
img.attr("width", "13");
122+
img.attr("alt", "Copy to clipboard");
123+
}
124+
}
125+
}

docs/src/main/java/io/jooby/adoc/JoobyExtensionRegistry.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ public class JoobyExtensionRegistry implements ExtensionRegistry {
1313
public void register(Asciidoctor asciidoctor) {
1414
asciidoctor.javaExtensionRegistry().block("dependency", DependencyProcessor.class);
1515
asciidoctor.javaExtensionRegistry().inlineMacro("javadoc", JavadocProcessor.class);
16+
asciidoctor.javaExtensionRegistry().postprocessor(DocPostprocessor.class);
1617
}
1718
}

0 commit comments

Comments
 (0)