---
name: devtool-svg-datauri
description: SVG 与 data URI 的双向转换。Use when 用户要把 SVG 转成 data URI（内联到 CSS/HTML/JS）、把 data URI 还原成 SVG 源码、或提到 svg、data uri、data:image/svg+xml、url 编码、percent-encoding、内联 SVG、base64 等词。
---

# SVG ↔ data URI 双向转换

两件事都做：把 SVG 源码编码成 `data:image/svg+xml,<percent-encoded>`（**编码**），把 data URI 还原成 SVG 源码（**解码**）。无论哪种，输出都必须经过真实运行验证。

## 铁律（不可违反）

1. **任何转换输出前必须实际运行验证**。禁止给未验证的编码/解码结果。
2. **编码必须可逆**：编码后 `decodeURIComponent` 回验必须与原文逐字节一致。解码同理，还原结果必须可人工核对的等价 SVG。
3. **编码方式固定为 percent-encoding（URL 编码）**，默认不产出 base64。base64 仅在用户明确要求时提供，并说明其取舍（见「何时用 base64」）。
4. **验证用真实引擎**：`node -e`。不靠脑补。

## 编码规则（RFC 3986 + data URI 惯例）

编码 = `encodeURIComponent(svg)`，其保留集（不转义）为：

```
A-Z a-z 0-9 - _ . ! ~ * ' ( )
```

其余全部按 UTF-8 字节转成 `%XX`。这与 `decodeURIComponent` 严格互逆。

### 关键字符行为（必查）

| 字符 | 编码后 | 说明 |
|------|--------|------|
| `#` | `%23` | 必须转义，否则被当 URL fragment 截断 |
| 空格 | `%20` | 必须转义 |
| `"` | `%22` | 必须转义，避免与包裹引号冲突 |
| `<` `>` | `%3C` `%3E` | 必须转义，避免 HTML 解析歧义 |
| `%` | `%25` | 本身需转义 |
| `'` | `'`（不转义） | `encodeURIComponent` 保留；在 HTML 属性里若用单引号包裹会冲突，改用双引号包裹或手动 `%27` |
| `(` `)` | 不转义 | CSS `url()` 中安全，一般无需处理 |
| `/` `?` `&` `=` | `%2F` `%3F` `%26` `%3D` | 都转义，避免歧义 |

## 模式一 · 编码（SVG → data URI）

1. **澄清**（缺什么问什么）：
   - SVG 来源：贴文本 / 给文件路径 / 描述要生成的 SVG
   - 用途场景：CSS `url()` / HTML `<img src>` / HTML 内联 / JS 字符串 —— 决定包裹引号建议
2. **实跑编码**：
   ```bash
   node -e 'const s=require("fs").readFileSync("x.svg","utf8");const u="data:image/svg+xml,"+encodeURIComponent(s);const d=decodeURIComponent(u.slice("data:image/svg+xml,".length));console.log("REVERSIBLE:",d===s);console.log(u);'
   ```
3. **回验**：`decodeURIComponent` 还原结果与原文 `===` 严格相等，才可输出。
4. **输出**：
   - data URI（单行）
   - 原文长度 vs 编码后长度（体积对比）
   - 回验结果（REVERSIBLE: true）
   - 场景化注意事项：CSS 里建议 `url("data:...")` 双引号包裹；HTML 属性同理

## 模式二 · 解码（data URI → SVG）

1. **识别前缀**：`data:image/svg+xml,`（percent-encoded）或 `data:image/svg+xml;base64,`。
   - 遇到 base64：默认提示「这是 base64 形式，用 `Buffer.from(s, "base64")` 还原」，并按用户要求处理。
2. **实跑解码**（percent-encoded 形式）：
   ```bash
   node -e 'const u=process.argv[1];const d=decodeURIComponent(u.slice("data:image/svg+xml,".length));console.log(d);' "<data-uri>"
   ```
3. **输出**：还原后的 SVG 源码，并标注是否含 XML 声明、命名空间、DOCTYPE 等（这些会极大影响能否直接内联）。

## 测试执行规范

- 优先用最短 `node -e` 命令实跑。
- 编码正例建议覆盖：含中文/emoji、多行、单引号、双引号、`#` 颜色值（如 `fill="#fff"`）、XML 声明。反例：非法 UTF-8 或空串。
- 解码正例覆盖：标准 percent-encoded、含 `%23`、含 `%22` 的 data URI。
- 回验必须 `true`，才允许把结果交付用户。

## 何时用 base64（说明，不默认）

- 优点：无转义困扰，任何字符都安全，兼容性最广。
- 缺点：体积约大 33%，完全不可读。
- 建议：默认 percent-encoding（可读、体积小、便于 diff）；当 SVG 里包含大量需要转义的字符、或要嵌入对编码要求严苛的旧系统时，用 base64。

## 输出格式约定

- data URI 用行内代码包裹，如 `data:image/svg+xml,%3Csvg%20...%3E`。
- 编码结果同时给出「原文首尾片段 → 编码后首尾片段」对照，便于核对。
- 注意事项用列表呈现，不用大段散文。
