Leonel FOFOU
2026-07-28 32450e295200b2bc7896518ff74161ff26772e2d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace("\"", "&quot;");
    }
}