Communitygithub.com

gslvly/sketch-inspector

AI 友善的 Sketch 設計解析器。將 Sketch 文件轉換為結構化 JSON、匯出資源與可直接實作的 LayoutIR (flex/grid/absolute/leaf),讓任何 LLM 代理都能將 Sketch 設計轉換為 HTML/CSS、React 或 Vue。支援 Claude Code、Cursor、opencode 等代理技能。

sketch-inspector 是什麼?

這是一個專為 AI 代理設計的 Sketch 設計解析工具,能將 Sketch 文件結構化為統一的 JSON 格式,並推斷佈局類型(flex、grid、absolute、leaf),讓 LLM 代理可以直接生成對應的 HTML/CSS、React 或 Vue 頁面。其主要功能包含:從 Sketch 文件匯出資源與 JSON、執行佈局推斷以產生 LayoutIR、以及針對大型文件的自動拆分與回填流程。該技能支援 Claude Code、Cursor、opencode 等開發者工具平台,並要求 Sketch MCP 服務運行於本機(localhost:31126)。使用流程強制包含掃描、導出、佈局推斷、分流(根據 JSON 行數區分小文件直接實現或大文件拆分實現),並提供多個固定腳本以確保一致性,最終產出包含佈局統計、資源清單與實作檔案路徑的交付報告。

相容平台✓Claude Code~Codex CLI✓Cursor✓OpenCode
npx skills add gslvly/sketch-inspector

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

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 | leaf
  • direction: row | column(僅 flex)
  • gap: 子元素間距
  • padding: 內邊距 { top, right, bottom, left }
  • justifyContent: flex 對齊方式
  • alignItems: 交叉軸對齊方式
  • hasAbsoluteChildren: 當 flex/grid 容器存在直屬 absolute 子節點時為 true
  • css.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):

  1. 禁止普通佈局使用 absolute:只有 kind: "absolute" 的節點才允許絕對定位
  2. 有直屬 absolute 子節點時,必須信任 result.json 的定位訊號:若節點輸出了 hasAbsoluteChildren: true 或 css.position: "relative",實作時必須給該父容器設定已定位狀態,不能忽略

生成流程:

  1. 讀取完整 result.json
  2. 遞迴遍歷佈局樹
  3. 根據 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: 無佈局,渲染內容即可
  4. 直接使用當前節點的 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 實作流程

相關技能