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、section JSON、section 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
Shell 運行:
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. 大檔案主流程:拆分 -> 單 Section 實作 -> 回填彙總
適用條件:result.json 行數 > 3000
7.1 拆分 JSON
Shell 運行:
node @scripts/split-result-json.js \
--inputJsonPath=<workTmpDir>/result.json \
--outputDir=<workTmpDir> \
--assetBasePath=images/ \
--splitStrategy=auto
輸出:
<workTmpDir>/manifest.json- 多個 section JSON
- 約定好的
implementationPath、htmlMarker、cssMarker manifest.json.root.layoutIR:頁面主佈局語義摘要manifest.json.sections[].layoutIR:section 節點自身的佈局語義摘要
7.2 單 Section 實作
每個 section 必須只讀取自己的 jsonPath,並依 manifest.json 寫入自己的 implementationPath。
強制規則:
- 單 section 實作流程見
@references/single-section-workflow.md - section 檔案必須是片段:一個
<section>+ 一個<style> - section 內只寫內部結構和內部樣式,不定義主佈局容器的外層 margin
- 非根選擇器必須依
className做作用域隔離 - 需要深度檢查時再用
@scripts/inspect-single-section.js
7.3 回填彙總
所有 section 實作完成後,必須把每個 section 片段回填到總佈局檔案,不能手動複製貼上 marker 內容。
主佈局檔案必須預先滿足:
htmlMarker放在頁面結構中需要插入 section 的位置cssMarker必須放在主佈局檔案的<style>區塊內部,不能放在其他標籤、註解區塊外層或正文結構中- 如果 HTML 和 CSS 分檔案,
cssMarker必須放在cssLayoutPath指向的 CSS 檔案中
Shell 運行:
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路徑、section 數量、回填目標檔案路徑 - 佈局類型統計(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和多個 section JSON@scripts/replace-section-placeholder.js:大檔案主流程腳本,把 section 實作回填到總佈局檔案@scripts/inspect-single-section.js:section 資訊不足時做局部深度檢查
禁止:自行生成導出腳本、複製腳本源碼、重新實作遍歷邏輯。
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。生成程式碼引用src,不用path- JSON 刪除空值和值為
0的 style 欄位 - 預設過濾隱藏圖層
- 含真實 Text 的節點必須拆分,不能整體導出為圖片
- 普通背景 Rectangle 用程式碼重建;品牌資產、複雜視覺組優先保真導出
參考索引
@references/export-assets.md:資源導出規則@references/script-api.md:腳本參數和返回結構@references/single-section-workflow.md:單 section 實作流程