package com.megatim.manuel.core.generate;
|
|
import com.megatim.manuel.core.convert.ConversionResult;
|
|
import java.io.IOException;
|
import java.nio.charset.StandardCharsets;
|
import java.nio.file.Files;
|
import java.nio.file.Path;
|
import java.util.List;
|
|
/**
|
* Ajoute la navigation au CHM :
|
* - une page d'accueil "index.html" (sommaire cliquable de toutes les pages) ;
|
* - une barre « ◀ Précédent | ▲ Sommaire | Suivant ▶ » en haut et en bas de chaque page.
|
*
|
* Ces liens fonctionnent à la fois dans l'aperçu de l'application et dans le CHM compilé,
|
* en complément des boutons natifs de la visionneuse (activés via la section [WINDOWS] du .hhp).
|
*/
|
public final class NavBuilder {
|
|
public static final String HOME = "index.html";
|
|
/** Construit la page d'accueil et injecte les barres de navigation. Renvoie le nom de la page d'accueil. */
|
public String build(Path dir, String title, List<ConversionResult> results) throws IOException {
|
writeHome(dir, title, results);
|
for (int i = 0; i < results.size(); i++) {
|
String prev = i > 0 ? results.get(i - 1).htmlFileName : null;
|
String next = i < results.size() - 1 ? results.get(i + 1).htmlFileName : null;
|
injectInto(dir.resolve(results.get(i).htmlFileName), prev, next);
|
}
|
return HOME;
|
}
|
|
private void writeHome(Path dir, String title, List<ConversionResult> results) throws IOException {
|
StringBuilder b = new StringBuilder();
|
b.append("<!DOCTYPE html>\n<html lang=\"fr\"><head>\n<meta charset=\"UTF-8\"/>\n")
|
.append("<title>").append(esc(title)).append("</title>\n")
|
.append("<link rel=\"stylesheet\" href=\"styles.css\"/>\n</head>\n<body>\n")
|
.append("<h1>").append(esc(title)).append("</h1>\n")
|
.append("<p>Sommaire de l'aide :</p>\n<ul class=\"home-toc\">\n");
|
for (ConversionResult r : results) {
|
b.append("<li><a href=\"").append(r.htmlFileName).append("\">")
|
.append(esc(r.title)).append("</a></li>\n");
|
}
|
b.append("</ul>\n</body></html>");
|
Files.write(dir.resolve(HOME), b.toString().getBytes(StandardCharsets.UTF_8));
|
}
|
|
private void injectInto(Path htmlFile, String prev, String next) throws IOException {
|
if (!Files.exists(htmlFile)) return;
|
String html = new String(Files.readAllBytes(htmlFile), StandardCharsets.UTF_8);
|
if (html.contains("class=\"navbar\"")) return; // déjà injecté
|
|
String bar = navbar(prev, next);
|
|
int bi = html.indexOf("<body>");
|
if (bi >= 0) {
|
int after = bi + "<body>".length();
|
html = html.substring(0, after) + "\n" + bar + html.substring(after);
|
}
|
int ci = html.lastIndexOf("</body>");
|
if (ci >= 0) {
|
html = html.substring(0, ci) + bar + "\n" + html.substring(ci);
|
}
|
Files.write(htmlFile, html.getBytes(StandardCharsets.UTF_8));
|
}
|
|
private String navbar(String prev, String next) {
|
StringBuilder b = new StringBuilder("<div class=\"navbar\">");
|
b.append(prev != null ? link(prev, "◀ Précédent") : disabled("◀ Précédent"));
|
b.append(link(HOME, "▲ Sommaire"));
|
b.append(next != null ? link(next, "Suivant ▶") : disabled("Suivant ▶"));
|
b.append("</div>");
|
return b.toString();
|
}
|
|
private String link(String href, String label) {
|
return "<a class=\"nav\" href=\"" + href + "\">" + label + "</a>";
|
}
|
|
private String disabled(String label) {
|
return "<span class=\"nav disabled\">" + label + "</span>";
|
}
|
|
private static String esc(String s) {
|
if (s == null) return "";
|
return s.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """);
|
}
|
}
|