1cd309d56d
Plan 4 Task 3:
- themes/pilot-minimal 入 workspace(astro ^5.18 纯静态;依赖仅 astro)
- theme.manifest:contracts isThemeManifest 守卫通过——key=pilot-minimal/
七模板条目(home/page/product-list/product-detail/news-list/news-detail/
not-found);brand 刻意不入 requiredSiteConfig(恒可能 {},Task 1 移交契约)
- load-render-data:全主题唯一取数入口(五禁纪律结构保证,JSDoc 钉死)——
SF_BUILD_INPUT 六文件、缺文件/形状破裂明确错误不静默空、同目录缓存单例、
name 空→'Untitled Site'/brand 缺席→{}、编码 slug 原样贯穿(源码令牌扫描
禁 percent-decode)
- 布局/组件:BaseLayout/SeoHead(title/desc/canonical/og)/SiteHeader(导航
路由缺席容忍隐藏)/SiteFooter/RichText(信任链:清洗+重写后直出)/
ResponsiveMedia/Breadcrumbs/ProductCard/NewsCard/Pagination(V1 禁用态)/
NotFound + tokens.css(75rem/系统字体/4-8-16-24-48/中性色+单 accent)
- 根 test 链并入主题(vitest 3 + astro getViteConfig,Container API 组件
渲染测试);typecheck 四段变五段;.astro/ 入 gitignore
354 根测试 + 16 主题测试全绿。
Co-Authored-By: Claude Code <noreply@anthropic.com>
32 lines
1.7 KiB
TypeScript
32 lines
1.7 KiB
TypeScript
// pilot 主题清单(spec §9.1;类型面 = contracts 冻结的 ThemeManifest——守卫 isThemeManifest
|
||
// 在测试里钉死通过)。import type 编译期擦除:astro build 不产生对 @sf/contracts 的运行时依赖。
|
||
//
|
||
// appliesTo 约定(声明性提示,派发真值在 Task 4 的模板分派器):
|
||
// 'route:<path>' 精确路由命中(home= '/',not-found = '/404')
|
||
// 'type:<typeKey>' 按内容类型分派(详情页)
|
||
// 'path-prefix:<pfx>' 按路径前缀分派(列表页;product-list 的 /category/ 别名前缀
|
||
// 由 Task 4 分派器一并处理——单一 appliesTo 字符串不承载多前缀)
|
||
import type { ThemeManifest } from '@sf/contracts'
|
||
|
||
export const themeManifest: ThemeManifest = {
|
||
key: 'pilot-minimal',
|
||
version: '0.1.0',
|
||
renderContractVersion: '1',
|
||
// 快线三类内容(与 build_input_snapshots 物化面一致);'basic_page' 覆盖 generic page
|
||
supportedContentTypes: ['news_article', 'product', 'basic_page'],
|
||
// site.json 必须提供的键(publish 首版 config v1 恰好满足;brand 刻意不在必填列——
|
||
// Task 1 审查移交:brand 恒可能 {},主题对 brand 全缺省容忍)
|
||
requiredSiteConfig: ['name', 'origin', 'locale'],
|
||
templates: [
|
||
{ key: 'home', appliesTo: 'route:/' },
|
||
{ key: 'page', appliesTo: 'type:basic_page' },
|
||
{ key: 'product-list', appliesTo: 'path-prefix:/product-category/' },
|
||
{ key: 'product-detail', appliesTo: 'type:product' },
|
||
{ key: 'news-list', appliesTo: 'path-prefix:/news/' },
|
||
{ key: 'news-detail', appliesTo: 'type:news_article' },
|
||
{ key: 'not-found', appliesTo: 'route:/404' },
|
||
],
|
||
}
|
||
|
||
export default themeManifest
|