EmDash 的 json 欄位類型可儲存任意結構化資料,但預設編輯器是單行文字輸入,需要手動輸入原始 JSON。Field Kit 是一個第一方外掛程式,為 json 欄位提供四個可組合的小工具,完全透過 seed options 設定 — 網站建置者無需使用 React。
安裝
npm i @emdash-cms/plugin-field-kit
在 astro.config.mjs 中註冊外掛程式:
import { defineConfig } from "astro/config";
import emdash from "emdash";
import { fieldKitPlugin } from "@emdash-cms/plugin-field-kit";
export default defineConfig({
integrations: [
emdash({
plugins: [fieldKitPlugin()],
}),
],
});
然後透過將 widget 設定為 field-kit:<name> 來為任何 json 欄位附加小工具:
{
"slug": "ingredients",
"type": "json",
"widget": "field-kit:list",
"options": { "fields": [...] }
}
小工具
| 小工具 | 用途 | 儲存值 |
|---|---|---|
object-form | 扁平 JSON 物件的內嵌表單 | { key: value, ... } |
list | 帶有新增/刪除/重排功能的有序陣列編輯器 | [{ ... }, ...] |
grid | 列 × 欄矩陣 | { rowKey: { colKey: value } } |
tags | 自由形式的標籤/晶片輸入 | ["tag1", "tag2"] |
如果小工具缺少必需的 options(例如 object-form/list 的 fields,或 grid 的 rows/columns),編輯器會轉譯內嵌警告「小工具設定錯誤」而不是損壞的輸入 — 這在迭代 seed 架構時很有用。
object-form
轉譯一組類型化的子欄位,作為單個 JSON 物件儲存。適用於固定形狀的結構化資料,如營養成分或聯絡資訊。
{
"slug": "nutrition",
"type": "json",
"widget": "field-kit:object-form",
"options": {
"collapsed": false,
"fields": [
{ "key": "calories", "label": "Calories", "type": "number", "suffix": "kcal" },
{ "key": "protein", "label": "Protein", "type": "number", "suffix": "g" },
{ "key": "fat", "label": "Fat", "type": "number", "suffix": "g" },
{ "key": "carbs", "label": "Carbs", "type": "number", "suffix": "g" }
]
}
}
儲存值:{ "calories": 250, "protein": 12.5, "fat": 8, "carbs": 30 }。
| 選項 | 類型 | 預設值 | 描述 |
|---|---|---|---|
fields | SubFieldDef[] | (必需) | 子欄位定義 — 參見子欄位。 |
collapsed | boolean | false | 預設摺疊轉譯組。 |
helpText | string | — | 小工具下方顯示的說明文字。 |
list
帶有新增、刪除和重新排序控制項的有序陣列編輯器。每一列是一個 JSON 物件,其形狀由 fields 定義。列標題顯示從 Mustache 風格範本轉譯的摘要。
{
"slug": "ingredients",
"type": "json",
"widget": "field-kit:list",
"options": {
"itemLabel": "Ingredient",
"min": 1,
"max": 50,
"sortable": true,
"summary": "{{name}} — {{amount}}",
"fields": [
{ "key": "name", "label": "Name", "type": "text", "required": true },
{ "key": "amount", "label": "Amount", "type": "text" },
{ "key": "optional", "label": "Optional", "type": "boolean" }
]
}
}
儲存值:
[
{ "name": "Flour", "amount": "500g", "optional": false },
{ "name": "Butter", "amount": "200g", "optional": false }
]
| 選項 | 類型 | 預設值 | 描述 |
|---|---|---|---|
fields | SubFieldDef[] | (必需) | 每列的子欄位定義。 |
itemLabel | string | "Item" | 列的單數標籤(用於「新增」按鈕和後備列標題)。 |
min | number | — | 最小項目數。低於此數時,刪除按鈕隱藏。 |
max | number | — | 最大項目數。達到此數時,新增按鈕隱藏。 |
sortable | boolean | true | 顯示上/下重排按鈕。 |
summary | string | — | 作為摺疊列標題轉譯的 Mustache 範本。參見摘要範本。 |
helpText | string | — | 小工具下方顯示的說明文字。 |
grid
列 × 欄的二維矩陣。每個儲存格可以是開關、文字輸入、數字輸入或選擇。適用於季節性可用性、價格表或功能比較等矩陣。
{
"slug": "availability",
"type": "json",
"widget": "field-kit:grid",
"options": {
"cell": "toggle",
"rows": [
{ "key": "berries", "label": "Berries" },
{ "key": "stoneFruit", "label": "Stone fruit" },
{ "key": "citrus", "label": "Citrus" }
],
"columns": [
{ "key": "spring", "label": "Spring" },
{ "key": "summer", "label": "Summer" },
{ "key": "autumn", "label": "Autumn" },
{ "key": "winter", "label": "Winter" }
]
}
}
儲存值:
{
"berries": { "spring": false, "summer": true, "autumn": false, "winter": false },
"stoneFruit": { "spring": false, "summer": true, "autumn": true, "winter": false },
"citrus": { "spring": false, "summer": false, "autumn": true, "winter": true }
}
| 選項 | 類型 | 預設值 | 描述 |
|---|---|---|---|
rows | GridAxisDef[] | (必需) | 列定義:{ key, label, image? }。 |
columns | GridAxisDef[] | (必需) | 欄定義:{ key, label, image? }。 |
cell | "toggle" | "text" | "number" | "select" | "toggle" | 儲存格輸入類型,統一套用於每個儲存格。 |
cellOptions | string[] | Array<{ label, value }> | [] | 當 cell 為 "select" 時必需。 |
helpText | string | — | 小工具下方顯示的說明文字。 |
tags
用於字串陣列的晶片樣式輸入。支援固定的 suggestions 清單、自由形式的自訂值(可切換)、大小寫轉換和可選的 max。
{
"slug": "keywords",
"type": "json",
"widget": "field-kit:tags",
"options": {
"placeholder": "Add a keyword…",
"max": 10,
"transform": "lowercase",
"allowCustom": true,
"suggestions": ["vegan", "vegetarian", "gluten-free", "dairy-free", "nut-free"]
}
}
儲存值:["vegan", "gluten-free"]。
按 Enter 或 , 提交標籤。在空輸入上按 Backspace 刪除最後一個標籤。重複標籤會被靜默忽略。
| 選項 | 類型 | 預設值 | 描述 |
|---|---|---|---|
placeholder | string | "Add..." | 沒有標籤時顯示的輸入預留位置。 |
max | number | — | 最大標籤數。達到限制時輸入隱藏。 |
suggestions | string[] | [] | 透過 <datalist> 顯示的自動完成建議。 |
allowCustom | boolean | true | 當為 false 時,只能新增來自 suggestions 的值。 |
transform | "none" | "lowercase" | "uppercase" | "trim" | "none" | 新增標籤時進行規範化。 |
helpText | string | — | 小工具下方顯示的說明文字。 |
子欄位
object-form 和 list 接受類型化子欄位定義的 options.fields 陣列。每個條目都有一個 key(它寫入的 JSON 物件鍵)、一個 label、一個 type 和特定於類型的額外內容。
| 子欄位類型 | 轉譯為 | 值得注意的額外內容 |
|---|---|---|
text | 單行輸入 | placeholder |
textarea | 多行輸入 | rows(預設 3)、placeholder |
number | 數字輸入 | min、max、step、prefix、suffix、placeholder |
boolean | 切換開關 | — |
select | 下拉選單 | options: string[] | Array<{ label, value }>、placeholder |
date | 日期輸入 | — |
color | 配對十六進位文字輸入的原生顏色選擇器 | — |
url | URL 輸入(HTML5 type="url") | placeholder |
每個子欄位的通用屬性:required、helpText、defaultValue。
摘要範本
list 小工具使用 options.summary 中的 Mustache 風格範本轉譯每個摺疊列。{{key}} 被替換為該鍵的列值(強制轉換為字串)。假值回退到 "{itemLabel} {n}"。
"summary": "{{name}} — {{amount}}"
轉譯類似 Flour — 500g 的列。範本是簡單的字串替換 — 沒有 HTML,沒有巢狀運算式。
資料持久性
Field Kit 小工具在欄位的現有欄中儲存純 JSON。沒有特定於外掛程式的表,沒有外鍵,沒有架構變更。如果您從設定中移除 @emdash-cms/plugin-field-kit,資料仍然有效 — 只有編輯 UI 會恢復到預設的 json 文字輸入。
即使更改小工具形狀也適用:儲存物件上的未知鍵在下次寫入時保留,因此您可以在不遺失在舊欄位集下擷取的資料的情況下演變架構。
另請參閱
- 外掛程式概述 — EmDash 外掛程式的工作原理。
- 選擇外掛程式格式 — 如果 Field Kit 不合適,撰寫您自己的欄位小工具。
- Discussion #571 — 促成此外掛程式的提案。