Sketch インスペクター
Sketchデザインを構造化データ、画像リソース、実装可能なページセクションに変換します。
使用シナリオ
- 開かれているSketchドキュメントまたは特定のレイヤーを検査する
- 構造、スタイル、テキスト、色、レイアウト、リソース情報を抽出する
- Sketch領域に基づいてHTML/CSS、React、Vue、またはその他のページを実装する
前提条件
- Sketchが実行中であり、対象のドキュメントが開かれている
- Sketch MCPが有効になっている:General -> Allow AI tools to interact with open documents
- MCPサービスアドレス:
http://localhost:31126/mcp - Sketch Run CodeはJavaScriptCore/CocoaScript環境で動作し、通常のNode.jsではない
ページ実装の強制フロー
Sketchからページを生成する際には、以下のフローを厳密に実行する必要があります。これが唯一最速でタスクを完了する方法であり、いずれかのステップが欠けると失敗と見なされます。
1. スキャン
ページまたはターゲットコンテナの浅い輪郭を抽出し、ルートノードの layerId を確認します。
2. パスの決定
imageOutputDir:プロジェクトの画像ディレクトリ。既存のimages/、assets/images/、public/images/などを優先的に使用しますworkTmpDir:一時ディレクトリ。少なくともresult.jsonを配置します。大きなファイルを分割する場合は、manifest.json、セクションJSON、セクションHTMLも配置します
3. 書き出し
sketch_run_code で書き出しスクリプトを実行します。
const sketch = require('sketch');
// パラメータ準備
const layerId = '<ターゲットレイヤーのlayerId>'; // ステップ1のスキャンで取得したターゲットルートノードID
const outputDir = '<imageOutputDirの絶対パス>'; // 例: '/Users/edy/project/images'
const outputJsonPath = '<workTmpDir/result.jsonの絶対パス>'; // 例: '/Users/edy/project/tmp/result.json'
// 書き出しスクリプトを実行
const exportScript = require('@scripts/export-text-split-assets.js');
const result = exportScript.runExportTextSplitAssets({
layerId: layerId,
outputDir: outputDir,
outputJsonPath: outputJsonPath
});
// 結果を出力(デバッグ用)
console.log(JSON.stringify(result, null, 2));
戻り値:
- 成功:書き出し統計情報を返す
- 失敗:エラー情報を返す。
layerIdが有効か、パスに書き込み権限があるかを確認する
注意:
- スクリプトはSketch JavaScriptCore環境で動作し、通常のNode.jsではない
- パスは絶対パスである必要がある
- 出力ディレクトリは事前に存在している必要があり、スクリプトが自動で作成することはない
4. レイアウト推論と result.json の上書き
シェルで実行:
npx tsx @scripts/sketch_layout_ir_inference.ts \
<workTmpDir>/result.json \
<workTmpDir>/result.json
このステップでは、書き出された元の構造を直接実装可能な統一レイアウトJSONに変換し、元の result.json を上書きします。
出力される統一 result.json の構造:
kind:flex|grid|absolute|leafdirection:row|column(flexのみ)gap: 子要素の間隔padding: 内側の余白 { top, right, bottom, left }justifyContent: flexの配置方法alignItems: 交差軸の配置方法hasAbsoluteChildren:flex/gridコンテナに直接のabsolute子ノードがある場合truecss.position: "relative":flex/gridコンテナに直接のabsolute子ノードがある場合に明示的に出力columns/rows: グリッドの列数/行数(gridのみ)source: 現在のレイアウトノードに対応する実装補足データ。sourceClass / asset / background / style / decision / backgroundLayers / derivedFromなどの非レイアウトフィールドのみ保持
5. レイアウト推論後の分岐判断
レイアウト推論が完了したら、感覚で実装方法を決めてはいけません。統一された result.json の実際の行数に基づいて分岐する必要があります。
result.jsonの行数が3000以下:result.json全体を読み込んで実装を完了し、分割は行わないresult.jsonの行数が3000を超える:「大ファイル分割フロー」に進む必要があり、JSON全体をそのまま後続の実装ステップに渡すことは禁止
行数確認の例:
wc -l <workTmpDir>/result.json
6. 小ファイルのメインフロー:直接実装
適用条件:result.json の行数 <= 3000
コアルール(MUST FOLLOW):
- 通常のレイアウトにabsoluteを使用してはならない:
kind: "absolute"のノードのみ絶対配置を許可 - 直接のabsolute子ノードがある場合、
result.jsonの位置情報を信頼する必要がある:ノードがhasAbsoluteChildren: trueまたはcss.position: "relative"を出力している場合、実装時にその親コンテナに位置指定状態を設定しなければならず、無視してはならない
生成フロー:
- 完全な
result.jsonを読み込む - レイアウトツリーを再帰的に走査する
kindに応じて対応するCSSを生成する:flex:display: flex; flex-direction: {direction}; gap: {gap}px; ...grid:display: grid; grid-template-columns: repeat({columns}, 1fr); ...absolute:position: relative;子要素position: absolute;leaf: レイアウトなし、内容をレンダリングするのみ
- 現在のノードの
sourceを直接使用して、テキスト、画像、背景、スタイル、決定事項を実装し、古い構造JSONを再参照しない
7. 大ファイルのメインフロー:分割 -> 単一セクション実装 -> 差し戻し集約
適用条件:result.json の行数 > 3000
7.1 JSONの分割
シェルで実行:
node @scripts/split-result-json.js \
--inputJsonPath=<workTmpDir>/result.json \
--outputDir=<workTmpDir> \
--assetBasePath=images/ \
--splitStrategy=auto
出力:
<workTmpDir>/manifest.json- 複数のセクションJSON
- 取り決められた
implementationPath、htmlMarker、cssMarker manifest.json.root.layoutIR:ページのメインレイアウトセマンティクス概要manifest.json.sections[].layoutIR:セクションノード自身のレイアウトセマンティクス概要
7.2 単一セクションの実装
各セクションは自身の jsonPath のみを読み取り、manifest.json に従って自身の implementationPath に書き込む必要があります。
強制ルール:
- 単一セクションの実装フローは
@references/single-section-workflow.mdを参照 - セクションファイルはフラグメントである必要がある:1つの
<section>+ 1つの<style> - セクション内では内部構造と内部スタイルのみを記述し、メインレイアウトコンテナの外側のマージンを定義しない
- 非ルートセレクターは
classNameでスコープ分離を行う必要がある - 深い検査が必要な場合のみ
@scripts/inspect-single-section.jsを使用する
7.3 差し戻し集約
すべてのセクションの実装が完了したら、各セクションフラグメントをメインレイアウトファイルに差し戻す必要があります。マーカーコンテンツを手動でコピー&ペーストしてはいけません。
メインレイアウトファイルは事前に以下を満たしている必要があります:
htmlMarkerがページ構造内でセクションを挿入する位置にあるcssMarkerがメインレイアウトファイルの<style>ブロックの内部に配置されている必要があり、他のタグ、コメントブロックの外側、または本文構造内にあってはならない- HTMLとCSSが別ファイルの場合、
cssMarkerはcssLayoutPathが指すCSSファイルに配置されている必要がある
シェルで実行:
node @scripts/replace-section-placeholder.js \
--layoutPath=/path/layout.html \
--sectionPath=/path/01-section.html \
--htmlMarker="<!-- 01-section HTML -->" \
--cssMarker="/* 01-section CSS */"
HTMLとCSSが異なるファイルの場合は、追加で --cssLayoutPath を渡します。
8. 実装チェックリスト
実装前に確認:
result.jsonを完全に読み込んだ- 各ノードの
kindフィールドを確認した meta.backgroundの背景レイヤー情報を確認した- テキスト、画像、レイヤー関係を確認した
- ブランドアセットと複雑なビジュアルグループを特定した
9. 納品
客観的な成果物を報告します:
- レイアウトの輪郭とターゲット領域ID
result.jsonのパスと実際の行数- 「小ファイル直接実装」と「大ファイル分割フロー」のどちらを使用したか
- 分割フローを使用した場合:
manifest.jsonのパス、セクション数、差し戻し対象ファイルのパス - レイアウトタイプの統計(flex/grid/absolute/leafの数)
- 書き出しリソースの一覧
- 生成されたHTML/CSSファイルのパス
「視覚的に確認済み」など、機械では判断できない結論を出力しないでください。
固定スクリプト
スクリプトのパラメータと戻り値の構造は @references/script-api.md を参照してください。
@scripts/export-text-split-assets.js:画像とJSONを書き出します。必須パラメータはlayerId、outputDir@scripts/sketch_layout_ir_inference.ts:レイアウトを推論し、統一されたresult.jsonを出力します@scripts/split-result-json.js:大ファイルメインフロースクリプト。manifest.jsonと複数のセクションJSONを生成します@scripts/replace-section-placeholder.js:大ファイルメインフロースクリプト。セクションの実装をメインレイアウトファイルに差し戻します@scripts/inspect-single-section.js:セクション情報が不足している場合に部分的な深い検査を行います
禁止:書き出しスクリプトを自作する、スクリプトのソースコードをコピーする、走査ロジックを再実装する。
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[] // 子要素は絶対配置が必要
}
interface LeafIR {
kind: 'leaf'
text?: string
css: { width?, height? }
}
リソース書き出しルール
- 画像は
imageOutputDirに出力し、一時JSONはworkTmpDirに配置する - 画像ファイル名はMD5の最初の8文字を使用し、同じ画像は再利用する
asset/exportsはpath、src、x、y、width、heightのみ保持する。コード生成時はpathではなくsrcを参照する- JSONからは空の値および値が
0のstyleフィールドを削除する - デフォルトで非表示レイヤーはフィルタリングする
- 実際のテキストを含むノードは分割する必要があり、画像として一括書き出ししてはならない
- 通常の背景Rectangleはコードで再構築する。ブランドアセットや複雑なビジュアルグループは、忠実度を優先して書き出す
参照インデックス
@references/export-assets.md:リソース書き出しルール@references/script-api.md:スクリプトのパラメータと戻り値の構造@references/single-section-workflow.md:単一セクションの実装フロー