feat(theme): 六类页面渲染与路由分派
单一动态路由 [...slug].astro 读 routes.json html 纯路径行分派六模板 (home/typeKey 详情/分类前缀列表/news 主列表),无法分派即构建明错; 404 独立静态页。夹具扩展为六页集(真实 hesupipe 抽样形状脱敏化: knownFields.postDate/title、media 块 attachmentRefs.* fieldPath、 /products/ 内容页占据、编码路径 + .html 字面路径防御)。 字面 .html 路径对齐钩子(astro.config 内联 integration):Astro 页面 产物在 directory/file/preserve 三态均产不出 dist/news/x.html 字面文件, 构建收尾把包装目录折平为字面文件——target_file 契约对齐。 构建级测试 8 例(render-cases):全量映射/编码字节原样/首页截断/ 产品参数相册/新闻字面 .html/列表两类/SEO 基线。372 → 380。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,41 @@
|
||||
import { resolve } from 'node:path'
|
||||
import { existsSync, renameSync, rmSync } from 'node:fs'
|
||||
import { join, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { defineConfig } from 'astro/config'
|
||||
|
||||
// 字面 .html 路径对齐(URL pathname 保真——快线 Task 4 钉死的映射规则之一):
|
||||
// Astro 页面产物在 build.format 三态下分别是 <path>/index.html(directory——尾斜杠路由
|
||||
// 的正确形态)或 <path>.html(file/preserve——会给无后缀路由追加后缀)。两者都产不出与
|
||||
// routes.json targetFile 逐字节一致的 dist/news/x.html 字面文件(file/preserve 会得到
|
||||
// x.html.html)。此钩子在构建收尾把 .html 后缀路由的包装目录折平为字面文件——
|
||||
// Task 5 管线的 manifest 对齐(target_file 是唯一权威)因此恒为 no-op。
|
||||
function literalHtmlPaths() {
|
||||
return {
|
||||
name: 'sf-literal-html-paths',
|
||||
hooks: {
|
||||
'astro:build:done': async ({ pages, dir, logger }) => {
|
||||
const dist = fileURLToPath(dir)
|
||||
let moved = 0
|
||||
for (const { pathname } of pages) {
|
||||
// pages 的 pathname 是相对 pageName(directory 格式恒带尾斜杠,如
|
||||
// 'news/x.html/')——剥尾斜杠后以 .html 后缀判定字面文件路由
|
||||
const rel = pathname.replace(/\/+$/, '')
|
||||
if (!rel.endsWith('.html')) continue
|
||||
const wrapper = join(dist, rel)
|
||||
const nested = join(wrapper, 'index.html')
|
||||
if (!existsSync(nested)) continue
|
||||
const tmp = join(dist, `.sf-literal-${moved}.tmp`)
|
||||
renameSync(nested, tmp)
|
||||
rmSync(wrapper, { recursive: true })
|
||||
renameSync(tmp, wrapper)
|
||||
moved++
|
||||
}
|
||||
if (moved > 0) logger.info(`字面 .html 路径对齐:${moved} 页`)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 纯静态输出(Task 4/5 消费)。页面数据全部来自 SF_BUILD_INPUT 六文件(load-render-data
|
||||
// 单一入口),不设 site——canonical/og 的 origin 是每站点数据(site.json 的 origin),
|
||||
// 不是主题级配置。@sf/contracts 直连源码(与根 tsconfig/vitest 同映射——契约包零依赖
|
||||
@@ -9,6 +44,7 @@ export default defineConfig({
|
||||
output: 'static',
|
||||
srcDir: './src',
|
||||
outDir: './dist',
|
||||
integrations: [literalHtmlPaths()],
|
||||
vite: {
|
||||
resolve: {
|
||||
alias: {
|
||||
|
||||
Reference in New Issue
Block a user