適用於 json-render 的預建自訂指令,涵蓋格式化、數學運算、字串操作與多國語言(i18n)。使用時機:使用 @json-render/directives、透過 defineDirective 定義自訂指令,或是需要在 spec 中加入 $format、$math、$concat、$count、$truncate、$pluralize、$join 或 $t 時。
@json-render/directives
專為 @json-render/core 打造的預建自訂指令。可以直接加入 catalog 與 renderer 中,輕鬆擴充格式化、數學運算、字串處理以及多國語言(i18n)功能。
快速開始
import { standardDirectives } from '@json-render/directives';
// 整合至 Prompt 生成流程
const prompt = catalog.prompt({ directives: standardDirectives });
// 整合至 Renderer(以 React 為例)
import { JSONUIProvider, Renderer } from '@json-render/react';
<JSONUIProvider registry={registry} directives={standardDirectives}>
<Renderer spec={spec} registry={registry} />
</JSONUIProvider>
若要加入像 createI18nDirective 這類工廠函式生成的指令,使用展開運算子即可:
import { standardDirectives, createI18nDirective } from '@json-render/directives';
const directives = [...standardDirectives, createI18nDirective(config)];
定義自訂指令
使用來自 @json-render/core 的 defineDirective:
import { defineDirective, resolvePropValue } from '@json-render/core';
import { z } from 'zod';
const doubleDirective = defineDirective({
name: '$double',
description: 'Double a numeric value.',
schema: z.object({
$double: z.unknown(),
}),
resolve(value, ctx) {
const resolved = resolvePropValue(value.$double, ctx);
return (resolved as number) * 2;
},
});
規則:
- 名稱必須以
$開頭 - 名稱不得與內建 Key 衝突(如
$state、$cond、$computed、$template、$item、$index、$bindState、$bindItem) - Resolver 應對子值呼叫
resolvePropValue以支援指令組合
內建指令
$format — 依語系區域格式化數值
使用 Intl 格式化工具處理數值。支援 date(日期)、currency(貨幣)、number(數字)與 percent(百分比)。
{ "$format": "currency", "value": { "$state": "/cart/total" }, "currency": "USD" }
{ "$format": "date", "value": { "$state": "/user/createdAt" } }
{ "$format": "number", "value": 1234567, "notation": "compact" }
{ "$format": "percent", "value": 0.75 }
{ "$format": "date", "value": { "$state": "/post/createdAt" }, "style": "relative" }
欄位:$format (date | currency | number | percent)、value (任意運算式)、locale? (字串)、currency? (字串,預設 "USD")、notation? (字串)、style? (相對日期請設為 "relative")、options? (額外的 Intl 選項)。
$math — 算術運算
{ "$math": "add", "a": { "$state": "/subtotal" }, "b": { "$state": "/tax" } }
{ "$math": "round", "a": 3.7 }
支援運算:add(加)、subtract(減)、multiply(乘)、divide(除)、mod(取餘數)、min(最小值)、max(最大值)、round(四捨五入)、floor(無條件捨去)、ceil(無條件進位)、abs(絕對值)。單元運算(round、floor、ceil、abs)僅使用 a。除以零時回傳 0。
欄位:$math (運算列舉)、a? (第一個運算元,預設 0)、b? (第二個運算元,預設 0)。
$concat — 字串串接
{ "$concat": [{ "$state": "/user/firstName" }, " ", { "$state": "/user/lastName" }] }
欄位:$concat (包含要解析並串接成字串的數值陣列)。
$count — 陣列/字串長度
{ "$count": { "$state": "/cart/items" } }
回傳陣列或字串的 .length,若為其他型別則回傳 0。
欄位:$count (要計算長度的值)。
$truncate — 文字截斷
{ "$truncate": { "$state": "/post/body" }, "length": 140, "suffix": "..." }
欄位:$truncate (要截斷的值)、length? (最大字數,預設 100)、suffix? (後綴字串,預設 "...")。
$pluralize — 單複數形式
{ "$pluralize": { "$state": "/cart/itemCount" }, "one": "item", "other": "items", "zero": "no items" }
輸出範例:"3 items"、"1 item" 或 "no items"。
欄位:$pluralize (數量值)、one (單數標籤)、other (複數標籤)、zero? (零數量標籤)。
$join — 陣列元素連接
{ "$join": { "$state": "/tags" }, "separator": ", " }
欄位:$join (要連接的陣列)、separator? (分隔字串,預設 ", ")。
createI18nDirective — 多國語言(i18n)工廠指令
import { createI18nDirective } from '@json-render/directives';
const tDirective = createI18nDirective({
locale: 'en',
messages: {
en: { "greeting": "Hello, {{name}}!", "checkout.submit": "Place Order" },
es: { "greeting": "Hola, {{name}}!", "checkout.submit": "Realizar Pedido" },
},
fallbackLocale: 'en',
});
在 spec 中的用法:
{ "$t": "checkout.submit" }
{ "$t": "greeting", "params": { "name": { "$state": "/user/name" } } }
欄位:$t (翻譯 Key)、params? (插值參數,其值接受運算式)。
設定項:locale (當前語系)、messages (Record<locale, Record<key, string>>)、fallbackLocale? (缺少 Key 時的備用語系)。
指令組合
指令之間可以自然地組合使用 — 每個 Resolver 都會對輸入呼叫 resolvePropValue,因此指令可以包裹其他指令或內建運算式:
{
"$format": "currency",
"value": { "$math": "multiply", "a": { "$state": "/price" }, "b": { "$state": "/qty" } },
"currency": "USD"
}
解析順序為由內而外:$state 從 state 讀取資料,$math 進行乘法計算,$format 將結果格式化為貨幣。
整合至 Renderer
所有四種 Renderer(React、Vue、Svelte、Solid)的 Provider 與 createRenderer 輸出皆接受 directives 參數:
// Provider 模式
<JSONUIProvider registry={registry} directives={directives}>
<Renderer spec={spec} registry={registry} />
</JSONUIProvider>
// createRenderer 模式
const MyRenderer = createRenderer(catalog, components);
<MyRenderer spec={spec} directives={directives} />
生成 Prompt 時,傳入相同的陣列即可:
const prompt = catalog.prompt({ directives });
核心匯出
| 匯出項目 | 用途 |
|---|---|
formatDirective |
$format 指令定義 |
mathDirective |
$math 指令定義 |
concatDirective |
$concat 指令定義 |
countDirective |
$count 指令定義 |
truncateDirective |
$truncate 指令定義 |
pluralizeDirective |
$pluralize 指令定義 |
joinDirective |
$join 指令定義 |
createI18nDirective |
$t i18n 指令的工廠函式 |
standardDirectives |
包含所有 7 個非工廠指令的陣列 |
I18nConfig |
i18n 設定項的型別定義 |






