
# shikiphp

shikiphp 是 [Shiki](https://shiki.style) 的纯 PHP 移植版；它是一款语法高亮器，使用与 VS Code 相同的 TextMate 语法和主题为代码着色。它使用相同的 **TextMate 语法**进行代码分词，并用 Shiki 使用的相同 **VS Code 主题**着色，生成与 Shiki 3.23.0 相同的 HTML——完全使用 PHP 实现。

无需 Node 运行时。除 `json` 和 `mbstring` 外，无需 PHP 扩展。无需原生 Oniguruma 绑定。无需调用 JavaScript 进程，也无需托管的 API。

```php
use Shikiphp\Shikiphp;

echo Shikiphp::codeToHtml(<<<'PHP'
<?php
function greet(string $name): string {
    return "Hello, {$name}!";
}
PHP, [
    'lang'  => 'php',
    'theme' => 'github-dark',
]);
```

## 为什么选择 shikiphp

在服务器端渲染 PHP 语法高亮通常意味着要在三种妥协中选择一种：调用 Node、请求托管的 API，或使用无法真正理解语言的正则表达式高亮器。这些方案都难以顺畅集成到 Laravel、WordPress 或静态站点构建流程中。

shikiphp 将 Shiki 的真实处理流程移植到 PHP，从而消除了这种妥协：

- TextMate 语法分词器（忠实移植自 [`vscode-textmate`](https://github.com/microsoft/vscode-textmate)），支持嵌入语言、注入和嵌套仓库
- VS Code 主题解析，支持作用域选择器优先级和父作用域匹配
- 兼容 Shiki 的 HTML：通过 CSS 变量实现亮色/暗色双主题，并支持 `codeToHast`、转换器（所有钩子）、装饰、`colorReplacements`、`structure: 'inline'` 和 ANSI（`lang: 'ansi'`）高亮
- **完整的 Shiki 捆绑内容**——包含所有 `tm-grammars` 语言（235，以及它们嵌入的 18 个辅助语法）和全部 `tm-themes` 主题（65 个）

## 与 Shiki 3.23.0 对照匹配

输出不是“足够接近”，而是经过固定版本 Shiki 的对照检查。

| 软件包 | 版本 | 用途 |
| --- | --- | --- |
| `shiki` | 3.23.0 | 基准工具，使用其 JavaScript 正则表达式引擎运行 |
| `tm-grammars` | 1.31.15 | 捆绑的语法 |
| `tm-themes` | 1.12.2 | 捆绑的主题 |
| `@shikijs/transformers` | 4.2.0 | 转换器一致性测试 |

Shiki 本身就是基准工具。回归测试框架包含 **214 个场景**，每个场景都是在一种语言和一种主题下使用默认选项进行的单个示例。每个场景都分别由 Shiki 和 shikiphp 高亮，去除首尾空白后，两者的 HTML 字符串必须完全一致。这些场景合计覆盖 253 个捆绑语法中的 167 个、`lang: 'ansi'` 以及全部 65 个主题。选项（`structure`、`tabindex`、`colorReplacements`、双主题、`defaultColor` 等）、`codeToTokensWithThemes` 和内置转换器则由单独的一致性测试覆盖；这些测试的预期输出取自相同版本的 Shiki。

这带来两项限制。Shiki 的默认引擎是编译为 WebAssembly 的 Oniguruma，而基准工具使用的是 Shiki 的 JavaScript 正则表达式引擎，该引擎也是 shikiphp 移植的对象。此外，后续的 Shiki 版本（4.x 系列）尚未经过检查。

## 工作原理

shikiphp 基于从 [`inline0/phasis`](https://github.com/inline0/phasis) 引入的纯 PHP **JavaScript 正则表达式引擎**，并使用 [`oniguruma-to-es`](https://github.com/slevithan/oniguruma-to-es) 的 PHP 移植版提供支持。Shiki 的 JavaScript 正则表达式引擎会将 TextMate 语法中的 Oniguruma 模式转换为 JavaScript `RegExp`，因此纯 JS 正则表达式引擎是理想的基础——它让 shikiphp 能够逐个偏移量地匹配该引擎的输出。

```
code → grammar tokenizer → theme resolver → themed tokens → HTML
              │
              └─ OnigScanner → PatternConverter (oniguruma-to-es) → Shikiphp\Regex (JS RegExp engine)
```

完整处理流程请参见 [架构](https://shikiphp.inline0.dev/zh/docs/architecture)。

## 要求

- PHP 8.2 或更高版本（CI 在 PHP 8.4 上运行测试套件）
- `ext-json` 和 `ext-mbstring`（几乎每个 PHP 构建都附带这两项）

## 接下来

- [入门](https://shikiphp.inline0.dev/zh/docs/getting-started) — 安装并渲染你的第一个代码块。
- [API](https://shikiphp.inline0.dev/zh/docs/api) — 完整的方法接口。
- [选项](https://shikiphp.inline0.dev/zh/docs/options) — `codeToHtml` 接受的所有选项。
- [转换器](https://shikiphp.inline0.dev/zh/docs/transformers) — 钩子流程和内置转换器。
- [CLI](https://shikiphp.inline0.dev/zh/docs/cli) — `bin/shikiphp highlight`、`langs` 和 `themes`。

## 许可证

MIT，版权所有者为 inline0。捆绑的 TextMate 语法和主题保留其上游许可证。
