Seed 檔案格式

本頁內容

Seed 檔案是初始化 EmDash 網站的 JSON 文件。它們定義集合、欄位、分類法、選單、重新導向、小工具區域、網站設定和可選的範例內容。

根結構

Seed 檔案具有以下頂層結構:

{
	"$schema": "https://emdashcms.com/seed.schema.json",
	"version": "1",
	"meta": {},
	"settings": {},
	"collections": [],
	"taxonomies": [],
	"bylines": [],
	"menus": [],
	"redirects": [],
	"widgetAreas": [],
	"sections": [],
	"content": {}
}
欄位類型必需描述
$schemastring用於編輯器驗證的 JSON 架構 URL
version"1"Seed 格式版本
metaobject關於 seed 的中繼資料
settingsobject網站設定
collectionsarray集合定義
taxonomiesarray分類法定義
bylinesarray署名檔案定義
menusarray導覽選單
redirectsarray重新導向規則
widgetAreasarray小工具區域定義
sectionsarray可重複使用的內容區塊
contentobject範例內容項目

Meta

meta 物件包含有關 seed 的可選描述性中繼資料:

{
	"meta": {
		"name": "Blog Starter",
		"description": "A simple blog with posts, pages, and categories",
		"author": "EmDash"
	}
}

Settings

settings 物件包含網站範圍的設定值:

{
	"settings": {
		"title": "My Site",
		"tagline": "A modern CMS",
		"postsPerPage": 10,
		"dateFormat": "MMMM d, yyyy"
	}
}

設定套用於帶有 site: 前綴的 options 資料表。設定精靈將從 seed 檔案(如果提供)預填 titletagline,允許使用者在初始設定期間覆寫它們。

Collections

每個集合定義在資料庫中建立一個內容類型:

{
	"collections": [
		{
			"slug": "posts",
			"label": "Posts",
			"labelSingular": "Post",
			"description": "Blog posts",
			"icon": "file-text",
			"supports": ["drafts", "revisions"],
			"fields": [
				{
					"slug": "title",
					"label": "Title",
					"type": "string",
					"required": true
				},
				{
					"slug": "content",
					"label": "Content",
					"type": "portableText"
				},
				{
					"slug": "featured_image",
					"label": "Featured Image",
					"type": "image"
				}
			]
		}
	]
}

集合屬性

屬性類型必需描述
slugstringURL 安全識別碼(小寫、底線)
labelstring複數顯示名稱
labelSingularstring單數顯示名稱
descriptionstring管理介面描述
iconstringLucide 圖示名稱
supportsarray功能:"drafts""revisions"
fieldsarray欄位定義

欄位屬性

屬性類型必需描述
slugstring欄位名稱(小寫、底線)
labelstring顯示名稱
typestring欄位類型
requiredboolean驗證:欄位必須有值
uniqueboolean驗證:值必須唯一
defaultValueany新項目的預設值
validationobject其他驗證規則
widgetstring管理介面小工具覆寫
optionsobject小工具特定設定

欄位類型

類型描述儲存為
string短文字TEXT
text長文字(文字區域)TEXT
number數值REAL
integer整數INTEGER
boolean真/假INTEGER
date日期值TEXT (ISO 8601)
datetime日期和時間TEXT (ISO 8601)
email電子郵件地址TEXT
urlURLTEXT
slugURL 安全字串TEXT
portableText富文字內容JSON
image圖像引用JSON
file檔案引用JSON
json任意 JSONJSON
reference對另一個項目的引用TEXT

Taxonomies

分類法是內容的分類系統:

{
	"taxonomies": [
		{
			"name": "category",
			"label": "Categories",
			"labelSingular": "Category",
			"hierarchical": true,
			"collections": ["posts"],
			"terms": [
				{ "slug": "news", "label": "News" },
				{ "slug": "tutorials", "label": "Tutorials" },
				{
					"slug": "advanced",
					"label": "Advanced Tutorials",
					"parent": "tutorials"
				}
			]
		},
		{
			"name": "tag",
			"label": "Tags",
			"labelSingular": "Tag",
			"hierarchical": false,
			"collections": ["posts"]
		}
	]
}

分類法屬性

屬性類型必需描述
namestring唯一識別碼
labelstring複數顯示名稱
labelSingularstring單數顯示名稱
hierarchicalboolean允許巢狀術語(類別)或扁平(標籤)
collectionsarray此分類法適用的集合
termsarray預定義術語

術語屬性

屬性類型必需描述
slugstringURL 安全識別碼
labelstring顯示名稱
descriptionstring術語描述
parentstring父術語 slug(僅階層式)

menus 陣列定義可從管理員編輯的導覽選單:

{
	"menus": [
		{
			"name": "primary",
			"label": "Primary Navigation",
			"items": [
				{ "type": "custom", "label": "Home", "url": "/" },
				{ "type": "page", "ref": "about" },
				{ "type": "custom", "label": "Blog", "url": "/posts" },
				{
					"type": "custom",
					"label": "External",
					"url": "https://example.com",
					"target": "_blank"
				}
			]
		}
	]
}

選單項目類型

類型描述必需欄位
custom自訂 URLurl
page連結到頁面項目ref
post連結到文章項目ref
taxonomy連結到分類法封存refcollection
collection連結到集合封存collection

選單項目屬性

屬性類型描述
typestring項目類型(見上文)
labelstring顯示文字(頁面/文章引用自動產生)
urlstring自訂 URL(用於 custom 類型)
refstringseed 中的內容 ID(用於 page/post 類型)
collectionstring集合 slug
targetstring新視窗使用 "_blank"
titleAttrstringHTML title 屬性
cssClassesstring自訂 CSS 類別
childrenarray巢狀選單項目

Bylines

署名檔案與所有權(author_id)分開。定義一次可重複使用的署名身分,然後從內容項目引用它們。

{
	"bylines": [
		{
			"id": "editorial",
			"slug": "emdash-editorial",
			"displayName": "EmDash Editorial"
		},
		{
			"id": "guest",
			"slug": "guest-contributor",
			"displayName": "Guest Contributor",
			"isGuest": true
		}
	]
}
屬性類型必需描述
idstringcontent[].bylines 使用的 seed 本地 ID
slugstringURL 安全的署名 slug
displayNamestring範本和 API 中顯示的名稱
biostring可選的檔案簡介
websiteUrlstring可選的網站 URL
isGuestboolean將署名標記為訪客檔案

Redirects

redirects 陣列定義在遷移後保留舊版 URL 的重新導向規則:

{
	"redirects": [
		{ "source": "/old-about", "destination": "/about" },
		{ "source": "/legacy-feed", "destination": "/rss.xml", "type": 308 },
		{
			"source": "/category/news",
			"destination": "/categories/news",
			"groupName": "migration"
		}
	]
}

重新導向屬性

屬性類型必需描述
sourcestring來源路徑(必須以 / 開頭)
destinationstring目標路徑(必須以 / 開頭)
typenumberHTTP 狀態:301302307308
enabledboolean重新導向是否處於作用中狀態(預設:true
groupNamestring用於管理篩選/搜尋的可選分組標籤

Widget Areas

widgetAreas 陣列定義可設定的內容區域:

{
	"widgetAreas": [
		{
			"name": "sidebar",
			"label": "Main Sidebar",
			"description": "Appears on blog posts and pages",
			"widgets": [
				{
					"type": "component",
					"title": "Recent Posts",
					"componentId": "core:recent-posts",
					"props": { "count": 5 }
				},
				{
					"type": "menu",
					"title": "Quick Links",
					"menuName": "footer"
				},
				{
					"type": "content",
					"title": "About",
					"content": [
						{
							"_type": "block",
							"style": "normal",
							"children": [{ "_type": "span", "text": "Welcome to our site!" }]
						}
					]
				}
			]
		}
	]
}

小工具類型

類型描述必需欄位
content富文字內容content(Portable Text)
menu呈現選單menuName
component已註冊的元件componentId

內建元件

元件 ID描述
core:recent-posts最近文章清單
core:categories類別清單
core:tags標籤雲
core:search搜尋表單
core:archives月度封存

Sections

Sections 是編輯者透過 /section 斜線命令插入到 Portable Text 欄位中的可重複使用內容區塊:

{
	"sections": [
		{
			"slug": "hero-centered",
			"title": "Centered Hero",
			"description": "Full-width hero with centered heading and CTA button",
			"keywords": ["hero", "banner", "header", "landing"],
			"content": [
				{
					"_type": "block",
					"style": "h1",
					"children": [{ "_type": "span", "text": "Welcome to Our Site" }]
				},
				{
					"_type": "block",
					"children": [
						{ "_type": "span", "text": "Your compelling tagline goes here." }
					]
				}
			]
		}
	]
}

Section 屬性

屬性類型必需描述
slugstringURL 安全識別碼
titlestring在 section 選擇器中顯示的顯示名稱
descriptionstring說明何時使用此 section
keywordsarray用於尋找 section 的搜尋詞彙
contentarrayPortable Text 區塊
sourcestring"theme"(seed 的預設值)或 "import"

來自 seed 檔案的 sections 標記為 source: "theme",不能從管理介面刪除。編輯者可以建立自己的 sections(source: "user"),並在編輯內容時插入任何 section 類型。

Content

content 物件包含按集合組織的範例內容項目:

{
	"content": {
		"posts": [
			{
				"id": "hello-world",
				"slug": "hello-world",
				"status": "published",
				"bylines": [
					{ "byline": "editorial" },
					{ "byline": "guest", "roleLabel": "Guest essay" }
				],
				"data": {
					"title": "Hello World",
					"content": [
						{
							"_type": "block",
							"style": "normal",
							"children": [{ "_type": "span", "text": "Welcome!" }]
						}
					],
					"excerpt": "Your first post."
				},
				"taxonomies": {
					"category": ["news"],
					"tag": ["welcome", "first-post"]
				}
			}
		],
		"pages": [
			{
				"id": "about",
				"slug": "about",
				"status": "published",
				"data": {
					"title": "About Us",
					"content": [
						{
							"_type": "block",
							"style": "normal",
							"children": [{ "_type": "span", "text": "About page content." }]
						}
					]
				}
			}
		]
	}
}

內容項目屬性

屬性類型必需描述
idstring用於引用的 seed 本地 ID
slugstringURL slug
statusstring"published""draft"(預設:"published"
dataobject欄位值
bylinesarray有序的署名積分(byline、可選 roleLabel
taxonomiesobject按分類法名稱的術語分配

Content References

使用 $ref: 前綴引用其他內容項目:

{
	"data": {
		"related_posts": ["$ref:another-post", "$ref:third-post"]
	}
}

$ref: 前綴在種子期間將 seed ID 解析為資料庫 ID。

Media References

從 URL 包含圖像:

{
	"data": {
		"featured_image": {
			"$media": {
				"url": "https://images.unsplash.com/photo-xxx",
				"alt": "Description of the image",
				"filename": "hero.jpg",
				"caption": "Photo by Someone"
			}
		}
	}
}

.emdash/media/ 包含本地圖像:

{
	"data": {
		"featured_image": {
			"$media": {
				"file": "hero.jpg",
				"alt": "Description of the image"
			}
		}
	}
}

媒體屬性

屬性類型必需描述
urlstring是*要下載的遠端 URL
filestring是*.emdash/media/ 中的本地檔案名稱
altstring用於無障礙性的替代文字
filenamestring覆寫檔案名稱
captionstring媒體標題

*需要 urlfile 之一,但不能同時需要兩者。

Applying Seeds Programmatically

對 CLI 工具或腳本使用 seed API:

import { applySeed, validateSeed } from "emdash/seed";
import seedData from "./.emdash/seed.json";

// 首先驗證
const validation = validateSeed(seedData);
if (!validation.valid) {
	console.error(validation.errors);
	process.exit(1);
}

// 套用 seed
const result = await applySeed(db, seedData, {
	includeContent: true,
	onConflict: "skip",
	storage: myStorage,
	baseUrl: "http://localhost:4321",
});

console.log(result);
// {
//   collections: { created: 2, skipped: 0 },
//   fields: { created: 8, skipped: 0 },
//   taxonomies: { created: 2, terms: 5 },
//   bylines: { created: 2, skipped: 0 },
//   menus: { created: 1, items: 4 },
//   redirects: { created: 3, skipped: 0 },
//   widgetAreas: { created: 1, widgets: 3 },
//   settings: { applied: 3 },
//   content: { created: 3, skipped: 0 },
//   media: { created: 2, skipped: 0 }
// }

Apply 選項

選項類型預設值描述
includeContentbooleanfalse建立範例內容項目
onConflictstring"skip""skip""update""error"
mediaBasePathstring本地媒體檔案的基本路徑
storageStorage用於媒體上傳的儲存配接器
baseUrlstring媒體 URL 的基本 URL

Idempotency

種子可以安全地執行多次。按實體類型的衝突行為:

實體行為
集合如果 slug 存在則跳過
欄位如果 collection + slug 存在則跳過
分類法定義如果名稱存在則跳過
分類法術語如果名稱 + slug 存在則跳過
署名檔案如果 slug 存在則跳過
選單如果名稱存在則跳過
選單項目全部取代(選單重新建立)
重新導向如果來源存在則跳過
小工具區域如果名稱存在則跳過
小工具全部取代(區域重新建立)
Section如果 slug 存在則跳過
設定更新(設定旨在變更)
內容如果 slug 在集合中存在則跳過

Validation

Seed 檔案在套用之前進行驗證:

import { validateSeed } from "emdash/seed";

const { valid, errors, warnings } = validateSeed(seedData);

if (!valid) {
	errors.forEach((e) => console.error(e));
}

warnings.forEach((w) => console.warn(w));

驗證檢查:

  • 必需欄位存在
  • Slug 對其類型有效(集合和欄位 slug 允許小寫字母、數字和底線;其他 slug 還允許連字號)
  • 欄位類型有效
  • 引用指向現有內容
  • 階層式術語父級存在
  • 重新導向路徑是安全的本地 URL
  • 重新導向來源是唯一的
  • 集合中沒有重複的 slug

CLI Commands

.emdash/seed.jsonpackage.json#emdash.seedseed/seed.json 中的 seed 檔案被內嵌到建置中,並在資料庫為空時的第一個請求時套用。要將現有網站的結構(以及可選的其內容)匯出為 seed 檔案:

# `mkdir -p` 因為在新專案上 .emdash/ 可能還不存在
mkdir -p .emdash

# 將目前結構匯出為 seed 檔案
npx emdash export-seed > .emdash/seed.json

# 匯出包含內容
npx emdash export-seed --with-content > .emdash/seed.json

Next Steps