Communitygithub.com

gslvly/sketch-inspector

Analyseur de design Sketch pour IA. Transforme les documents Sketch en JSON structuré, ressources exportées et LayoutIR implémentable (flex/grid/absolute/leaf) pour que tout agent LLM puisse convertir les designs Sketch en HTML/CSS, React ou Vue. Compatible avec Claude Code, Cursor, opencode.

Qu'est-ce que sketch-inspector ?

Sketch Inspector est un outil agentisé qui permet à un agent IA (comme Claude Code, Cursor ou opencode) d'extraire et d'analyser la structure d'un document Sketch en cours d'édition. Il produit un JSON unifié contenant l'arbre de mise en page (LayoutIR avec des nœuds de type flex, grid, absolute ou leaf), les métadonnées de style, les textes, les couleurs et les ressources exportées (images). Ce JSON est conçu pour être directement utilisé par un agent afin de générer du code HTML/CSS, React ou Vue fidèle au design original. Le processus en plusieurs étapes (scan, export, inférence de mise en page, implémentation) est fortement contraint par le SKILL.md : il impose des vérifications de lignes pour choisir entre une implémentation directe (fichier JSON ≤ 3000 lignes) ou un découpage en sections (JSON > 3000 lignes) avec réassemblage automatique. Des scripts automatisés (export-text-split-assets.js, sketch_layout_ir_inference.ts, split-result-json.js, replace-section-placeholder.js) sont fournis et doivent être utilisés sans modification. Le résumé insiste sur le respect strict du workflow pour garantir une conversion 100 % fiable, évitant les erreurs de positionnement ou d'ignorance des conteneurs absolus.

Compatible avec✓Claude Code~Codex CLI✓Cursor✓OpenCode
npx skills add gslvly/sketch-inspector

Demander à votre IA préférée

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

Documentation

Inspecteur Sketch

Convertit les designs Sketch en données structurées, ressources image et découpage de page implémentable.

Cas d'utilisation

  • Inspecter un document Sketch ouvert ou un calque spécifique
  • Extraire les informations de structure, style, texte, couleur, mise en page et ressources
  • Générer du HTML/CSS, React, Vue ou toute autre page à partir d'une zone Sketch

Prérequis

  • Sketch est en cours d'exécution, le document cible est ouvert
  • Le MCP de Sketch est activé : Général -> Autoriser les outils IA à interagir avec les documents ouverts
  • Adresse du service MCP : http://localhost:31126/mcp
  • Sketch Run Code s'exécute dans l'environnement JavaScriptCore/CocoaScript, pas Node.js standard

Flux obligatoire pour l'implémentation de page

Lors de la génération d'une page à partir de Sketch, le flux suivant doit être strictement respecté. C'est la seule manière d'accomplir la tâche le plus rapidement possible ; l'absence d'une étape est considérée comme un échec.

1. Analyse

Extraire le profil superficiel de la page ou du conteneur cible, confirmer le layerId racine.

2. Détermination des chemins

  • imageOutputDir : répertoire des images du projet, utiliser de préférence les répertoires existants images/, assets/images/, public/images/, etc.
  • workTmpDir : répertoire temporaire, doit contenir au moins result.json ; en cas de découpage de gros fichier, il contiendra aussi manifest.json, les JSON de section, et les HTML de section.

3. Exportation

Exécuter le script d'exportation dans sketch_run_code.

const sketch = require('sketch');

// Préparation des paramètres
const layerId = '<layerId du calque cible>'; // ID racine du nœud cible obtenu depuis l'étape 1
const outputDir = '<chemin absolu de imageOutputDir>';  // Ex: '/Users/edy/project/images'
const outputJsonPath = '<chemin absolu de workTmpDir/result.json>';  // Ex: '/Users/edy/project/tmp/result.json'

// Exécution du script d'exportation
const exportScript = require('@scripts/export-text-split-assets.js');
const result = exportScript.runExportTextSplitAssets({
  layerId: layerId,
  outputDir: outputDir,
  outputJsonPath: outputJsonPath
});

// Sortie du résultat pour débogage
console.log(JSON.stringify(result, null, 2));

Résultat retourné :

  • Succès : retourne des informations statistiques d'exportation
  • Échec : retourne un message d'erreur, vérifier si layerId est valide et si le chemin a les permissions d'écriture

Remarques :

  • Le script s'exécute dans l'environnement Sketch JavaScriptCore, pas Node.js standard
  • Les chemins doivent être absolus
  • Le répertoire de sortie doit exister, le script ne le crée pas automatiquement

4. Inférence de mise en page et remplacement de result.json

Exécution en shell :

npx tsx @scripts/sketch_layout_ir_inference.ts \
  <workTmpDir>/result.json \
  <workTmpDir>/result.json

Cette étape transforme la structure brute exportée en un JSON de mise en page unifié directement implémentable, et remplace le fichier result.json d'origine.

Structure du result.json unifié :

  • kind: flex | grid | absolute | leaf
  • direction: row | column (uniquement pour flex)
  • gap: espacement entre les éléments enfants
  • padding: marges internes { top, right, bottom, left }
  • justifyContent: alignement flex
  • alignItems: alignement sur l'axe transversal
  • hasAbsoluteChildren: true lorsqu'un conteneur flex/grid a des enfants absolute directs
  • css.position: "relative" : émis explicitement lorsqu'un conteneur flex/grid a des enfants absolute directs
  • columns / rows: nombre de lignes/colonnes de la grille (uniquement pour grid)
  • source: données de complément d'implémentation correspondant au nœud de mise en page actuel, ne conserve que les champs non liés à la mise en page comme sourceClass / asset / background / style / decision / backgroundLayers / derivedFrom

5. Après l'inférence de mise en page, orientation obligatoire

Une fois l'inférence de mise en page terminée, il est interdit de décider de la méthode d'implémentation au feeling. Il faut s'appuyer sur le nombre réel de lignes du result.json unifié :

  • result.json a moins de ou exactement 3000 lignes : lire l'intégralité du result.json et réaliser l'implémentation directement, sans découpage
  • result.json a plus de 3000 lignes : suivre obligatoirement le « flux de découpage des gros fichiers », il est interdit de passer l'intégralité du JSON aux étapes suivantes

Exemple de vérification du nombre de lignes :

wc -l <workTmpDir>/result.json

6. Flux pour petits fichiers : implémentation directe

Condition d'application : nombre de lignes de result.json <= 3000

Règles fondamentales (À SUIVRE ABSOLUMENT) :

  1. Interdiction d'utiliser absolute pour une mise en page normale : seuls les nœuds avec kind: "absolute" sont autorisés à être positionnés en absolute
  2. Lorsqu'il y a des enfants absolute directs, il faut impérativement faire confiance aux signaux de positionnement de result.json : si un nœud émet hasAbsoluteChildren: true ou css.position: "relative", l'implémentation doit positionner le conteneur parent en conséquence, sans l'ignorer

Processus de génération :

  1. Lire l'intégralité du result.json
  2. Parcourir récursivement l'arbre de mise en page
  3. Générer le CSS correspondant selon kind :
    • flex: display: flex; flex-direction: {direction}; gap: {gap}px; ...
    • grid: display: grid; grid-template-columns: repeat({columns}, 1fr); ...
    • absolute: position: relative; pour le parent, position: absolute; pour les enfants
    • leaf: pas de disposition, seulement le rendu du contenu
  4. Utiliser directement le source du nœud courant pour implémenter le texte, l'image, le fond, le style, la décision ; ne pas revenir à l'ancienne structure JSON

7. Flux pour gros fichiers : découpage -> implémentation section par section -> réassemblage

Condition d'application : nombre de lignes de result.json > 3000

7.1 Découpage du JSON

Exécution en shell :

node @scripts/split-result-json.js \
  --inputJsonPath=<workTmpDir>/result.json \
  --outputDir=<workTmpDir> \
  --assetBasePath=images/ \
  --splitStrategy=auto

Produit :

  • <workTmpDir>/manifest.json
  • Plusieurs JSON de section
  • Les implementationPath, htmlMarker, cssMarker convenus
  • manifest.json.root.layoutIR : résumé sémantique de la mise en page principale
  • manifest.json.sections[].layoutIR : résumé sémantique de la mise en page du nœud de section

7.2 Implémentation d'une section individuelle

Chaque section doit lire uniquement son propre jsonPath et écrire dans son propre implementationPath conformément à manifest.json.

Règles impératives :

  • Le flux d'implémentation d'une section individuelle est détaillé dans @references/single-section-workflow.md
  • Le fichier de section doit être un fragment : un <section> + un <style>
  • À l'intérieur de la section, écrire uniquement la structure interne et les styles internes, sans définir les marges externes du conteneur de mise en page principal
  • Les sélecteurs non racine doivent être isolés par portée via le className
  • Si une vérification approfondie est nécessaire, utiliser @scripts/inspect-single-section.js

7.3 Réassemblage

Une fois toutes les sections implémentées, chaque fragment de section doit être réinséré dans le fichier de mise en page principal. Il est interdit de copier-coller manuellement le contenu des marqueurs.

Le fichier de mise en page principal doit être préparé à l'avance :

  • htmlMarker est placé dans la structure de la page à l'endroit où la section doit être insérée
  • cssMarker doit être placé à l'intérieur du bloc <style> du fichier de mise en page principal ; il ne doit pas être placé dans d'autres balises, blocs de commentaires ou en dehors de la structure du corps
  • Si le HTML et le CSS sont dans des fichiers séparés, cssMarker doit être placé dans le fichier CSS pointé par cssLayoutPath

Exécution en shell :

node @scripts/replace-section-placeholder.js \
  --layoutPath=/path/layout.html \
  --sectionPath=/path/01-section.html \
  --htmlMarker="<!-- HTML section 01 -->" \
  --cssMarker="/* CSS section 01 */"

Si le HTML et le CSS sont dans des fichiers différents, ajouter l'option --cssLayoutPath.

8. Liste de contrôle avant implémentation

Avant de procéder à l'implémentation, vérifier :

  • Lecture complète du result.json
  • Vérification du champ kind de chaque nœud
  • Vérification des informations de calque de fond meta.background
  • Texte, images, relations entre calques déjà vérifiés
  • Ressources de marque et groupes visuels complexes identifiés

9. Livraison

Rapporter les éléments objectifs :

  • Contour de la mise en page et ID de la zone cible
  • Chemin du result.json et nombre réel de lignes
  • Utilisation du « flux d'implémentation directe pour petits fichiers » ou du « flux de découpage pour gros fichiers »
  • Si flux de découpage : chemin du manifest.json, nombre de sections, chemin du fichier de réassemblage
  • Statistiques des types de mise en page (nombre de flex/grid/absolute/leaf)
  • Liste des ressources exportées
  • Chemins des fichiers HTML/CSS générés

Ne pas inclure de conclusions que la machine ne peut pas vérifier, comme « visuellement validé ».

Scripts fixes

Les paramètres et structures de retour des scripts sont détaillés dans @references/script-api.md.

  • @scripts/export-text-split-assets.js : exporte les images et le JSON. Paramètres obligatoires layerId, outputDir
  • @scripts/sketch_layout_ir_inference.ts : inférence de mise en page et sortie du result.json unifié
  • @scripts/split-result-json.js : script pour le flux des gros fichiers, génère manifest.json et plusieurs JSON de section
  • @scripts/replace-section-placeholder.js : script pour le flux des gros fichiers, réinsère les implémentations de section dans le fichier de mise en page principal
  • @scripts/inspect-single-section.js : inspection locale approfondie lorsque les informations de section sont insuffisantes

Interdit : générer son propre script d'exportation, copier le code source des scripts, ou réimplémenter la logique de parcours.

Description des types LayoutIR

type LayoutKind = 'leaf' | 'flex' | 'grid' | 'absolute'

interface FlexIR {
  kind: 'flex'
  direction: 'row' | 'column'
  gap: number
  padding: { top, right, bottom, left }
  justifyContent: 'flex-start' | 'center' | 'flex-end' | 'space-between'
  alignItems: 'flex-start' | 'center' | 'flex-end' | 'stretch'
  children: LayoutIR[]
}

interface GridIR {
  kind: 'grid'
  columns: number
  rows: number
  columnGap: number
  rowGap: number
  padding: { top, right, bottom, left }
  children: LayoutIR[]
}

interface AbsoluteIR {
  kind: 'absolute'
  children: LayoutIR[]  // les enfants doivent être positionnés en absolute
}

interface LeafIR {
  kind: 'leaf'
  text?: string
  css: { width?, height? }
}

Règles d'exportation des ressources

  • Les images sont exportées dans imageOutputDir, les JSON temporaires dans workTmpDir
  • Les noms de fichiers image utilisent les 8 premiers caractères du MD5, les images identiques sont réutilisées
  • asset/exports ne conservent que path, src, x, y, width, height. Le code généré référence src, pas path
  • Les champs de style vides ou à valeur 0 sont supprimés du JSON
  • Les calques cachés sont filtrés par défaut
  • Les nœuds contenant du texte réel doivent être décomposés, ils ne peuvent pas être exportés en une seule image
  • Les rectangles d'arrière-plan ordinaires sont reconstruits en code ; les ressources de marque et les groupes visuels complexes sont exportés de préférence avec une haute fidélité

Index des références

  • @references/export-assets.md : règles d'exportation des ressources
  • @references/script-api.md : paramètres et structures de retour des scripts
  • @references/single-section-workflow.md : flux d'implémentation d'une section individuelle

Skills associés