Extraire du HTML statique
Extraire un fichier HTML statique autonome à partir de n'importe quelle application web.
Quelle stratégie utiliser
Vous DEVEZ demander à l'utilisateur de choisir quelle stratégie utiliser avant de continuer. Présentez les options clairement, recommandez la stratégie A comme valeur par défaut préférée, et fournissez un résumé bref avantages/inconvénients pour chaque option pour l'aider à prendre une décision éclairée.
| Stratégie A (Puppeteer) | Stratégie B (Subagent navigateur) | |
|---|---|---|
| Quand | App exécutée localement, pas de mur d'authentification | Besoin d'interagir avec la page d'abord (cliquer, remplir des formulaires) |
| Fidélité | Maximale — styles calculés résolus | Élevée — DOM rendu |
| Configuration | Zéro — aucun mock nécessaire | Zéro — aucun mock nécessaire |
| Framework | Quelconque | Quelconque |
| Sortie | Écrit dans un fichier — pas de limite de taille | Peut être tronquée dans le contexte agent |
[!WARNING] Point de contrôle — Confirmation utilisateur requise. Vous DEVEZ demander à l'utilisateur quelle stratégie il préfère avant de continuer. Présentez le tableau de comparaison ci-dessus, recommandez la stratégie A par défaut, et attendez l'approbation explicite. Ne DÉCIDEZ PAS vous-même et ne continuez PAS jusqu'à la confirmation de l'utilisateur.
Stratégie A : Snapshot Puppeteer (Recommandé)
Lance Chrome sans interface, capture le DOM entièrement rendu, et produit un fichier HTML autonome avec tout le CSS intégré et les images en base64. Fonctionne avec n'importe quel framework — aucun MockPage.jsx nécessaire.
Prérequis
- App exécutée localement (par exemple,
npm run dev) - Node.js avec
puppeteerdisponible (vérifiez :node -e "require('puppeteer')")
Flux de travail
-
Démarrer l'app et noter le port.
[!WARNING] Point de contrôle — Confirmation utilisateur requise. Après avoir démarré le serveur local, vous DEVEZ faire une pause et demander la confirmation de l'utilisateur avant d'exécuter le script snapshot ou de lancer un subagent navigateur. Rapportez l'URL et le port à l'utilisateur afin qu'il puisse vérifier que l'app s'exécute et s'affiche correctement. Ne CONTINUEZ PAS jusqu'à l'étape snapshot jusqu'à la confirmation de l'utilisateur.
-
Exécutez le script snapshot :
npx tsx <SKILL_DIR>/scripts/snapshot.ts \ --url http://localhost:5173 \ --output .stitch/home.html \ --wait 2000 -
Pages multiples — exécutez une fois par route :
npx tsx <SKILL_DIR>/scripts/snapshot.ts \ --url http://localhost:5173 --output .stitch/home.html --wait 2000 npx tsx <SKILL_DIR>/scripts/snapshot.ts \ --url http://localhost:5173/pricing --output .stitch/pricing.html --wait 2000 npx tsx <SKILL_DIR>/scripts/snapshot.ts \ --url http://localhost:5173/dashboard --output .stitch/dashboard.html --wait 2000 --html-class dark
Drapeaux du script
| Drapeau | Par défaut | Description |
|---|---|---|
--url |
(requis) | URL à capturer |
--output |
(requis) | Chemin du fichier de sortie |
--wait |
1000 |
Attente supplémentaire (ms) après l'inactivité réseau. Augmentez pour les apps avec chargement différé. |
--viewport |
1280x800 |
Taille de la fenêtre comme LARGEURxHAUTEUR |
--html-class |
— | Classe(s) pour l'élément <html> (par exemple, dark) |
--remove-fixed |
false |
Supprimer les éléments fixed/sticky (bandeaux de cookies, widgets de chat) |
--full-height |
false |
Redimensionner la fenêtre à la hauteur complète du défilement |
--title |
— | Remplacer le titre de la page |
Ce qu'il fait automatiquement
- Intègre tous les
<link rel="stylesheet">→ blocs<style> - Convertit les
srcdes<img>etsrcset→ data URIs base64 (ignore les polices) - Intègre les URLs
<source srcset>en base64 - Supprime les entrées
srcsetdéfaillantes/mortes pour que le navigateur revienne ausrcintégré - Supprime les balises
<script>, l'overlay Vite, les indicateurs de développement Next.js - Résout les chemins
url()CSS relatifs avant intégration
Remarques par framework
| Framework | Remarques |
|---|---|
| React + Vite | Fonctionne d'emblée. --wait 1000. |
| Next.js | --wait 3000 pour l'hydratation SSR. URL : http://localhost:3000. <img srcset> depuis /_next/image est intégré automatiquement en base64. |
| Vue / Nuxt | Fonctionne d'emblée. |
| Svelte / SvelteKit | Fonctionne d'emblée. |
| Storybook | Utilisez l'URL de story : --url http://localhost:6006/?path=/story/... |
| SSR (Webpack) | Peut nécessiter un --wait plus long. |
Dépannage
| Problème | Solution |
|---|---|
| Images manquantes | Augmentez --wait |
| Les images s'affichent cassées après arrêt du serveur | Vérifiez que srcset a été intégré — consultez le journal pour « Inlined N images ». Si les URLs srcset ont échoué, elles sont auto-supprimées pour que src (intégré) soit utilisé. |
Next.js /_next/image non intégré |
Assurez-vous que le serveur de développement s'exécute lors de l'execution du snapshot — le script récupère les images optimisées depuis le serveur en cours d'exécution. |
| Mode sombre non appliqué | --html-class dark |
| Bandeau de cookies dans la sortie | --remove-fixed |
| La page nécessite une connexion | Utilisez le Static Fallback (appendice ci-dessous) |
Cannot find module 'puppeteer' |
npm install -g puppeteer |
Stratégie B : Capture avec subagent navigateur
À utiliser quand vous devez interagir avec la page (cliquer sur des boutons, remplir des formulaires, naviguer dans les onglets) avant de la capturer. Le subagent navigateur vous donne un contrôle total mais la sortie peut être tronquée pour les grandes pages.
Flux de travail
-
Démarrer l'app localement.
-
Naviguer en utilisant un subagent navigateur.
-
Interagir comme nécessaire (cliquer, défiler, remplir des formulaires).
-
Extraire le DOM :
document.documentElement.outerHTML[!WARNING] Les grandes pages peuvent être tronquées. Pour gérer cela :
- Supprimez les balises
<style>avant extraction :document.querySelectorAll('style').forEach(el => el.remove()) - Rajoutez les styles statiquement (lien CDN Tailwind, CSS source)
- Supprimez les balises
-
Enregistrer dans un fichier.
Appendice : Fallback statique (MockPage.jsx)
[!NOTE] Cette méthode est un dernier recours pour quand l'app ne peut pas s'exécuter localement (dépendances cassées, backend manquant, murs d'authentification sans contournement). Elle nécessite d'aplatir manuellement les composants React en un seul fichier JSX. Préférez la stratégie A chaque fois que possible.
Quand l'utiliser
- L'app ne peut pas du tout s'exécuter localement
- La page nécessite une authentification sans mock/contournement
- Vous avez besoin d'un état UI spécifique impossible à atteindre par navigation (écrans d'erreur, états vides)
Référence rapide
npx tsx <SKILL_DIR>/scripts/extract_inline_html.ts \
--index-css src/css/App.css \
--extra-css index.html \
--outdir .stitch \
--page src/MockPage.jsx:Page.html:"Page Title"
Drapeaux clés : --no-tailwind (apps non-Tailwind), --html-class dark (mode sombre), --css-files (fichiers CSS supplémentaires).
Auto-détection : La configuration Tailwind est auto-détectée. Les directives @apply utilisent automatiquement <style type="text/tailwindcss">.
Règles MockPage.jsx
- Inclure la mise en page complète — en-tête, barre latérale, pied de page (lisez d'abord
App.js) - Aplatir tous les conditionnels — choisissez un état, supprimez tous les ternaires et gardes
&& - Coder en dur toutes les données — remplacez
{variable}par des valeurs concrètes, déroulez les boucles.map() - Conserver les logos — utilisez
<img>avec des chemins locaux (le post-traitement les intégrera) - Supprimer les éléments flottants — bandeaux de cookies, widgets de chat, boutons de rétroaction
Post-traitement
Intégrer les images locales :
npx tsx <SKILL_DIR>/scripts/post_process.ts \
.stitch/Page.html --base-dir <app-directory>