ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

EmDash Seed 文件完全指南:从 Schema 定义到数据导出的实战手册

EmDash Seed 文件完全指南:从 Schema 定义到数据导出的实战手册 EmDash Seed 文件完全指南从 Schema 定义到数据导出的实战手册【免费下载链接】emdashEmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress项目地址: https://gitcode.com/gh_mirrors/emdas/emdashseed 文件seed/seed.json是 EmDash 站点的蓝图它以一份 JSON 同时定义整个内容模型collections、fields、taxonomies与可选的演示数据并在首次请求、数据库为空且尚未完成设置向导时被内联进构建产物并自动应用。本文将以 schema-and-seed.md 为骨架结合 EmDash 源码种子引擎、CLI 命令与仓库中的真实种子文件如 templates/starter/seed/seed.json系统讲解 seed 文件的结构、字段类型、内容写法、校验规则与导入导出全流程帮助你从零搭建一个可运行、可复现的 EmDash 站点。Seed 文件的作用与应用时机EmDash 采用schema 存于数据库而非代码的设计集合、字段、分类法等结构不是写在 TypeScript 里而是通过 seed 文件在初始化时写入数据库。一份 seed 文件被内联进构建产物并在以下条件同时满足时自动应用数据库为空尚无任何数据设置向导尚未完成。关键保证已有数据永远不会被覆盖。种子引擎在应用时会跳过已经存在的实体默认onConflict: skip因此 seed 文件具备幂等性——applySeed的实现注释明确写着safe to run multiple times见 packages/core/src/seed/apply.ts。Seed 文件的位置约定从 packages/core/src/cli/commands/seed.ts 的resolveSeedPath可以确认seed 文件按以下优先级解析命令行位置参数显式传入的路径约定路径.emdash/seed.jsonpackage.json中的emdash.seed字段指定的路径项目中常见的seed/seed.json仓库模板即采用此布局。Seed 文件结构总览{ $schema: https://emdashcms.com/seed.schema.json, version: 1, meta: { name: My Site, description: A description of this site, author: Author Name }, settings: { ... }, collections: [ ... ], taxonomies: [ ... ], menus: [ ... ], widgetAreas: [ ... ], sections: [ ... ], bylines: [ ... ], content: { ... } }各顶层键的含义与源码中SeedFile接口packages/core/src/seed/types.ts一一对应键作用可选性$schemaJSON Schema 引用用于编辑器校验可选version种子格式版本当前固定为1必填meta站点名称、描述、作者可选settings站点级设置title、tagline等可选collections内容类型定义每个集合对应一张ec_{slug}表可选taxonomies分类/标签体系可选menus导航菜单可选widgetAreas部件区域侧边栏等可选sections可复用内容块类似 WordPress 的 pattern/reusable block可选bylines署名作者档案独立于用户账号可选content按集合组织的示例内容可选源码中的SeedFile还包含redirects重定向规则与defaultLocale单语言项目默认 locale见 packages/core/src/seed/types.ts两个扩展键——defaultLocale是为export-seed→seed往返保留非en默认语言而设计的。Collections定义内容类型Collections 定义内容类型每个 collection 会成为一张数据库表ec_{slug}{ slug: posts, label: Posts, labelSingular: Post, supports: [drafts, revisions, search, seo], commentsEnabled: true, fields: [ ... ] }结合 SeedCollection 接口 与导出命令 export-seed.tscollection 还支持以下可选项description/icon后台展示用描述与图标urlPatternURL 模式例如/{slug}templates/starter/seed/seed.json 中的pages集合即使用此模式routable: false该集合不生成公开路由titleField/dateField指定标题字段与日期字段在字段创建后单独写入校验见 apply.tseditLocking、hidden、sortOrder、group后台编辑锁、隐藏、排序与分组。Collection SupportsSupport描述drafts草稿/发布工作流revisions修订历史search全文搜索索引seo后台中的 SEO 元字段Slug 规则小写字母数字 下划线/^[a-z][a-z0-9_]*$/最长 63 个字符不能与保留 slug 冲突Field Types字段类型与存储映射字段类型决定了数据库列类型与运行时数据结构Type列类型运行时形态备注stringTEXTstring单行文本textTEXTstring多行文本textareanumberREALnumber浮点数integerINTEGERnumber整数booleanINTEGERboolean存储为 0/1datetimeTEXTDate数据库中为 ISO 8601 字符串imageTEXT{ id, src?, alt?, width?, height? }对象而非字符串referenceTEXTstringID引用其他条目portableTextJSONPortableTextBlock[]富文本结构化 JSONjsonJSONany任意 JSON 数据易错点image字段的运行时值是对象。若在模板中写img src{post.data.featured_image} /会渲染成[object Object]必须使用emdash/ui的Image image{...} /组件参见 SKILL.md 的 Common Gotchas。Field Definition{ slug: title, label: Title, type: string, required: true, searchable: true }字段可具备的属性与 SeedField 接口 一致slug必填—— 字段标识符label必填—— 后台显示标签type必填—— 上述类型之一required—— 校验是否必填searchable—— 是否纳入全文搜索索引另有可选unique、indexed、defaultValue、validation、widget后台组件、options如 reference 字段的目标集合常见字段模式博客文章fields: [ { slug: title, label: Title, type: string, required: true, searchable: true }, { slug: featured_image, label: Featured Image, type: image }, { slug: content, label: Content, type: portableText, searchable: true }, { slug: excerpt, label: Excerpt, type: text } ]作品集项目fields: [ { slug: title, label: Title, type: string, required: true, searchable: true }, { slug: featured_image, label: Featured Image, type: image, required: true }, { slug: client, label: Client, type: string }, { slug: year, label: Year, type: string }, { slug: summary, label: Summary, type: text, searchable: true }, { slug: content, label: Content, type: portableText, searchable: true }, { slug: gallery, label: Gallery, type: json }, { slug: url, label: Project URL, type: string } ]页面极简fields: [ { slug: title, label: Title, type: string, required: true, searchable: true }, { slug: content, label: Content, type: portableText, searchable: true } ]Taxonomies分类法分类法taxonomy是挂接到集合上的标签/分类体系类似 WordPress 的分类与标签{ name: category, label: Categories, labelSingular: Category, hierarchical: true, collections: [posts], terms: [ { slug: development, label: Development }, { slug: design, label: Design } ] }hierarchical: true—— 树形结构类似 WordPress 分类目录 categorieshierarchical: false—— 扁平列表类似 WordPress 标签 tagscollections—— 该分类法应用于哪些集合terms—— 预定义的术语term列表从导出实现export-seed.ts可以看到taxonomy 还支持id、description术语描述、parent父术语 slug以及多语言下的locale/translationOf字段导入时会先写锚点anchor再写翻译项以保证translationOf可解析。注意查询时 taxonomy 名称必须与 seed 中完全一致——定义了name: category就必须用getTerm(category, slug)查询写错名称只会得到空结果而不会报错SKILL.md Gotcha #3。Menus导航菜单菜单由后台管理seed 中可预置初始项{ name: primary, label: Primary Navigation, items: [ { type: custom, label: Home, url: / }, { type: custom, label: About, url: /pages/about }, { type: custom, label: Posts, url: /posts } ] }菜单项类型custom—— 任意 URL内容引用type非 custom 时导出为collectionref见 buildMenuItemTree在渲染时解析菜单项还可选target: _blank、titleAttr、cssClasses、子菜单children树形结构多语言下支持locale与translationOf。Widget Areas部件区域部件区域是命名区域编辑者可以在其中添加可配置部件。完整的侧边栏示例{ name: sidebar, label: Sidebar, description: Widget area displayed on single post pages, widgets: [ { type: component, componentId: core:search, title: Search }, { type: component, componentId: core:categories, title: Categories }, { type: component, componentId: core:tags, title: Tags }, { type: component, componentId: core:recent-posts, title: Recent Posts, settings: { count: 5, showDate: true } }, { type: component, componentId: core:archives, title: Archives, settings: { type: monthly, limit: 6 } }, { type: content, title: About, content: [ { _type: block, style: normal, children: [{ _type: span, text: Some rich text content. }] } ] } ] }说明原文档中settings键在导出的 seed 中对应源码里的props组件属性见 exportWidgetAreas。部件类型类型描述关键字段content富文本Portable Textcontentmenu导航菜单menuNamecomponent核心或自定义组件componentId、settings核心部件组件core:search—— 搜索表单core:categories—— 带计数的分类列表core:tags—— 标签云core:recent-posts—— 最新文章列表core:archives—— 月度归档链接Sections可复用内容块可复用内容块编辑者可通过编辑器中的/section斜杠命令插入{ slug: newsletter-signup, title: Newsletter Signup, description: A call-to-action block for newsletter subscriptions, keywords: [newsletter, subscribe, email, cta], source: theme, content: [ { _type: block, style: h3, children: [{ _type: span, text: Stay in the loop }] }, { _type: block, style: normal, children: [{ _type: span, text: Get notified when new posts are published. }] } ] }source: theme表示该 section 由主题提供keywords用于编辑器的搜索联想。Bylines署名作者档案署名档案独立于用户账号用于内容的呈现性署名{ id: byline-editorial, slug: emdash-editorial, displayName: EmDash Editorial }客座作者{ id: byline-guest, slug: guest-contributor, displayName: Guest Contributor, isGuest: true }从 exportBylines 可见导出时 byline 还可能携带bio、websiteUrl内容条目通过bylines数组以{ byline: byline-editorial }的形式引用见下文 Content 示例。SKILL.md 还提醒查询内容时条目自带data.byline与data.bylines一般无需单独调用getByline。Settings站点设置settings: { title: My Blog, tagline: Thoughts on building for the web }可用键title、tagline、logo、favicon、social、timezone、dateFormat。实现上设置以site:前缀存入 options 表见 exportSettings 与 applySiteSettings应用时会使用 compare-and-set 避免覆盖已有设置。Content示例内容示例内容按集合 slug 组织content: { posts: [ { id: post-1, slug: hello-world, status: published, data: { title: Hello World, excerpt: My first post., featured_image: { $media: { url: https://images.unsplash.com/photo-xxx?w1200h800fitcrop, alt: Description of image, filename: hello-world.jpg } }, content: [ { _type: block, style: normal, children: [{ _type: span, text: This is the body text. }] } ] }, bylines: [ { byline: byline-editorial } ], taxonomies: { category: [development], tag: [webdev, opinion] } } ], pages: [ { id: about, slug: about, status: published, data: { title: About, content: [ { _type: block, style: normal, children: [{ _type: span, text: About this site. }] } ] } } ] }仓库中的 templates/starter/seed/seed.json 提供了一个完整可运行的例子包含posts支持 drafts/revisions/search/seo与pagesurlPattern: /{slug}两个集合、category与tag两个分类法、primary菜单、sidebar部件区域以及一个欢迎文章taxonomies引用general/starter/example和 about 页面。Content 中的媒体引用$media图片字段使用$media时EmDash 会下载并存储该图片featured_image: { $media: { url: https://images.unsplash.com/photo-xxx?w1200h800fitcrop, alt: Description, filename: my-image.jpg } }若不想下载、直接使用外部图片featured_image: https://images.unsplash.com/photo-xxx?w1200从源码看applySeed支持skipMediaDownload选项packages/core/src/seed/apply.ts媒体下载还会经过ssrfSafeFetch/validateExternalUrl做 SSRF 防护同文件 import 语句。导出时processDataForExport图片字段会被反向转换为$media语法export-seed.ts。Content 中的引用字段$ref使用$ref:id格式引用其他条目author: $ref:byline-editorial导出时引用字段会被转换为$ref:${seedId}export-seed.ts。导入引擎按引用目标先后顺序处理集合保证被引用的条目先写入orderByReferenceTargetsexport-seed.ts。Content 中的 Portable TextportableText字段是 block 数组[ { _type: block, style: normal, children: [{ _type: span, text: A paragraph. }] }, { _type: block, style: h2, children: [{ _type: span, text: A heading }] }, { _type: block, style: blockquote, children: [{ _type: span, text: A quote. }] } ]内联标记粗体、斜体、链接{ _type: block, style: normal, children: [ { _type: span, text: This is }, { _type: span, text: bold, marks: [strong] }, { _type: span, text: and }, { _type: span, text: italic, marks: [em] } ] }块样式normal、h1–h6、blockquote。草稿内容设置status: draft即可创建未发布内容{ id: post-draft, slug: work-in-progress, status: draft, data: { ... } }应用 Seeds校验与常见错误seed 的加载路径依次为.emdash/seed.json、package.json#emdash.seed或seed/seed.json以及 CLI 位置参数被内联进构建并在数据库为空且设置向导未完成时于首次请求应用。已有数据不会被覆盖。校验在应用时执行validateSeed见 packages/core/src/seed/apply.ts常见错误图片字段使用原始 URL应使用$media引用字段使用原始 ID应使用$ref:idPortableText 不是数组或缺少_type类型不匹配string vs number 等若 seed 无效首次请求会失败并记录错误。修复后需重启开发服务器。CLI 也提供了独立的校验/应用入口emdash seed支持--validate仅校验不应用、--no-content跳过示例内容、--on-conflictskip/update/error默认 skip与--uploads-dir等参数packages/core/src/cli/commands/seed.ts。另外要注意从旧版本数据库导出前需先执行emdash migrate否则导出会因 pending migrations 而失败export-seed.ts。导出 Seeds将已有数据库变为可复现的 seednpx emdash export-seed # 仅 Schema npx emdash export-seed --with-content # Schema 全部内容 npx emdash export-seed --with-contentposts,pages # 指定集合export-seed命令packages/core/src/cli/commands/export-seed.ts从当前数据库导出完整 schemasettings、collections/fields、taxonomies、menus、widget areas、bylines--with-content时附带内容。该命令是幂等往返的基石导出的 seed 可再次通过emdash seed或首次启动自动应用到新数据库实现站点结构的版本化与可复现部署。导出时还应注意输出写入 stdout诊断信息写入 stderr因此emdash export-seed seed.json重定向是安全的命令自动检测数据库是否为多语言多 locale项目并在导出中自描述defaultLocale保证非en单语言项目往返不丢失export-seed.ts集合按引用依赖排序输出被引用的集合排在前面确保重新导入时$ref可解析orderByReferenceTargets。小结一条从空白站点到可复现内容的完整链路设计在seed/seed.json中声明 collections、fields、taxonomies、menus、widgetAreas、sections、bylines 与示例 content启动pnpm dev后首次请求自动迁移数据库并应用 seedemdash migrate手动迁移亦可校验emdash seed --validate或依赖应用时校验遵循$media、$ref:id、Portable Text 结构规范版本化emdash export-seed --with-content把线上/开发数据库还原成 seed 文件实现 schema 与演示数据的迁移与备份。进一步阅读完整的站点搭建流程astro.config、live.config、查询渲染、站点特性可参考 building-emdash-site SKILL以及同目录下的 configuration.md、querying-and-rendering.md 与 site-features.md。【免费下载链接】emdashEmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress项目地址: https://gitcode.com/gh_mirrors/emdas/emdash创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表