feat: guide d'utilisation - couverture complete, telechargement MD/PDF, section Architecture Mermaid, guide desktop elargi (#105, BUG-067)
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Insère le nouveau contenu guide #105 dans frontend/index.html.
|
||||
|
||||
- 8 nouvelles sections + entrées de TOC (guide_content.py)
|
||||
- compléments h3 dans 5 sections existantes
|
||||
- BUG-067 : le bloc « Édition mobile » de help-edition devient la section
|
||||
dédiée help-mobile-editor (ancre morte → ancre vivante)
|
||||
- retire l'attribut data-i18n-placeholder dupliqué sur #help-nav-search
|
||||
|
||||
Idempotent : refuse de tourner deux fois (détecte guide105.* déjà présent).
|
||||
Préserve les fins de ligne CRLF de index.html.
|
||||
"""
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
from guide_content import ( # noqa: E402
|
||||
CONTENT,
|
||||
EXTRA_BLOCKS,
|
||||
NEW_SECTIONS,
|
||||
TOC_INSERT_BEFORE,
|
||||
)
|
||||
|
||||
HTML = Path("C:/dev/git/python/ObsiGate/frontend/index.html")
|
||||
|
||||
|
||||
_CRLF = False
|
||||
|
||||
|
||||
def to_crlf(s: str) -> str:
|
||||
return s.replace("\n", "\r\n") if _CRLF else s
|
||||
|
||||
|
||||
def main() -> int:
|
||||
with open(HTML, encoding="utf-8", newline="") as f:
|
||||
raw = f.read()
|
||||
global _CRLF
|
||||
_CRLF = "\r\n" in raw
|
||||
if _CRLF:
|
||||
raw = raw.replace("\r\n", "\n") # normaliser ; régénéré à l'écriture
|
||||
if "guide105." in raw:
|
||||
print("already inserted — abort")
|
||||
return 1
|
||||
|
||||
# Localise le guide (après la modale de config) : on opère uniquement dans
|
||||
# la fenêtre help-modal pour ne pas toucher le TOC #cfg-* de la config.
|
||||
guide_start = raw.index('<div class="editor-modal" id="help-modal">')
|
||||
head, guide = raw[:guide_start], raw[guide_start:]
|
||||
|
||||
# ── Fix BUG-067 : section mobile dédiée ────────────────────────────────
|
||||
m_h3 = guide.index('<h3 data-i18n="help.mobile_editor_title">')
|
||||
# le bloc va jusqu'à la fin de la section help-edition
|
||||
m_sec_end = guide.index("</section>", m_h3)
|
||||
mobile_block = guide[m_h3:m_sec_end]
|
||||
guide = guide[:m_h3] + guide[m_sec_end:]
|
||||
# h3 -> h2, et on emballe en section dédiée
|
||||
mobile_h2 = mobile_block.replace('<h3 data-i18n="help.mobile_editor_title">',
|
||||
'<h2 data-i18n="help.mobile_editor_title">', 1)
|
||||
mobile_h2 = mobile_h2.replace("</h3>", "</h2>", 1)
|
||||
mobile_section = (
|
||||
' <section class="help-section" id="help-mobile-editor">\n'
|
||||
+ mobile_h2.rstrip()
|
||||
+ "\n </section>\n\n"
|
||||
)
|
||||
# insérer après help-edition (donc avant help-graphe)
|
||||
anchor = guide.index('<section class="help-section" id="help-graphe">')
|
||||
guide = guide[:anchor] + mobile_section + guide[anchor:]
|
||||
|
||||
# ── Compléments h3 dans sections existantes ────────────────────────────
|
||||
for sec_id, block in EXTRA_BLOCKS:
|
||||
pat = 'id="%s"' % sec_id
|
||||
a = guide.index(pat)
|
||||
b = guide.index("</section>", a)
|
||||
guide = guide[:b] + to_crlf(block) + guide[b:]
|
||||
|
||||
# ── Nouvelles sections ─────────────────────────────────────────────────
|
||||
for sec_id, html, before_id in NEW_SECTIONS:
|
||||
anchor = guide.index('<section class="help-section" id="%s">' % before_id)
|
||||
guide = guide[:anchor] + to_crlf(html) + guide[anchor:]
|
||||
|
||||
# ── Entrées TOC ────────────────────────────────────────────────────────
|
||||
for key, href, before_href in TOC_INSERT_BEFORE:
|
||||
label = CONTENT[key][0]
|
||||
entry = to_crlf(
|
||||
" <li>\n"
|
||||
' <a href="%s" class="help-nav-link" data-i18n="guide105.%s">%s</a>\n'
|
||||
" </li>\n" % (href, key, label)
|
||||
)
|
||||
needle = 'href="%s"' % before_href
|
||||
# l'entrée <li> qui contient ce href
|
||||
i = guide.index(needle)
|
||||
li_start = guide.rindex("<li>", 0, i)
|
||||
guide = guide[:li_start] + entry + guide[li_start:]
|
||||
|
||||
# ── Anchor #help-ia mort (nav) → #help-ai (id de section réel) ─────────
|
||||
guide = guide.replace('href="#help-ia"', 'href="#help-ai"')
|
||||
|
||||
# ── Attribut dupliqué sur #help-nav-search ─────────────────────────────
|
||||
guide = guide.replace(
|
||||
' data-i18n-placeholder="help.search_placeholder" data-i18n-placeholder="help.search_placeholder"',
|
||||
' data-i18n-placeholder="help.search_placeholder"',
|
||||
1,
|
||||
)
|
||||
|
||||
out = head + guide
|
||||
if _CRLF:
|
||||
out = out.replace("\n", "\r\n")
|
||||
with open(HTML, "w", encoding="utf-8", newline="") as f:
|
||||
f.write(out)
|
||||
|
||||
# ── Vérifications structurelles ────────────────────────────────────────
|
||||
d = HTML.read_text(encoding="utf-8")
|
||||
opens, closes = len(re.findall(r"<section[\s>]", d)), d.count("</section>")
|
||||
print("section balance:", opens, closes)
|
||||
hrefs = set(re.findall(r'href="#(help-[a-z-]+)"', d))
|
||||
ids = set(re.findall(r'id="(help-[a-z-]+)"', d))
|
||||
missing = sorted(hrefs - ids)
|
||||
print("dead anchors:", missing or "none")
|
||||
return 0 if not missing else 2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user