diff --git a/astro.config.mjs b/astro.config.mjs index 9eeb6bb..9a6f1e7 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -3,6 +3,7 @@ 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'; @@ -18,9 +19,38 @@ const 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(), linkCardsReport()], + 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), diff --git a/infra/deploy/build.sh b/infra/deploy/build.sh index 1a7b3e0..72479e5 100755 --- a/infra/deploy/build.sh +++ b/infra/deploy/build.sh @@ -39,12 +39,9 @@ pnpm astro build [ -f scripts/build-perf/gen-sw-precache.mjs ] && node scripts/build-perf/gen-sw-precache.mjs dist || echo "[build] sw-precache 生成器未就绪,跳过" [ -f scripts/build-perf/inline-home-css.mjs ] && node scripts/build-perf/inline-home-css.mjs || echo "[build] inline-home 脚本未就绪,跳过" -# README 动效资产(5i T8):**不在此跑抓取**(避免发布链被外网抖动拖累),只做存在性守卫 + 缺资产告警 -if [ -f public/github-assets/manifest.json ]; then - echo "[build] github-assets 就绪:$(find public/github-assets -name '*.svg' | wc -l) 个自托管 SVG" -else - echo "[build] WARN public/github-assets/manifest.json 缺失——开源页数据板将只显示原生统计(可手动跑 node scripts/build-perf/fetch-readme-assets.mjs 补齐)" -fi +# README 动效资产(5i 引入、5j T2 退役):贡献蛇与 streak 快照已删——连续贡献改为 +# 热力图同源本地计算(见 src/lib/heatmap.ts 的 streakStats),界面上标注"数据更新于"。 +# fetch-readme-assets.mjs 保留骨架但 ASSETS 已清空,如将来要加新的自托管资产再启用。 # 内容 lint(T3):断链/缺图在部署前拦截;CONTENT_LINT=skip|warn 逃生门见脚本头注 [ -f scripts/build-perf/content-lint.mjs ] && node scripts/build-perf/content-lint.mjs dist || echo "[build] content-lint 未就绪,跳过" diff --git a/public/admin/config.yml b/public/admin/config.yml index 454b7fa..4cb6e9e 100644 --- a/public/admin/config.yml +++ b/public/admin/config.yml @@ -55,7 +55,12 @@ collections: widget: string required: false hint: '填 /media/xxx.jpg(先上传到 public/media 取路径);缺省浏览器自取首帧' - - { label: 隐藏(不进列表/sitemap), name: hiddenTag, widget: boolean, required: false, hint: '对应 tags 含 hidden;保存后请人工核对' } + - label: 隐藏(不进列表 / RSS / sitemap) + name: hidden + widget: boolean + required: false + default: false + hint: '打开后这篇不进首页/归档/书架/RSS/sitemap,但页面本身仍生成、链接可分享(想彻底不生成请用草稿)。与「置顶」同时打开时以隐藏为准——2026-11-04 修:旧开关只写一个没人读的字段,导致隐藏+置顶的文章照样显示还排第一' - { label: 草稿, name: draft, widget: boolean, required: false, default: false } - { label: 正文, name: body, widget: markdown } diff --git a/public/github-assets/snake.svg b/public/github-assets/snake.svg deleted file mode 100644 index 0f5c918..0000000 --- a/public/github-assets/snake.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/github-assets/streak-dark.svg b/public/github-assets/streak-dark.svg deleted file mode 100644 index 060b351..0000000 --- a/public/github-assets/streak-dark.svg +++ /dev/null @@ -1,104 +0,0 @@ - diff --git a/public/github-assets/streak-light.svg b/public/github-assets/streak-light.svg deleted file mode 100644 index 54aaa17..0000000 --- a/public/github-assets/streak-light.svg +++ /dev/null @@ -1,104 +0,0 @@ - diff --git a/scripts/build-perf/fetch-readme-assets.mjs b/scripts/build-perf/fetch-readme-assets.mjs index 37b5f88..4eafc5b 100644 --- a/scripts/build-perf/fetch-readme-assets.mjs +++ b/scripts/build-perf/fetch-readme-assets.mjs @@ -42,18 +42,6 @@ const ASSETS = [ `&text_color=${theme === 'dark' ? INK_DARK : INK_LIGHT}`, label: '语言分布', }, - { - name: 'streak', - url: (theme) => - `https://streak-stats.demolab.com/?user=${LOGIN}&hide_border=true` + - '&background=00000000' + - `&ring=${ACCENT}&fire=${ACCENT}&currStreakLabel=${ACCENT}` + - `&currStreakNum=${theme === 'dark' ? INK_DARK : INK_LIGHT}` + - `&sideNums=${theme === 'dark' ? INK_DARK : INK_LIGHT}` + - `&sideLabels=${theme === 'dark' ? MUTED_DARK : MUTED_LIGHT}` + - `&dates=${theme === 'dark' ? MUTED_DARK : MUTED_LIGHT}`, - label: '连续贡献', - }, { // 贡献蛇:GitHub Action 生成,配色由 action 侧决定,无法传参 → 只抓一份 name: 'snake', diff --git a/src/components/geek/GithubProfile.astro b/src/components/geek/GithubProfile.astro index b728d3c..d6490ef 100644 --- a/src/components/geek/GithubProfile.astro +++ b/src/components/geek/GithubProfile.astro @@ -5,7 +5,6 @@ // 0600 文件,缺位或失败即隐藏该数字)④src/lib/projects.ts 的仓库列表(语言占比与星标汇总) // 降级纪律:任何一项取数失败只隐藏该项,绝不炸构建、不出现空图片框 import { Image } from 'astro:assets'; -import { existsSync } from 'node:fs'; import TypingLines from './TypingLines.astro'; import { homeAvatar, homeSocials, openSourceCopy, renderRich } from '../../lib/site-content'; import { githubUserStats, loadProjects } from '../../lib/projects'; @@ -71,26 +70,7 @@ const lines = typingLines.length ? typingLines : DEFAULT_TYPING; // 自托管 SVG 数据卡(public/github-assets/,由 scripts/build-perf/fetch-readme-assets.mjs 产出入仓) // 缺文件即跳过该卡(异步抓取失败不影响构建),明暗各一份时用 CSS 切换 -const assetPath = (name: string) => `/github-assets/${name}`; -const hasAsset = (name: string) => existsSync(`public/github-assets/${name}`); -const boardCards: { label: string; light: string; dark?: string }[] = []; -for (const [key, label] of [ - ['stats', locale === 'zh' ? '统计' : 'Stats'], - ['top-langs', locale === 'zh' ? '语言分布' : 'Top languages'], - ['streak', locale === 'zh' ? '连续贡献' : 'Streak'], -] as const) { - if (!hasAsset(`${key}-light.svg`)) continue; - boardCards.push({ - label, - light: assetPath(`${key}-light.svg`), - dark: hasAsset(`${key}-dark.svg`) ? assetPath(`${key}-dark.svg`) : undefined, - }); -} -// 只有一张非通栏卡时让它占满整行(否则右半空档;stats/top-langs 上游 503 时就是这种情形) -const soloCard = boardCards.length === 1; -const snakeCard = hasAsset('snake.svg') - ? { label: locale === 'zh' ? '贡献蛇' : 'Contribution snake', src: assetPath('snake.svg') } - : null; +// 数据板已并入热力图区(Phase 5j T2):连续贡献由同源计算 + 更新时间标注,不再使用第三方 SVG const L = { zh: { followers: '关注者', repos: '公开仓库', stars: '总星标', langs: '语言占比' }, en: { followers: 'Followers', repos: 'Public repos', stars: 'Total stars', langs: 'Languages' }, @@ -171,33 +151,6 @@ const L = { )} - {(boardCards.length > 0 || snakeCard) && ( -
{locale === 'zh' ? '数据板' : 'Data board'}
-