Dingnuooo's Notes

Back

记录一下构建新博客站的过程、自定义功能需求和 bug 的解决,以及在这个过程中了解到的一些 js 相关的知识。参考资料:pure 主题文档astro 文档。我不太懂 js 及其专有名词,很多内容也是自己折腾半天、大模型生成、勉强理解之后写的,未经过专业的考证。如果您有相关的专业知识,欢迎评论详细说明。


起因:知乎上刷到一个关于个人博客的回答,看到了这个博客 https://arthals.ink/ ,很喜欢这种干净整洁的画面,而且还是个开源项目。再加上使用 hexo + shoka 的旧站非常卡,很多功能都不完善,维护起来很麻烦。于是启动了这次搬家。感谢两位开发者 cworld1Arthals

环境与工具:

  • node 22.15.8
  • npm 10.9.2
  • astro-pure 4.0.8

阶段一:Installation#

Step 1:把主题 clone 下来#

git clone https://github.com/cworld1/astro-theme-pure.git
shell

Step 2:删除 .git 目录#

除非完全掌握 git 的使用方法,否则删除原有的 git 文件夹。贸然沿用原有的 git 文件可能会影响原项目

Step 3:安装依赖项#

一般 js 项目都不会上传依赖包,因为太大了。因此需要在根目录下运行:

npm install
shell

这一步文件比较多 要等一会儿

如果是 windows 系统,注意在根目录下的 package.json 文件中,要把 clean 的指令改一下,windows 没有 rm

package.json
{
  // ...
  "scripts": {
    // ...
    "clean": "rm -rf .astro .vercel dist", 
    "clean": "rmdir /s /q .astro .vercel dist"
  },
  // ...
}
json

Step 4:测试#

启动 astro 开发服务器,默认监听 4321 端口

npm run dev
shell

如果能够正常运行说明安装成功。开发过程中将会自动监看文件的变化

Step 5:删除 docs 目录#

这里是存放 pure 主题官方文档的地方。在配置文件中删除 docs 相关的内容:

src/site.config.ts
export const theme: ThemeUserConfig = {
   // ...
   header: {
      menu: [
         { title: 'Blog', link: '/blog' },
         { title: 'Docs', link: '/docs' },  
         { title: 'Projects', link: '/projects' },
         // ...
      ],
   },
}
ts
src/content.config.ts
const docs = defineCollection({ 
	// ...
}) 
export const collections = { blog, docs } 
export const collections = { blog } 
ts

注:官方文档中建议删除 packages 目录,packages/pure 里头是 astro-pure 的依赖包,在安装依赖项的时候已经装到 node_modules 里面了。

但是我的习惯是保留 packages 目录,并做以下处理:

  1. 打开 packages 目录,将 pure 重命名为 astro-pure。这是为了与 node_modules 里头的名字一致。
  2. packages 目录移动到 src 里头

基于这个方式进行后续操作,将会使得 customization 的流程变得简单。

Step 6:测试部署#

不急着对网页做修改,先看看能不能部署成功。连接 Github 并部署到托管平台。例如 vercel 能够识别 astro 项目,自动填好 buildcommand 等配置。

阶段二:Customization#

如果不涉及依赖包、或者作者提供了接口的东西,直接改就行了,例如 author、title、avatar、icon 等。

如果要修改依赖包里面的东西,不能直接在 node_modules 里面改。因为 node_modules 这个目录被 ignore 掉了,即使把它从 ignore 里头移走,部署平台在构建时一般也不会访问它。

本来尝试的方法是直接在本地构建后再部署到云端,但没有成功(理论上应该可以才对呐,,,用 vercel 整了好久还是用云端构建)。因此使用改变引用路径的方式,在外部进行修改,称为 Swizzling。官方给出的步骤是:

  1. 先找到需要修改的文件
  2. 复制出来并对文件做出修改
  3. 修改引用路径

下面举一个例子详细说明:修改页面底端的 Quote 组件。原本是一个显示随机名言的元素,我希望改成显示固定名言。

Step 1:找到元素源码位置#

找到该元素源码所在的位置。“显示随机名言”这个元素位于 src/pages/index.astro

import { Quote } from 'astro-pure/advanced'
// ...
---
// ...
<Quote class='mt-12' />
// ...
json

ctrl+左键 点击下面这个 Quote,定位到实现 Quote 的文件 node_modules\astro-pure\components\advanced\Quote.astro

Step 2:复制文件#

官方给出的做法是,把 node_modules\astro-pure\components\advanced\Quote.astro 复制到自定义的路径下,再做出修改。

但是我们在阶段一中没有删除 packages 目录,因此我们可以直接去 packages 中对应的文件里做修改,也即修改 src\packages\astro-pure\components\advanced\Quote.astro

Step 3:修改文件#

// src\packages\astro-pure\components\advanced\Quote.astro
---
import { cn } from '../../utils'

const { class: className } = Astro.props
---

<quote-component class={cn('not-prose inline-block', className)} >
  <div class='flex flex-row items-center gap-x-3 rounded-full border px-4 py-2 shadow-sm' style='font-size: 0.9375rem;'>
    <span class='relative flex items-center justify-center'>
      <span
        class='absolute size-2.2 animate-ping rounded-full border border-green-400 bg-green-400 opacity-75'
      ></span>
      <span class='size-2.2 rounded-full bg-green-400'></span>
    </span>
    <p id='quote-sentence' class='font-medium text-muted-foreground'>握紧你的锄头 - Never put down your hammer.</p>
  </div>
</quote-component>

<script>
  class Quote extends HTMLElement {
    constructor() {
      super()
    }
  }
  customElements.define('quote-component', Quote)
</script>
ts

(还有一些其他小改动,只是这一部分文字很早就写了所以没加进去)

Step 4:修改引用#

回到引用 Quote 的 import 语句处(即 src/pages/index.astro),修改引用方式。

src/pages/index.astro
import { Quote } from 'astro-pure/advanced'
import { Quote } from '../packages/astro-pure/components/advanced/index.ts'
astro

这与原始的引用逻辑看起来不太一样。

因为像 astro-pure 这种包,作者在它的 package.json 里设置了入口,称为命名导入:

// node_modules/astro-pure/package.json
"exports": {
    ".": "./index.ts",
    "./user": "./components/user/index.ts",
    "./advanced": "./components/advanced/index.ts",
    "./components/pages": "./components/pages/index.ts",
    "./components/basic": "./components/basic/index.ts",
    "./utils": "./utils/index.ts",
    "./server": "./utils/server.ts",
    "./types": "./types/index.ts",
    "./libs": "./libs/index.ts"
  },
json

例如原本的引用句 import { Quote } from 'astro-pure/advanced',后面的路径并非真实的文件路径,而是映射到内部的真实目录: node_modules/astro-pure/components/advanced/index.ts

因此在引用修改后文件的路径时,需要把完整的真实目录写出来。

另外做一个说明:大括号的用法。index.ts 长这样

// Web content render
export { default as Quote } from './Quote.astro'
export { default as GithubCard } from './GithubCard.astro'
export { default as LinkPreview } from './LinkPreview.astro'

// Data transformer
export { default as QRCode } from './QRCode.astro'
export { default as MediumZoom } from './MediumZoom.astro'
ts

因此 { Quote } 则表示“导入成员 Quote”,称为解构导入

Step 5:级联修改引用#

这就体现出保留 packages 的好处了。由于整个依赖包使用的都是相对路径,一旦某个部件里头还需要同一个依赖包里的其他文件,程序可以通过相对路径直接定位。反而,如果采用官方给出的做法,会导致“找不到这些二级依赖”而报错,因此需要级联地把二级依赖复制过来并且修改引用路径。

所以说我们才选择使用 packages 做 customization,这样就不用级联修改了。除非它引用了其他依赖包里头的东西。这时候只需要把依赖到的包也复制进 packages 文件夹,与 astro-pure 同级即可。也就是说,packages 就相当于一个小型的 node_modules,可以正常上传到部署平台进行构建。

阶段三:Writing#

创建文章#

法 1:指令创建#

npm run new <title>
shell

用于在 Astro 项目的 src/content/blog/ 目录下创建新的博客文章。

  • 指令:astro-pure new [options] <post-title>
  • 参数,默认都是否:
    • -l, --lang <en|zh>:文章语言
    • -d, --draft:是否是草稿
    • -m, --mdx:使用 .mdx 格式
    • -f, --folder:是否在单独文件夹下创建文章 (无法在文件夹内新建文章)
    • -h, --help:显示帮助信息
  • 默认路径:src/content/blog/
  • 文件命名:
    • 默认直接生成 slug.md
    • 如果加 -f,会生成一个目录 slug/,里面放 index.md
  • 内容模板:YAML Frontmatter(包含 titledescriptionpublishDatedraftlangtags 等)。

法 2:直接创建#

在 blog 文件夹下直接新建文件即可。注意,如果开着 dev 可能会报错,不用管他

Waline 配置#

官方文档:https://waline.js.org/guide/get-started 大陆访问:https://blog.csdn.net/Panzer_Jack/article/details/127418379

阶段四:Sitemap#

Bing#

进入 bing webmaster,添加网站。然后验证网站,使用第一种,下载 BingSiteAuth.xml,提交到网站的根目录中(在 astro 中也即放到 public 目录中),更新网站后点击验证

然后是 sitemap,astro-pure 会在构建时自动生成 sitemap

sitemap 里头的元素说明:

  • <urlset>: 根元素,包含所有 URL 信息。必须包含 xmlns=“http://www.sitemaps.org/schemas/sitemap/0.9” 命名空间。
  • <url>: 每个 URL 的信息块。
  • <loc>: 页面 URL,必须是绝对路径(包括协议,如 https://)。
  • <lastmod>: 页面最后修改时间(可选),格式为 YYYY-MM-DD。
  • <changefreq>: 页面内容更新频率(可选),值包括:always(始终)、hourly(每小时)、daily(每天)、weekly(每周)、monthly(每月)、yearly(每年)、never(从不)。
  • <priority>: 页面优先级(可选),范围为 0.0 到 1.0,默认值为 0.5。
  • 注意事项:
    1. 编码: 文件必须使用 UTF-8 编码。
    2. 文件大小限制: 单个 sitemap.xml 文件不能超过 50MB 或包含超过 50,000 个 URL。如果超出限制,可以使用 sitemap index 文件。

在 webmaster 中上传 sitemap,这里可以用 https://www.example.com/sitemap-0.xml 或者 https://www.example.com/sitemap-index.xml

最后要让 bing 自动更新 url,使用 indexnow,划到下面,下载 key(通常是一个 txt 文件,文件名及其内容是一串字符),放到 public 目录下,更新网站,然后在浏览器访问(把 <yourkey> 换成那一串字符)

https://www.bing.com/indexnow?url=https://www.example.com&key=<yourkey>
plaintext

刷新几次确认连上了就可以关了。回到 webmaster,看看 indexnow 那一栏里头有没有刚刚提交过的 url 列表。

bug 与其他小修改#

名言条动画#

名言左侧的绿色原点,有一个动画(tailwind 实现的,animate-ping),没有动起来。一般不会有问题,可能是 tailwindcss 的问题,于是在 app.css 中重写了这个动画

/* src/assets/styles/app.css */

/* Animations */
@keyframes ping {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  75%, 100% {
    transform: scale(2);
    opacity: 0;
  }
}

.animate-ping {
  animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
}
css

rehype-tabs 报错的解决#

src\packages\astro-pure\plugins\rehype-tabs.ts
// ...
interface Panel { 
export interface Panel { 
  panelId: string
  tabId: string
  label: string
}
// ...
export const processPanels = (html: string) => { 
export const processPanels = (html: string): { panels: Panel[]; html: string } => { 
  const file = tabsProcessor.processSync({ value: html })
  return {
    panels: file.data.panels, 
    panels: file.data.panels as Panel[], 
    html: file.toString()
  }
}
ts

数学公式#

latex 正常写。行间公式必须单独成行,并且双美元也要单独成行

暗色模式颜色#

标题:从二级标题开始写。

行内代码和引用文字的颜色:做如下修改

./uno.config.ts
const typographyConfig = {
	cssExtend: {
    //...
    pre: { 
      color: fg
    }, 
   	'.dark blockquote': { 
   	  color: 'hsl(var(--muted-foreground))'
   	}, 
   	'.dark :not(pre) > code': { 
   	  color: 'hsl(var(--foreground))'
   	}, 
		// Blockquote
    blockquote: {
    	//...
    },
    //...
	//...
	}
}
json

文字颜色变浅#

(需要 mdx)

<span class="text-foreground/40">文字</span>
mdx
Astro + Theme.Pure 建站流程记录
https://dingnuooo.top/blog/default/astropure-note
Author Dingnuooo
Published at September 26, 2025
Comment seems to stuck. Try to refresh?✨