- A 站点文案单例:content/site/{home,about,opensource}.yaml +
src/lib/site-content.ts 访问层(字段级回落默认,默认值=原文案逐字
一致,零回归);接线主页 tagline(en 首页新增该块)、关于页 intro、
开源页叙述三段 + PINNED 参数化(projects.ts: loadProjects(pinned)
/orderPinned,PINNED_DEFAULT 仅缺省兜底)
- loader 语义修正(返工如实入档):Astro 7 的 file() 把 YAML 顶层对象
按 Object.entries 拆成多条目(id=key、data=value),单例字段必炸
schema;改 glob 精确到单文件 = 真单例语义,data 即文件根对象,
Sveltia 可编辑根字段零嵌套(比包 main: 层的方案后台体验更好)
- B 文章媒体:posts +video/+poster;Sveltia file 字段
(media_folder=public/media、public_folder=/media、hint ≤50MB);
正文后渲染 video controls preload=metadata playsinline,无则不渲染;
图片链路核对本已一致(./assets 走 Astro 管线);链接 markdown 原生
- docs/写作指南.md 补「后台上传」节(三类媒体 + 三单例操作 + 体积纪律)
Sveltia 集合:posts / moments / photos / site_pages(三单例)
车道:op-gitea(实测 tagline 改 yaml 产物联动、置空回落默认、pinned
改名排序变、视频临时件渲染全对、构建绿 + lint 45 页 0/0/0);收编
复验:构建 44 页 + E2E 37/37 + 三 yaml 扁平键就位
验证: pnpm astro build 44 页 exit 0;E2E 37/37 PASS;content-lint
0/0/0;播放器/单例/置顶 playwright 实测全过
Spec: none (内容管理闭环,车道级交付)
Co-authored-by: GLM-5.3
151 lines
7.4 KiB
YAML
151 lines
7.4 KiB
YAML
# yaml-language-server: $schema=https://unpkg.com/@sveltia/cms/schema/sveltia-cms.json
|
||
# Sveltia CMS 配置(T3 试水):仅 photos 集合,见 docs 预研报告
|
||
# 纪律:不开内建图片优化(transformations 会把原图转 webp 抹掉 EXIF,构建期提取报废)
|
||
backend:
|
||
name: gitea
|
||
repo: wait4x/blog
|
||
branch: main
|
||
# 走博客域同源反代(nginx /gitea/ → 127.0.0.1:13020):
|
||
# ①绕开 git.wait4x.online 的 ESA 522 ②同源无 CORS ③ESA 缓存规则已排除 /artalk/api
|
||
base_url: https://wait4x.online/gitea
|
||
api_root: https://wait4x.online/gitea/api/v1
|
||
|
||
media_folder: content/photos
|
||
site_url: https://wait4x.online
|
||
|
||
output:
|
||
# Astro zod optional 兼容:空可选字段不写文件(官方 Astro 指南建议)
|
||
omit_empty_optional_fields: true
|
||
|
||
collections:
|
||
# 文章(含书评/技术/照片三轨;书=category:reading 的文章,同一集合管理)
|
||
- name: posts
|
||
label: 文章
|
||
label_singular: 文章
|
||
folder: content/posts
|
||
create: true
|
||
# 中文主稿;英文为 TMT 预翻译入仓的 .en.md(posts-en 集合不在后台,防误改译文)
|
||
slug: '{{slug}}'
|
||
summary: '{{title}} · {{category}}'
|
||
sortable_fields: [pubDate, title]
|
||
media_folder: content/posts/assets
|
||
public_folder: ./assets
|
||
fields:
|
||
- { label: 标题, name: title, widget: string }
|
||
- { label: 日期, name: pubDate, widget: datetime, date_format: 'YYYY-MM-DD', time_format: false, format: 'YYYY-MM-DD' }
|
||
- { label: 分轨, name: category, widget: select, options: [{label: 阅读, value: reading}, {label: 技术, value: tech}, {label: 照片, value: photo}] }
|
||
- { label: 标签, name: tags, widget: list, required: false }
|
||
- { label: 情绪色(书评色脊), name: mood, widget: color, required: false, hint: '#RRGGBB,仅阅读轨使用' }
|
||
- { label: 原书作者, name: bookAuthor, widget: string, required: false }
|
||
- { label: 一句话描述(书架策展语), name: description, widget: text, required: false }
|
||
- { label: 书封图, name: cover, widget: image, required: false, hint: '上传后自动生成,无需手填路径;仅阅读轨展示' }
|
||
- label: 附视频(可选)
|
||
name: video
|
||
widget: file
|
||
required: false
|
||
media_folder: public/media
|
||
public_folder: /media
|
||
hint: '展示在正文之后;mp4/webm ≤50MB(走 public/media,构建时原样拷贝,不做转码)'
|
||
- label: 视频封面(可选)
|
||
name: poster
|
||
widget: string
|
||
required: false
|
||
hint: '填 /media/xxx.jpg(先上传到 public/media 取路径);缺省浏览器自取首帧'
|
||
- { label: 隐藏(不进列表/sitemap), name: hiddenTag, widget: boolean, required: false, hint: '对应 tags 含 hidden;保存后请人工核对' }
|
||
- { label: 草稿, name: draft, widget: boolean, required: false, default: false }
|
||
- { label: 正文, name: body, widget: markdown }
|
||
|
||
# 瞬间:随手发(text/image 至少其一——Sveltia 无法表达条件必填,两者都设可选,
|
||
# 保存前自查;pubDate 必填)。图片走图库媒体库(content/photos 同源可复用)
|
||
- name: moments
|
||
label: 瞬间
|
||
folder: content/moments
|
||
create: true
|
||
slug: '{{year}}-{{month}}-{{day}}-{{slug}}'
|
||
summary: '{{fields.pubDate}} · {{fields.text}}'
|
||
fields:
|
||
- { label: 时间, name: pubDate, widget: datetime, date_format: 'YYYY-MM-DD', time_format: false, format: 'YYYY-MM-DD' }
|
||
- { label: 文字, name: text, widget: text, required: false, hint: '一句话(与图片至少填一项)' }
|
||
- { label: 图片, name: image, widget: image, required: false, hint: '与文字至少填一项;建议先压缩' }
|
||
- label: 标签
|
||
name: tags
|
||
widget: list
|
||
required: false
|
||
- name: photos
|
||
label: 图库照片
|
||
folder: content/photos
|
||
# 整文件 JSON(非 frontmatter)= 现有 sidecar 同构;不设 format 条目不列出
|
||
format: json
|
||
create: true
|
||
# 入口相对:jpg 与 sidecar 同目录;image 引用写裸文件名(loader new URL 等价解析)
|
||
media_folder: ''
|
||
public_folder: ''
|
||
summary: '{{fields.group}} · {{fields.title}}'
|
||
fields:
|
||
# title 必填:Astro schema z.string() 无 .optional(),omit 纪律下必需且有值才会落键(空 title 会让 main 不可构建)
|
||
- { label: 标题, name: title, widget: string, required: true }
|
||
- { label: 图片, name: image, widget: image }
|
||
- { label: 分组, name: group, widget: select, options: [street, landscape] }
|
||
- { label: 替代文本, name: alt, widget: string, required: false }
|
||
- { label: 人为描述, name: caption, widget: text, required: false, hint: 展示在灯箱里的人为描述(一句话策展文案) }
|
||
- label: EXIF 覆盖(一般留空,构建期自动从图提取)
|
||
name: exif
|
||
widget: object
|
||
required: false
|
||
fields:
|
||
- { label: 机身, name: make, widget: string, required: false }
|
||
- { label: 镜头, name: lens, widget: string, required: false }
|
||
- { label: 光圈值, name: fNumber, widget: number, required: false }
|
||
- { label: 曝光秒, name: exposureTime, widget: number, required: false }
|
||
- { label: ISO, name: iso, widget: number, required: false }
|
||
|
||
# 页面文案单例(cms 车道 A):三个文件型入口,保存即写 content/site/*.yaml,
|
||
# 字段与 Astro siteHome/siteAbout/siteOpenSource 的 schema 一一对应(zh/en 双字段,留空回落默认)
|
||
- name: site_pages
|
||
label: 页面文案
|
||
files:
|
||
- name: home
|
||
label: 主页设置
|
||
file: content/site/home.yaml
|
||
fields:
|
||
- label: 身份语
|
||
name: tagline
|
||
widget: object
|
||
fields:
|
||
- { label: 中文, name: zh, widget: string, required: false }
|
||
- { label: 英文, name: en, widget: string, required: false }
|
||
- name: about
|
||
label: 关于页
|
||
file: content/site/about.yaml
|
||
fields:
|
||
- label: 身份陈述段
|
||
name: intro
|
||
widget: object
|
||
hint: 渲染在「关于」标题下方、名片之上;留空用默认文案
|
||
fields:
|
||
- { label: 中文, name: zh, widget: text, required: false }
|
||
- { label: 英文, name: en, widget: text, required: false }
|
||
- name: opensource
|
||
label: 开源页
|
||
file: content/site/opensource.yaml
|
||
fields:
|
||
- label: 叙述(链接前)
|
||
name: blurb
|
||
widget: object
|
||
fields:
|
||
- { label: 中文, name: zh, widget: string, required: false }
|
||
- { label: 英文, name: en, widget: string, required: false }
|
||
- { label: 仓库链接地址, name: repo_url, widget: string, required: false }
|
||
- { label: 仓库链接文字, name: repo_label, widget: string, required: false }
|
||
- label: 叙述(链接后)
|
||
name: blurb_after
|
||
widget: object
|
||
fields:
|
||
- { label: 中文, name: zh, widget: text, required: false }
|
||
- { label: 英文, name: en, widget: text, required: false }
|
||
- label: 置顶项目(仓库短名,顺序即展示顺序)
|
||
name: pinned
|
||
widget: list
|
||
required: false
|
||
hint: '如 blog;留空则回落默认 blog。填写的名字须与仓库短名一致'
|