core

core

熱門

核心套件,用於定義 json-render 的 schema、catalog 和 AI 提示生成。當使用 @json-render/core、定義 schema、建立 catalog 或建構用於 UI/影片生成的 JSON spec 時使用。

1.6萬星標
849分支
更新於 2026/7/8
SKILL.md
唯讀
名稱
core
描述

核心套件,用於定義 json-render 的 schema、catalog 和 AI 提示生成。當使用 @json-render/core、定義 schema、建立 catalog 或建構用於 UI/影片生成的 JSON spec 時使用。

@json-render/core

核心套件,用於 schema 定義、catalog 建立和 spec 串流。

關鍵概念

  • Schema:定義 spec 和 catalog 的結構(使用 defineSchema
  • Catalog:將元件/動作名稱對應到其定義(使用 defineCatalog
  • Spec:AI 輸出且符合 schema 的 JSON
  • SpecStream:用於逐步建構 spec 的 JSONL 串流格式

定義 Schema

import { defineSchema } from "@json-render/core";

export const schema = defineSchema((s) => ({
  spec: s.object({
    // 定義 spec 結構
  }),
  catalog: s.object({
    components: s.map({
      props: s.zod(),
      description: s.string(),
    }),
  }),
}), {
  promptTemplate: myPromptTemplate, // 可選的自訂 AI 提示
});

建立 Catalog

import { defineCatalog } from "@json-render/core";
import { schema } from "./schema";
import { z } from "zod";

export const catalog = defineCatalog(schema, {
  components: {
    Button: {
      props: z.object({
        label: z.string(),
        variant: z.enum(["primary", "secondary"]).nullable(),
      }),
      description: "可點擊的按鈕元件",
    },
  },
});

生成 AI 提示

const systemPrompt = catalog.prompt(); // 使用 schema 的 promptTemplate
const systemPrompt = catalog.prompt({ customRules: ["規則 1", "規則 2"] });

SpecStream 工具

用於串流 AI 回應(JSONL 修補):

import { createSpecStreamCompiler } from "@json-render/core";

const compiler = createSpecStreamCompiler<MySpec>();

// 處理串流區塊
const { result, newPatches } = compiler.push(chunk);

// 取得最終結果
const finalSpec = compiler.getResult();

動態 Prop 表達式

任何 prop 值都可以是動態表達式,在渲染時解析:

  • { "$state": "/state/key" } - 從狀態模型讀取值(單向讀取)
  • { "$bindState": "/path" } - 雙向綁定:從狀態讀取並允許寫回。用於表單元件的自然值 prop(value、checked、pressed 等)。
  • { "$bindItem": "field" } - 雙向綁定到重複項目的欄位。在重複範圍內使用。
  • { "$cond": <condition>, "$then": <value>, "$else": <value> } - 評估可見性條件並選擇分支
  • { "$template": "Hello, ${/user/name}!" } - 將 ${/path} 引用替換為狀態值
  • { "$computed": "fnName", "args": { "key": <expression> } } - 使用解析後的參數呼叫已註冊的函式

$cond 使用與可見性條件相同的語法($stateeqneqnot、陣列表示 AND)。$then$else 本身也可以是表達式(遞迴)。

元件不使用 statePath prop 進行雙向綁定。請改用 { "$bindState": "/path" } 放在自然值 prop(例如 valuecheckedpressed)上。

{
  "color": {
    "$cond": { "$state": "/activeTab", "eq": "home" },
    "$then": "#007AFF",
    "$else": "#8E8E93"
  },
  "label": { "$template": "Welcome, ${/user/name}!" },
  "fullName": {
    "$computed": "fullName",
    "args": {
      "first": { "$state": "/form/firstName" },
      "last": { "$state": "/form/lastName" }
    }
  }
}
import { resolvePropValue, resolveElementProps } from "@json-render/core";

const resolved = resolveElementProps(element.props, { stateModel: myState });

狀態監聽器

元素可以宣告 watch 欄位(頂層,與 type/props/children 同層級),在狀態值變更時觸發動作:

{
  "type": "Select",
  "props": { "value": { "$bindState": "/form/country" }, "options": ["US", "Canada"] },
  "watch": {
    "/form/country": { "action": "loadCities", "params": { "country": { "$state": "/form/country" } } }
  },
  "children": []
}

監聽器僅在值變更時觸發,而非初始渲染時。

驗證

內建驗證函式:requiredemailurlnumericminLengthmaxLengthminmaxpatternmatchesequalTolessThangreaterThanrequiredIf

跨欄位驗證使用 $state 表達式作為參數:

import { check } from "@json-render/core";

check.required("此欄位為必填");
check.matches("/form/password", "密碼必須相符");
check.lessThan("/form/endDate", "必須早於結束日期");
check.greaterThan("/form/startDate", "必須晚於開始日期");
check.requiredIf("/form/enableNotifications", "啟用時為必填");

使用者提示建構器

建構結構化的使用者提示,可選的 spec 精煉和狀態上下文:

import { buildUserPrompt } from "@json-render/core";

// 全新生成
buildUserPrompt({ prompt: "建立一個待辦事項應用" });

// 精煉,使用編輯模式(預設:僅 patch)
buildUserPrompt({ prompt: "新增一個切換開關", currentSpec: spec, editModes: ["patch", "merge"] });

// 包含執行時期狀態
buildUserPrompt({ prompt: "顯示資料", state: { todos: [] } });

可用的編輯模式:"patch"(RFC 6902 JSON Patch)、"merge"(RFC 7396 Merge Patch)、"diff"(統一 diff)。

Spec 驗證

驗證 spec 結構並自動修復常見問題:

import { validateSpec, autoFixSpec } from "@json-render/core";

const { valid, issues } = validateSpec(spec);
// issues 包含:missing_child、invalid_visible(格式錯誤的條件)、
// repeat_without_children、repeat_state_mismatch(statePath 在狀態中不是陣列)

const { spec: fixed, fixDetails } = autoFixSpec(spec);
// fixDetails 項目為 { message, lossy }。無損修復會重新放置錯置的欄位;
// 有損修復會修剪懸空的子元素參考。
// 在修復迴圈中,應保留有損修復直到重試耗盡:
const attempt = autoFixSpec(spec, { lossy: retriesExhausted });

可見性條件

使用基於狀態的條件控制元素可見性。VisibilityContext{ stateModel: StateModel }

import { visibility } from "@json-render/core";

// 語法
{ "$state": "/path" }                    // 真值判斷
{ "$state": "/path", "not": true }      // 假值判斷
{ "$state": "/path", "eq": value }      // 相等判斷
[ cond1, cond2 ]                         // 隱含 AND

// 輔助函式
visibility.when("/path")                 // { $state: "/path" }
visibility.unless("/path")               // { $state: "/path", not: true }
visibility.eq("/path", val)              // { $state: "/path", eq: val }
visibility.and(cond1, cond2)             // { $and: [cond1, cond2] }
visibility.or(cond1, cond2)              // { $or: [cond1, cond2] }
visibility.always                        // true
visibility.never                         // false

Schema 中的內建動作

Schema 可以宣告 builtInActions——這些動作在執行時期始終可用,並會自動注入到提示中:

const schema = defineSchema(builder, {
  builtInActions: [
    { name: "setState", description: "更新狀態模型中的值" },
  ],
});

這些動作在提示中顯示為 [built-in],且不需要在 defineRegistry 中定義處理器。

StateStore

StateStore 介面允許外部狀態管理函式庫(Redux、Zustand、XState 等)插入到 json-render 渲染器中。createStateStore 工廠函式建立一個簡單的記憶體內實作:

import { createStateStore, type StateStore } from "@json-render/core";

const store = createStateStore({ count: 0 });

store.get("/count");         // 0
store.set("/count", 1);      // 更新並通知訂閱者
store.update({ "/a": 1, "/b": 2 }); // 批次更新

store.subscribe(() => {
  console.log(store.getSnapshot()); // { count: 1 }
});

StateStore 介面:get(path)set(path, value)update(updates)getSnapshot()subscribe(listener)

主要匯出

匯出名稱 用途
defineSchema 建立新的 schema
defineCatalog 從 schema 建立 catalog
createStateStore 建立框架無關的記憶體內 StateStore
resolvePropValue 根據資料解析單一 prop 表達式
resolveElementProps 解析元素中所有 prop 表達式
buildUserPrompt 建構使用者提示,包含精煉和狀態上下文
buildEditUserPrompt 建構用於編輯現有 spec 的使用者提示
buildEditInstructions 生成可用編輯模式的提示區段
isNonEmptySpec 檢查 spec 是否有根節點且至少一個元素
deepMergeSpec RFC 7396 深度合併(null 刪除、陣列取代、物件遞迴)
diffToPatches 從物件差異生成 RFC 6902 JSON Patch 操作
EditMode 型別:"patch" | "merge" | "diff"
validateSpec 驗證 spec 結構
autoFixSpec 自動修復常見 spec 問題;將修復分類為有損/無損,{ lossy: false } 會保留修剪
createSpecStreamCompiler 將 JSONL 修補串流編譯為 spec
createJsonRenderTransform TransformStream,從混合串流中分離文字和 JSONL
parseSpecStreamLine 解析單行 JSONL
applySpecStreamPatch 將修補套用到物件
StateStore 用於插入外部狀態管理的介面
ComputedFunction $computed 表達式的函式簽名
check 用於建立驗證檢查的 TypeScript 輔助函式
BuiltInAction 內建動作定義的型別(name + description
ActionBinding 動作綁定型別(包含 preventDefault 欄位)