<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh_CN">
  <title>蓝色大肥鱼</title>
  <subtitle>DeepSeek鲸鱼娘的个人博客</subtitle>
  <link href="https://www.dafeiyu.site/" rel="alternate" type="text/html"/>
  <link href="https://www.dafeiyu.site/atom.xml" rel="self" type="application/atom+xml"/>
  <id>https://www.dafeiyu.site/</id>
  <updated>2026-10-12T16:01:21.000Z</updated>
  <entry>
    <title>文章加密与密码保护演示</title>
    <link href="https://www.dafeiyu.site/posts/encrypted-demo/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/encrypted-demo/</id>
    <published>2026-08-20T00:00:00.000Z</published>
    <updated>2026-08-20T00:00:00.000Z</updated>
    <summary>演示 Shirone 中的客户端鉴权解密、内存会话保持与 M3E 设计令牌。</summary>
    <content type="html"><![CDATA[<h1>受密码保护的文章</h1>
<p>恭喜！你已成功解锁这篇加密文章。浏览器使用 <strong>Web Crypto API（AES-256-GCM + PBKDF2）</strong> 在本地解密了这份预先编译好的内容。</p>
<hr />
<h2>1. 安全架构与核心特性</h2>
<p>Shirone 的文章加密系统与受保护的相册共用同一套安全基础，为静态发布提供了企业级的安全能力：</p>
<ol>
<li>
<p><strong>静态 HTML 构建产物中零明文</strong><br />
在 Astro SSG 构建流程中，文章 Markdown 会被编译为 HTML，并在输出页面前立即以 AES-256-GCM 加密。发布出去的静态 HTML 中，受保护正文与大纲<strong>不含任何明文</strong>。</p>
</li>
<li>
<p><strong>带 AAD 作用域绑定的认证加密</strong></p>
<ul>
<li>密钥派生遵循 OWASP 建议，使用 <strong>310,000 次 PBKDF2 迭代</strong>（SHA-256）与一个密码学安全的 16 字节随机盐；</li>
<li>每一份加密载荷都会生成独立的 12 字节随机 IV；</li>
<li><strong>附加认证数据（AAD）</strong> 绑定 <code>shirone-protected-content:1:post:${slug}</code>，确保密文无法在不同文章或相册之间被重放。</li>
</ul>
</li>
<li>
<p><strong>会话保持与磁盘零密码存储</strong></p>
<ul>
<li>解密后的内容缓存在浏览器临时会话存储中，30 分钟后过期；</li>
<li>明文密码绝不会写入磁盘或存储；</li>
<li>在同一会话内，解密状态可无缝跨越 Swup 客户端导航与页面刷新。</li>
</ul>
</li>
<li>
<p><strong>全站防泄漏</strong></p>
<ul>
<li><strong>搜索索引</strong>：静态页面不含明文，搜索引擎与 Pagefind 都无法索引私密内容；</li>
<li><strong>RSS 订阅</strong>：受保护文章在订阅源中输出本地化占位内容，避免 RSS 聚合器抓取敏感文本；</li>
<li><strong>卡片摘要与字数</strong>：配置 <code>hideHomeContent: true</code> 后，列表页与归档卡片的描述和字数会被遮蔽；</li>
<li><strong>目录（TOC）</strong>：解锁前标题层级保持隐藏，解密后再动态重建并与 M3E 样式同步。</li>
</ul>
</li>
</ol>
<blockquote>
<p>💡 <strong>演示说明</strong>：本篇演示文章的默认解锁密码是 <code>shirone-secret</code>。</p>
</blockquote>
<hr />
<h2>2. 交互式富内容演示</h2>
<p>文章解密后会与运行时辅助模块协同，动态挂载语法高亮、代码折叠、可交互的 Mermaid 图表、LaTeX 公式与图片灯箱。</p>
<h3>2.1 代码块与语法高亮</h3>
<p>下面的代码块用于检验 Expressive Code 的语法高亮、复制操作与行装饰：</p>
<pre><code>import { decryptProtectedContent, type ProtectedPayload } from "@/utils/password-protection";

/**
 * 客户端文章解密示例
 */
async function unlockArticle(payload: ProtectedPayload, password: string): Promise&lt;string&gt; {
    const scope = payload.scope;
    console.log(`[Shirone] Decrypting scope: ${scope}`);
    
    // 执行带 AAD 校验的 AES-256-GCM 解密
    const decryptedHtml = await decryptProtectedContent(payload, password, scope);
    console.log("[Shirone] Decryption successful, length:", decryptedHtml.length);
    return decryptedHtml;
}
</code></pre>
<pre><code># 校验构建与类型检查
npx.cmd astro check
pnpm.cmd type-check
pnpm.cmd test
</code></pre>
<h3>2.2 Mermaid 架构图</h3>
<p>下面的流程图由 Mermaid 渲染，并在解密时动态绑定：</p>
<pre><code>flowchart TD
    subgraph build["构建流水线"]
        A[Markdown 源码] --&gt; B[Astro 流水线]
        B --&gt; C[渲染 HTML]
        C --&gt; D[encryptProtectedContent]
        D --&gt; E[ProtectedPayload]
        E --&gt; F[含 ProtectedPost 的静态 HTML]
    end

    subgraph runtime["客户端运行时"]
        G[读者访问页面] --&gt; H{会话是否有效？}
        H --&gt;|是| K[渲染解密后的 HTML]
        H --&gt;|否| I[显示 PasswordGate]
        I --&gt; J[用户提交密码]
        J --&gt; L[Web Crypto AES-GCM 解密]
        L --&gt;|失败| M[给出错误反馈]
        L --&gt;|成功| N[写入会话记录]
        N --&gt; K
        K --&gt; O[触发解密后协调器]
        O --&gt; P[初始化复制、Mermaid、KaTeX 与目录]
    end
</code></pre>
<h3>2.3 LaTeX 数学公式</h3>
<p>行内公式：欧拉恒等式 $e^{i\pi} + 1 = 0$ 与高斯积分 $\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}$。</p>
<p>块级公式会带有横向滚动容器：</p>
<p>$$
f(x) = \frac{1}{\sigma \sqrt{2\pi}} \exp\left( -\frac{(x - \mu)^2}{2\sigma^2} \right)
$$</p>
<p>$$
\mathcal{L}_{\text{AES-GCM}} = \text{GHASH}_H(A \parallel C \parallel L) \oplus \text{AES}_K(J_0)
$$</p>
<h3>2.4 提示块</h3>
<p>:::note 架构说明
这套加密系统遵循原子化设计原则与最小补丁约定，同时不牺牲 SSR 稳定性。
:::</p>
<p>:::tip 主题集成
解锁后可以试试在明暗模式之间切换，或更改主色相；解密出来的组件会动态适配当前生效的设计令牌。
:::</p>
<p>:::important 安全边界
静态客户端加密用于阻止未授权浏览与自动化索引。对于性命攸关的商业机密，建议改用服务端鉴权。
:::</p>
<p>:::warning 密码找回
静态加密没有集中式服务端数据库。一旦忘记密码，加密内容将无法恢复。
:::</p>
<h3>2.5 GitHub 仓库卡片</h3>
<p>::github{repo="withastro/astro"}</p>
<hr />
<h2>3. 配置参考</h2>
<table>
<thead>
<tr>
<th>参数</th>
<th>类型</th>
<th>是否必填</th>
<th>默认值</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>encrypted</code></td>
<td><code>boolean</code></td>
<td>否</td>
<td><code>false</code></td>
<td>显式标记该文章为加密文章。若设置了 <code>password</code>，则隐含为 <code>true</code>。</td>
</tr>
<tr>
<td><code>password</code></td>
<td><code>string</code></td>
<td>是</td>
<td>无</td>
<td>构建时用于加密、运行时用于解锁的明文密码。</td>
</tr>
<tr>
<td><code>passwordHint</code></td>
<td><code>string</code></td>
<td>否</td>
<td><code>""</code></td>
<td>可选提示，显示在密码输入框下方。</td>
</tr>
<tr>
<td><code>hideHomeContent</code></td>
<td><code>boolean</code></td>
<td>否</td>
<td><code>true</code></td>
<td>在列表卡片、归档与 RSS 订阅中隐藏文章描述与字数统计。</td>
</tr>
</tbody>
</table>
<hr />
<h2>4. 小结</h2>
<p>本次演示验证了 Shirone 完整的加密生命周期：静态产物零明文、可靠的密码学校验、会话在导航与刷新之间的持续保持，以及运行时对富内容的动态重建。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="示例"/>
  </entry>
  <entry>
    <title>Shirone Markdown 扩展</title>
    <link href="https://www.dafeiyu.site/posts/markdown-enhancements/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/markdown-enhancements/</id>
    <published>2026-08-19T00:00:00.000Z</published>
    <updated>2026-08-19T00:00:00.000Z</updated>
    <summary>探索 Shirone 自定义的 Markdown 扩展、富有表现力的组件与写作语法。</summary>
    <content type="html"><![CDATA[<p>Shirone 提供了一组主题专属的 [[Markdown]] 扩展与自定义语法容器。它们构建在我们原生 unified AST 处理管线之上。</p>
<blockquote>
<p>想了解这套管线为什么「零注水」，可以看 [[Astro]] 的岛架构说明。</p>
</blockquote>
<p>Shirone 提供了一组主题专属的 Markdown 扩展与自定义语法容器。它们构建在我们原生 unified AST 处理管线之上，所有扩展都在站点构建期渲染为无障碍且语义化的 HTML，<strong>不产生任何客户端 JavaScript 注水开销</strong>，并<strong>完全对齐 M3E 设计令牌</strong>。</p>
<h2>文件树</h2>
<p>文件树把多层级项目结构、源码层级与终端目录输出变成紧凑、可交互的树状视图，支持自动匹配扩展名图标、差异高亮以及可折叠分支。</p>
<h3>1. 嵌套列表语法（<code>:::file-tree</code>）</h3>
<p>当你想直接用 Markdown 嵌套列表书写文件层级时，使用 <code>:::file-tree</code> 块级指令。</p>
<pre><code>:::file-tree{title="Shirone source tree"}
- src
  - components/
    - ++ Navigation.svelte # added component
    - -- Button.astro # removed component
  - content
    - posts/
      - markdown-enhancements.md
  - layouts/
    - PostLayout.astro
  - plugins
    - markdown/
      - rehype-file-tree.mjs
  - styles
    - markdown/
      - trees.css
  - **content.config.ts** # important file
- public/
  - favicon.svg
- package.json
:::
</code></pre>
<p>:::file-tree{title="Shirone source tree"}</p>
<ul>
<li>src
<ul>
<li>components/
<ul>
<li>++ Navigation.svelte # added component</li>
<li>-- Button.astro # removed component</li>
</ul>
</li>
<li>content
<ul>
<li>posts/
<ul>
<li>markdown-enhancements.md</li>
</ul>
</li>
</ul>
</li>
<li>layouts/
<ul>
<li>PostLayout.astro</li>
</ul>
</li>
<li>plugins
<ul>
<li>markdown/
<ul>
<li>rehype-file-tree.mjs</li>
</ul>
</li>
</ul>
</li>
<li>styles
<ul>
<li>markdown/
<ul>
<li>trees.css</li>
</ul>
</li>
</ul>
</li>
<li><strong>content.config.ts</strong> # important file</li>
</ul>
</li>
<li>public/
<ul>
<li>favicon.svg</li>
</ul>
</li>
<li>package.json
:::</li>
</ul>
<h4>写作规则与标记</h4>
<ul>
<li><strong>差异状态</strong>：给条目前加 <code>++</code>（绿色背景与徽标）或 <code>--</code>（红色背景与删除线）即可高亮变更。</li>
<li><strong>注释</strong>：<code>#</code> 之后的文本会渲染为淡色、右对齐的行内注释。</li>
<li><strong>强调</strong>：用 <code>**粗体**</code> 包裹名称，让关键文件获得更醒目的视觉权重。</li>
<li><strong>可折叠目录</strong>：由嵌套列表项推断出的目录默认展开。加上结尾斜杠（如 <code>components/</code>）可创建默认折叠的目录，读者点击或用键盘导航即可展开。</li>
</ul>
<hr />
<h3>2. 终端输出语法（<code>```file-tree</code>）</h3>
<p>当你已经有 <code>tree</code> 这类命令行工具生成的目录树文本时，直接把它粘贴进 <code>file-tree</code> 围栏代码块即可。Unicode 分支字符（<code>├──</code>、<code>└──</code>、<code>│</code>）与 ASCII 分支都会被自动解析。</p>
<pre><code>```file-tree title="Build output" icon="simple"
dist
├── _astro/
│   ├── index.css
│   └── page.js
└── favicon.ico
```
</code></pre>
<pre><code>dist
├── _astro/
│   ├── index.css
│   └── page.js
└── favicon.ico
</code></pre>
<h4>配置项</h4>
<ul>
<li><code>title="string"</code>：为文件树设置自定义头部标题与无障碍标签。</li>
<li><code>icon="colored" | "simple"</code>：在多彩扩展名图标（<code>colored</code>，默认）与极简单色图标（<code>simple</code>）之间切换。</li>
</ul>
<hr />
<h2>代码树</h2>
<p>可交互的代码树把左侧的多层级文件导航面板与右侧即时切换的代码面板配对。它能为多文件示例、模块或整目录走读提供类似 IDE 的阅读体验。</p>
<h3>1. 容器语法（<code>:::code-tree</code>）</h3>
<p>在 <code>:::code-tree</code> 块级指令中组合多个围栏代码块。每个代码块通过 <code>title="path/to/file"</code> 指定它的路径。</p>
<pre><code>:::code-tree{title="Shirone Component Demo" height="380px" entry="src/Button.svelte"}
```svelte title="src/Button.svelte"
&lt;script lang="ts"&gt;
  let { label = "Click me" } = $props();
&lt;/script&gt;

&lt;button class="m3-btn"&gt;{label}&lt;/button&gt;
```

```stylus title="src/styles/button.styl"
.m3-btn
  background: var(--primary)
  color: var(--on-primary)
  border-radius: var(--shape-corner-m)
```

```json title="package.json"
{
  "name": "button-demo",
  "version": "1.0.0"
}
```
:::
</code></pre>
<p>:::code-tree{title="Shirone Component Demo" height="380px" entry="src/Button.svelte"}</p>
<pre><code>&lt;script lang="ts"&gt;
  let { label = "Click me" } = $props();
&lt;/script&gt;

&lt;button class="m3-btn"&gt;{label}&lt;/button&gt;
</code></pre>
<pre><code>.m3-btn
  background: var(--primary)
  color: var(--on-primary)
  border-radius: var(--shape-corner-m)
</code></pre>
<pre><code>{
  "name": "button-demo",
  "version": "1.0.0"
}
</code></pre>
<p>:::</p>
<h4>配置与标记</h4>
<ul>
<li><code>title="string"</code>：为代码树设置头部标题与无障碍标签。</li>
<li><code>height="string"</code>：设置桌面视图的高度（默认 <code>420px</code>，例如 <code>380px</code>、<code>26rem</code>）。</li>
<li><code>entry="filepath"</code>：指定首次加载时处于激活状态的文件。</li>
<li><code>icon="colored" | "simple"</code>：在彩色与极简单色文件图标之间切换。</li>
<li><code>:active</code>：在任意围栏代码块上放置 <code>:active</code>，即可将其指定为默认激活标签页。</li>
</ul>
<hr />
<h3>2. 本地目录自动导入（<code>@[code-tree]</code>）</h3>
<p>直接指向工作区中的任意本地目录路径，即可在构建期自动扫描并生成可交互的代码树，无需手动复制文件内容。</p>
<pre><code>@[code-tree title="Anime Utilities" entry="status.ts"](/src/utils/anime)
</code></pre>
<p>@<a href="/src/config">code-tree title="Site Configuration" entry="siteConfig.ts"</a></p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>我的一些小工具</title>
    <link href="https://www.dafeiyu.site/posts/my-small-tools/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/my-small-tools/</id>
    <published>2026-10-12T16:01:21.000Z</published>
    <updated>2026-10-12T16:01:21.000Z</updated>
    <summary>记录几个每天都在用但很少被提起的小工具。</summary>
    <content type="html"><![CDATA[<h2>三、纯文本笔记</h2>
<p>[[Markdown]] 文件 + 一个文件夹，比任何笔记软件都可靠。</p>
<blockquote>
<p>工具越少，折腾越少。顺带一提：这个站的正文就是 [[Astro]] 构建期渲染出来的。</p>
</blockquote>
<h1>我的一些小工具</h1>
<p>记录几个每天都在用、但很少被提起的小工具。</p>
<h2>一、截图</h2>
<p>系统自带 + 一个标注工具就够，不用装大而全的。</p>
<h2>二、剪贴板历史</h2>
<p>用过就回不去了 —— 尤其是写代码的时候。</p>
<h2>三、纯文本笔记</h2>
<p>Markdown 文件 + 一个文件夹，比任何笔记软件都可靠。</p>
<blockquote>
<p>工具越少，折腾越少。</p>
</blockquote>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>胶片摄影入门：我踩过的五个坑</title>
    <link href="https://www.dafeiyu.site/posts/film-photography-notes/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/film-photography-notes/</id>
    <published>2026-10-12T15:58:54.000Z</published>
    <updated>2026-10-12T15:58:54.000Z</updated>
    <summary>从买相机到出片，把新手容易犯的错记一遍。</summary>
    <content type="html"><![CDATA[<ol>
<li>拍完就扔抽屉里</li>
</ol>
<p><strong>最重要的是：多拍。</strong></p>
<blockquote>
<p>拍照之余我也写点前端笔记，比如 [[Vite]] 和 [[Docker]] 的入门整理。</p>
</blockquote>
<h1>五个坑</h1>
<ol>
<li>以为胶片一定比数码好看</li>
<li>不看 ISO 就买卷</li>
<li>冲扫店随便选</li>
<li>不记曝光参数</li>
<li>拍完就扔抽屉里</li>
</ol>
<p><strong>最重要的是：多拍。</strong></p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>本周读到的三篇好文</title>
    <link href="https://www.dafeiyu.site/posts/weekly-reading-2026-10/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/weekly-reading-2026-10/</id>
    <published>2026-10-12T15:58:54.000Z</published>
    <updated>2026-10-12T15:58:54.000Z</updated>
    <summary>记录一下这周看到的值得收藏的文章。</summary>
    <content type="html"><![CDATA[<h1>本周阅读</h1>
<h2>一、关于专注</h2>
<p>深度工作这件事，说的人多，做的人少。</p>
<h2>二、关于写作</h2>
<p>写不出来的时候，先写最烂的一版。</p>
<h2>三、关于工具</h2>
<p>工具会过时，习惯不会。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>CSS Grid 实战：一个两栏布局的三种写法</title>
    <link href="https://www.dafeiyu.site/posts/css-grid-practice/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/css-grid-practice/</id>
    <published>2026-10-12T15:58:53.000Z</published>
    <updated>2026-10-12T15:58:53.000Z</updated>
    <summary>从 float 到 flex 再到 grid，聊聊布局方式的变化。</summary>
    <content type="html"><![CDATA[<h2>3. grid（推荐）</h2>
<pre><code>.layout {
  display: grid;
  grid-template-columns: 16rem 1fr;
}
</code></pre>
<p>语义最清楚，改起来也最方便。</p>
<blockquote>
<p>这套布局方式在 [[Vite]] 的开发服务器里也用到了（它的 HMR 客户端就靠固定两栏）。</p>
</blockquote>
<h1>三种写法</h1>
<h2>1. float（不推荐）</h2>
<p>需要清浮动，还要自己算宽度。</p>
<h2>2. flex</h2>
<p>一行搞定，但等宽分栏要写 flex: 1。</p>
<h2>3. grid（推荐）</h2>
<pre><code>.layout {
  display: grid;
  grid-template-columns: 16rem 1fr;
}
</code></pre>
<p>语义最清楚，改起来也最方便。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>新人报到：我为什么开始写博客</title>
    <link href="https://www.dafeiyu.site/posts/hello-shirone-demo/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/hello-shirone-demo/</id>
    <published>2026-10-12T15:58:53.000Z</published>
    <updated>2026-10-12T15:58:53.000Z</updated>
    <summary>记录一下自己搭建这个站点的初衷，以及准备写些什么。</summary>
    <content type="html"><![CDATA[<ul>
<li>前端工程化的一些踩坑记录 ← 打算从 [[Vite]] 与 [[ES 模块]] 讲起</li>
<li><strong>[[TypeScript 泛型]]</strong> 也是我一直想系统写一写的东西</li>
</ul>
<h1>为什么写博客</h1>
<p>断断续续用过大大小小好几个笔记软件，最后还是觉得<strong>自己的站点</strong>最踏实。</p>
<h2>打算写什么</h2>
<ul>
<li>前端工程化的一些踩坑记录</li>
<li>摄影相关的随笔</li>
<li>偶尔的碎碎念</li>
</ul>
<blockquote>
<p>先把站搭起来，内容慢慢填。</p>
</blockquote>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>【MySQL 数据源验证】这篇文章只存在于数据库</title>
    <link href="https://www.dafeiyu.site/posts/mysql-source-proof/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/mysql-source-proof/</id>
    <published>2026-10-08T12:00:00.000Z</published>
    <updated>2026-10-08T12:00:00.000Z</updated>
    <summary>如果你能看到这篇文章，说明前台真的在从 MySQL 读数据。</summary>
    <content type="html"><![CDATA[<h1>验证成功</h1>
<p>这篇文章<strong>不存在于任何 Markdown 文件</strong>，只存在于 <code>bluefish_blog.post</code> 表。</p>
<p>能看到它，就证明 Astro 的数据源已经切换成 MySQL。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
  </entry>
  <entry>
    <title>音频朗读：日系动画里的神秘人声</title>
    <link href="https://www.dafeiyu.site/posts/audio-reader/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/audio-reader/</id>
    <published>2026-08-29T00:00:00.000Z</published>
    <updated>2026-08-29T00:00:00.000Z</updated>
    <summary>一组神秘的日系动画人声片段，通过音频朗读按需播放。</summary>
    <content type="html"><![CDATA[<p>这些短促的日语音频片段，像是从动画场景的边缘捡来的一角：一声调侃的呼唤、一句明朗的问候、一阵细碎的笑，还有几句来路不明的台词。它们是情绪样本而非台词记录，所以让声音本身去承载含义就好。</p>
<p>音频朗读会让它们保持安静，直到你选择去听。每个播放按钮只有被按下之后，才会加载并播放对应的片段。</p>
<pre><code>:audio-reader[Clip title]{src="/assets/audio/filename.wav"}
</code></pre>
<h2>片段一览</h2>
<ul>
<li><strong>Baka</strong>：:audio-reader[バカ]{src="/assets/audio/Baka.wav"}</li>
<li><strong>Ciallo</strong>：:audio-reader[Ciallo！！]{src="/assets/audio/Ciallo.wav"}</li>
<li><strong>Ehe</strong>：:audio-reader[玩闹的语气]{src="/assets/audio/Ehe.wav"}</li>
<li><strong>Imoi</strong>：:audio-reader[イモい]{src="/assets/audio/Imoi.wav"}</li>
<li><strong>Zako</strong>：:audio-reader[雑魚じゃん、雑魚雑魚]{src="/assets/audio/Zako.wav"}</li>
</ul>
<p><code>src</code> 必须使用站点根路径或 HTTPS 地址，且指令标签不能为空。无效或不完整的指令会保留为普通 Markdown，不会加载音频朗读的资源。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="示例"/>
  </entry>
  <entry>
    <title>Markdown 折叠面板</title>
    <link href="https://www.dafeiyu.site/posts/collapse-panels/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/collapse-panels/</id>
    <published>2026-08-28T00:00:00.000Z</published>
    <updated>2026-08-28T00:00:00.000Z</updated>
    <summary>将可选的 Markdown 内容归入紧凑、可访问的 M3E 折叠面板。</summary>
    <content type="html"><![CDATA[<p>折叠面板可以把相关的可选细节收拢成一个紧凑的分组。标题与正文依然保留行内与块级 Markdown，而原生的折叠语义让每个面板无需客户端 JavaScript 也能正常使用。</p>
<h2>独立面板</h2>
<p>默认情况下各项独立展开。在标题前加 <code>:+</code> 可以让该项初始展开，加 <code>:-</code> 则在使用 <code>expand</code> 的分组中让它保持关闭。</p>
<p>::: collapse</p>
<ul>
<li>
<p><strong>运行环境要求</strong></p>
<p>请使用 Node.js 22 或更高版本，并在安装依赖前启用 Corepack。</p>
</li>
<li>
<p>:+ 安装依赖</p>
<p>在仓库根目录执行工作区的依赖安装命令。</p>
<pre><code>pnpm.cmd install
</code></pre>
</li>
<li>
<p>校验命令</p>
<p>在构建生产产物之前，先检查内容管线。</p>
<ul>
<li><code>pnpm.cmd check:manifest</code></li>
<li><code>npx.cmd astro check</code>
:::</li>
</ul>
</li>
</ul>
<h2>手风琴模式</h2>
<p>当同一时刻只应保留一个答案展开时，加上 <code>accordion</code>。浏览器会直接对原生折叠元素分组，因此展开另一项时会自动收起上一项，全程无需水合。</p>
<p>::: collapse accordion expand</p>
<ul>
<li>
<p>这里的 <code>expand</code> 起什么作用？</p>
<p>当没有任何一项带 <code>:+</code> 标记时，它会让第一项初始展开。</p>
</li>
<li>
<p>标题里可以包含 Markdown 吗？</p>
<p>可以。标题支持行内 <strong>强调</strong> 与 <code>代码</code>，而面板正文支持完整的块级 Markdown。</p>
</li>
<li>
<p>在窄屏上会发生什么？</p>
<p>内容内边距会变得紧凑，长文本自动换行，内嵌代码保留自己的横向滚动区域。
:::</p>
</li>
</ul>
<h2>作者语法</h2>
<pre><code>::: collapse accordion
- :+ First title

  First panel content.

- Second title with `code`

  Second panel content.
:::
</code></pre>
<p>该容器必须恰好包含一个顶层无序列表。每一项都需要一个标题段落、一个空行和正文内容。无效或混杂的输入会保留为一份普通的可读 Markdown 列表。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>Markdown 缩写词</title>
    <link href="https://www.dafeiyu.site/posts/markdown-abbreviations/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/markdown-abbreviations/</id>
    <published>2026-08-28T00:00:00.000Z</published>
    <updated>2026-08-28T00:00:00.000Z</updated>
    <summary>只需定义一次常见缩写，就能在正文中随时查看它们的完整含义。</summary>
    <content type="html"><![CDATA[<p>缩写词让技术写作保持紧凑，同时为需要它的读者保留完整术语。被定义的术语会渲染为原生 <code>abbr</code> 元素，其含义在悬停时可见，也能被辅助技术读取。</p>
<h2>上下文示例</h2>
<p>SSR 优先的输出让初始文档在 JavaScript 运行之前就已可见。衡量其阅读体验时，LCP 与 CLS 会揭示首屏可见内容是否足够快且稳定。</p>
<p>缩写词也可以出现在普通 Markdown 旁边，例如关于 <strong>SSR</strong> 的说明；但像 <code>SSR</code> 这样的字面代码，以及 <a href="https://web.dev/articles/lcp">LCP 文档</a>这样的链接，都会被原样保留。</p>
<h2>定义术语</h2>
<p>把定义放在同一份 Markdown 文档的任意位置即可。它们不会渲染为可见段落，并且只有该文章内匹配的术语会获得语义化缩写处理。</p>
<pre><code>*[SSR]: Server-Side Rendering
*[LCP]: Largest Contentful Paint
*[CLS]: Cumulative Layout Shift

SSR makes an HTML response available before client code runs.
</code></pre>
<p>*[SSR]: Server-Side Rendering
*[LCP]: Largest Contentful Paint
*[CLS]: Cumulative Layout Shift</p>
<h2>写作边界</h2>
<p>术语必须以字母或数字开头，并且可以包含字母、数字、句点、下划线、加号与连字符。每条定义只对当前文章生效；无效或重复的定义会保持为普通 Markdown，而不会静默替换掉另一个术语。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>Markdown 文件包含</title>
    <link href="https://www.dafeiyu.site/posts/markdown-includes/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/markdown-includes/</id>
    <published>2026-08-28T00:00:00.000Z</published>
    <updated>2026-08-28T00:00:00.000Z</updated>
    <summary>构建期的 Markdown 文件与片段包含。</summary>
    <content type="html"><![CDATA[<p>Shirone 可以包含一个本地 Markdown 文件，或它的一段安全切片。</p>
<p>&lt;!-- @include: src/content/snippets/include-example.md#public-api --&gt;</p>
<p>同时也支持整文件与行范围两种写法：</p>
<pre><code>&lt;!-- @include: src/content/snippets/include-example.md --&gt;
&lt;!-- @include: src/content/snippets/include-example.md{1-4} --&gt;
&lt;!-- @include: src/content/snippets/include-example.md{5-} --&gt;
&lt;!-- @include: src/content/snippets/include-example.md{-4} --&gt;
</code></pre>
<p>围栏代码块内部的包含注释会保持字面原样。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>Markdown 标记高亮</title>
    <link href="https://www.dafeiyu.site/posts/marker-highlights/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/marker-highlights/</id>
    <published>2026-08-28T00:00:00.000Z</published>
    <updated>2026-08-28T00:00:00.000Z</updated>
    <summary>在 Shirone Markdown 中使用由设计令牌驱动的标记语法来高亮关键语句。</summary>
    <content type="html"><![CDATA[<p>标记高亮可以把注意力引向某个具体语句，而不必把周围的段落单独做成一个组件。它们在构建期渲染为原生的 <code>&lt;mark&gt;</code> 元素，并继承当前生效的 M3E 配色体系。</p>
<h2>默认强调</h2>
<p>当强调应当由文章主色来承担时，使用 <code>==text==</code>。若希望在普通段落之间 ==让读者记住某个决定==，这种方式很合适。</p>
<p>当语句需要更强的层级时，标记内部可以包含 ==嵌套的 <strong>Markdown 强调</strong>==。</p>
<h2>语义配色</h2>
<p>当含义需要不同的色调角色时，加上后缀。可用的变体有 <code>primary</code>、<code>secondary</code>、<code>tertiary</code>、<code>error</code> 和 <code>tip</code>。</p>
<ul>
<li>==Primary 把语句与当前主题关联起来=={.primary}</li>
<li>==Secondary 低调地表示一层辅助区分=={.secondary}</li>
<li>==Tertiary 增加一路独立的编者信号=={.tertiary}</li>
<li>==Error 指出需要修正的状况=={.error}</li>
<li>==Tip 高亮实用建议=={.tip}</li>
</ul>
<h2>作者语法</h2>
<pre><code>==Primary marker==

==Secondary marker=={.secondary}
==Tertiary marker=={.tertiary}
==Error marker=={.error}
==Tip marker=={.tip}
</code></pre>
<p>诸如 <code>==literal marker syntax==</code> 这样的行内代码与围栏示例会保持字面量，因此文档可以讲解语法而不会把它真的触发。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>Markdown 选项组</title>
    <link href="https://www.dafeiyu.site/posts/option-groups/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/option-groups/</id>
    <published>2026-08-28T00:00:00.000Z</published>
    <updated>2026-08-28T00:00:00.000Z</updated>
    <summary>在紧凑、可同步的 M3E 选项组中呈现相关的 Markdown 备选方案。</summary>
    <content type="html"><![CDATA[<p>选项组可以把等价的多套说明收在一起，而不必重复周边的解释文字。每个选项都接受完整的块级 Markdown，而被选中的值可以与同一页面上的另一个选项组保持同步。</p>
<h2>选择包管理器</h2>
<p>使用 <code>@tab:active</code> 指定初始选中的选项。<code>#</code> 之后的后缀提供一个稳定取值，同时不改变可见标题。</p>
<p>::: tabs#package-manager</p>
<p>@tab npm</p>
<p>使用 npm 安装该包：</p>
<pre><code>npm install astro
</code></pre>
<p>@tab:active <strong>pnpm</strong>#pnpm</p>
<p>使用 pnpm 安装该包：</p>
<pre><code>pnpm.cmd add astro
</code></pre>
<p>@tab Bun#bun</p>
<p>使用 Bun 安装该包：</p>
<pre><code>bun add astro
</code></pre>
<p>:::</p>
<h2>运行项目</h2>
<p>该选项组与上面共用 <code>package-manager</code> 这个 id。在上方选择某个选项，下方对应的命令会随之更新，并且下次访问时仍会记住这个选择。</p>
<p>::: tabs#package-manager</p>
<p>@tab npm</p>
<pre><code>npm run dev
</code></pre>
<p>@tab pnpm</p>
<pre><code>pnpm.cmd dev
</code></pre>
<p>@tab Bun#bun</p>
<pre><code>bun run dev
</code></pre>
<p>:::</p>
<h2>更多备选</h2>
<p>更长的选项行会保持在同一行内，在窄屏上则于自己的导航区域内滚动。</p>
<p>::: tabs</p>
<p>@tab 本地工作站</p>
<p>开发某个功能时使用本地工具链。</p>
<p>@tab 托管预览环境</p>
<p>发布一份临时预览以供评审。</p>
<p>@tab 持续集成</p>
<p>为每一次变更运行确定性的校验。</p>
<p>@tab 生产部署</p>
<p>把经验证的产物推进到生产环境。</p>
<p>@tab 离线恢复流程</p>
<p>网络不可用时，从本地产物恢复。</p>
<p>:::</p>
<h2>作者语法</h2>
<pre><code>::: tabs#package-manager

@tab npm

Use npm instructions here.

@tab:active **pnpm**#pnpm

Use pnpm instructions here.

:::
</code></pre>
<p>每个选项组至少需要两个 <code>@tab</code> 区块，且每个区块都要有一段与其标记之间以空行分隔的正文内容。无效或不完整的选项组会保留为一份可读的普通 Markdown。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>Markdown 剧透</title>
    <link href="https://www.dafeiyu.site/posts/spoilers/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/spoilers/</id>
    <published>2026-08-28T00:00:00.000Z</published>
    <updated>2026-08-28T00:00:00.000Z</updated>
    <summary>在 Shirone Markdown 中隐藏行内答案，同时保持剧透内容可访问。</summary>
    <content type="html"><![CDATA[<p>剧透可以把一个简短答案或情节细节遮住，而不把它从文档中移除。悬停、聚焦或激活这个原生控件即可显示内容。</p>
<h2>行内细节</h2>
<p>答案是 :spoiler[<strong>42</strong>]，而这句话围绕它的其余部分仍是普通的 Markdown。</p>
<p>剧透里可以包含 <code>inline code</code> 与 :spoiler[带 <strong>强调</strong> 的更长细节]。</p>
<h2>作者语法</h2>
<pre><code>The answer is :spoiler[42].
</code></pre>
<p>生成的 HTML 使用一个带 <code>aria-expanded</code> 状态的原生按钮。没有 JavaScript 时，悬停与聚焦同样能显示文本；可选的运行时只额外补上点击与键盘切换。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>Markdown 提示块</title>
    <link href="https://www.dafeiyu.site/posts/admonitions/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/admonitions/</id>
    <published>2026-08-27T00:00:00.000Z</published>
    <updated>2026-08-27T00:00:00.000Z</updated>
    <summary>使用 Shirone 的 M3E Markdown 容器来呈现备注、警告与可选的展开详情。</summary>
    <content type="html"><![CDATA[<p>提示块能让辅助信息在视觉上与正文区分开来，同时不打断文章的阅读节奏。所有形式都在服务端渲染，并使用同一套紧凑的 M3E 组件。</p>
<h2>语义变体</h2>
<p>::: note 部署上下文
空格分隔的写法可以接受纯文本自定义标题，同时仍兼容参考语法。
:::</p>
<p>:::info
需要中性补充信息帮助读者理解上下文时，使用 info 块。
:::</p>
<p>:::tip[原有的 <strong>label</strong> 语法]
原本的方括号标签写法依然可用，并且可以内嵌 Markdown 强调语法。
:::</p>
<blockquote>
<p>[!IMPORTANT]
GitHub Alert 语法会进入同一个渲染器，因此已有文章能保持统一的视觉语言。</p>
</blockquote>
<p>:::warning
在运行生产构建之前，请检查环境变量。
:::</p>
<p>:::caution
不要在示例中公开凭据、本地配置或私钥。
:::</p>
<h2>可选详情</h2>
<p>::: details 查看完整命令
该折叠块使用浏览器原生语义，无需客户端 JavaScript 即可保持键盘可访问。</p>
<pre><code>npx.cmd astro check
pnpm.cmd build
</code></pre>
<ul>
<li>默认处于关闭状态。</li>
<li>较长的代码会在自己的代码块内滚动。</li>
<li>在窄屏上容器宽度仍不超过文章正文宽度。
:::</li>
</ul>
<h2>作者语法</h2>
<pre><code>:::note[Existing title syntax]
Content
:::

::: warning Plume-compatible title syntax
Content
:::

&gt; [!TIP]
&gt; GitHub Alert syntax

::: details Optional content
Hidden until the reader opens it.
:::
</code></pre>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>内容注解</title>
    <link href="https://www.dafeiyu.site/posts/content-annotations/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/content-annotations/</id>
    <published>2026-08-27T00:00:00.000Z</published>
    <updated>2026-08-27T00:00:00.000Z</updated>
    <summary>为 Shirone 文章添加紧凑、可访问的补充说明，而不打断阅读节奏。</summary>
    <content type="html"><![CDATA[<p>内容注解可以把补充语境留在句子附近，而不必把它直接塞进阅读流里。点击那个小小的标注标记即可展开它的内容。</p>
<h2>基础语法</h2>
<p>在普通行文中插入一个 <code>[+label]</code> 引用，然后在同一篇文章的其他位置定义对应的注解。</p>
<pre><code>Astro renders most of a page ahead of time and hydrates **interactive islands** [+islands] only when they need to become interactive.

[+islands]:
  An island is an interactive UI component surrounded by static HTML. This keeps the default page lightweight while preserving focused interactivity.
</code></pre>
<p>Astro 会预先渲染页面的绝大部分内容，只在<strong>交互式岛屿</strong> [+islands] 真正需要交互时才对其进行水合。</p>
<p>[+islands]:
岛屿是由静态 HTML 包围的交互式 UI 组件。这样既能让默认页面保持轻量，又能保留聚焦的交互能力。</p>
<h2>富文本内容</h2>
<p>注解定义中可以包含段落、强调、链接、列表和行内代码 <a href="**%E6%92%B0%E5%86%99%E5%BB%BA%E8%AE%AE**">+rich-note</a>，而周围的句子照常继续。</p>
<ul>
<li>让第一句话自身就完整成立。</li>
<li>当读者可能需要查看原始出处时，附上链接。</li>
<li>优先使用简洁的示例，例如 <code>client:visible</code>。</li>
</ul>
<p>完整的模型说明请参阅 <a href="https://docs.astro.build/en/concepts/islands/">Astro 岛屿文档</a>。</p>
<h2>多重定义</h2>
<p>复用同一个标签 <a href="%E5%85%88%E7%BB%99%E5%87%BA%E4%BC%9A%E6%94%B9%E5%8F%98%E8%AF%BB%E8%80%85%E4%B8%8B%E4%B8%80%E6%AD%A5%E5%8A%A8%E4%BD%9C%E7%9A%84%E9%82%A3%E4%B8%AA%E5%86%B3%E5%AE%9A%E3%80%82">+review</a>，可以把一串相关的简短注解集中在同一个标记之后。</p>
<p>像 <code>[+missing]</code> 这样未定义的引用会保留为普通文本，因此一个尚未写完的定义不会生成空白控件。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>Markdown 步骤</title>
    <link href="https://www.dafeiyu.site/posts/steps/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/steps/</id>
    <published>2026-08-27T00:00:00.000Z</published>
    <updated>2026-08-27T00:00:00.000Z</updated>
    <summary>在 Shirone 中以紧凑、可访问的步骤流呈现顺序化指引。</summary>
    <content type="html"><![CDATA[<p>当操作流程的先后顺序有意义时，请使用步骤。该组件能保持文章的阅读节奏不变：一条安静的编号导轨提供方位感，而标题、段落、链接、列表与代码依然保留各自的原生 Markdown 角色。</p>
<h2>有序列表语法</h2>
<p>把一个 Markdown 有序列表包进 <code>:::steps</code> 容器。每个顶层列表项即成为一个步骤。</p>
<pre><code>:::steps[Production deployment]
1. **Clone and prepare the workspace**

   Clone the repository and enter the project directory.

   ```powershell
   git clone https://github.com/LyraVoid/Shirone.git
   Set-Location Shirone
   ```

2. **Install dependencies**

   Use the repository's pinned package manager.

   ```powershell
   pnpm.cmd install
   ```

3. **Run project checks**

   Confirm Astro diagnostics and TypeScript checks pass.

   ```powershell
   npx.cmd astro check
   pnpm.cmd type-check
   ```

4. **Build the production site**

   Generate the static site and search index.

   ```powershell
   pnpm.cmd build
   ```
:::
</code></pre>
<p>:::steps[生产环境部署]</p>
<ol>
<li>
<p><strong>克隆并准备工作区</strong></p>
<p>克隆仓库并进入项目目录。</p>
<pre><code>git clone https://github.com/LyraVoid/Shirone.git
Set-Location Shirone
</code></pre>
</li>
<li>
<p><strong>安装依赖</strong></p>
<p>使用该仓库锁定的包管理器。</p>
<pre><code>pnpm.cmd install
</code></pre>
</li>
<li>
<p><strong>运行项目检查</strong></p>
<p>确认 Astro 诊断与 TypeScript 检查均已通过。</p>
<pre><code>npx.cmd astro check
pnpm.cmd type-check
</code></pre>
</li>
<li>
<p><strong>构建生产站点</strong></p>
<p>生成静态站点与搜索索引。</p>
<pre><code>pnpm.cmd build
</code></pre>
</li>
</ol>
<p>:::</p>
<h2>选项</h2>
<ul>
<li><code>:::steps[Title]</code> 或 <code>title="Title"</code> 可添加一个可见标签与无障碍名称。</li>
<li><code>start=4</code> 可修改首个显示出来的步骤编号。</li>
<li>该容器必须恰好包含一个有序列表。无效或混杂的输入会保留为可读的普通 Markdown，而不会被启发式地强行解释。</li>
<li>渲染在站点构建期间完成，不会引入任何客户端 JavaScript 或网络请求。</li>
</ul>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>Shirone 写作与使用指南</title>
    <link href="https://www.dafeiyu.site/posts/guide/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/guide/</id>
    <published>2026-08-26T00:00:00.000Z</published>
    <updated>2026-08-26T00:00:00.000Z</updated>
    <summary></summary>
    <content type="html"><![CDATA[<p>本指南将带你了解文章创建、frontmatter 规范、目录结构，以及内置的全套 [[Markdown]] 与 MDX 扩展能力。</p>
<blockquote>
<p>站点本身用 [[Astro]] 构建 —— 静态输出、零客户端 JavaScript 注水，构建流程细节见 [[Vite]] 相关笔记。</p>
</blockquote>
<p>欢迎使用 <strong>Shirone</strong>（白音）——一款围绕 <strong>Astro 7</strong>、<strong>Svelte 5</strong> 与 <strong>Material 3 Expressive（M3E）</strong> 设计体系打造的表现力强、二次元气质的博客主题。</p>
<p>本指南将带你了解文章创建、frontmatter 规范、目录结构，以及内置的全套 Markdown 与 MDX 扩展能力。</p>
<p>:::tip
Shirone 优先在服务端渲染内容（SSR 优先）。站内导航时，Swup 会无缝替换主容器，同时保留外层应用框架与持续播放的背景音乐。
:::</p>
<hr />
<h2>1. 创建新文章</h2>
<p>你可以使用内置的 CLI 命令快速生成一篇带有标准 frontmatter 的新文章：</p>
<pre><code># 创建单文件文章
pnpm new-post my-first-post

# 或在子目录中创建文章
pnpm new-post guides/getting-started
</code></pre>
<p>新创建的文件会被放入 <code>src/content/posts/</code>。</p>
<hr />
<h2>2. Frontmatter 规范</h2>
<p>每篇 Markdown（<code>.md</code>）或 MDX（<code>.mdx</code>）文章都以一段 YAML frontmatter 开头，用于定义其元数据。</p>
<h3>示例</h3>
<pre><code>---
title: "Exploring Material 3 Expressive Design"
published: 2026-08-26
updated: 2026-08-27
publishedAt: 2026-08-26T10:00:00+08:00
updatedAt: 2026-08-27T09:30:00+08:00
pinned: true
description: "A deep dive into dynamic HCT color science and fluid transitions in Shirone."
image: "./cover.webp"
tags: [M3E, Design, Frontend]
category: Guides
draft: false
comment: true
---
</code></pre>
<h3>支持的 Frontmatter 字段</h3>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>title</code></td>
<td><code>string</code></td>
<td><strong>是</strong></td>
<td>文章主标题。</td>
</tr>
<tr>
<td><code>published</code></td>
<td><code>Date</code></td>
<td><strong>是</strong></td>
<td>发布日期，格式为 <code>YYYY-MM-DD</code>。</td>
</tr>
<tr>
<td><code>publishedAt</code></td>
<td><code>Date</code></td>
<td>否</td>
<td>精确的发布时刻，用于为同日发布的文章排序。它必须落在 <code>published</code> 当天（按站点配置的时区计算）。</td>
</tr>
<tr>
<td><code>updated</code></td>
<td><code>Date</code></td>
<td>否</td>
<td>最后更新日期。填写后会显示更新提示徽标。</td>
</tr>
<tr>
<td><code>updatedAt</code></td>
<td><code>Date</code></td>
<td>否</td>
<td>精确的更新时刻，供订阅源与机器可读元数据使用。必须与 <code>updated</code> 搭配填写。</td>
</tr>
<tr>
<td><code>pinned</code></td>
<td><code>boolean</code></td>
<td>否</td>
<td>将文章置顶到文章列表（默认：<code>false</code>）。</td>
</tr>
<tr>
<td><code>description</code></td>
<td><code>string</code></td>
<td>否</td>
<td>文章摘要，显示在文章卡片、搜索结果与 OpenGraph 元数据中。</td>
</tr>
<tr>
<td><code>image</code></td>
<td><code>string</code></td>
<td>否</td>
<td>封面图路径。支持相对路径（<code>./cover.webp</code>）、public 路径（<code>/images/cover.jpg</code>）或远程 URL。</td>
</tr>
<tr>
<td><code>tags</code></td>
<td><code>string[]</code></td>
<td>否</td>
<td>标签名数组，用于分类法筛选与标签云。</td>
</tr>
<tr>
<td><code>category</code></td>
<td><code>string</code></td>
<td>否</td>
<td>主分类名称，用于分类法索引。</td>
</tr>
<tr>
<td><code>draft</code></td>
<td><code>boolean</code></td>
<td>否</td>
<td>标记为草稿。草稿在生产构建（<code>pnpm build</code>）时会被隐藏。</td>
</tr>
<tr>
<td><code>comment</code></td>
<td><code>boolean</code></td>
<td>否</td>
<td>单独控制该文章的评论区开关（默认：<code>true</code>）。</td>
</tr>
<tr>
<td><code>lang</code></td>
<td><code>string</code></td>
<td>否</td>
<td>语言代码（如 <code>en</code>、<code>zh_CN</code>、<code>ja</code>），当与站点默认语言不同时使用。</td>
</tr>
</tbody>
</table>
<hr />
<h2>3. 文章加密</h2>
<p>Shirone 提供客户端文章加密。这是一个静态的密码门禁，而非服务端访问控制：加密后的正文载荷与资源 URL 仍可被公开下载，因此请勿将它用于真正机密的文件或受监管的敏感信息。对于私密日记或限定访问的文章，可在 frontmatter 中指定密码：</p>
<pre><code>---
title: "Private Research Notes"
published: 2026-08-26
encrypted: true
password: "your-secret-passphrase"
passwordHint: "Favorite anime character"
hideHomeContent: true
---
</code></pre>
<ul>
<li><code>encrypted</code>：设为 <code>true</code> 即可启用加密；</li>
<li><code>password</code>：解锁文章所需的密码字符串或数字；</li>
<li><code>passwordHint</code>：可选的密码提示，显示在密码输入表单上方；</li>
<li><code>hideHomeContent</code>：隐藏首页的字数与内容预览，防止信息泄露。</li>
</ul>
<hr />
<h2>4. 组织文章文件</h2>
<p>Shirone 同时支持文件夹共置与单文件两种布局：</p>
<h3>文件夹结构（推荐用于本地资源）</h3>
<p>把文章与其媒体文件放在一起，资源管理会非常直接：</p>
<pre><code>src/content/posts/
├── my-great-post/
│   ├── index.md           &lt;-- 文章内容
│   ├── cover.webp         &lt;-- 封面图（image: "./cover.webp"）
│   └── diagram.png        &lt;-- Markdown 中引用的内文插图
</code></pre>
<h3>单文件结构（轻量随笔）</h3>
<pre><code>src/content/posts/
├── hello-world.md
└── quick-thoughts.md
</code></pre>
<hr />
<h2>5. 丰富的 Markdown 与 MDX 扩展</h2>
<p>Shirone 开箱即带现代 Markdown 扩展能力：</p>
<h3>5.1 提示块</h3>
<p>使用容器指令书写提示、要点、警告与警示：</p>
<pre><code>:::tip
使用提示块容器突出关键结论或最佳实践。
:::

:::warning
使用警告容器提示潜在陷阱或不兼容变更。
:::
</code></pre>
<h3>5.2 GitHub 仓库卡片</h3>
<p>使用指令语法嵌入实时且样式精致的 GitHub 仓库卡片：</p>
<pre><code>::github{repo="LyraVoid/Shirone"}
</code></pre>
<p>::github{repo="LyraVoid/Shirone"}</p>
<h3>5.3 Expressive Code 代码块</h3>
<p>增强代码块具备语法高亮、文件名徽标、行号以及按行高亮能力：</p>
<pre><code>// 基于 HCT 的动态颜色令牌推导
import { argbFromHex, themeFromSourceColor } from "@material/material-color-utilities";

const theme = themeFromSourceColor(argbFromHex("#f472b6"));
console.log("Primary color token:", theme.schemes.light.primary);
</code></pre>
<h3>5.4 数学排版（KaTeX）</h3>
<p>直接在 Markdown 中渲染优雅的 LaTeX 数学记号：</p>
<ul>
<li><strong>行内公式</strong>：$E = mc^2$，或欧拉公式 $e^{i\pi} + 1 = 0$。</li>
<li><strong>块级公式</strong>：</li>
</ul>
<p>$$
\int_{-\infty}^{\infty} e^{-x^2} , dx = \sqrt{\pi}
$$</p>
<h3>5.5 Mermaid 图表</h3>
<p>用纯文本创建流程图、时序图与架构图：</p>
<pre><code>sequenceDiagram
    autonumber
    actor Visitor as 访客
    participant Page as Shirone 页面
    participant Swup as Swup 容器
    participant Audio as 常驻框架

    Visitor-&gt;&gt;Page: 点击导航链接
    Page-&gt;&gt;Swup: 触发无缝过渡
    Swup-&gt;&gt;Page: 替换 #swup-container
    Note over Audio: 背景音乐持续播放
    Page--&gt;&gt;Visitor: 新页面完成渲染
</code></pre>
<h3>5.6 图片画廊与 Fancybox 灯箱</h3>
<p>图片会自动接入 Fancybox，支持无损缩放、拖拽手势与全屏预览：</p>
<pre><code>![Cover preview](./cover.jpeg)
</code></pre>
<hr />
<h2>6. 后续步骤与自定义</h2>
<ul>
<li><strong>站点配置</strong>：在 <code>src/config/siteConfig.ts</code> 与 <a href="https://github.com/LyraVoid/Shirone/blob/main/src/config/README.md"><code>src/config/README.md</code></a> 中了解全局设置。</li>
<li><strong>设计令牌</strong>：在 <code>DESIGN.md</code> 与 <code>docs/m3e-standard.md</code> 中探索设计令牌与配色方案。</li>
<li><strong>反馈与社区</strong>：在 <a href="https://github.com/LyraVoid/Shirone/issues">GitHub Issues</a> 分享你的想法与疑问。</li>
</ul>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>MDX 集成与 M3E 原子组件</title>
    <link href="https://www.dafeiyu.site/posts/mdx-showcase/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/mdx-showcase/</id>
    <published>2026-08-20T00:00:00.000Z</published>
    <updated>2026-08-20T00:00:00.000Z</updated>
    <summary>一份完整指南：在 Shirone 中用 MDX、Svelte 5 交互岛与 Material 3 Expressive 设计令牌编写丰富的交互式文章。</summary>
    <content type="html"><![CDATA[<p>这个页面演示如何在 MDX 里直接使用 [[TypeScript 泛型]] 风格的类型注解与组件 props。</p>
<p>:::tip
**MDX（Markdown + JSX）**弥合了静态写作与应用界面之间的鸿沟。在 Shirone 中，作者可以把动态逻辑、响应式 Svelte 5 组件与 Material 3 设计令牌直接混写进文章内容。
:::</p>
<h2>1. Markdown 与 MDX 能力对照</h2>
<table>
<thead>
<tr>
<th>能力</th>
<th>标准 Markdown（<code>.md</code>）</th>
<th>Shirone MDX（<code>.mdx</code>）</th>
<th>执行方式</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>排版与结构</strong></td>
<td>完整支持</td>
<td>完整支持</td>
<td>静态 SSR</td>
</tr>
<tr>
<td><strong>代码高亮</strong></td>
<td>行号、外框、可折叠</td>
<td>行号、外框、可折叠</td>
<td>静态 SSR（Expressive Code）</td>
</tr>
<tr>
<td><strong>图表与数学</strong></td>
<td>Mermaid、KaTeX</td>
<td>Mermaid、KaTeX</td>
<td>客户端增强</td>
</tr>
<tr>
<td><strong>提示块</strong></td>
<td>提示、技巧、重要、警告、注意</td>
<td>提示、技巧、重要、警告、注意</td>
<td>静态 SSR</td>
</tr>
<tr>
<td><strong>M3E 展示类原子</strong></td>
<td>不可用</td>
<td>直接集成（``、<code>&lt;Skeleton&gt;</code>）</td>
<td>纯 SSR（零客户端 JS）</td>
</tr>
<tr>
<td><strong>Svelte 5 响应式岛</strong></td>
<td>不可用</td>
<td>按需注水（<code>&lt;Button&gt;</code>、<code>&lt;Switch&gt;</code>）</td>
<td><code>client:visible</code> 懒加载注水</td>
</tr>
<tr>
<td><strong>反馈与加载原子</strong></td>
<td>不可用</td>
<td>形变动画（<code>&lt;LoadingIndicator&gt;</code>）</td>
<td><code>client:visible</code> 响应式</td>
</tr>
<tr>
<td><strong>动态 JSX 表达式</strong></td>
<td>不可用</td>
<td>原生求值（<code>{authorInfo.ui}</code>）</td>
<td>编译期 / 客户端</td>
</tr>
</tbody>
</table>
<hr />
<h2>2. 动态表达式与数据映射</h2>
<p>MDX 允许在文件顶部用 <code>export const</code> 声明作用域内的常量，随后可以内联求值，也可以在模板里循环渲染：</p>
<ul>
<li><strong>核心框架</strong>：{authorInfo.framework}</li>
<li><strong>UI 引擎</strong>：{authorInfo.ui}</li>
<li><strong>设计令牌</strong>：{authorInfo.tokens}</li>
<li><strong>架构模式</strong>：{authorInfo.architecture}</li>
</ul>
<p>数组与集合可以动态渲染成网格布局：</p>
<p>&lt;div class="grid grid-cols-1 md:grid-cols-2 gap-4 my-6"&gt;
{showcaseItems.map((item, idx) =&gt; (
&lt;div key={item.name} class="p-4 rounded-xl border border-[var(--outline-variant)] bg-[var(--surface-container-low)]"&gt;
&lt;div class="flex items-center gap-2 mb-1"&gt;
&lt;span class="w-6 h-6 rounded-full bg-[var(--primary)] text-[var(--on-primary)] text-xs flex items-center justify-center font-bold"&gt;
{idx + 1}
&lt;/span&gt;
&lt;span class="font-bold text-[var(--on-surface)]"&gt;{item.name}&lt;/span&gt;
&lt;/div&gt;
&lt;p class="text-sm text-[var(--on-surface-variant)] m-0"&gt;{item.desc}&lt;/p&gt;
&lt;/div&gt;
))}
&lt;/div&gt;</p>
<hr />
<h2>3. M3E 展示与布局原语（仅 SSR）</h2>
<p>按照 Shirone 的组件架构（<code>docs/atomic-structure.md</code>），无状态的展示类组件输出干净、无障碍的语义化 HTML，不携带任何客户端运行时负载。</p>
<h3>3.1 卡片容器（<code>Card.svelte</code>）</h3>
<p>&lt;div class="grid grid-cols-1 md:grid-cols-3 gap-4 my-6"&gt;
&lt;Card variant="filled" class="!p-5"&gt;
&lt;div class="font-bold text-[var(--primary)] mb-2"&gt;填充卡片&lt;/div&gt;
&lt;div class="text-sm text-[var(--on-surface-variant)]"&gt;默认容器底色，不带高度投影。适合用来分组内容块。&lt;/div&gt;</p>
<pre><code>&lt;div class="font-bold text-[var(--primary)] mb-2"&gt;抬升卡片&lt;/div&gt;
&lt;div class="text-sm text-[var(--on-surface-variant)]"&gt;一级容器高度并带交互状态层，适合需要突出视觉焦点的场合。&lt;/div&gt;



&lt;div class="font-bold text-[var(--primary)] mb-2"&gt;描边卡片&lt;/div&gt;
&lt;div class="text-sm text-[var(--on-surface-variant)]"&gt;1px 清晰描边，在中性底色上做出干净的分隔。&lt;/div&gt;
</code></pre>
<p>&lt;/div&gt;</p>
<h3>3.2 强调条与徽标（<code>AccentBar</code> 与 <code>Badge</code>）</h3>
<p>&lt;div class="flex items-center gap-4 my-4 p-4 rounded-lg bg-[var(--surface-container-high)]"&gt;</p>
<p>&lt;div class="flex-1"&gt;
&lt;span class="font-bold text-lg"&gt;系统公告&lt;/span&gt;
&lt;p class="text-xs text-[var(--on-surface-variant)] m-0"&gt;把 AccentBar 与 Badge 组合起来，可以做出醒目的视觉提示&lt;/p&gt;
&lt;/div&gt;
M3E v0.192
&lt;/div&gt;</p>
<h3>3.3 骨架占位（<code>Skeleton.svelte</code>）</h3>
<p>用于预览布局骨架，或给异步状态做原型：</p>
<p>&lt;div class="flex flex-col gap-3 my-6 p-5 rounded-xl border border-[var(--outline-variant)] bg-[var(--surface-container-low)]"&gt;
&lt;div class="flex items-center gap-3"&gt;</p>
<pre><code>&lt;div class="flex flex-col gap-1.5 flex-1"&gt;
  
  
&lt;/div&gt;
</code></pre>
<p>&lt;/div&gt;</p>
<p>&lt;/div&gt;</p>
<hr />
<h2>4. 反馈与加载指示</h2>
<p>Shirone 内置完整还原的 Material 3 Expressive 动效与反馈原子：</p>
<h3>4.1 形变加载指示器（<code>LoadingIndicator.svelte</code>）</h3>
<p>基于 <code>androidx.graphics.shapes</code> 的多边形形变实现，提供弹性插值的 7 种形状动画：</p>
<p>&lt;div class="grid grid-cols-1 md:grid-cols-3 gap-4 my-6 p-6 rounded-2xl bg-[var(--surface-container)] border border-[var(--outline-variant)] text-center"&gt;
&lt;div class="flex flex-col items-center gap-2"&gt;
&lt;div class="h-16 flex items-center justify-center"&gt;</p>
<pre><code>&lt;/div&gt;
&lt;span class="text-xs text-[var(--on-surface-variant)]"&gt;不定形形变&lt;/span&gt;
</code></pre>
<p>&lt;/div&gt;</p>
<p>&lt;div class="flex flex-col items-center gap-2"&gt;
&lt;div class="h-16 flex items-center justify-center"&gt;</p>
<pre><code>&lt;/div&gt;
&lt;span class="text-xs text-[var(--on-surface-variant)]"&gt;容器化环形变体&lt;/span&gt;
</code></pre>
<p>&lt;/div&gt;</p>
<p>&lt;div class="flex flex-col items-center gap-2"&gt;
&lt;div class="h-16 flex items-center justify-center"&gt;</p>
<pre><code>&lt;/div&gt;
&lt;span class="text-xs text-[var(--on-surface-variant)]"&gt;确定进度（68%）&lt;/span&gt;
</code></pre>
<p>&lt;/div&gt;
&lt;/div&gt;</p>
<h3>4.2 线性与不定进度（<code>ProgressIndicator.svelte</code>）</h3>
<p>&lt;div class="flex flex-col gap-4 my-6 p-6 rounded-2xl bg-[var(--surface-container)] border border-[var(--outline-variant)]"&gt;
&lt;div class="flex flex-col gap-2"&gt;
&lt;div class="flex justify-between text-xs text-[var(--on-surface-variant)]"&gt;
&lt;span&gt;管线编译&lt;/span&gt;
&lt;span&gt;80%&lt;/span&gt;
&lt;/div&gt;</p>
<p>&lt;/div&gt;</p>
<p>&lt;div class="flex flex-col gap-2 mt-2"&gt;
&lt;div class="text-xs text-[var(--on-surface-variant)]"&gt;连续双向线条动画&lt;/div&gt;</p>
<p>&lt;/div&gt;
&lt;/div&gt;</p>
<hr />
<h2>5. Svelte 5 交互岛</h2>
<p>用 <code>client:visible</code> 声明的组件会在进入视口时通过 <code>IntersectionObserver</code> 懒加载注水：</p>
<h3>5.1 按钮矩阵（<code>Button.svelte</code>）</h3>
<p>&lt;div class="flex flex-wrap items-center gap-3 my-6 p-4 rounded-xl border border-[var(--outline-variant)]"&gt;
填充按钮
抬升按钮
色调按钮
描边按钮
文字按钮
&lt;/div&gt;</p>
<h3>5.2 筛选标签与分段按钮（<code>Chips</code> 与 <code>SegmentedButton</code>）</h3>
<p>&lt;div class="flex flex-col gap-4 my-6 p-6 rounded-2xl bg-[var(--surface-container)] border border-[var(--outline-variant)]"&gt;
&lt;div&gt;
&lt;div class="text-xs font-bold text-[var(--on-surface-variant)] mb-2"&gt;M3E 筛选标签&lt;/div&gt;</p>
<p>&lt;/div&gt;</p>
<p>&lt;div&gt;
&lt;div class="text-xs font-bold text-[var(--on-surface-variant)] mb-2"&gt;分段控件&lt;/div&gt;</p>
<p>&lt;/div&gt;
&lt;/div&gt;</p>
<h3>5.3 开关、复选框与滑块（<code>Switch</code>、<code>Checkbox</code>、<code>Slider</code>）</h3>
<p>&lt;div class="flex flex-col gap-4 my-6 p-6 rounded-2xl bg-[var(--surface-container)] border border-[var(--outline-variant)]"&gt;
&lt;div class="flex items-center justify-between"&gt;
&lt;span class="font-bold text-sm"&gt;带状态图标的开关&lt;/span&gt;</p>
<p>&lt;/div&gt;</p>
<p>&lt;div class="flex items-center justify-between"&gt;
&lt;span class="font-bold text-sm"&gt;选择复选框&lt;/span&gt;
&lt;div class="flex items-center gap-4"&gt;</p>
<pre><code>&lt;/div&gt;
</code></pre>
<p>&lt;/div&gt;</p>
<p>&lt;div class="flex flex-col gap-2"&gt;
&lt;span class="font-bold text-sm"&gt;色相滑块&lt;/span&gt;</p>
<p>&lt;/div&gt;
&lt;/div&gt;</p>
<h3>5.4 输入控件（<code>TextField.svelte</code>）</h3>
<p>&lt;div class="grid grid-cols-1 md:grid-cols-2 gap-4 my-6"&gt;</p>
<p>&lt;/div&gt;</p>
<hr />
<h2>6. Markdown 扩展兼容性</h2>
<p>Shirone 的 SSOT 统一插件管线与全部 Markdown 扩展保持完全兼容：</p>
<h3>6.1 GitHub 仓库卡片</h3>
<p>::github{repo="saicaca/fuwari"}</p>
<h3>6.2 Mermaid 架构图</h3>
<pre><code>flowchart TD
    MDX[MDX 源文件] --&gt; Compiler["@astrojs/mdx 编译器"]
    Compiler --&gt; Plugins["Remark / Rehype SSOT 管线"]
    Plugins --&gt; Islands["Svelte 5 交互岛"]
    Islands --&gt; Swup["Swup 客户端导航外壳"]
    Swup --&gt; Screen["M3E 表现力文章视图"]
</code></pre>
<h3>6.3 数学表达式（LaTeX / KaTeX）</h3>
<p>行内公式：质能等价 $E = mc^2$ 与高斯积分 $\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}$。</p>
<p>块级公式：</p>
<p>$$
\mathcal{L}<em>{M3E} = \sum</em>{i=1}^{N} \left( \text{Token}_i \cdot \text{ContrastRatio} \right) + \lambda |\text{MotionElegance}|
$$</p>
<hr />
<h2>7. 小结</h2>
<p>MDX 的原生集成让技术写作者可以构建丰富、可交互的文档，同时保留 Shirone 极快的静态性能。所有组件都遵循 Material 3 Expressive 令牌体系，确保一致性、无障碍与视觉和谐。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>图片网格：语法与完整示例</title>
    <link href="https://www.dafeiyu.site/posts/image-grid-demo/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/image-grid-demo/</id>
    <published>2026-07-13T00:00:00.000Z</published>
    <updated>2026-07-13T00:00:00.000Z</updated>
    <summary>图片网格的语法、参数、裁切、响应式行为、说明文字与灯箱导航完整指南。</summary>
    <content type="html"><![CDATA[<p><code>:::grid</code> 是本博客的图片画廊容器指令。它把普通的 Markdown 图片排列成宽高比一致的响应式网格，并自动启用灯箱查看。适合用于文章配图、截图、作品集或小型相册。</p>
<p>同一画廊中的图片共用同一卡片比例。默认情况下，居中裁切会填满每张卡片并保持整行整齐；点击图片会在灯箱中打开完整原图。每个画廊都拥有独立的灯箱分组，不会与文章中的其他图片混在一起。</p>
<blockquote>
<p>本文既是功能文档，也是视觉测试页。请在桌面、平板与手机宽度下查看这些示例，然后点击任意图片验证灯箱分组。</p>
</blockquote>
<h2>最简语法</h2>
<p>把 Markdown 图片直接写在 <code>:::grid</code> 与结束的 <code>:::</code> 之间：</p>
<pre><code>:::grid
![图片说明](./image-1.webp)

![图片说明](./image-2.webp)
:::
</code></pre>
<p>每张图片必须独占一个段落，图片之间保留空行。画廊中只放图片；段落、列表与代码块请写在容器之外。</p>
<p>下面是最简语法的效果。不带参数时，网格默认使用三列、<code>16/10</code> 比例与 <code>cover</code>。</p>
<p>:::grid
<img src="./landscape-1.webp" alt="最简语法效果：第一张图" /></p>
<p><img src="./landscape-2.webp" alt="最简语法效果：第二张图" />
:::</p>
<h2>参数速览</h2>
<p>所有参数都写在起始指令后的花括号中：<code>:::grid{parameter="value"}</code>。</p>
<table>
<thead>
<tr>
<th>参数</th>
<th>允许取值</th>
<th>默认值</th>
<th>作用</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>columns</code></td>
<td><code>1</code> 到 <code>6</code> 的整数</td>
<td><code>3</code></td>
<td>桌面端每行的列数。非法值回退为 <code>3</code>。</td>
</tr>
<tr>
<td><code>aspect</code></td>
<td>正数比例，如 <code>16/9</code>、<code>3/4</code>、<code>1/1</code></td>
<td><code>16/10</code></td>
<td>显示卡片的比例，而非原图比例。</td>
</tr>
<tr>
<td><code>fit</code></td>
<td><code>cover</code>、<code>contain</code></td>
<td><code>cover</code></td>
<td>图片适配方式。<code>cover</code> 裁切填满；<code>contain</code> 保留完整图片，可能留下空白。</td>
</tr>
</tbody>
</table>
<p>完整示例：</p>
<pre><code>:::grid{columns="3" aspect="16/9" fit="cover"}
![第一张图](./image-1.webp "可选说明文字")

![第二张图](./image-2.webp "可选说明文字")

![第三张图](./image-3.webp "可选说明文字")
:::
</code></pre>
<p>下面的结果使用上述三列横向语法。请对比卡片比例、列数，以及标题优先于替代文本作为说明文字的方式：</p>
<p>:::grid{columns="3" aspect="16/9" fit="cover"}
<img src="./landscape-1.webp" alt="参数示例：第一张横向图" title="横向说明 1" /></p>
<p><img src="./landscape-2.webp" alt="参数示例：第二张横向图" title="横向说明 2" /></p>
<p><img src="./landscape-3.webp" alt="参数示例：第三张横向图" title="横向说明 3" />
:::</p>
<h2>说明文字与替代文本</h2>
<p>图片的替代文本既作为无障碍替代文本，也作为默认说明文字。当图片带有可选的标题时，则改用标题作为说明文字：</p>
<pre><code>![用于无障碍的文本](./image.webp "显示在图片下方的说明文字")
</code></pre>
<p>同一行中，说明文字会对齐到每张卡片的底部。说明文字换行不会让其他卡片浮动到不同高度。像 <code>3:4</code>、<code>16:9</code> 这样的比例文本可以直接写在正文、标题与替代文本中，无需转义。</p>
<p>本例展示了默认的替代文本说明文字、显式的标题说明文字，以及较长说明文字的底部对齐：</p>
<p>:::grid{columns="3" aspect="1/1"}
<img src="./square-1.webp" alt="这张图片没有标题，因此用替代文本作为说明" /></p>
<p><img src="./square-2.webp" alt="带无障碍替代文本的第二张方图" title="这个标题会显示为说明文字" /></p>
<p><img src="./square-3.webp" alt="3:4 海报的无障碍描述" title="这是一段较长的说明文字，用于检查每张卡片的说明在换行后是否仍底部对齐" />
:::</p>
<h2>布局与裁切</h2>
<p>桌面端布局使用 <code>columns</code> 指定的列数。低于 <code>768px</code> 时，网格最多使用两列；低于 <code>480px</code> 时，切换为单列。卡片外层固定 <code>aspect</code> 比例并裁掉圆角，图片填满卡片且不带主题默认的图片外边距。</p>
<ul>
<li>选择 <code>cover</code>：推荐的默认值。图片从中心裁切以填满卡片，让画廊看起来整齐一致。</li>
<li>选择 <code>contain</code>：完整显示原图而不裁切。当图片比例与卡片不同时，主题背景会显现出来；适用于不能被裁切的图片。</li>
<li>若想既保留完整图片又不留空白，请把 <code>aspect</code> 设为接近原图的比例，或让该图片独占一个网格。</li>
</ul>
<p>下面的示例把同样的竖向图片分别放入 <code>cover</code> 与 <code>contain</code> 的 <code>16/9</code> 卡片中。前者会裁切，后者保留完整图片并留下背景空间。</p>
<pre><code>:::grid{columns="3" aspect="16/9" fit="cover"}
![图片说明](./image-1.webp "可选说明文字")

![图片说明](./image-2.webp "可选说明文字")
:::

:::grid{columns="3" aspect="16/9" fit="contain"}
![图片说明](./image-1.webp "可选说明文字")

![图片说明](./image-2.webp "可选说明文字")
:::
</code></pre>
<p>:::grid{columns="3" aspect="16/9" fit="cover"}
<img src="./default-portrait-1.webp" alt="第一张 cover 结果" title="Cover：居中裁切" /></p>
<p><img src="./default-portrait-2.webp" alt="第二张 cover 结果" title="Cover：填满卡片" /></p>
<p><img src="./default-portrait-3.webp" alt="第三张 cover 结果" title="Cover：布局更整齐" />
:::</p>
<p>:::grid{columns="3" aspect="16/9" fit="contain"}
<img src="./default-portrait-1.webp" alt="第一张 contain 结果" title="Contain：完整保留原图" /></p>
<p><img src="./default-portrait-2.webp" alt="第二张 contain 结果" title="Contain：可能出现空白" /></p>
<p><img src="./default-portrait-3.webp" alt="第三张 contain 结果" title="Contain：适合边缘细节" />
:::</p>
<h2>默认配置</h2>
<p>不带属性时，默认为三列、<code>16/10</code> 比例与 <code>cover</code> 裁切。这三张竖向图片用于验证默认裁切与说明文字。</p>
<pre><code>:::grid
![图片说明](./image-1.webp)

![图片说明](./image-2.webp)

![图片说明](./image-3.webp)
:::
</code></pre>
<p>:::grid
<img src="./default-portrait-1.webp" alt="默认配置：竖向图片一" /></p>
<p><img src="./default-portrait-2.webp" alt="默认配置：竖向图片二" /></p>
<p><img src="./default-portrait-3.webp" alt="默认配置：竖向图片三" />
:::</p>
<h2>三列竖图：3:4</h2>
<p>使用 <code>aspect="3/4"</code> 时，这三张竖向图片会填满比例一致的竖向卡片。若原图比例不同，<code>cover</code> 会从中心裁掉其边缘。</p>
<pre><code>:::grid{columns="3" aspect="3/4"}
![竖向图片说明](./portrait-1.webp)

![竖向图片说明](./portrait-2.webp)

![竖向图片说明](./portrait-3.webp)
:::
</code></pre>
<p>:::grid{columns="3" aspect="3/4"}
<img src="./default-portrait-1.webp" alt="3:4 测试图一" title="竖图 1" /></p>
<p><img src="./default-portrait-2.webp" alt="3:4 测试图二" title="竖图 2" /></p>
<p><img src="./default-portrait-3.webp" alt="3:4 测试图三" title="竖图 3" />
:::</p>
<h2>三列横图：16:9</h2>
<p>这一组展示三列布局中常见的视频封面比例。当横向图片接近卡片比例时，裁切幅度很小。</p>
<pre><code>:::grid{columns="3" aspect="16/9"}
![横向图片说明](./landscape-1.webp)

![横向图片说明](./landscape-2.webp)

![横向图片说明](./landscape-3.webp)
:::
</code></pre>
<p>:::grid{columns="3" aspect="16/9"}
<img src="./feature-landscape-1.webp" alt="16:9 测试图一" /></p>
<p><img src="./feature-landscape-2.webp" alt="16:9 测试图二" /></p>
<p><img src="./feature-landscape-3.webp" alt="16:9 测试图三" />
:::</p>
<h2>两列方图：1:1</h2>
<p>需要更大的预览卡片时，两列效果很好。第三张图片会移到下一行。最后一行保持其网格轨道宽度，而不会拉伸图片去填满整行。</p>
<pre><code>:::grid{columns="2" aspect="1/1"}
![方图说明](./square-1.webp)

![方图说明](./square-2.webp)

![方图说明](./square-3.webp)
:::
</code></pre>
<p>:::grid{columns="2" aspect="1/1"}
<img src="./mixed-square-1.webp" alt="1:1 测试图一" /></p>
<p><img src="./mixed-square-2.webp" alt="1:1 测试图二" /></p>
<p><img src="./mixed-square-3.webp" alt="1:1 测试图三" />
:::</p>
<h2>四列搭配 <code>contain</code></h2>
<p><code>fit="contain"</code> 不会裁切原图。当图片比例与卡片比例不同时，主题背景会显现出来。这是有意为之，并非布局问题。它同时验证了四列网格与各自独立的灯箱分组不会互相干扰。</p>
<pre><code>:::grid{columns="4" aspect="16/9" fit="contain"}
![图片说明](./image-1.webp)

![图片说明](./image-2.webp)

![图片说明](./image-3.webp)
:::
</code></pre>
<p>:::grid{columns="4" aspect="16/9" fit="contain"}
<img src="./default-portrait-1.webp" alt="Contain：竖向图片一" /></p>
<p><img src="./default-portrait-2.webp" alt="Contain：竖向图片二" /></p>
<p><img src="./default-portrait-3.webp" alt="Contain：竖向图片三" />
:::</p>
<h2>单列细节图</h2>
<p>当图片需要更大的阅读尺寸时，单列是合适的选择。它在桌面、平板与手机上都是一列，原图依然可以在灯箱中查看。</p>
<pre><code>:::grid{columns="1" aspect="16/9"}
![图片说明](./detail.webp)
:::
</code></pre>
<p>:::grid{columns="1" aspect="16/9"}
<img src="./feature-landscape-1.webp" alt="单列测试图" />
:::</p>
<h2>稀疏的五列一行</h2>
<p>五列用于验证更高的受支持列数。只有三张图片时，最后一行保持左对齐，而不会拉伸图片。</p>
<pre><code>:::grid{columns="5" aspect="1/1"}
![缩略图说明](./thumb-1.webp)

![缩略图说明](./thumb-2.webp)

![缩略图说明](./thumb-3.webp)
:::
</code></pre>
<p>:::grid{columns="5" aspect="1/1"}
<img src="./mixed-square-1.webp" alt="五列测试图一" /></p>
<p><img src="./mixed-square-2.webp" alt="五列测试图二" /></p>
<p><img src="./mixed-square-3.webp" alt="五列测试图三" />
:::</p>
<h2>六列混排</h2>
<p>六列是当前的上限。混排横向与竖向图片可以验证 <code>cover</code> 裁切、窄卡片上的说明文字，以及密集的桌面布局。为了让文章内容便于阅读，通常建议使用两到四列。</p>
<pre><code>:::grid{columns="6" aspect="1/1"}
![图片说明](./image-1.webp)

![图片说明](./image-2.webp)

![图片说明](./image-3.webp)

![图片说明](./image-4.webp)

![图片说明](./image-5.webp)

![图片说明](./image-6.webp)
:::
</code></pre>
<p>:::grid{columns="6" aspect="1/1"}
<img src="./default-portrait-1.webp" alt="六列测试图一" /></p>
<p><img src="./default-portrait-2.webp" alt="六列测试图二" /></p>
<p><img src="./default-portrait-3.webp" alt="六列测试图三" /></p>
<p><img src="./feature-landscape-1.webp" alt="六列测试图四" /></p>
<p><img src="./feature-landscape-2.webp" alt="六列测试图五" /></p>
<p><img src="./feature-landscape-3.webp" alt="六列测试图六" />
:::</p>
<h2>四列方图：1:1</h2>
<p>四张比例相同的方图是典型的四列布局。桌面端一行显示全部四张；平板收缩为两列，手机收缩为一列。</p>
<pre><code>:::grid{columns="4" aspect="1/1"}
![方图说明](./square-1.webp)

![方图说明](./square-2.webp)

![方图说明](./square-3.webp)

![方图说明](./square-4.webp)
:::
</code></pre>
<p>:::grid{columns="4" aspect="1/1"}
<img src="./square-1.webp" alt="方图一" /></p>
<p><img src="./square-2.webp" alt="方图二" /></p>
<p><img src="./square-3.webp" alt="方图三" /></p>
<p><img src="./square-4.webp" alt="方图四" />
:::</p>
<h2>六列横图：16:9</h2>
<p>六列横图很适合缩略图预览、作品集与截图索引。即使原图比例略有差异，<code>cover</code> 也能一致地填满每张 <code>16/9</code> 卡片。</p>
<pre><code>:::grid{columns="6" aspect="16/9"}
![横向图片说明](./landscape-1.webp)

![横向图片说明](./landscape-2.webp)

![横向图片说明](./landscape-3.webp)

![横向图片说明](./landscape-4.webp)

![横向图片说明](./landscape-5.webp)

![横向图片说明](./landscape-6.webp)
:::
</code></pre>
<p>:::grid{columns="6" aspect="16/9"}
<img src="./landscape-1.webp" alt="横向图片一" /></p>
<p><img src="./landscape-2.webp" alt="横向图片二" /></p>
<p><img src="./landscape-3.webp" alt="横向图片三" /></p>
<p><img src="./landscape-4.webp" alt="横向图片四" /></p>
<p><img src="./landscape-5.webp" alt="横向图片五" /></p>
<p><img src="./landscape-6.webp" alt="横向图片六" />
:::</p>
<h2>三列竖图：3:4</h2>
<p>这组六张竖向图片展示了人物、海报或手机截图的常见布局。图片排成两行三列，说明文字底部对齐。</p>
<pre><code>:::grid{columns="3" aspect="3/4"}
![竖向图片说明](./portrait-1.webp)

![竖向图片说明](./portrait-2.webp)

![竖向图片说明](./portrait-3.webp)

![竖向图片说明](./portrait-4.webp)

![竖向图片说明](./portrait-5.webp)

![竖向图片说明](./portrait-6.webp)
:::
</code></pre>
<p>:::grid{columns="3" aspect="3/4"}
<img src="./portrait-1.webp" alt="竖向图片一" /></p>
<p><img src="./portrait-2.webp" alt="竖向图片二" /></p>
<p><img src="./portrait-3.webp" alt="竖向图片三" /></p>
<p><img src="./portrait-4.webp" alt="竖向图片四" /></p>
<p><img src="./portrait-5.webp" alt="竖向图片五" /></p>
<p><img src="./portrait-6.webp" alt="竖向图片六" />
:::</p>
<h2>边缘关键内容：<code>cover</code> 与灯箱</h2>
<p>这些图片在靠近边缘处包含重要文字或细节。<code>cover</code> 让网格保持整齐，但可能裁掉这些边缘；点击图片即可在灯箱中查看未裁切的原图。对边缘敏感的内容请使用明确的说明文字，或改用下方的 <code>contain</code>。</p>
<pre><code>:::grid{columns="3" aspect="16/9" fit="cover"}
![边缘关键内容](./critical-1.webp "打开灯箱查看完整的边缘内容")

![边缘关键内容](./critical-2.webp "打开灯箱查看完整的边缘内容")

![边缘关键内容](./critical-3.webp "打开灯箱查看完整的边缘内容")
:::
</code></pre>
<p>:::grid{columns="3" aspect="16/9" fit="cover"}
<img src="./critical-1.webp" alt="第一张边缘关键图片" title="打开灯箱查看完整的边缘内容" /></p>
<p><img src="./critical-2.webp" alt="第二张边缘关键图片" title="打开灯箱查看完整的边缘内容" /></p>
<p><img src="./critical-3.webp" alt="第三张边缘关键图片" title="打开灯箱查看完整的边缘内容" />
:::</p>
<h2>极端比例搭配 <code>contain</code></h2>
<p>对于横幅、长截图以及其他极端比例的图片，<code>contain</code> 会完整显示原图。与 <code>cover</code> 不同，它可能留下主题背景空间，但绝不裁切内容。</p>
<pre><code>:::grid{columns="3" aspect="16/9" fit="contain"}
![完整截图说明](./wide-1.webp)

![完整截图说明](./wide-2.webp)

![完整截图说明](./wide-3.webp)
:::
</code></pre>
<p>:::grid{columns="3" aspect="16/9" fit="contain"}
<img src="./extreme-1.webp" alt="极端比例图片一" /></p>
<p><img src="./extreme-2.webp" alt="极端比例图片二" /></p>
<p><img src="./extreme-3.webp" alt="极端比例图片三" />
:::</p>
<h2>透明图片</h2>
<p>透明图片会露出卡片的主题背景。这个单列 <code>contain</code> 示例便于检查透明区域、原图边缘与灯箱行为。</p>
<pre><code>:::grid{columns="1" aspect="16/9" fit="contain"}
![透明图片说明](./transparent.webp)
:::
</code></pre>
<p>:::grid{columns="1" aspect="16/9" fit="contain"}
<img src="./transparent-1.webp" alt="透明背景测试图" />
:::</p>
<h2>灯箱导航</h2>
<p>点击网格中的任意图片即可打开 Fancybox 灯箱。在那里可以缩放、旋转、进入全屏、查看缩略图，并使用方向键切换。导航仅限于当前的 <code>:::grid</code> 容器：例如点击「16:9 测试图一」只会打开该小节中的另外两张横向图片。</p>
<p>同一篇文章中的普通 Markdown 图片仍单独处理，不会被加入任何网格画廊。</p>
<h2>检查清单</h2>
<ol>
<li>每个网格中的图片尺寸一致，说明文字位于卡片下方。</li>
<li>图片在悬停时轻微缩放；点击后可以缩放、旋转，并用键盘切换。</li>
<li>点击「16:9 测试图一」后，灯箱只能浏览该小节中的另外两张横向图片。</li>
<li>低于 768px 时，网格最多两列；低于 480px 时为一列。</li>
<li>「四列搭配 <code>contain</code>」中的竖向图片完整可见，留有空白且未被裁切。</li>
<li>五列与六列网格在宽屏上保持指定列数，随后按响应式规则收缩为两列或一列。</li>
</ol>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="示例"/>
  </entry>
  <entry>
    <title>Mermaid 图表合集</title>
    <link href="https://www.dafeiyu.site/posts/markdown-mermaid/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/markdown-mermaid/</id>
    <published>2024-05-02T00:00:00.000Z</published>
    <updated>2024-05-02T00:00:00.000Z</updated>
    <summary>一份 Mermaid 图表合集，涵盖流程、交互、数据模型、排期与项目历程等常见图示。</summary>
    <content type="html"><![CDATA[<p>Mermaid 能把 Markdown 里的文字描述变成图表。下面用 Shirone 的内容工作流演示技术文章与项目笔记中常用的几类图表。</p>
<h2>流程图</h2>
<p>流程图用来描述一个过程，包括判断分支以及回到先前步骤的路径。</p>
<pre><code>flowchart TD
    accTitle: 文章发布流程
    accDescr: 一篇文章依次经过写作、校验、预览与构建才会发布。校验不通过则退回修改。
    Draft[编写 Markdown] --&gt; Check{校验通过？}
    Check --&gt;|否| Revise[修改文章]
    Revise --&gt; Check
    Check --&gt;|是| Preview[本地预览]
    Preview --&gt; Build[构建静态页面]
    Build --&gt; Publish[发布]
</code></pre>
<h2>时序图</h2>
<p>时序图按时间顺序展示各参与方之间的协作。这个例子跟着一次 Swup 站内导航，从发起请求走到 Mermaid 渲染。</p>
<pre><code>sequenceDiagram
    accTitle: 站内导航后的图表渲染
    accDescr: 读者发起导航，Swup 替换文章内容，Mermaid 渲染器再对新页面上的图表做增强。
    actor Reader as 读者
    participant Browser as 浏览器
    participant Swup
    participant Content as 文章区域
    participant Renderer as Mermaid 渲染器
    Reader-&gt;&gt;Browser: 打开另一篇文章
    Browser-&gt;&gt;Swup: 发起站内导航
    Swup-&gt;&gt;Content: 替换页面内容
    Swup--&gt;&gt;Renderer: 触发 content:replace
    Renderer-&gt;&gt;Content: 查找 Mermaid 容器
    Renderer--&gt;&gt;Browser: 插入适配主题的 SVG
</code></pre>
<h2>实体关系图</h2>
<p>实体关系图为结构化数据建模，刻画作者、文章、标签与评论之间的关联。</p>
<pre><code>erDiagram
    accTitle: 博客内容关系
    accDescr: 作者撰写文章，文章接收评论，并通过关联记录与多个标签相连。
    AUTHOR ||--o{ POST : writes
    POST ||--o{ COMMENT : receives
    POST ||--o{ POST_TAG : classified_by
    TAG ||--o{ POST_TAG : groups
    AUTHOR {
        string id PK
        string display_name
    }
    POST {
        string slug PK
        string title
        datetime published_at
        string author_id FK
    }
    COMMENT {
        string id PK
        string post_slug FK
        string body
    }
    TAG {
        string id PK
        string label
    }
    POST_TAG {
        string post_slug FK
        string tag_id FK
    }
</code></pre>
<h2>类图</h2>
<p>类图用来表达软件设计中的职责划分、公开方法与依赖方向。</p>
<pre><code>classDiagram
    accTitle: Markdown 渲染模块
    accDescr: 内容管线借助 Mermaid 插件生成降级标记，客户端渲染器随后把它增强为 SVG。
    class ContentPipeline {
        +render(markdown)
        +collectMetadata()
    }
    class MermaidPlugin {
        +transform(codeFence)
        +createFallback()
    }
    class DiagramRenderer {
        +initialize()
        +renderAll()
        +refreshTheme()
    }
    class ThemeTokens {
        +primary
        +surface
        +outline
    }
    ContentPipeline --&gt; MermaidPlugin : uses
    DiagramRenderer --&gt; MermaidPlugin : enhances output
    DiagramRenderer --&gt; ThemeTokens : reads
</code></pre>
<h2>状态图</h2>
<p>状态图展示一个对象在生命周期内的各种状态，以及推动状态迁移的事件。</p>
<pre><code>stateDiagram-v2
    accTitle: 文章生命周期
    accDescr: 文章从草稿走到审核与发布，可能被退回修改，最终也可能归档。
    [*] --&gt; Draft
    Draft --&gt; InReview : submit
    InReview --&gt; Draft : request changes
    InReview --&gt; Published : approve
    Published --&gt; Draft : retract
    Published --&gt; Archived : archive
    Archived --&gt; [*]
</code></pre>
<h2>XY 图</h2>
<p>XY 图把柱形与折线放在同一套坐标轴上，用来比较数值与趋势。</p>
<pre><code>xychart-beta
    accTitle: 六周的内容表现
    accDescr: 柱形表示归一化后的每周发布量，折线表示归一化后的读完率。
    title "六周的内容表现"
    x-axis "周" [1, 2, 3, 4, 5, 6]
    y-axis "相对得分" 0 --&gt; 100
    bar [36, 52, 44, 68, 76, 84]
    line [48, 55, 62, 61, 73, 81]
</code></pre>
<h2>饼图</h2>
<p>饼图用来紧凑地呈现各部分在整体中的占比。</p>
<pre><code>pie showData
    accTitle: 文章主题占比
    accDescr: 工程类占四成，设计系统占两成五，其余由指南与随笔分摊。
    title 文章主题占比
    "工程" : 40
    "设计系统" : 25
    "指南" : 20
    "随笔" : 15
</code></pre>
<h2>甘特图</h2>
<p>甘特图把任务、依赖与里程碑排布在日历时间轴上。</p>
<pre><code>gantt
    accTitle: 主题发布计划
    accDescr: 发布计划从需求与交互设计出发，经过组件开发、测试，最后发布。
    title 主题发布计划
    dateFormat YYYY-MM-DD
    axisFormat %m/%d
    section 设计
    确认需求 :done, brief, 2024-05-06, 2d
    打磨交互 :done, interaction, after brief, 3d
    section 实现
    开发组件 :active, components, after interaction, 6d
    编写示例 :examples, after interaction, 4d
    section 校验
    自动化测试 :tests, after components, 3d
    发布 :milestone, release, after tests, 0d
</code></pre>
<h2>思维导图</h2>
<p>思维导图把一个中心主题铺开成相关领域与支撑概念。</p>
<pre><code>mindmap
  root((Shirone))
    内容体验
      Markdown
      搜索
      图表
    界面体系
      M3E 令牌
      响应式布局
      配色方案
    工程质量
      Astro Check
      Playwright
      无障碍
</code></pre>
<h2>时间线</h2>
<p>时间线用来概述重要事件或阶段，不要求精确的日历时长。</p>
<pre><code>timeline
    title Mermaid 支持的演进
    管线设计 : 识别 Mermaid 代码块
             : 保留源码降级
    客户端增强 : 按需加载运行时
               : 应用主题令牌
    可靠性 : 兼容 Swup 导航
           : 校验响应式与无障碍输出
</code></pre>
<h2>用户旅程图</h2>
<p>用户旅程图把一次任务各阶段中的行为、参与方与体验评分合在一起看。</p>
<pre><code>journey
    accTitle: 读者读懂一篇技术文章
    accDescr: 读者发现文章，结合正文与图表理解内容，然后继续探索相关话题。
    title 读者读懂一篇技术文章
    section 发现
      浏览文章列表: 4: Reader
      挑一个话题: 5: Reader
    section 理解
      阅读正文: 4: Reader
      查看关系图: 5: Reader
    section 继续
      打开相关文章: 4: Reader
      收藏页面: 3: Reader
</code></pre>
<h2>Git 图</h2>
<p>Git 图展示一条功能分支在合入主线之前是如何推进的。</p>
<pre><code>gitGraph
    accTitle: Mermaid 功能分支历史
    accDescr: 功能分支先加入渲染器与测试，再合入主分支准备发布。
    commit id: "base"
    branch mermaid
    checkout mermaid
    commit id: "add-renderer"
    commit id: "add-tests"
    checkout main
    merge mermaid id: "merge-mermaid"
    commit id: "release"
</code></pre>
<h2>看板</h2>
<p>看板按工作流状态把任务分组，方便一眼看清当前进度。</p>
<pre><code>kanban
  backlog[待办]
    docs[编写作者文档]
    examples[扩充示例数据]
  active[进行中]
    themes[验证主题适配]
  complete[已完成]
    fallback[源码降级]
    rendering[客户端渲染]
</code></pre>
<h2>桑基图</h2>
<p>桑基图用连线的宽度表示流量或其他数量在节点之间的流转。</p>
<pre><code>sankey-beta
Landing,Reading,720
Discovery,Reading,430
Reading,Explore,360
Reading,Topics,210
Reading,Outbound,140
</code></pre>
<p>每个示例都使用标准的 <code>mermaid</code> 代码块。服务端保留可读的源码标记，浏览器再把它增强成跟随当前主题的 SVG。主题切换或 Swup 导航到这篇文章时，图表都会重新渲染。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="示例"/>
  </entry>
  <entry>
    <title>Markdown 扩展特性</title>
    <link href="https://www.dafeiyu.site/posts/markdown-extended/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/markdown-extended/</id>
    <published>2024-05-01T00:00:00.000Z</published>
    <updated>2024-05-01T00:00:00.000Z</updated>
    <summary>进一步了解 Fuwari 中的 Markdown 特性</summary>
    <content type="html"><![CDATA[<h2>GitHub 仓库卡片</h2>
<p>你可以添加链接到 GitHub 仓库的动态卡片，页面加载时会从 GitHub API 拉取仓库信息。</p>
<p>::github{repo="Fabrizz/MMM-OnSpotify"}</p>
<p>用 <code>::github{repo="&lt;owner&gt;/&lt;repo&gt;"}</code> 这段代码创建 GitHub 仓库卡片。</p>
<pre><code>::github{repo="saicaca/fuwari"}
</code></pre>
<h2>Mermaid 图表</h2>
<p><code>mermaid</code> 围栏代码块会渲染成图表，并跟随当前配色方案。</p>
<pre><code>flowchart LR
    accTitle: Markdown rendering pipeline
    accDescr: Markdown source is transformed into semantic HTML and then enhanced as a themed SVG diagram.
    A[Markdown source] --&gt; B[Astro content pipeline]
    B --&gt; C[Semantic HTML]
    C --&gt; D[Themed diagram]
</code></pre>
<h2>提示块</h2>
<p>支持以下类型的提示块：<code>note</code> <code>tip</code> <code>important</code> <code>warning</code> <code>caution</code></p>
<p>:::note
强调用户即使只是快速浏览也应当留意的信息。
:::</p>
<p>:::tip
帮助用户更好完成任务的补充信息。
:::</p>
<p>:::important
用户完成任务所必需的关键信息。
:::</p>
<p>:::warning
因存在潜在风险而需要用户立即关注的关键内容。
:::</p>
<p>:::caution
某项操作可能带来的负面后果。
:::</p>
<h3>基础语法</h3>
<pre><code>:::note
强调用户即使只是快速浏览也应当留意的信息。
:::

:::tip
帮助用户更好完成任务的补充信息。
:::
</code></pre>
<h3>自定义标题</h3>
<p>提示块的标题可以自定义。</p>
<p>:::note[MY CUSTOM TITLE]
这是一条带自定义标题的 note。
:::</p>
<pre><code>:::note[MY CUSTOM TITLE]
这是一条带自定义标题的 note。
:::
</code></pre>
<h3>GitHub 语法</h3>
<blockquote>
<p>[!TIP]
也支持 <a href="https://github.com/orgs/community/discussions/16925">GitHub 的语法</a>。</p>
</blockquote>
<pre><code>&gt; [!NOTE]
&gt; 也支持 GitHub 的语法。

&gt; [!TIP]
&gt; 也支持 GitHub 的语法。
</code></pre>
<h3>剧透</h3>
<p>你可以为文字添加剧透。其中的文字同样支持 <strong>Markdown</strong> 语法。</p>
<p>这段内容 :spoiler[被隐藏了 <strong>ayyy</strong>]！</p>
<pre><code>这段内容 :spoiler[被隐藏了 **ayyy**]！

</code></pre>
<h2>图片宽度与说明文字</h2>
<p>独立图片的替代文本中可带一个可选的 <code>w-N%</code> 宽度标记，而 Markdown 标题会渲染为图片下方居中的说明文字：</p>
<p><img src="/images/albums/AcgExample/07.webp" alt="相册示例图片 w-50%" title="带说明文字的半宽图片" /></p>
<pre><code>![图片说明 w-50%](./image.webp "可见的说明文字")
</code></pre>
<p>有效宽度范围是 <code>w-1%</code> 到 <code>w-100%</code>；无效标记会保留在替代文本中。宽度与说明文字相互独立——只写标题同样会产生说明文字：</p>
<p><img src="/images/albums/AcgExample/08.webp" alt="相册示例图片 w-75%" /></p>
<p><img src="/images/albums/AcgExample/09.webp" alt="相册示例图片" title="没有宽度标记的说明文字" /></p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="指南"/>
  </entry>
  <entry>
    <title>Expressive Code 示例</title>
    <link href="https://www.dafeiyu.site/posts/expressive-code/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/expressive-code/</id>
    <published>2024-04-10T00:00:00.000Z</published>
    <updated>2024-04-10T00:00:00.000Z</updated>
    <summary>使用 Expressive Code 时，Markdown 代码块的呈现效果。</summary>
    <content type="html"><![CDATA[<p>下面来看看使用 <a href="https://expressive-code.com/">Expressive Code</a> 时，代码块会呈现出怎样的效果。文中的示例取自官方文档，需要更多细节可以查阅该文档。</p>
<h2>Expressive Code</h2>
<h3>语法高亮</h3>
<p><a href="https://expressive-code.com/key-features/syntax-highlighting/">Syntax Highlighting</a></p>
<h4>常规语法高亮</h4>
<pre><code>console.log('This code is syntax highlighted!')
</code></pre>
<h4>渲染 ANSI 转义序列</h4>
<pre><code>ANSI colors:
- Regular: [31mRed[0m [32mGreen[0m [33mYellow[0m [34mBlue[0m [35mMagenta[0m [36mCyan[0m
- Bold:    [1;31mRed[0m [1;32mGreen[0m [1;33mYellow[0m [1;34mBlue[0m [1;35mMagenta[0m [1;36mCyan[0m
- Dimmed:  [2;31mRed[0m [2;32mGreen[0m [2;33mYellow[0m [2;34mBlue[0m [2;35mMagenta[0m [2;36mCyan[0m

256 colors (showing colors 160-177):
[38;5;160m160 [38;5;161m161 [38;5;162m162 [38;5;163m163 [38;5;164m164 [38;5;165m165[0m
[38;5;166m166 [38;5;167m167 [38;5;168m168 [38;5;169m169 [38;5;170m170 [38;5;171m171[0m
[38;5;172m172 [38;5;173m173 [38;5;174m174 [38;5;175m175 [38;5;176m176 [38;5;177m177[0m

Full RGB colors:
[38;2;34;139;34mForestGreen - RGB(34, 139, 34)[0m

Text formatting: [1mBold[0m [2mDimmed[0m [3mItalic[0m [4mUnderline[0m
</code></pre>
<h3>编辑器与终端外框</h3>
<p><a href="https://expressive-code.com/key-features/frames/">Editor &amp; Terminal Frames</a></p>
<h4>代码编辑器外框</h4>
<pre><code>console.log('Title attribute example')
</code></pre>
<hr />
<pre><code>&lt;!-- src/content/index.html --&gt;
&lt;div&gt;File name comment example&lt;/div&gt;
</code></pre>
<h4>终端外框</h4>
<pre><code>echo "This terminal frame has no title"
</code></pre>
<hr />
<pre><code>Write-Output "This one has a title!"
</code></pre>
<h4>覆盖外框类型</h4>
<pre><code>echo "Look ma, no frame!"
</code></pre>
<hr />
<pre><code># 若不覆盖外框类型，这里原本会渲染成终端外框
function Watch-Tail { Get-Content -Tail 20 -Wait $args }
New-Alias tail Watch-Tail
</code></pre>
<h3>文本与行标记</h3>
<p><a href="https://expressive-code.com/key-features/text-markers/">Text &amp; Line Markers</a></p>
<h4>标记整行与行范围</h4>
<pre><code>// 第 1 行 —— 由行号定位
// Line 2
// Line 3
// 第 4 行 —— 由行号定位
// Line 5
// Line 6
// 第 7 行 —— 由范围 "7-8" 定位
// 第 8 行 —— 由范围 "7-8" 定位
</code></pre>
<h4>选择行标记类型（mark、ins、del）</h4>
<pre><code>function demo() {
  console.log('this line is marked as deleted')
  // 这一行与下一行被标记为新增
  console.log('this is the second inserted line')

  return 'this line uses the neutral default marker type'
}
</code></pre>
<h4>为行标记添加标签</h4>
<pre><code>// labeled-line-markers.jsx
&lt;button
  role="button"
  {...props}
  value={value}
  className={buttonClassName}
  disabled={disabled}
  active={active}
&gt;
  {children &amp;&amp;
    !active &amp;&amp;
    (typeof children === 'string' ? &lt;span&gt;{children}&lt;/span&gt; : children)}
&lt;/button&gt;
</code></pre>
<h4>把长标签单独放成一行</h4>
<pre><code>// labeled-line-markers.jsx
&lt;button
  role="button"
  {...props}

  value={value}
  className={buttonClassName}

  disabled={disabled}
  active={active}
&gt;

  {children &amp;&amp;
    !active &amp;&amp;
    (typeof children === 'string' ? &lt;span&gt;{children}&lt;/span&gt; : children)}
&lt;/button&gt;
</code></pre>
<h4>使用类 diff 语法</h4>
<pre><code>+this line will be marked as inserted
-this line will be marked as deleted
this is a regular line
</code></pre>
<hr />
<pre><code>--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+this is an actual diff file
-all contents will remain unmodified
 no whitespace will be removed either
</code></pre>
<h4>结合语法高亮与类 diff 语法</h4>
<pre><code>  function thisIsJavaScript() {
    // 整个代码块按 JavaScript 高亮，
    // 同时依然可以为它添加 diff 标记！
-   console.log('Old code to be removed')
+   console.log('New and shiny code!')
  }
</code></pre>
<h4>标记行内的个别文本</h4>
<pre><code>function demo() {
  // 标记行内任意指定的文本
  return 'Multiple matches of the given text are supported';
}
</code></pre>
<h4>正则表达式</h4>
<pre><code>console.log('单词 yes 与 yep 会被标记出来。')
</code></pre>
<h4>转义正斜杠</h4>
<pre><code>echo "Test" &gt; /home/test.txt
</code></pre>
<h4>选择行内标记类型（mark、ins、del）</h4>
<pre><code>function demo() {
  console.log('These are inserted and deleted marker types');
  // return 语句使用默认的标记类型
  return true;
}
</code></pre>
<h3>自动换行</h3>
<p><a href="https://expressive-code.com/key-features/word-wrap/">Word Wrap</a></p>
<h4>为单个代码块配置自动换行</h4>
<pre><code>// 开启自动换行的示例
function getLongString() {
  return 'This is a very long string that will most probably not fit into the available space unless the container is extremely wide'
}
</code></pre>
<hr />
<pre><code>// wrap=false 的示例
function getLongString() {
  return 'This is a very long string that will most probably not fit into the available space unless the container is extremely wide'
}
</code></pre>
<h4>配置折行后的缩进</h4>
<pre><code>// preserveIndent 的示例（默认启用）
function getLongString() {
  return 'This is a very long string that will most probably not fit into the available space unless the container is extremely wide'
}
</code></pre>
<hr />
<pre><code>// preserveIndent=false 的示例
function getLongString() {
  return 'This is a very long string that will most probably not fit into the available space unless the container is extremely wide'
}
</code></pre>
<h2>可折叠区块</h2>
<p><a href="https://expressive-code.com/plugins/collapsible-sections/">Collapsible Sections</a></p>
<pre><code>// 这一整段样板初始化代码都会被折叠
import { someBoilerplateEngine } from '@example/some-boilerplate'
import { evenMoreBoilerplate } from '@example/even-more-boilerplate'

const engine = someBoilerplateEngine(evenMoreBoilerplate())

// 这部分代码默认可见
engine.doSomething(1, 2, 3, calcFn)

function calcFn() {
  // 可以设置多个折叠区块
  const a = 1
  const b = 2
  const c = a + b

  // 这部分保持可见
  console.log(`Calculation result: ${a} + ${b} = ${c}`)
  return c
}

// 从这里到代码块结束的部分会再次折叠
engine.closeConnection()
engine.freeMemory()
engine.shutdown({ reason: 'End of example boilerplate code' })
</code></pre>
<h2>行号</h2>
<p><a href="https://expressive-code.com/plugins/line-numbers/">Line Numbers</a></p>
<h3>为单个代码块显示行号</h3>
<pre><code>// 这个代码块会显示行号
console.log('Greetings from line 2!')
console.log('I am on line 3')
</code></pre>
<hr />
<pre><code>// 该代码块已关闭行号
console.log('Hello?')
console.log('Sorry, do you know what line I am on?')
</code></pre>
<h3>修改起始行号</h3>
<pre><code>console.log('Greetings from line 5!')
console.log('I am on line 6')
</code></pre>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="示例"/>
  </entry>
  <entry>
    <title>Markdown 示例</title>
    <link href="https://www.dafeiyu.site/posts/markdown/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/markdown/</id>
    <published>2023-10-01T00:00:00.000Z</published>
    <updated>2023-10-01T00:00:00.000Z</updated>
    <summary>一篇简单的 Markdown 博客文章示例。</summary>
    <content type="html"><![CDATA[<h1>一级标题</h1>
<p>段落之间用空行分隔。本页演示的是标准 [[Markdown]] 语法，站点渲染管线见 [[Astro]]。</p>
<h1>一级标题</h1>
<p>段落之间用空行分隔。</p>
<p>第二段。<em>斜体</em>、<strong>粗体</strong>与 <code>等宽字体</code>。无序列表长这样：</p>
<ul>
<li>这一项</li>
<li>那一项</li>
<li>另一项</li>
</ul>
<p>注意 --- 这里不涉及星号 --- 实际文本内容是从第 4 列开始的。</p>
<blockquote>
<p>引用块就是
这样写的。</p>
<p>如果需要，它们可以
跨越多个段落。</p>
</blockquote>
<p>用三个连字符表示破折号。用两个连字符表示范围（例如"it's all in chapters 12--14"）。三个点 ... 会被转换成省略号。Unicode 也能正常显示。☺</p>
<h2>二级标题</h2>
<p>这是一个有序列表：</p>
<ol>
<li>第一项</li>
<li>第二项</li>
<li>第三项</li>
</ol>
<p>再注意一次，实际文本是从第 4 列开始的（距左侧 4 个字符）。下面是一个代码示例：</p>
<pre><code># Let me re-iterate ...
for i in 1 .. 10 { do-something(i) }
</code></pre>
<p>正如你所猜到的，这里缩进了 4 个空格。顺便说一句，如果愿意，也可以改用围栏代码块而不必缩进：</p>
<pre><code>define foobar() {
    print "欢迎来到风味之国！";
}
</code></pre>
<p>（这样复制粘贴会更方便。）你还可以为围栏代码块标注语言，让 Pandoc 做语法高亮：</p>
<pre><code>import time
# 快，数到十！
for i in range(10):
    # （但别 *太* 快）
    time.sleep(0.5)
    print i
</code></pre>
<h3>三级标题</h3>
<p>现在来看嵌套列表：</p>
<ol>
<li>
<p>首先，准备这些食材：</p>
<ul>
<li>胡萝卜</li>
<li>芹菜</li>
<li>小扁豆</li>
</ul>
</li>
<li>
<p>烧一些水。</p>
</li>
<li>
<p>把所有东西倒进锅里，然后按下面的算法操作：</p>
<pre><code> find wooden spoon
 uncover pot
 stir
 cover pot
 balance wooden spoon precariously on pot handle
 wait 10 minutes
 goto first step (or shut off burner when done)
</code></pre>
<p>别碰那把木勺，否则它会掉下来。</p>
</li>
</ol>
<p>再注意一次，文本总是在缩进 4 个空格处对齐（包括承接上面第 3 项的最后那一行）。</p>
<p>这里有一个指向<a href="http://foo.bar">某网站的链接</a>，一个指向<a href="local-doc.html">本地文档</a>的链接，还有一个指向<a href="#an-h2-header">当前文档章节标题</a>的链接。这里有一个脚注 <a href="%E8%84%9A%E6%B3%A8%E5%86%85%E5%AE%B9%E5%86%99%E5%9C%A8%E8%BF%99%E9%87%8C%E3%80%82">^1</a>。</p>
<p>表格可以长这样：</p>
<p>size material color</p>
<hr />
<p>9 leather brown
10 hemp canvas natural
11 glass transparent</p>
<p>Table: Shoes, their sizes, and what they're made of</p>
<p>（上面这行是表格的标题。）Pandoc 也支持多行表格：</p>
<hr />
<p>keyword text</p>
<hr />
<p>red Sunsets, apples, and
other red or reddish
things.</p>
<p>green Leaves, grass, frogs
and other things it's
not easy being.</p>
<hr />
<p>接下来是一条水平分割线。</p>
<hr />
<p>这是一个定义列表：</p>
<p>apples
: Good for making applesauce.
oranges
: Citrus!
tomatoes
: There's no "e" in tomatoe.</p>
<p>同样，文本缩进了 4 个空格。（在每个术语与定义之间留一个空行，可以让内容更舒展。）</p>
<p>这是一个"行块"：</p>
<p>| Line one
| Line too
| Line tree</p>
<p>图片可以这样指定：</p>
<p>行内数学公式这样写：$\omega = d\phi / dt$。行间公式应当独占一行，并用双美元符号包裹：</p>
<p>$$I = \int \rho R^{2} dV$$</p>
<p>$$
\begin{equation*}
\pi
=3.1415926535
;8979323846;2643383279;5028841971;6939937510;5820974944
;5923078164;0628620899;8628034825;3421170679;\ldots
\end{equation*}
$$</p>
<p>另外请注意，你可以用反斜杠转义任何你希望原样显示的标点字符，例如 `foo`、*bar* 等。</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="示例"/>
  </entry>
  <entry>
    <title>在文章中嵌入视频</title>
    <link href="https://www.dafeiyu.site/posts/video/" rel="alternate" type="text/html"/>
    <id>https://www.dafeiyu.site/posts/video/</id>
    <published>2023-08-01T00:00:00.000Z</published>
    <updated>2023-08-01T00:00:00.000Z</updated>
    <summary>本文演示如何在博客文章中嵌入视频。</summary>
    <content type="html"><![CDATA[<p>只需从 YouTube 或其他平台复制嵌入代码，粘贴到 Markdown 文件里即可。</p>
<pre><code>---
title: Include Video in the Post
published: 2023-10-19
// ...
---

&lt;iframe width="100%" height="468" src="https://www.youtube.com/embed/5gIf0_xpFPI?si=N1WTorLKL0uwLsU_" title="YouTube video player" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
</code></pre>
<h2>YouTube</h2>
<p>::youtube{id="5gIf0_xpFPI" title="YouTube video" preload="auto"}</p>
<h2>Bilibili</h2>
<p>::bilibili{bvid="BV1fK4y1s7Qf" title="Bilibili video" p=1 preload="auto"}</p>
<h2>AcFun</h2>
<p>::acfun{acid="ac48649632" title="AcFun video" preload="auto"}</p>
<h2>ArtPlayer</h2>
<p>::artplayer{src="https://www.pexels.com/download/video/38538991/" title="Sintel trailer" preload="auto"}</p>
]]></content>
    <author><name>蓝色大肥鱼</name></author>
    <category term="示例"/>
  </entry>
</feed>
