package com.megatim.manuel.core.generate;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.megatim.manuel.core.convert.ConversionResult;
|
import com.megatim.manuel.core.convert.FrontMatter;
|
import com.megatim.manuel.core.convert.Heading;
|
|
import java.io.IOException;
|
import java.nio.charset.StandardCharsets;
|
import java.nio.file.Files;
|
import java.nio.file.Path;
|
import java.util.ArrayDeque;
|
import java.util.ArrayList;
|
import java.util.Deque;
|
import java.util.List;
|
|
/**
|
* Écrit le sommaire de l'aide sous forme de {@code toc.json} dans le dossier de sortie,
|
* rendant le dossier HTML autonome et lisible par le viewer JavaFX (remplace le .chm).
|
*/
|
public class HelpExporter {
|
|
public static final String TOC_JSON = "toc.json";
|
|
public void writeToc(Path dir, String title, List<ConversionResult> results, String homePage) throws IOException {
|
writeToc(dir, title, results, homePage, null, null);
|
}
|
|
public void writeToc(Path dir, String title, List<ConversionResult> results, String homePage,
|
String project, String version) throws IOException {
|
HelpManifest m = new HelpManifest();
|
m.project = project;
|
m.version = version;
|
m.title = title;
|
// Page d'accueil = page de garde du 1er document
|
m.home = results.isEmpty() ? homePage : results.get(0).htmlFileName;
|
|
for (ConversionResult r : results) {
|
HelpToc doc = new HelpToc(r.title, r.htmlFileName);
|
|
// 1. Accueil -> page de garde du document
|
doc.children.add(new HelpToc("Accueil (page de garde)", r.htmlFileName));
|
|
// 2. Préambule : regroupe Résumé, Mots clés, Historique, Diffusion (ordre canonique)
|
HelpToc preambule = new HelpToc("Préambule", null);
|
for (String key : FrontMatter.ENTRY_ORDER) {
|
String wanted = FrontMatter.label(key);
|
for (Heading lm : r.landmarks) {
|
if (wanted.equals(lm.text)) {
|
preambule.children.add(new HelpToc(lm.text, r.htmlFileName + "#" + lm.anchor));
|
break;
|
}
|
}
|
}
|
if (!preambule.children.isEmpty()) doc.children.add(preambule);
|
|
// 3. Sommaire (chapitres), numéroté hiérarchiquement (1, 1.1, 1.1.1, 2…)
|
List<HelpToc> tree = buildHeadingTree(r);
|
if (!tree.isEmpty()) {
|
numberTree(tree, "");
|
HelpToc som = new HelpToc("Sommaire", null);
|
som.children.addAll(tree);
|
doc.children.add(som);
|
}
|
|
// 4. Illustrations (légendes)
|
if (!r.figures.isEmpty()) {
|
HelpToc figs = new HelpToc("Illustrations", null);
|
for (Heading f : r.figures) {
|
figs.children.add(new HelpToc(f.text, r.htmlFileName + "#" + f.anchor));
|
}
|
doc.children.add(figs);
|
}
|
|
m.nodes.add(doc);
|
}
|
|
ObjectMapper mapper = new ObjectMapper();
|
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(m);
|
Files.write(dir.resolve(TOC_JSON), json.getBytes(StandardCharsets.UTF_8));
|
}
|
|
/** Préfixe chaque titre du sommaire par sa numérotation hiérarchique (1, 1.1, 1.1.1, 2…). */
|
private void numberTree(List<HelpToc> nodes, String prefix) {
|
int i = 1;
|
for (HelpToc n : nodes) {
|
String num = prefix.isEmpty() ? String.valueOf(i) : prefix + "." + i;
|
n.title = num + ". " + n.title;
|
numberTree(n.children, num);
|
i++;
|
}
|
}
|
|
/** Convertit la liste plate de titres (avec niveaux) en arbre imbriqué. */
|
private List<HelpToc> buildHeadingTree(ConversionResult r) {
|
List<HelpToc> roots = new ArrayList<>();
|
if (r.headings.isEmpty()) return roots;
|
|
int min = Integer.MAX_VALUE;
|
for (Heading h : r.headings) min = Math.min(min, Math.max(1, h.level));
|
|
Deque<HelpToc> nodes = new ArrayDeque<>();
|
Deque<Integer> levels = new ArrayDeque<>();
|
for (Heading h : r.headings) {
|
int lvl = Math.max(1, h.level) - min + 1;
|
HelpToc node = new HelpToc(h.text, r.htmlFileName + "#" + h.anchor);
|
while (!levels.isEmpty() && levels.peek() >= lvl) { levels.pop(); nodes.pop(); }
|
if (nodes.isEmpty()) roots.add(node); else nodes.peek().children.add(node);
|
nodes.push(node);
|
levels.push(lvl);
|
}
|
return roots;
|
}
|
}
|