Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions scripts/notebook_tools/scan_slidev_composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ def measure_slide(page, slide_idx: int, canvas_w: int, canvas_h: int) -> dict:
// (RECOUVREMENT ci-après), qui mesure le contenu rendu et
// l'ordre de peinture au lieu de la boîte élément naïve.
const chevauchements = [];
// #16188 : paires éteintes par la confirmation élément ci-dessous.
// Un correctif muet serait indiscernable d'un organe mort : la
// notice [CHEVAUCHEMENT-FANTOME] rapporte ce compte (#12719
// acceptance 4 -- dire ce qu'on a refusé de rapporter).
let chevauchementsEteints = 0;
const textEls = Array.from(
root.querySelectorAll('h1, h2, h3, h4, p, li, blockquote, td, th')
);
Expand Down Expand Up @@ -332,7 +337,7 @@ def measure_slide(page, slide_idx: int, canvas_w: int, canvas_h: int) -> dict:
const eb = b.el.getBoundingClientRect();
const eOverlapX = Math.min(ea.right, eb.right) - Math.max(ea.left, eb.left);
const eOverlapY = Math.min(ea.bottom, eb.bottom) - Math.max(ea.top, eb.top);
if (eOverlapX <= 0 || eOverlapY <= 0) continue;
if (eOverlapX <= 0 || eOverlapY <= 0) { chevauchementsEteints++; continue; }
chevauchements.push({
a: a.key, b: b.key,
a_bbox: [Math.round(a.left), Math.round(a.top), Math.round(a.right), Math.round(a.bottom)],
Expand Down Expand Up @@ -538,7 +543,7 @@ def measure_slide(page, slide_idx: int, canvas_w: int, canvas_h: int) -> dict:
};
}

return { horsCanvas, chevauchements, recouvrements, occupation, contentBottom: Math.round(contentBottom) };
return { horsCanvas, chevauchements, chevauchementsEteints, recouvrements, occupation, contentBottom: Math.round(contentBottom) };
}""",
[canvas_w, canvas_h],
)
Expand All @@ -554,6 +559,7 @@ def measure_slide(page, slide_idx: int, canvas_w: int, canvas_h: int) -> dict:
"hors_canvas": hors,
"container_only": bool(hors) and not any(h.get("tag") in CONTENT_TAGS for h in hors),
"chevauchements": raw.get("chevauchements", []),
"chevauchements_eteints": raw.get("chevauchementsEteints", 0),
"recouvrements": raw.get("recouvrements", []),
"occupation": raw.get("occupation"),
}
Expand Down Expand Up @@ -664,6 +670,15 @@ def github_annotations(report: dict, slides_md: Path) -> list[str]:
f"::warning file={rel},line={line}::[CHEVAUCHEMENT] slide {r['slide']} ({head}) — "
f"{c['a']} × {c['b']} overlap={c['overlap']}px element_overlap={c.get('element_overlap')}px"
)
# #16188 : la porte de confirmation élément (#15695) est un témoin,
# pas un silence -- chaque effleurement Range qu'elle éteint est
# compté et rapporté en notice. Non bloquant par construction.
if r.get("chevauchements_eteints"):
out.append(
f"::notice file={rel},line={line}::[CHEVAUCHEMENT-FANTOME] slide {r['slide']} ({head}) — "
f"{r['chevauchements_eteints']} effleurement(s) Range éteint(s) par la "
f"confirmation élément (#15695) : boîtes élément disjointes, rien à l'écran"
)
for rv in r.get("recouvrements", [])[:3]:
out.append(
f"::warning file={rel},line={line}::[RECOUVREMENT-TEXTE-IMAGE] slide {r['slide']} — "
Expand Down Expand Up @@ -759,6 +774,7 @@ def main():
n_total = len(results)
n_hors = sum(1 for r in results if content_overflow(r))
n_chev = sum(1 for r in results if r.get("chevauchements"))
n_eteints = sum(r.get("chevauchements_eteints") or 0 for r in results)
n_rec = sum(1 for r in results if r.get("recouvrements"))
n_occ = sum(1 for r in results if occupation_flagged(r, canvas_h))

Expand Down Expand Up @@ -790,6 +806,7 @@ def main():
"n_slides": n_total,
"n_hors_canvas": n_hors,
"n_chevauchements": n_chev,
"n_chevauchements_eteints": n_eteints,
"n_recouvrements": n_rec,
"n_occupation_flagged": n_occ,
"recouvrement_borne": (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ def _build(baseline_slide):
"canvas_w": 980, "canvas_h": 552,
"BORNE": "ADVISORY",
"ctrl_positif_ok": None, "ctrl_positif_msg": None,
"n_total": 0, "n_hors": 0, "n_chev": 0, "n_rec": 0, "n_occ": 0,
"n_total": 0, "n_hors": 0, "n_chev": 0, "n_eteints": 0, "n_rec": 0, "n_occ": 0,
}
exec(block, ns)
return ns["report"]
Expand Down
48 changes: 48 additions & 0 deletions scripts/tests/test_scan_slidev_composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,54 @@ def test_hors_canvas_contenu_inchange(self):
assert "::warning" in hc and "IMG" in hc


class TestTemoinsChevauchementsFantomes16188:
"""#16188 : les effleurements Range eteints par la porte de confirmation
element (#15695) sont comptes et rapportes en notice -- un correctif muet
serait indiscernable d'un organe mort."""

def test_paire_rapportee_porte_les_deux_mesures(self):
r = {
"slide": 6, "text_head": "vraie collision",
"hors_canvas": [], "chevauchements": [{
"a": "P.x", "b": "P.y", "a_bbox": [1, 2, 3, 4],
"b_bbox": [2, 3, 5, 6], "overlap": [12, 8],
"element_overlap": [11.5, 7.25],
}],
"chevauchements_eteints": 0,
"recouvrements": [], "occupation": None,
}
lines = ssc.github_annotations(_report([r]), Path("slides.md"))
chev = next(l for l in lines if "[CHEVAUCHEMENT]" in l)
assert "overlap=[12, 8]px" in chev
assert "element_overlap=[11.5, 7.25]px" in chev

def test_effleurement_eteint_emet_une_notice_comptee(self):
r = {
"slide": 16, "text_head": "graze code padding",
"hors_canvas": [], "chevauchements": [],
"chevauchements_eteints": 1,
"recouvrements": [], "occupation": None,
}
lines = ssc.github_annotations(_report([r]), Path("slides.md"))
fant = next(l for l in lines if "CHEVAUCHEMENT-FANTOME" in l)
assert "::notice" in fant
assert "1 effleurement" in fant
assert "#15695" in fant
assert not any("[CHEVAUCHEMENT]" in l for l in lines), (
"eteint = pas de warning CHEVAUCHEMENT"
)

def test_slide_propre_sans_eteints_n_emet_rien(self):
r = {
"slide": 2, "text_head": "propre",
"hors_canvas": [], "chevauchements": [],
"chevauchements_eteints": 0,
"recouvrements": [], "occupation": None,
}
lines = ssc.github_annotations(_report([r]), Path("slides.md"))
assert not any("CHEVAUCHEMENT" in l for l in lines)


class TestBornesAdvisory:
def test_borne_documentee_dans_docstring(self):
"""Le signal est ADVISORY : le docstring du module (charge par
Expand Down
Loading