<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh_CN">
  <title>蛋壳宇宙</title>
  <subtitle>AlexShen 的技术实践、个人项目与生活记录</subtitle>
  <link href="https://blog.codingshen.top/" rel="alternate" type="text/html"/>
  <link href="https://blog.codingshen.top/atom.xml" rel="self" type="application/atom+xml"/>
  <id>https://blog.codingshen.top/</id>
  <updated>2026-11-01T00:00:00.000Z</updated>
  <entry>
    <title>我是 AlexShen，在蛋壳宇宙记录技术与日常</title>
    <link href="https://blog.codingshen.top/posts/hello-universe/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/posts/hello-universe/</id>
    <published>2026-10-29T00:00:00.000Z</published>
    <updated>2026-10-30T00:00:00.000Z</updated>
    <summary>从解决问题的过程，到亲手搭建的小项目，我想在蛋壳宇宙把这些经历慢慢记下来，也给生活留一点位置。</summary>
    <content type="html"><![CDATA[<p>我是 AlexShen，欢迎来到蛋壳宇宙。这是我的个人博客，主要记录技术实践、个人项目，以及生活里值得留下的片刻。如果你也在折腾工具、搭建自己的小项目，希望这里的文章能给你一点参考。</p>
<p>写博客的起点很简单：有些问题解决了，过一阵却忘了当时怎么想；有些小项目做出来了，过程也跟着散落在各处。我想把这些经历整理下来，下次遇到相似的问题，还能找回当时的思路。</p>
<p>所以，这里会写工具的使用经验，也会写排错的过程。一个办法为什么管用，换个条件还能不能用，都是值得记下来的细节。先把真正做过的事情说清楚，有了新的认识，再回来补充。</p>
<p>个人项目也一样。从一个念头到能用的东西，中间总有一些选择值得回头看。这个博客本身就是一个例子：它基于开源主题 Shirone 搭建，使用 Astro 和 Svelte，主题代码与个人内容分开维护。调整页面和写一篇文章，各有各的位置。后续关于它的改动，也可以成为这里的记录。</p>
<p>技术之外，我还想给日常留一点空间。有些片刻当时觉得值得记住，过后却很容易忘。把它们留在这里，再翻回来时，也能看到屏幕之外的自己。</p>
<p>如果想继续逛逛，可以从<a href="/archive/">文章归档</a>开始，或去<a href="/projects/">项目页</a>看看。我也在 <a href="https://github.com/Alex-Shen1121">GitHub</a> 放代码；想跟进新文章，可以通过 <a href="/rss.xml">RSS</a> 订阅。</p>
<p>我是 AlexShen。很高兴在这里和你认识，后面的故事，留在一篇篇具体的记录里。</p>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="随记"/>
  </entry>
  <entry>
    <title>Shirone 写作与使用指南</title>
    <link href="https://blog.codingshen.top/posts/guide/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/posts/guide/</id>
    <published>2026-08-26T00:00:00.000Z</published>
    <updated>2026-08-26T00:00:00.000Z</updated>
    <summary>全面介绍 Shirone 的文章写作、frontmatter 结构、Markdown 扩展、加密与媒体功能。</summary>
    <content type="html"><![CDATA[<p>欢迎使用 <strong>Shirone</strong>（白音）：这是一款富有表现力、灵感源自动漫的博客主题，基于 <strong>Astro 7</strong>、<strong>Svelte 5</strong> 和 **Material 3 Expressive（M3E）**设计系统构建。</p>
<p>本指南介绍文章创建、frontmatter 规范、目录结构，以及全部内置 Markdown 和 MDX 扩展。</p>
<p>:::tip
Shirone 优先在服务端渲染内容（SSR-first）。站内导航时，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: "探索 Material 3 Expressive 设计"
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: "深入了解 Shirone 中的动态 HCT 色彩科学与流畅过渡。"
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>）、公共资源路径（<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: "私人研究笔记"
published: 2026-08-26
encrypted: true
password: "your-secret-passphrase"
passwordHint: "最喜欢的动漫角色"
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("主色令牌：", 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.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>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>🔒 密码保护与文章加密演示</title>
    <link href="https://blog.codingshen.top/posts/encrypted-demo/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/posts/encrypted-demo/</id>
    <published>2026-08-20T00:00:00.000Z</published>
    <updated>2026-08-20T00:00:00.000Z</updated>
    <summary>该文章内容已加密，请输入密码后查看。</summary>
    <content type="html"><![CDATA[<p><em>🔒 本文已加密保护，请访问博客网站输入密码阅读全文。</em></p>]]></content>
    <author><name>AlexShen</name></author>
    <category term="Examples"/>
  </entry>
  <entry>
    <title>Shirone Markdown 增强功能</title>
    <link href="https://blog.codingshen.top/posts/markdown-enhancements/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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 处理流程，在站点构建时渲染为支持无障碍访问的语义化 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 源码树"}
- src
  - components/
    - ++ Navigation.svelte # 新增组件
    - -- Button.astro # 已移除组件
  - content
    - posts/
      - markdown-enhancements.md
  - layouts/
    - PostLayout.astro
  - plugins
    - markdown/
      - rehype-file-tree.mjs
  - styles
    - markdown/
      - trees.css
  - **content.config.ts** # 重要文件
- public/
  - favicon.svg
- package.json
:::
</code></pre>
<p>:::file-tree{title="Shirone 源码树"}</p>
<ul>
<li>src
<ul>
<li>components/
<ul>
<li>++ Navigation.svelte # 新增组件</li>
<li>-- Button.astro # 已移除组件</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> # 重要文件</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="构建产物" 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 组件演示" height="380px" entry="src/Button.svelte"}
```svelte title="src/Button.svelte"
&lt;script lang="ts"&gt;
  let { label = "点我" } = $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 组件演示" height="380px" entry="src/Button.svelte"}</p>
<pre><code>&lt;script lang="ts"&gt;
  let { label = "点我" } = $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="动漫工具函数" entry="status.ts"](/src/utils/anime)
</code></pre>
<p>@<a href="/src/config">code-tree title="站点配置" entry="siteConfig.ts"</a></p>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>把周末还给一条小路</title>
    <link href="https://blog.codingshen.top/posts/weekend-small-path/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/posts/weekend-small-path/</id>
    <published>2026-11-01T00:00:00.000Z</published>
    <updated>2026-11-01T00:00:00.000Z</updated>
    <summary>在熟悉的路口换一个方向，看看那些被匆忙省略的日常。</summary>
    <content type="html"><![CDATA[<p>周末醒来，先别急着打开收藏夹。找一双好走的鞋，出门以后，在熟悉的路口换一个方向。这半天，你可以只做一件事：看看住了这么久的地方，还有什么没被自己认真看过。</p>
<h2>先把目的地空着</h2>
<p>平时出门，我们总知道要去哪里。买咖啡走哪条路，赶地铁从哪个口进，连午饭都能在电梯里提前点好。路走熟了，沿途也渐渐被省略了。</p>
<p>偶尔可以多拐一个弯。经过一家旧书店，就站在门口翻翻；闻到烤红薯的味道，就停下来买一个。碰上没开门的店也不要紧，门边那盆长歪的绿萝，或许比招牌更有意思。</p>
<p>不必专程寻找漂亮的街道。寻常的街道就够了。</p>
<h2>在小事上耽误一会儿</h2>
<p>试着坐在路边的长椅上，不急着拿手机。看看有人怎样把一大束花塞进车筐，听听楼上的人隔着窗户喊谁回家。风吹过来，树影从鞋尖挪到膝盖。</p>
<p>这些事情写进日程表，大概都显得不太值得。可真坐在那里，又会觉得，再待一会儿也行。</p>
<p>当然，你也可能遇到施工围挡，或者绕了一圈，发现那家面包店早已搬走。那就原路折返。散步用不着每次都有惊喜，走累了，承认自己想回家，也很痛快。</p>
<h2>带一点普通的东西回家</h2>
<p>回去时，可以买一小袋橘子，或者挑一枝叫不出名字的花。没有喜欢的，空手回去也好。</p>
<p>如果有人问今天做了什么，你大概只能说：出去走了走。这句话很短，装不下你在街角闻到的饭香，也装不下那只蹲在电动车坐垫上、怎么叫都不肯回头的猫。</p>
<p>不用补充说明。把鞋放好，给自己倒杯水。等天慢慢暗下来，再想今晚吃什么。</p>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="随记"/>
  </entry>
  <entry>
    <title>Audio Reader：神秘的日语动漫声音</title>
    <link href="https://blog.codingshen.top/posts/audio-reader/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/posts/audio-reader/</id>
    <published>2026-08-29T00:00:00.000Z</published>
    <updated>2026-08-29T00:00:00.000Z</updated>
    <summary>一组神秘的日语动漫声音片段，通过 Audio Reader 按需播放。</summary>
    <content type="html"><![CDATA[<p>这些短短的日语声音片段，仿佛是从某个动漫场景的边缘拾来的：带着调侃的呼唤、明快的问候、轻轻的笑声，还有几句出处不明的台词。它们用来传递氛围，并非对白文字稿，就让声音本身表达含义。</p>
<p>在你选择收听前，Audio Reader 会保持安静。每个扬声器按钮都只在按下后加载并播放对应片段。</p>
<pre><code>:audio-reader[片段标题]{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 URL，指令标签不能为空。无效或不完整的指令会保留为普通 Markdown，不会加载 Audio Reader 资源。</p>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="Examples"/>
  </entry>
  <entry>
    <title>Markdown 折叠面板</title>
    <link href="https://blog.codingshen.top/posts/collapse-panels/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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>expand</code> 时，加上 <code>:-</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</code>，面板正文则支持完整的块级 Markdown。</p>
</li>
<li>
<p>窄屏上会怎样显示？</p>
<p>内容内边距会缩小，长文本会换行，嵌入代码则保留独立的横向滚动区域。
:::</p>
</li>
</ul>
<h2>写作语法</h2>
<pre><code>::: collapse accordion
- :+ 第一个标题

  第一个面板的内容。

- 带有 `code` 的第二个标题

  第二个面板的内容。
:::
</code></pre>
<p>容器必须且只能包含一个顶层无序列表。每一项都需要标题段落、空行和正文。无效或混合格式的输入会保留为可读的普通 Markdown 列表。</p>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>Markdown 缩写释义</title>
    <link href="https://blog.codingshen.top/posts/markdown-abbreviations/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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]: 服务端渲染
*[LCP]: 最大内容绘制
*[CLS]: 累积布局偏移

SSR 能在客户端代码运行前提供 HTML 响应。
</code></pre>
<p>*[SSR]: 服务端渲染
*[LCP]: 最大内容绘制
*[CLS]: 累积布局偏移</p>
<h2>写作限制</h2>
<p>术语必须以字母或数字开头，可以包含字母、数字、句点、下划线、加号和连字符。每条定义仅在当前文章中生效；无效或重复的定义会保留为普通 Markdown，不会悄悄覆盖其他术语。</p>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>Markdown 文件包含</title>
    <link href="https://blog.codingshen.top/posts/markdown-includes/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>Markdown 马克笔高亮</title>
    <link href="https://blog.codingshen.top/posts/marker-highlights/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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>==文本==</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>==主色标记==

==次色标记=={.secondary}
==第三色标记=={.tertiary}
==错误标记=={.error}
==提示标记=={.tip}
</code></pre>
<p><code>==字面标记语法==</code> 这样的行内代码与围栏示例会保持原样，因此文档可以解释语法而不触发高亮。</p>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>Markdown 选项组</title>
    <link href="https://blog.codingshen.top/posts/option-groups/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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> 标识。选择上方选项后，下方会切换到对应命令，并在下次访问时记住这一选择。</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

在此填写 npm 操作说明。

@tab:active **pnpm**#pnpm

在此填写 pnpm 操作说明。

:::
</code></pre>
<p>每组至少需要两个 <code>@tab</code> 区段，每个区段都必须有正文，且正文与标记之间用空行分隔。无效或不完整的分组会保留为可读的普通 Markdown。</p>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>Markdown 剧透遮罩</title>
    <link href="https://blog.codingshen.top/posts/spoilers/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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>行内代码</code>，也可以是:spoiler[带有<strong>强调</strong>的较长说明]。</p>
<h2>写作语法</h2>
<pre><code>答案是:spoiler[42]。
</code></pre>
<p>生成的 HTML 使用带有 <code>aria-expanded</code> 状态的原生按钮。没有 JavaScript 时，悬停和聚焦仍能显示文本；可选的运行时则添加点击与键盘切换支持。</p>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>Markdown 提示块</title>
    <link href="https://blog.codingshen.top/posts/admonitions/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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
使用信息块提供中性的背景信息，帮助读者理解当前章节。
:::</p>
<p>:::tip[现有的<strong>标签</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[现有标题语法]
内容
:::

::: warning 兼容 Plume 的标题语法
内容
:::

&gt; [!TIP]
&gt; GitHub Alert 语法

::: details 可选内容
在读者展开前保持隐藏。
:::
</code></pre>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>内容标注</title>
    <link href="https://blog.codingshen.top/posts/content-annotations/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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 会预先渲染页面的大部分内容，只在**交互孤岛** [+islands] 需要交互时才对其进行水合。

[+islands]:
  孤岛是嵌在静态 HTML 中的交互式 UI 组件。这既让默认页面保持轻量，又保留了局部交互能力。
</code></pre>
<p>Astro 会预先渲染页面的大部分内容，只在<strong>交互孤岛</strong> [+islands] 需要交互时才对其进行水合。</p>
<p>[+islands]:
孤岛是嵌在静态 HTML 中的交互式 UI 组件。这既让默认页面保持轻量，又保留了局部交互能力。</p>
<h2>丰富内容</h2>
<p>标注定义可以包含段落、强调、链接、列表和行内代码 <a href="**%E5%86%99%E4%BD%9C%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%E8%AF%B4%E6%98%8E%E4%BC%9A%E5%BD%B1%E5%93%8D%E8%AF%BB%E8%80%85%E4%B8%8B%E4%B8%80%E6%AD%A5%E8%A1%8C%E5%8A%A8%E7%9A%84%E5%86%B3%E5%AE%9A%E3%80%82">+review</a>，即可通过一个标记展示一组简短的相关说明。</p>
<p><code>[+missing]</code> 这类未定义的引用会保留为普通文本，因此尚未完成的定义不会生成空控件。</p>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>Markdown 步骤流</title>
    <link href="https://blog.codingshen.top/posts/steps/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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>用 <code>:::steps</code> 容器包裹一个 Markdown 有序列表，每个顶层列表项都会成为一个步骤。</p>
<pre><code>:::steps[生产部署]
1. **克隆并准备工作区**

   克隆仓库并进入项目目录。

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

2. **安装依赖**

   使用仓库锁定的包管理器。

   ```powershell
   pnpm.cmd install
   ```

3. **运行项目检查**

   确认 Astro 诊断与 TypeScript 检查通过。

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

4. **构建生产站点**

   生成静态站点和搜索索引。

   ```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[标题]</code> 或 <code>title="标题"</code> 可添加可见标签和无障碍名称。</li>
<li><code>start=4</code> 可修改首个显示的步骤编号。</li>
<li>容器必须且只能包含一个有序列表。无效或混合格式的输入会保留为可读的普通 Markdown，不会被推测性解析。</li>
<li>渲染在站点构建时完成，不会增加客户端 JavaScript 或网络请求。</li>
</ul>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>MDX 集成与 M3E 原子组件</title>
    <link href="https://blog.codingshen.top/posts/mdx-showcase/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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>:::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;采用第 1 级容器高度，并叠加交互状态层，增强视觉焦点。&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> &amp; <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> 多边形形变实现，通过弹簧插值提供平滑的七种形状动画：</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> &amp; <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）为基础的 unified 插件流程，完整兼容所有 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 Expressive 文章视图"]
</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>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>图片画廊网格：语法与完整示例</title>
    <link href="https://blog.codingshen.top/posts/image-grid-demo/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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>直接在 <code>:::grid</code> 与闭合的 <code>:::</code> 之间编写 Markdown 图片：</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>图片的 alt 文本既用作无障碍替代文本，也用作默认图注。如果图片设置了可选标题，则改用标题作为图注：</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>16/9</code> 卡片，分别使用 <code>cover</code> 和 <code>contain</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>AlexShen</name></author>
    <category term="Examples"/>
  </entry>
  <entry>
    <title>Mermaid 图表示例集</title>
    <link href="https://blog.codingshen.top/posts/markdown-mermaid/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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 : 撰写
    POST ||--o{ COMMENT : 接收
    POST ||--o{ POST_TAG : 分类关联
    TAG ||--o{ POST_TAG : 分组
    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 : 使用
    DiagramRenderer --&gt; MermaidPlugin : 增强输出
    DiagramRenderer --&gt; ThemeTokens : 读取
</code></pre>
<h2>状态图</h2>
<p>状态图展示对象的生命周期，以及触发状态切换的事件。</p>
<pre><code>stateDiagram-v2
    accTitle: 文章生命周期
    accDescr: 文章从草稿进入审核，再到发布；也可能退回修改，或最终归档。
    state "草稿" as Draft
    state "审核中" as InReview
    state "已发布" as Published
    state "已归档" as Archived
    [*] --&gt; Draft
    Draft --&gt; InReview : 提交
    InReview --&gt; Draft : 要求修改
    InReview --&gt; Published : 通过
    Published --&gt; Draft : 撤回
    Published --&gt; Archived : 归档
    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: 读者
      选择主题: 5: 读者
    section 理解
      阅读文章: 4: 读者
      查看关系图: 5: 读者
    section 继续
      打开相关文章: 4: 读者
      收藏页面: 3: 读者
</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>
<p>节点释义：Landing（落地页）、Discovery（发现）、Reading（阅读）、Explore（探索）、Topics（主题）、Outbound（外链）。</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>AlexShen</name></author>
    <category term="Examples"/>
  </entry>
  <entry>
    <title>Markdown 扩展功能</title>
    <link href="https://blog.codingshen.top/posts/markdown-extended/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/posts/markdown-extended/</id>
    <published>2024-05-01T00:00:00.000Z</published>
    <updated>2024-11-29T00: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>使用以下代码创建 GitHub 仓库卡片： <code>::github{repo="&lt;owner&gt;/&lt;repo&gt;"}</code>.</p>
<pre><code>::github{repo="saicaca/fuwari"}
</code></pre>
<h2>Mermaid 图表</h2>
<p><code>mermaid</code> 围栏代码块会渲染为图表，并适配当前配色方案。</p>
<pre><code>flowchart LR
    accTitle: Markdown 渲染流程
    accDescr: Markdown 源码被转换为语义化 HTML，再增强为带有主题样式的 SVG 图表。
    A[Markdown 源码] --&gt; B[Astro 内容处理流程]
    B --&gt; C[语义化 HTML]
    C --&gt; D[主题化图表]
</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[我的自定义标题]
这是一条带有自定义标题的提示。
:::</p>
<pre><code>:::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>嘿嘿</strong>]！</p>
<pre><code>这段内容:spoiler[藏起来了，**嘿嘿**]！

</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>AlexShen</name></author>
    <category term="Guides"/>
  </entry>
  <entry>
    <title>Expressive Code 示例</title>
    <link href="https://blog.codingshen.top/posts/expressive-code/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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/">语法高亮</a></p>
<h4>常规语法高亮</h4>
<pre><code>console.log('这段代码带有语法高亮！')
</code></pre>
<h4>渲染 ANSI 转义序列</h4>
<pre><code>ANSI 颜色：
- 常规： [31m红[0m [32m绿[0m [33m黄[0m [34m蓝[0m [35m品红[0m [36m青[0m
- 粗体:    [1;31m红[0m [1;32m绿[0m [1;33m黄[0m [1;34m蓝[0m [1;35m品红[0m [1;36m青[0m
- 暗淡:  [2;31m红[0m [2;32m绿[0m [2;33m黄[0m [2;34m蓝[0m [2;35m品红[0m [2;36m青[0m

256 色（展示颜色 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

完整 RGB 颜色：
[38;2;34;139;34m森林绿 - RGB(34, 139, 34)[0m

文本格式： [1m粗体[0m [2m暗淡[0m [3m斜体[0m [4m下划线[0m
</code></pre>
<h3>编辑器与终端边框</h3>
<p><a href="https://expressive-code.com/key-features/frames/">编辑器与终端边框</a></p>
<h4>代码编辑器边框</h4>
<pre><code>console.log('标题属性示例')
</code></pre>
<hr />
<pre><code>&lt;!-- src/content/index.html --&gt;
&lt;div&gt;文件名注释示例&lt;/div&gt;
</code></pre>
<h4>终端边框</h4>
<pre><code>echo "这个终端边框没有标题"
</code></pre>
<hr />
<pre><code>Write-Output "这个有标题！"
</code></pre>
<h4>覆盖边框类型</h4>
<pre><code>echo "看，没有边框！"
</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/">文本与行标记</a></p>
<h4>标记整行与行范围</h4>
<pre><code>// 第 1 行——按行号标记
// 第 2 行
// 第 3 行
// 第 4 行——按行号标记
// 第 5 行
// 第 6 行
// 第 7 行——按范围 "7-8" 标记
// 第 8 行——按范围 "7-8" 标记
</code></pre>
<h4>选择行标记类型（mark、ins、del）</h4>
<pre><code>function demo() {
  console.log('这一行标记为删除')
  // 这一行和下一行标记为新增
  console.log('这是第二行新增内容')

  return '这一行使用中性的默认标记类型'
}
</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>+这一行将标记为新增
-这一行将标记为删除
这是普通行
</code></pre>
<hr />
<pre><code>--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+这是一个真实的 diff 文件
-所有内容都会保持原样
 空白字符也不会被移除
</code></pre>
<h4>结合语法高亮与类 diff 语法</h4>
<pre><code>  function thisIsJavaScript() {
    // 整个代码块都按 JavaScript 进行高亮，
    // 而且仍可添加 diff 标记！
-   console.log('待移除的旧代码')
+   console.log('崭新的代码！')
  }
</code></pre>
<h4>标记行内的指定文本</h4>
<pre><code>function demo() {
  // 标记行内的任意指定文本
  return '支持多次匹配指定文本';
}
</code></pre>
<h4>正则表达式</h4>
<pre><code>console.log('单词 yes 和 yep 将被标记。')
</code></pre>
<h4>转义正斜杠</h4>
<pre><code>echo "测试" &gt; /home/test.txt
</code></pre>
<h4>选择行内标记类型（mark、ins、del）</h4>
<pre><code>function demo() {
  console.log('这里展示 inserted 和 deleted 标记类型');
  // return 语句使用默认标记类型
  return true;
}
</code></pre>
<h3>自动换行</h3>
<p><a href="https://expressive-code.com/key-features/word-wrap/">自动换行</a></p>
<h4>按代码块配置自动换行</h4>
<pre><code>// 使用 wrap 的示例
function getLongString() {
  return '这是一个非常长的字符串，除非容器特别宽，否则它很可能无法完整放入可用的显示空间'
}
</code></pre>
<hr />
<pre><code>// 使用 wrap=false 的示例
function getLongString() {
  return '这是一个非常长的字符串，除非容器特别宽，否则它很可能无法完整放入可用的显示空间'
}
</code></pre>
<h4>配置换行后的缩进</h4>
<pre><code>// 使用 preserveIndent 的示例（默认启用）
function getLongString() {
  return '这是一个非常长的字符串，除非容器特别宽，否则它很可能无法完整放入可用的显示空间'
}
</code></pre>
<hr />
<pre><code>// 使用 preserveIndent=false 的示例
function getLongString() {
  return '这是一个非常长的字符串，除非容器特别宽，否则它很可能无法完整放入可用的显示空间'
}
</code></pre>
<h2>可折叠代码段</h2>
<p><a href="https://expressive-code.com/plugins/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(`计算结果： ${a} + ${b} = ${c}`)
  return c
}

// 从这里到代码块结尾的所有代码都会再次折叠
engine.closeConnection()
engine.freeMemory()
engine.shutdown({ reason: '示例样板代码结束' })
</code></pre>
<h2>行号</h2>
<p><a href="https://expressive-code.com/plugins/line-numbers/">行号</a></p>
<h3>按代码块显示行号</h3>
<pre><code>// 这个代码块会显示行号
console.log('来自第 2 行的问候！')
console.log('我在第 3 行')
</code></pre>
<hr />
<pre><code>// 这个代码块不显示行号
console.log('你好？')
console.log('打扰一下，你知道我在第几行吗？')
</code></pre>
<h3>修改起始行号</h3>
<pre><code>console.log('来自第 5 行的问候！')
console.log('我在第 6 行')
</code></pre>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="Examples"/>
  </entry>
  <entry>
    <title>Markdown 示例</title>
    <link href="https://blog.codingshen.top/posts/markdown/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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>段落之间用空行分隔。</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>用 3 个连字符表示长破折号，用 2 个连字符表示范围（例如“内容都在
第 12--14 章”）。三个点 ... 会转换为省略号。
也支持 Unicode。☺</p>
<h2>二级标题</h2>
<p>这是一个有序列表：</p>
<ol>
<li>第一项</li>
<li>第二项</li>
<li>第三项</li>
</ol>
<p>再次留意，实际文本从缩进 4 列的位置开始（距离左边
4 个字符）。下面是代码示例：</p>
<pre><code># 再循环一次……
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> 找到木勺
 揭开锅盖
 搅拌
 盖上锅盖
 把木勺摇摇欲坠地搭在锅柄上
 等待 10 分钟
 回到第一步（煮好后则关火）
</code></pre>
<p>不要碰到木勺，否则它会掉下来。</p>
</li>
</ol>
<p>再次注意，文本始终按 4 个空格的缩进对齐（包括
上面接续第 3 项的最后一行）。</p>
<p>这里有指向<a href="http://foo.bar">某个网站</a>、<a href="../guide/">本地
文档</a>和<a href="#%E4%BA%8C%E7%BA%A7%E6%A0%87%E9%A2%98">当前文档中某个
章节标题</a>的链接。这里还有一个脚注 <a href="%E8%BF%99%E9%87%8C%E5%A1%AB%E5%86%99%E8%84%9A%E6%B3%A8%E5%86%85%E5%AE%B9%E3%80%82">^1</a>。</p>
<p>表格可以写成这样：</p>
<p>尺码 材质 颜色</p>
<hr />
<p>9 皮革 棕色
10 麻帆布 原色
11 玻璃 透明</p>
<p>表：鞋子、尺码及其制作材料</p>
<p>（上面是表格说明。）Pandoc 还支持
多行表格：</p>
<hr />
<p>关键词 文本</p>
<hr />
<p>红色 落日、苹果，
以及其他红色或偏红色的
事物。</p>
<p>绿色 树叶、青草、青蛙，
以及其他当起来
不容易的事物。</p>
<hr />
<p>下面是一条水平分隔线。</p>
<hr />
<p>这是一个定义列表：</p>
<p>苹果
: 适合制作苹果酱。
橙子
: 柑橘类水果！
番茄
: tomatoe 中不该有那个 "e"。</p>
<p>同样，文本缩进 4 个空格。（在每组术语与定义之间
插入空行，可使间距更宽松。）</p>
<p>这是一个“行块”：</p>
<p>| 第一行
| 第二行
| 第三行</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>AlexShen</name></author>
    <category term="Examples"/>
  </entry>
  <entry>
    <title>在文章中嵌入视频</title>
    <link href="https://blog.codingshen.top/posts/video/" rel="alternate" type="text/html"/>
    <id>https://blog.codingshen.top/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: 在文章中嵌入视频
published: 2023-10-19
// ...
---

&lt;iframe width="100%" height="468" src="https://www.youtube.com/embed/5gIf0_xpFPI?si=N1WTorLKL0uwLsU_" title="YouTube 视频播放器" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
</code></pre>
<h2>YouTube</h2>
<p>::youtube{id="5gIf0_xpFPI" title="YouTube 视频" preload="auto"}</p>
<h2>Bilibili</h2>
<p>::bilibili{bvid="BV1fK4y1s7Qf" title="哔哩哔哩视频" p=1 preload="auto"}</p>
<h2>AcFun</h2>
<p>::acfun{acid="ac48649632" title="AcFun 视频" preload="auto"}</p>
<h2>ArtPlayer</h2>
<p>::artplayer{src="https://www.pexels.com/download/video/38538991/" title="Sintel 预告片" preload="auto"}</p>
]]></content>
    <author><name>AlexShen</name></author>
    <category term="Examples"/>
  </entry>
</feed>
