Communitygithub.com

KehanLiu/anim-slides

Transformez des diapositives ennuyeuses en illustrations SVG animées et autonomes. Créez des animations riches en CSS qui remplacent les blocs de texte et les captures d'écran dans n'importe quel diaporama HTML, directement à partir de documentation de processus, dépendances, chronologies ou architectures.

Qu'est-ce que anim-slides ?

Ce skill génère des illustrations SVG animées pour des diaporamas, à partir de diapositives existantes ou de documentation. La sortie est toujours un **fragment** : un fichier HTML unique avec une balise `<style>` et un `<svg>`, sans scripts, sans fichiers externes, thématisé par variables CSS, prêt à être intégré dans n'importe quel diaporama. Il est particulièrement utile lorsque le contenu d'une diapositive (texte, liste à puces, capture d'écran) représente un processus, un flux, une structure de dépendances, une chronologie, une comparaison, une architecture ou une série temporelle. Le skill suit un workflow en plusieurs étapes : (0) récupération de la diapositive HTML source, (1) spécification du fragment avec un fichier YAML décrivant les nœuds, arêtes, groupes et phases, (2) mesure du slot disponible et rédaction d'un brief détaillé, (3) construction du fragment à partir de la spécification, (4) vérification visuelle et validation automatique, et (5) intégration dans le diaporama via des marqueurs de commentaires. Il prend en charge deux modes de contrôle : `once` (lecture automatique unique au passage de la diapositive) et `step` (navigation pas à pas au clic). Le skill s'intègre avec des frameworks HTML comme reveal.js, impress.js, Slidev ou frontend-slides, et peut également traiter des fichiers PPTX ou Markdown convertis au préalable par un skill de diaporama dédié.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/KehanLiu/anim-slides/tree/HEAD

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait anim-slides ?

Illustrations SVG animées pour diaporamas, à partir de diapositives existantes ou de documentation. La sortie est toujours un fragment : un fichier HTML avec une balise <style> et un <svg>, sans scripts, sans fichiers externes, thématisé par variables CSS, qui s'intègre dans n'importe quel diaporama. references/fragment-contract.md est le contrat. Lisez-le avant de construire quoi que ce soit.

Quand l'utiliser

  • Une diapositive contient une rangée de cartes textuelles, une liste à puces ou une capture d'écran, et le contenu représente un processus, un flux, une structure de dépendances, une chronologie, une comparaison, une architecture ou une série temporelle.
  • Un document (Markdown, export Confluence, README, bloc Mermaid) décrit un processus ou des dépendances et l'utilisateur souhaite le voir affiché sous forme d'animation sur une diapositive ou une page.
  • L'hôte est un diaporama HTML (frontend-slides, reveal.js, impress.js, Slidev, écrit à la main) ou une page web simple. Un fichier .pptx ou une source Markdown est d'abord converti en diaporama HTML conçu par un skill de diaporama (étape 0) ; ce skill ajoute ensuite les illustrations.

Workflow

<skill-dir> ci-dessous est le dossier qui contient ce SKILL.md (Claude Code l'expose sous $CLAUDE_SKILL_DIR ; dans d'autres environnements, utilisez le chemin à partir duquel vous avez chargé ce fichier). Les scripts nécessitent Python 3.9+ et, pour le rendu, un binaire Chrome ou Chromium. anim/<name>/ est un dossier à côté du diaporama de l'utilisateur.

0. Récupération

Obtenez d'abord un diaporama HTML. anim-slides ajoute des figures à un diaporama HTML ; il n'en conçoit pas un.

  • La source est déjà un diaporama HTML (reveal.js, impress.js, tout <section> ou .slide diaporama) : continuez.
  • La source est un fichier .pptx, Markdown, remark, un document ou tout autre chose qui n'est pas un diaporama HTML : un skill de diaporama construit d'abord le diaporama HTML, pas anim-slides. Par ordre de préférence : (a) le propre skill de diaporama de l'utilisateur ou de l'organisation, s'il est installé ; (b) frontend-slides, lorsqu'il est installé (il convertit pptx et Markdown en un diaporama HTML conçu ; lorsqu'il propose des aperçus esthétiques, choisissez celui qui se rapproche le plus de la marque du diaporama source, sauf si l'utilisateur souhaite un nouveau look) ; (c) uniquement lorsqu'aucun skill de diaporama n'est installé, scripts/md_to_deck.py comme solution de repli (voir la puce de repli ci-dessous), et dites à l'utilisateur en une phrase que sa sortie est un hôte simple, pas un design, et qu'elle ressemblera à un document jusqu'à ce qu'un skill de diaporama ou un designer le style. Dans les cas (a) et (b), le fichier .pptx original reste la source pour extract_slides.py et render_deck.py de triage (graphiques, figures, notes), mais l'intégration cible le diaporama produit par le skill, et l'apparence correspondante provient de la palette de ce diaporama via host_theme.py. Demandez au skill de diaporama (ou faites-le juste après) d'envelopper le corps de chaque diapositive candidate dans un slot <div id="sN-slot"> de taille fixe entre <!-- sN-body --> et <!-- /sN-body --> (l'identifiant et les noms de marqueurs que md_to_deck.py utilise, bien qu'ici le slot soit un frère vide du corps) : measure_slot.py --selector '#sN-slot' est alors exact, et integrate_fragment.py --anchor/--replace-until cible les marqueurs. Le lien de police propre au skill de diaporama (Google Fonts, Fontshare) est le chargement du diaporama, pas un ajouté par anim-slides ; conservez-le et intégrez-le lors de la remise avec bundle_deck.py --fetch.

Ensuite, décidez quel point d'entrée s'applique :

  • Diaporama existant : exécutez python3 <skill-dir>/scripts/extract_slides.py deck.pptx|deck.html|doc.md -o anim/outline.json et python3 <skill-dir>/scripts/render_deck.py deck -o anim/render, puis regardez les planches de contact sheet-NN.png (12 diapositives numérotées chacune), pas page par page (lorsque le nombre d'images d'une diapositive dans outline.json diffère des images dans son rendu, examinez les images de la mise en page de la diapositive : une photo de couverture sur la mise en page est facile à manquer) ; puis triez avec references/input-stage.md et écrivez le tableau dans anim/triage.md : chaque diapositive, une décision et une raison, pas de sauts silencieux (3 à 8 illustrations pour 30 diapositives est normal ; sur un petit diaporama, chaque processus, structure, chronologie, comparaison ou diapositive de données en reçoit une). Ensuite, définissez l'apparence une fois pour l'ensemble du diaporama : match (les fragments prennent la palette et les polices de l'hôte, la valeur par défaut pour les diaporamas de marque ou d'entreprise) ou lean (les fragments conservent la palette épurée sur un fond sombre, pour les discours et les présentations). python3 <skill-dir>/scripts/host_theme.py deck.html --mode match -o anim/host-theme.css dérive la colle de correspondance du CSS du diaporama (--mode lean écrit la colle épurée) ; comparez le bloc dérivé une fois avec les propres variables du diaporama (une couleur de texte atténuée, un arrière-plan secondaire) et corrigez manuellement là où la dérivation a choisi un mélange calculé ; rendez le premier fragment des deux manières (render-phases.sh --theme anim/host-theme.css ...) et montrez les deux images avant de construire le reste, sauf si l'utilisateur a déjà nommé une apparence. Seules les couleurs et les polices changent entre les deux : les règles de forme de references/style.md s'appliquent aux deux. Le contrôle est once pour l'ensemble du diaporama, sauf si l'utilisateur demande un clic : la figure de chaque diapositive joue un passage calme lorsque la diapositive apparaît, puis se repose. Ne recommandez pas step de votre propre chef. Mentionnez-le en une ligne uniquement lorsque outline.json signale des builds supérieurs à 0 (la source se construit déjà par clic : fragments reveal.js, animations PowerPoint par clic, sous-étapes impress.js, les propres étapes de construction du diaporama) : "votre diaporama se construit par clic ; les figures peuvent faire de même (step), dites-le si vous le souhaitez". Sous step, l'entrée se dessine et chaque clic amène la phase suivante ; les phases sont les phases narrées du brief (3 à 5 par diapositive), le fichier fragment est le même, et le clic repose sur la propre navigation du diaporama. Step écoute uniquement les touches, donc un diaporama step est présenté avec le clavier ou un cliqueur (un diaporama qui navigue également par roue ou balayage, comme le fait frontend-slides, saute les phases lors d'un défilement). Écrivez Apparence et Contrôle dans l'en-tête de anim/triage.md.
  • Repli, aucun skill de diaporama installé (Markdown, remark, ou un pptx extrait en Markdown) : python3 <skill-dir>/scripts/md_to_deck.py deck.md -o deck.html crée un hôte simple et autonome pour l'intégration (une <section> par diapositive, portail .visible, mise en page d'impression, marqueurs <!-- sN-body --> autour du corps de chaque diapositive). Ce n'est pas un diaporama conçu : dites-le à l'utilisateur en une phrase. Récupérez d'abord les images référencées par le Markdown (chemins relatifs) dans le même dossier, sinon le diaporama affiche des espaces réservés ; puis extrayez de la source originale (le fichier .pptx s'il y en avait un) ou du Markdown.
  • Documentation : lisez la source, choisissez l'archétype avec le tableau dans references/archetypes.md, extrayez une spécification (étape 1).
  • Demande de diapositive unique : allez directement à l'étape 1 pour cette diapositive. Demandez à l'utilisateur uniquement lorsque la source est ambiguë quant à l'ordre, la direction ou le regroupement. Sinon, énoncez l'hypothèse dans le brief et continuez.

1. Spécification

Écrivez anim/<name>/spec.yaml en suivant references/spec-format.md : nom, archétype, nœuds, arêtes, groupes, phases avec marques de secondes, cycle (la durée du passage), contrôle (le choix du diaporama lors de la récupération : once, un passage calme de 4 à 10 s lorsque la diapositive devient courante, se terminant sur le cadre de repos ; step, le même passage coupé aux marques de phase pour que chaque clic amène la phase suivante ; loop uniquement lorsque l'utilisateur demande une boucle continue). Le fichier fragment est le même sous once et step ; les marques de phase deviennent data-anim-phases. Réutilisez les propres mots de la source comme étiquettes. Gardez une spécification sous environ 12 nœuds ; sinon, divisez.

1b. Vérifier le pool

Lisez <skill-dir>/pool/index.yaml, puis $ANIM_POOL/index.yaml (ou listez $ANIM_POOL/*/) si cette variable est définie, et cherchez une entrée avec le même archétype et une histoire ou des balises similaires.

  • Correspondance proche : copiez le dossier dans anim/<name>/, renommez le fragment et chaque préfixe en <name>, puis adaptez les étiquettes, les données, le timing et la viewBox à la spécification à l'étape 3 au lieu de l'échafaudage. Son spec.yaml, s'il est présent, est un point de départ pour le vôtre.
  • Même archétype uniquement : échafaudez comme d'habitude et ouvrez le fragment du pool comme barre de qualité pour la densité, le mouvement et le cadre de repos.
  • Rien ne correspond : construisez à partir de la spécification ; l'entrée la plus proche du pool vaut toujours un coup d'œil. Ne copiez jamais un fragment du pool inchangé dans un diaporama : son histoire est un exemple, pas celle de l'utilisateur.

2. Slot et brief

Mesurez la zone libre sur la diapositive : python3 <skill-dir>/scripts/measure_slot.py deck.html --slide N [--selector SEL] [--ignore .body] affiche la zone en pixels de la scène, une viewBox correspondante et les indicateurs de vérificateur (references/layouts.md explique la méthode manuelle). Sur une mise en page positionnée de manière absolue, la mesure sans --selector renvoie des données inutilisables ; mesurez le div slot (--selector '#sN-slot', étape 0). Choisissez une viewBox avec le même rapport d'aspect, et remplissez anim/<name>/brief.md à partir de references/brief-template.md. Le brief fixe la viewBox et la taille rendue, la composition, les phases, le cadre de repos, les jetons de thème et la taille minimale du texte, et nomme ce que le fragment remplace sur la diapositive (les pilules, le diagramme en boîte, la colonne de puces). La qualité du fragment suit la qualité du brief.

3. Construction

python3 <skill-dir>/scripts/scaffold_from_spec.py anim/<name>/spec.yaml -o anim/<name>/<name>.html --rendered-width <px> valide la spécification et écrit un squelette conforme au contrat (mise en page, phases, paquets, notes, cadre de repos ; tailles de police relevées au minimum pour la largeur rendue), puis exécute le vérificateur dessus. Le commentaire en haut de la sortie liste ce qui doit être affiné manuellement. Affinez-le en l'illustration que le brief décrit, en utilisant references/archetypes.md pour la composition et le mouvement, references/motion-rules.md pour le timing et l'assouplissement, et references/style.md pour l'apparence (lean : anneaux et lignes fines, pas de boîtes, un accent lumineux, sous-étiquettes mono, légendes simples). Pour plusieurs illustrations, construisez un fragment à la fois à partir des briefs partagés, ou un sous-agent parallèle par fragment si l'environnement les supporte ; l'intégration reste toujours dans le thread principal.

4. Vérification visuelle

  1. python3 <skill-dir>/scripts/check_fragment.py anim/<name>/<name>.html --name <name> --rendered-width <px> --stage-width <largeur de scène du diaporama> doit réussir (préfixes, jetons, portails, taille du texte, contenu interdit). --stage-width définit le seuil de texte (18 px à 1920, 12 px à 1280) ; outline.json indique la scène.
  2. <skill-dir>/scripts/render-phases.sh anim/<name> <W> <H> 1.5 4 7 10 rest rend les PNG de phase et une planche de contact avec la méthode pause et délai négatif, dans un dossier temporaire qu'il imprime (passez --out DIR pour choisir). Après intégration, render-phases.sh --page deck.html 1920 1080 rest vérifie le cadre de repos de la page hôte ; sur une page multi-diapositives, ajoutez --slide N (ou #hash, ou un sélecteur CSS). Utilisez --no-script pour les images de marque temporelle ou de phase lorsque le propre script de la page bascule la classe de portail, jamais pour rest : dans les diaporamas frontend-slides, .visible est à la fois le portail et la classe qui affiche la diapositive, le rendu du repos l'enlève, et la diapositive reste affichée uniquement parce que le script du diaporama définit également .active ; sans script, le cadre de repos est vide. Ouvrez chaque PNG avec votre outil de visualisation d'images. Corrigez le rognage, les chevauchements, le texte illisible, les panneaux vides. Itérez au moins une fois.
  3. Le cadre de repos doit être lisible comme une image fixe complète (l'export PDF n'affiche que cela).
  4. python3 <skill-dir>/scripts/verify_facts.py anim/<name>/<name>.html --source anim/outline.json --slide <N> (ou --source doc.md) doit réussir : chaque nombre dans le fragment provient de la source ou est marqué comme illustratif ; lisez chaque AVERTISSEMENT et remplacez les formulations introuvables par les propres mots de la source ou supprimez-les. Règles dans references/accuracy.md. Une figure n'est pas terminée tant que cela ne réussit pas. Ne faites jamais confiance à --virtual-time-budget, et ne faites jamais confiance à la lecture de la source au lieu du PNG.

5. Intégration

python3 <skill-dir>/scripts/integrate_fragment.py deck.html anim/<name>/<name>.html --name <name> --anchor '<chaîne unique dans la diapositive>' [--replace-until '<chaîne>'] [--gate 'section.present'] [--control once|step] --backup lève le style dans l'en-tête, insère le fragment entre les marqueurs <!-- anim:<name>:start --> et <!-- anim:<name>:end --> (le style entre les marqueurs anim-style ; une réexécution remplace les deux copies), réécrit le portail pour le diaporama hôte, et préfixe toute classe qui aurait échappé. Pour les pages simples, copiez <skill-dir>/scripts/snippets/observer.html dans la page. --control définit le contrôle du diaporama sur le wrapper ; --control step met également scripts/snippets/step-host.html (un petit script simple, sans bibliothèque) dans l'en-tête une fois et définit son portail à partir de --gate. Le contrôle est un commutateur à l'échelle du diaporama lors de l'intégration : réexécutez avec l'autre valeur pour le modifier, les fragments restent tels quels. L'ancre et la chaîne jusqu'à sont conservées ; ce qui se trouve entre elles est remplacé. Le portail est le marqueur "diapositive courante" de l'hôte : section.present pour reveal.js, .visible pour les pages simples (scripts/snippets/observer.html) et pour les diaporamas de md_to_deck.py. Dans les diaporamas md_to_deck.py, et dans les diaporamas de skills de diaporama avec les marqueurs de slot de l'étape 0, le fragment remplace le corps : --anchor '<!-- sN-body -->' --replace-until '<!-- /sN-body -->'. Vérifiez que les titres et le texte du corps de la diapositive s'affichent sans le script du diaporama et à l'impression. Les animations d'entrée des skills de diaporama animent souvent leurs révélations uniquement sur la classe de diapositive courante (frontend-slides affiche les éléments .reveal uniquement sous .slide.visible), donc les rendus de repos et les PDF affichent des diapositives vides ; animez également ces révélations sur la classe active du diaporama (.slide.active) et ajoutez une règle d'impression qui les affiche. (Le nom de classe .reveal correspond également à la détection reveal.js dans les sélecteurs de diapositives de host_theme.py ; inoffensif jusqu'à présent, mais vérifiez quelles diapositives il a trouvées.) Il ajoute également un garde d'impression afin que l'export PDF (le ?print-pdf de reveal marque chaque diapositive présente) affiche les cadres de repos. Gardez le diaporama de travail léger : les fragments sont du petit texte SVG et s'insèrent par marqueurs, mais ne intégrez pas de polices, d'images, de bibliothèques ou de feuilles de style pendant que vous travaillez, et ne lisez jamais l'ensemble du diaporama dans le contexte ; lisez des tranches autour de l'ancre (grep -n, sed -n) et laissez les scripts l'éditer. Ouvrez ensuite le diaporama dans un vrai navigateur et regardez...

Skills associés