跳转到内容

搜索

Wake up...

What is real? How do you define real? If you’re talking about what you can feel, what you can smell, what you can taste and see, then real is simply electrical signals interpreted by your brain.
This is the world that you know. The world as it was at the end of the twentieth century. It exists now only as part of a neural-interactive simulation that we call the Matrix. You’ve been living in a dream world.
This is the world as it exists today… Welcome… to the desert… of the real.
We have only bits and pieces of information but what we know for certain is that at some point in the early twenty-first century all of mankind was united in celebration. We marveled at our own magnificence as we gave birth to AI.

AI? You mean artificial intelligence?

A singular consciousness that spawned an entire race of machines. We don’t know who struck first, us or them. But we know that it was us that scorched the sky. At the time they were dependent on solar power and it was believed that they would be unable to survive without an energy source as abundant as the sun. Throughout human history, we have been dependent on machines to survive. Fate, it seems, is not without a sense of irony. The human body generates more bio-electricity than a 120-volt battery and over 25,000 BTUs of body heat. Combined with a form of fusion, the machines have found all the energy they would ever need. There are fields, endless fields, where human beings are no longer born. We are grown. For the longest time I wouldn’t believe it, and then I saw the fields with my own eyes. Watch them liquefy the dead so they could be fed intravenously to the living. And standing there, facing the pure horrifying precision, I came to realize the obviousness of the truth.
What is the Matrix?
Control.
The Matrix is a computer generated dream world built to keep us under control in order to change a human being into battery.

Obsidian × Astro 链接兼容

写一个 remark 插件,构建时将 Obsidian 的 .md 文件路径自动转为 Astro 路由。区分两种写法——有 ./../ 前缀的从当前文件解析,没有的从 vault 根(src/content/)解析。post/webmentions.md/posts/webmentions/

问题

Obsidian 和 Astro 对链接的理解完全不同:

维度ObsidianAstro
链接目标文件系统路径URL 路由
文件扩展名需要 .md
路径风格相对 vault 根的路径(无/开头)根绝对路径(/开头)
末尾斜杠

Obsidian 的两种链接写法:

  • Vault-relativepost/webmentions.md,相对于 vault 根(src/content/
  • File-relative../post/webmentions.md,相对于当前文件所在目录

两种在 Obsidian 中都能正常跳转,但 Astro 编译后都指向不存在的路径,404。

思路

在 Obsidian 中用文件路径写,Astro 构建时自动转换成 URL 路由。

Astro 的 Markdown 管线支持 remark 插件,在 Markdown 编译为 HTML 之前操作 AST,可以修改任何链接节点。写一个 remark 插件,把 .md 链接转换为路由即可。

实现

依赖准备

依赖分析

  • unist-util-visit — 遍历 mdast 语法树,按节点类型查找 link 节点
  • node:path — Node.js 内置模块,解析相对路径、拼接路由

依赖安装

pnpm add unist-util-visit

实现插件

创建 src/plugins/remark-obsidian-links.mjs,核心逻辑分四步。

1. 遍历 & 过滤

import { visit } from 'unist-util-visit';
 
visit(tree, 'link', (node) => {
    let href = node.url;
    if (href.startsWith('http') || href.startsWith('#') || href.startsWith('mailto:')) return;
    if (!href.endsWith('.md')) return;
    // ...
});

remark 将 Markdown 解析为 mdast,visit 遍历 link 节点。外部链接、锚点、mailto、非 .md 链接直接跳过。

2. 解码 URL 编码

try {
    href = decodeURIComponent(href);
} catch {}

Obsidian 的 useMarkdownLinks: true 模式会对非 ASCII 字符做 percent-encode:

reference/%E6%B2%81%E5%9B%AD%E6%98%A5.md
→ reference/沁园春.md

不解码,后续路径解析会失败。

3. 区分两种路径风格

这是核心。根据是否有 ./../ 前缀区分处理策略:

const isFileRelative = href.startsWith('./') || href.startsWith('../');
 
if (isFileRelative) {
    // 相对于当前文件解析
    const resolved = path.resolve(path.dirname(currentFile), href);
    // 从 content root 截取相对路径
    withoutExt = resolved.replace(contentRoot, '');
} else {
    // vault-relative:直接从 content root 算
    // "post/webmentions.md" → "post/webmentions"
    withoutExt = href.replace(/\.md$/, '');
}

为什么必须区分?series/citrus-docs.md 中写 post/webmentions.md,如果当 file-relative 处理,会从 series/ 目录出发,算出 series/post/webmentions,路径就错了。vault-relative 写法直接按 content root 解析,结果是正确的 post/webmentions

4. 生成路由 URL

const segments = withoutExt.split('/');
const collection = segments[0]; // "post" | "til" | ...
 
if (collection === 'post') {
    prefix = '/posts';
    slug = segments.slice(1).join('/'); // 去掉集合名前缀
} else if (collection === 'til') {
    prefix = '/tils';
    slug = segments.slice(1).join('/');
}
 
node.url = `${prefix}/${slug}/`.replace(/\/+/g, '/');

集合名 (post/til) 是文件系统目录,不是 URL 的一部分,需要去掉。最终映射:

post/webmentions.md    → /posts/webmentions/
post/deepseek.md       → /posts/deepseek/
til/daily-log.md       → /tils/daily-log/
../post/other.md       → /posts/other/

注册插件

astro.config.ts 中引入:

import { remarkObsidianLinks } from './src/plugins/remark-obsidian-links.mjs';
 
export default defineConfig({
    markdown: {
        remarkPlugins: [remarkObsidianLinks],
    },
});

重启生效

remark 插件在 dev server 启动时加载并缓存,修改插件代码后必须完整重启(Ctrl+C 再 pnpm dev),热更新不会触发重编译。

总结

Obsidian 编辑时                      Astro 构建时
┌──────────────────────┐            ┌────────────────────────┐
│ [text](post/x.md)    │──remark──→ │ [text](/posts/x/)      │   vault-relative
│ [text](../post/x.md) │──remark──→ │ [text](/posts/x/)      │   file-relative
│ 文件系统路径           │   插件转换  │ URL 路由               │
└──────────────────────┘            └────────────────────────┘

两种 Obsidian 写法,一种 Astro 结果。源文件服务于编辑体验,构建时自动适配路由规则,互不干扰。

What is the F-Method in Resume Writing?

When recruiters review resumes, they spend only a few seconds on the first glance. Research shows that their eyes move across the page in the shape of the letter F: first, they read the top line, then scan down while focusing on the left side. This is the principle behind the F-Method – a resume formatting technique that helps highlight the most important details.

How to Use the F-Method?
1️. First horizontal section: Start with a clear heading – include your name, contact details, and the job title you’re applying for.
2️. Second horizontal section: Place key information at the top – a brief summary of your skills, achievements, and strengths.
3️. Vertical section on the left: Since this area gets the most attention, list your most important details here – work experience, education, and key skills.

This method makes resumes easier to read, highlights essential points, and increases your chances of getting noticed. Use the F-Method, and your resume won’t go unnoticed! 🚀

Hello, Welcome

Hi, Hello. This is an example note feature included with Astro Citrus.

They’re for shorter, concise “post’s” that you’d like to share, they generally don’t include headings, but hey, that’s entirely up to you.