// @ts-check import { defineConfig } from 'astro/config'; import pagefind from 'astro-pagefind'; import sitemap from '@astrojs/sitemap'; import { execSync } from 'node:child_process'; import { readdirSync, readFileSync } from 'node:fs'; import rehypeLinkCards, { linkCardsReport } from './src/lib/rehype-link-cards'; import rehypeClassWhitelist from './src/lib/rehype-class-whitelist'; import rehypeRaw from 'rehype-raw'; // 构建透明(T7):commit/时间经 vite.define 注入,页脚与 /about 引用。 // 四重回退:CI 环境变量优先(GITEA_ACTIONS/GITHUB_SHA)→ 本地 git → dev 占位。 const sha = process.env.GITEA_COMMIT_SHA || process.env.GITHUB_SHA || (() => { try { return execSync('git rev-parse HEAD').toString().trim(); } catch { return 'dev'; } })(); const date = process.env.GITEA_COMMIT_DATE || process.env.GITHUB_COMMIT_DATE || (() => { try { return execSync('git log -1 --format=%cI').toString().trim(); } catch { return new Date().toISOString(); } })(); // 隐藏文章不进 sitemap(内容侧契约见 src/lib/post-visibility.ts)。 // 这里在配置期直接扫 frontmatter:Astro 的 content collections 在配置上下文不可用, // 而 sitemap 的 filter 只拿到 URL。判定两条通道:`hidden: true` 与 tags 里的 hidden。 const hiddenSlugs = (() => { const set = new Set(); try { const dir = 'content/posts'; for (const file of readdirSync(dir)) { if (!file.endsWith('.md')) continue; const raw = readFileSync(`${dir}/${file}`, 'utf8'); const head = (raw.split('\n---\n')[0] ?? '').replace(/^---\n/, ''); if (/^hidden:\s*true\s*$/m.test(head)) { set.add(file.replace(/\.md$/, '')); continue; } // tags 可能是行内数组,也可能是多行列表:抓出 tags 段再找 hidden 词 const m = /^tags:[ \t]*([\s\S]*?)(?=^\w|\s*$)/m.exec(head); const tagBlock = m ? m[1] : ''; if (/\bhidden\b/.test(tagBlock)) set.add(file.replace(/\.md$/, '')); } } catch { /* 内容目录不可读时宁可不排除,也不让构建挂掉 */ } return [...set]; })(); export default defineConfig({ site: 'https://wait4x.online', integrations: [ pagefind(), sitemap({ filter: (page) => !hiddenSlugs.some((slug) => page.includes(`/archives/${slug}/`)), }), linkCardsReport(), ], markdown: { // 独立成段的裸链接 → OG 预览卡(构建期抓取,失败回落普通链接;见 src/lib/rehype-link-cards.ts) // 顺序:rehypeRaw 先把 markdown 里的 raw HTML 解析成 hast element(否则白名单看不到 span), // 再白名单净化(剥 style/on*/非白名单类),最后链接卡片(节点由插件自建,不经净化) rehypePlugins: [rehypeRaw, rehypeClassWhitelist, rehypeLinkCards], }, i18n: { defaultLocale: 'zh', locales: ['zh', 'en'], routing: { prefixDefaultLocale: false }, }, vite: { define: { 'import.meta.env.GIT_COMMIT_SHA': JSON.stringify(sha), 'import.meta.env.GIT_COMMIT_DATE': JSON.stringify(date), }, }, });