Files
cms-website/themes/pilot-minimal/astro.config.mjs
T
浅念 f916f723ab 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>
2026-10-22 09:34:58 +08:00

56 lines
2.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 同映射——契约包零依赖
// 纯 TS,vite 直接编译内联,无需预构建 dist)。
export default defineConfig({
output: 'static',
srcDir: './src',
outDir: './dist',
integrations: [literalHtmlPaths()],
vite: {
resolve: {
alias: {
'@sf/contracts': resolve(import.meta.dirname, '../../packages/contracts/src/index.ts'),
},
},
},
})