EmDash의 json 필드 타입은 임의의 구조화된 데이터를 저장하며, 기본적으로 원시 JSON을 받는 단일 줄 텍스트 입력으로 편집됩니다. Field Kit는 시드 options를 통해 완전히 구성되는 json 필드용 4개의 조합 가능한 위젯을 제공하는 자사 플러그인으로, 사이트 빌더가 시드 스키마만으로 이를 사용할 수 있습니다.
설치
npm에서 패키지를 설치합니다:
npm i @emdash-cms/plugin-field-kit
다음 구성은 플러그인을 등록합니다:
import { defineConfig } from "astro/config";
import emdash from "emdash/astro";
import { fieldKitPlugin } from "@emdash-cms/plugin-field-kit";
export default defineConfig({
integrations: [
emdash({
plugins: [fieldKitPlugin()],
}),
],
});
widget을 field-kit:<name>으로 설정하여 모든 json 필드에 위젯을 첨부합니다. 다음 필드 정의는 list 위젯을 사용합니다:
{
"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), 편집기는 손상된 입력 대신 인라인 “위젯이 잘못 구성됨” 경고를 렌더링합니다 — 시드 스키마를 반복할 때 유용합니다.
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
추가, 제거 및 재정렬 컨트롤이 있는 순서 있는 배열 편집기입니다. 각 행은 fields로 형태가 정의된 JSON 객체입니다. 행 헤더는 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
행 × 열의 2차원 매트릭스입니다. 각 셀은 토글, 텍스트 입력, 숫자 입력 또는 선택일 수 있습니다. 계절별 가용성, 가격표 또는 기능 비교와 같은 매트릭스에 유용합니다. 다음 필드 정의는 계절별 가용성 그리드를 구성합니다:
{
"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 | 16진수 텍스트 입력과 쌍을 이루는 기본 색상 선택기 | — |
url | URL 입력(HTML5 type="url") | placeholder |
모든 하위 필드의 공통 속성: required, helpText, defaultValue.
요약 템플릿
list 위젯은 options.summary의 Mustache 스타일 템플릿을 사용하여 접힌 각 행을 렌더링합니다. {{key}}는 해당 키에 대한 행의 값(문자열로 변환됨)으로 대체됩니다. Falsy 값은 "{itemLabel} {n}"으로 대체됩니다. 다음 템플릿은 두 키를 결합합니다:
"summary": "{{name}} — {{amount}}"
Flour — 500g와 같은 행을 렌더링합니다. 템플릿은 단순 문자열 치환입니다 — HTML 없음, 중첩 표현식 없음.
데이터 내구성
Field Kit 위젯은 필드의 기존 열에 일반 JSON을 저장하며, 해당 열만 사용합니다. 구성에서 @emdash-cms/plugin-field-kit를 제거하면 데이터는 유효하게 유지됩니다 — 필드는 기본 json 텍스트 입력으로 되돌아갑니다.
이는 위젯 형태를 변경할 때도 적용됩니다: 저장된 객체의 알 수 없는 키는 다음 쓰기 시 보존되므로, 이전 필드 세트에서 캡처된 데이터를 잃지 않고 스키마를 발전시킬 수 있습니다.
참고 항목
- 플러그인 개요 — EmDash 플러그인 작동 방식.
- 플러그인 형식 선택 — Field Kit가 맞지 않으면 자체 필드 위젯을 작성하세요.
- 토론 #571 — 이 플러그인으로 이어진 제안.