"""7.68.0 — colonnes/math/TOC rendus + copier-couper-coller multi-blocs.""" from pathlib import Path ROOT = Path(__file__).resolve().parent.parent SRC = (ROOT / "static" / "js" / "page_editor_scripts.js").read_text(encoding="utf-8") CSS = (ROOT / "static" / "css" / "app.css").read_text(encoding="utf-8") def _fn(name: str, span: int = 1500) -> str: i = SRC.index(name + "(") return SRC[i:i + span] def test_renderers_are_actually_dispatched(): # les trois renderers existaient mais n'étaient JAMAIS appelés → # colonnes (slash + Turn into), équation et TOC rendaient un paragraphe vide dispatch = _fn("renderBlock") for call in ("renderColumnsBlock(b)", "renderMathBlock(b)", "renderTOC(b)"): assert call in dispatch, call assert SRC.count("function " + call.split("(")[0] + "(") == 1 # la suppression d'une colonne n'est plus un bouton invisible assert ".block-column-wrapper:hover .block-actions {" in CSS def test_gfm_tables_without_leading_pipe(): # l'IA rend souvent « A | B » / « --- | --- » — le pipe de tête est optionnel assert "s.indexOf('|')>=0&&_tblSplitLine(s).length>=2" in SRC # une ligne de séparation doit rester ≥2 cellules (sinon « texte » + « --- ») assert "if(cells.length<2)return false;return cells.every" in SRC # md2b ET paste2b passent par les mêmes helpers (alignés) assert SRC.count("_tblIsSep(lines[i+1])") == 2 def test_clipboard_multi_block_selection(): # état : sélection vivante traversant ≥2 blocs ; sinon null (natif) for tok in ("_clipState(){", "!s||!s.rangeCount||s.isCollapsed)return null;", "_srcOffset(sblk,r.startContainer,r.startOffset)", "_srcOffset(eblk,r.endContainer,r.endOffset)"): assert tok in SRC, tok # markdown : début partiel → blocs entiers → fin partielle assert "_clipMarkdown(st){" in SRC assert "blocksToMarkdown(b)" in SRC # coupure : premier/trois restent (têtes/queues), milieu supprimé assert "this.blocks.slice(0,st.si+1).concat([last],this.blocks.slice(st.ei+1))" in SRC # copy/cut restent branchés (menu contextuel, execCommand)… assert "ct.addEventListener('copy'," in SRC assert "ct.addEventListener('cut'," in SRC assert "ev.clipboardData.setData('text/plain',md)" in SRC # …mais le VRAI raccourci clavier est intercepté au keydown : le navigateur # n'émet aucun événement copy pour une sélection à travers deux # contenteditable (v7.69). assert "document.addEventListener('keydown'," in SRC assert "if(k!=='c'&&k!=='x')return;" in SRC # menu clic droit : groupe Clipboard Cut/Copy/Paste assert "'