algo/v0/compile_livre.py
Nicolas Cantu e93b10a719 Script de compilation, livre consolidé v0, structure v1 et correctifs
**Motivations:**
- Compilation du livre à partir des chapitres v0
- Création de la structure v1 avec chapitres et correctifs

**Evolutions:**
- v0/compile_livre.py : script de compilation
- v0/livre.md : livre consolidé généré
- Modifications des chapitres v0 (1-32), introduction, fermeture, plan_total_ouvrage, references, analyses critiques
- v1 : abstract, chapitres 1-16, correctifs chapitres 17-32, introduction, fermeture, plan_total_ouvrage, references

**Pages affectées:**
- v0/ : compile_livre.py (nouveau), livre.md (nouveau), chapitre1-32.md, introduction.md, fermeture.md, plan_total_ouvrage.md, references.md, analyse_critique_ouvrage*.md
- v1/ : abstract.md, chapitre1-16.md, correctifs/chapitre17-32.md, introduction.md, fermeture.md, plan_total_ouvrage.md, references.md (nouveaux)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-14 00:44:58 +01:00

119 lines
3.0 KiB
Python

from __future__ import annotations
from pathlib import Path
ROOT_DIR = Path(__file__).resolve().parent
OUTPUT_PATH = ROOT_DIR / "livre.md"
def strip_yaml_front_matter(text: str) -> str:
"""
Remove a leading YAML front-matter block:
---
...
---
Only strips when the file starts with '---' on the first line.
"""
lines = text.splitlines(keepends=True)
if not lines:
return text
if lines[0].strip() != "---":
return text
for idx in range(1, len(lines)):
if lines[idx].strip() == "---":
# Strip the closing '---' line too.
return "".join(lines[idx + 1 :])
return text
def normalize_section(source_filename: str, raw_text: str) -> str:
content = strip_yaml_front_matter(raw_text).lstrip("\n")
# Chapter 2 is missing a proper heading in v0; add it deterministically.
if source_filename == "chapitre2.md":
if content.startswith("Introduction\n\n"):
content = content.removeprefix("Introduction\n\n")
content = (
"# Chapitre 2 : Itération, finitude locale et répétition nécessaire\n\n"
"## Introduction\n\n"
f"{content}"
)
return f"{content.rstrip()}\n"
def build_sources() -> list[str]:
sources: list[str] = []
sources.append("introduction.md")
for i in range(1, 17):
sources.append(f"chapitre{i}.md")
sources.append("fermeture.md")
sources.append("analyse_critique_ouvrage.md")
for i in range(17, 24):
sources.append(f"chapitre{i}.md")
sources.append("analyse_critique_ouvrage2.md")
for i in range(24, 33):
sources.append(f"chapitre{i}.md")
sources.append("references.md")
sources.append("plan_total_ouvrage.md")
return sources
def main() -> None:
sources = build_sources()
missing = [name for name in sources if not (ROOT_DIR / name).exists()]
if missing:
missing_list = ", ".join(missing)
raise FileNotFoundError(f"Missing sources in {ROOT_DIR}: {missing_list}")
out_parts: list[str] = [
"---\n"
'livre: "Théorie des futurs accessibles"\n'
"version: v0\n"
"auteur: Nicolas Cantu\n"
"---\n\n"
"<!-- Compiled from v0/*.md sources. -->\n"
"<!-- Do not edit manually: run v0/compile_livre.py -->\n\n"
]
print(f"Writing {OUTPUT_PATH} from {len(sources)} sources.")
for idx, source in enumerate(sources):
source_path = ROOT_DIR / source
raw = source_path.read_text(encoding="utf-8")
content = normalize_section(source, raw)
print(f"- {source} ({content.count(chr(10))} lines)")
out_parts.append(f"<!-- BEGIN v0/{source} -->\n\n")
out_parts.append(content)
out_parts.append(f"\n<!-- END v0/{source} -->\n")
is_last = idx == len(sources) - 1
if not is_last:
out_parts.append("\n---\n\n")
OUTPUT_PATH.write_text("".join(out_parts), encoding="utf-8")
if __name__ == "__main__":
main()