npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

koishi-plugin-quote-debug-msg-json-image

v0.2.0-beta.8

Published

📋把一条消息的数据结构用json/yaml/toml的格式渲染成图片,🎨支持typst或者markdown。还支持用puppeteer渲染onebot的合并转发成图片🖼️

Downloads

117

Readme

koishi-plugin-quote-debug-msg-json-image

📋 koishi-plugin-quote-debug-msg-json-image

npm npm-download GitHub Gitee

回复一条消息,将其渲染为精美的 JSON/YAML/TOML 格式图片(防止超出聊天平台的文字长度上限)。还支持渲染 OneBot 的合并转发消息为图片。

✨ 功能特性

  • 📋 dump 指令:将消息对象序列化为 JSON/YAML/TOML 格式,渲染成图片
  • 📨 render-forward 指令:将合并转发消息渲染成精美的图片
  • 🎨 双渲染引擎:支持 Typst(推荐)和 Markdown 两种渲染模式
  • 🌈 代码语法高亮:JSON/YAML/TOML 自动语法着色
  • 🧵 嵌套转发支持:智能处理多层嵌套的合并转发消息

📦 依赖服务

required:
  - markdownToImage   # koishi-plugin-markdown-to-image-service
  - toImageService    # koishi-plugin-to-image-service
  - node              # koishi-plugin-w-node
  - puppeteer         # koishi-plugin-puppeteer

可选依赖(推荐安装以获得最佳 Typst 渲染效果):

  • @myriaddreamin/typst-ts-node-compiler >= 0.7.0-rc2

📋 package.json 依赖详解

以下是本插件的依赖配置及其用途说明:

{
  // === peerDependencies: 宿主环境必须提供的依赖 ===
  // 这些依赖由 Koishi 主程序或其他插件提供,插件不会自己安装
  "peerDependencies": {
    // Typst 编译器 - 将 Typst 源码编译为 SVG/PDF
    // 用于 dump 指令的 Typst 渲染模式,实现精美排版和代码语法高亮
    "@myriaddreamin/typst-ts-node-compiler": ">=0.7.0-rc2",

    // Koishi 核心框架 - 插件运行的基础环境
    "koishi": "^4.18.7",

    // 图片服务 - 提供 SVG → PNG 转换(resvg)和字体管理
    // Typst 编译输出 SVG,需要此服务转换为最终的 PNG 图片
    "koishi-plugin-to-image-service": ">=0.1.0",

    // Node.js 模块加载器 - 动态加载 npm 包
    // 用于运行时安全加载 @myriaddreamin/typst-ts-node-compiler
    "koishi-plugin-w-node": ">=1.0.0"
  },

  // === peerDependenciesMeta: peerDependencies 的元数据 ===
  "peerDependenciesMeta": {
    // Typst 编译器标记为可选
    // 如果用户只使用 Markdown 渲染模式,可以不安装此依赖
    "@myriaddreamin/typst-ts-node-compiler": {
      "optional": true
    }
  },

  // === dependencies: 插件自带的运行时依赖 ===
  // 这些依赖会随插件一起安装到 node_modules
  "dependencies": {
    // TOML 解析器 - 将消息对象序列化为 TOML 格式
    // 支持 dump-toml 指令输出 TOML 格式的消息数据
    "@iarna/toml": "^2.2.5",

    // YAML 解析/序列化库 - 将消息对象序列化为 YAML 格式
    // 支持 dump-yaml 指令输出 YAML 格式的消息数据
    "js-yaml": "^4.1.1",

    // Markdown 转图片服务 - 将 Markdown 渲染为图片
    // 作为 Typst 渲染的备选方案,适合简单快速的场景
    "koishi-plugin-markdown-to-image-service": "^1.3.6"
  },

  // === devDependencies: 仅开发时需要的依赖 ===
  // 发布后不会包含在 npm 包中
  "devDependencies": {
    // Typst 编译器(开发版本)- 用于本地开发测试
    "@myriaddreamin/typst-ts-node-compiler": "^0.7.0-rc2",

    // js-yaml 的 TypeScript 类型定义
    // 提供 IDE 智能提示和类型检查
    "@types/js-yaml": "^4.0.9",

    // 以下两个服务的开发版本,用于本地测试
    "koishi-plugin-to-image-service": "^0.1.5",
    "koishi-plugin-w-node": "^1.0.1"
  }
}

依赖关系图

┌─────────────────────────────────────────────────────────┐
│                    dump 指令渲染流程                      │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  消息对象 ──┬──▶ JSON (内置)                              │
│            ├──▶ YAML (js-yaml)                          │
│            └──▶ TOML (@iarna/toml)                      │
│                       │                                 │
│                       ▼                                 │
│         ┌─────────────┴─────────────┐                   │
│         │                           │                   │
│    [Typst 模式]              [Markdown 模式]            │
│         │                           │                   │
│  typst-ts-node-compiler    markdown-to-image-service   │
│  (via w-node 动态加载)              │                   │
│         │                           │                   │
│         ▼                           │                   │
│    SVG 输出                         │                   │
│         │                           │                   │
│  to-image-service                   │                   │
│  (resvg: SVG → PNG)                 │                   │
│         │                           │                   │
│         └───────────┬───────────────┘                   │
│                     ▼                                   │
│                 PNG 图片                                 │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│               render-forward 指令渲染流程                 │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  合并转发消息 ──▶ HTML 生成 ──▶ Puppeteer 截图 ──▶ PNG   │
│                                                         │
└─────────────────────────────────────────────────────────┘

🚀 使用方法

dump 指令

回复一条消息并发送指令:

dump-json          # 渲染为 JSON 格式图片
dump-yaml          # 渲染为 YAML 格式图片  
dump-toml          # 渲染为 TOML 格式图片

可用选项

  • -m, --mode <typst|markdown> - 选择渲染引擎
  • -r, --reply <forward|image> - 回复模式(合并转发/仅图片)
  • -s, --self - 解析当前消息而非被引用的消息

效果预览

dump-json 效果预览

render-forward 指令

回复一条合并转发消息并发送:

render-forward     # 渲染合并转发为图片

可用选项

  • -i, --index <0|1> - 样式选择(0=Source Han Serif 毛玻璃风格, 1=LXGW WenKai 简约风格)

效果预览

| Source Han Serif 风格 (index=0) | LXGW WenKai 风格 (index=1) | |:---:|:---:| | Source 风格预览 | LXGW 风格预览 |


🔧 技术实现细节

🎨 代码语法高亮

Typst 渲染引擎

Typst 内置了对多种编程语言的语法高亮支持。本插件使用 Fenced Code Block 语法来触发高亮:

` ` `json
{"key": "value", "count": 42}
` ` `

⚠️ 技术要点:Typst 的 #raw(variable, lang: "json") 函数对变量内容不会触发语法高亮,只有直接写在源码中的 Fenced Code Block 才会启用高亮。因此本插件将数据直接嵌入 Typst 源码中。

resvg 兼容性修复

Typst 生成的 SVG 使用了 CSS 变量来设置字形颜色:

.outline_glyph path { fill: var(--glyph_fill); }

然而 resvg 不支持 CSS 变量,这会导致所有文字变成默认颜色。本插件通过 fixSvgForResvg() 函数在 SVG 转 PNG 之前移除这些 CSS 变量规则,让颜色从父元素的 fill 属性正确继承:

private fixSvgForResvg(svg: string): string {
  // 移除 CSS 变量规则,让颜色从父元素 <g fill="#color"> 继承
  return svg.replace(
    /\.outline_glyph[^}]*fill:\s*var\(--glyph_fill\)[^}]*}/g,
    ''
  )
}

Markdown 渲染引擎

Markdown 渲染使用 koishi-plugin-markdown-to-image-service,通过标准的 Markdown Fenced Code Block 实现语法高亮:

```json
{"key": "value"}
```

📨 合并转发渲染的排版设计

Puppeteer 页面截图

合并转发渲染使用 Puppeteer 将 HTML 页面渲染为图片。关键的排版技巧:

1. 自适应高度

使用 height: auto 的卡片容器,让内容自然撑开高度:

.card {
  width: 920px;
  height: auto; /* 内容自适应 */
  border-radius: 32px;
}

2. 双风格系统

  • Source Han Serif 风格:毛玻璃效果,使用 backdrop-filter: blur() 实现
  • LXGW WenKai 风格:简约扁平设计,清晰易读
/* 毛玻璃效果 */
.card {
  background: rgba(255,255,255,.13);
  backdrop-filter: blur(13px) saturate(130%);
  box-shadow: 0 16px 48px rgba(0,0,0,.3);
}

3. 头像与布局

每条消息使用 Flex 布局,头像固定尺寸,内容区自适应:

.message-item {
  display: flex;
  gap: 14px;
}
.message-avatar {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  flex-shrink: 0; /* 不压缩 */
}
.message-main {
  flex: 1;
  min-width: 0; /* 防止内容溢出 */
}

🧵 嵌套合并转发的处理

OneBot 的合并转发消息可能包含多层嵌套。本插件通过递归渲染深度限制来优雅处理:

递归解析架构

function parseMessageElement(
  element: MessageElement,
  currentDepth: number,  // 当前嵌套深度
  maxDepth: number       // 最大允许深度(可配置,默认 3)
): string {
  if (element.type === 'forward') {
    // 达到最大深度时折叠显示
    if (currentDepth >= maxDepth) {
      return `<span class="collapsed">[合并转发: ${count}条消息,已达最大嵌套深度]</span>`
    }
    // 递归渲染嵌套内容
    return generateNestedForwardHtml(element.data.content, currentDepth + 1, maxDepth)
  }
  // ... 其他消息类型处理
}

视觉层级区分

嵌套的合并转发使用不同的视觉样式来区分层级:

.nested-forward {
  margin: 12px 0;
  border-radius: 12px;
  border: 1px solid rgba(255,255,255,.6);
  background: rgba(255,255,255,.2);
}

.nested-forward[data-depth="2"] {
  /* 更深层级可以有不同样式 */
}

深度标识

每个嵌套层级都会显示深度信息,帮助用户理解消息结构:

📨 嵌套合并转发 (5条消息, 深度:2)

⚙️ 配置项

🔤 字体配置

本插件需要配置字体路径才能正常渲染。你可以:

  1. 下载预置字体:前往 Gitee Releases - fonts 下载字体文件
  2. 使用自己喜欢的字体:支持 .ttf.otf 格式

下载后将字体文件放到服务器上,然后在配置中填入绝对路径即可。

需要配置的字体路径(共 3 个)

| 配置项 | 用途 | 推荐字体 | |--------|------|----------| | dumpTypstFontPath | dump 指令 (Typst 渲染) | LXGW WenKai Mono | | renderForwardSourceFontPath | render-forward Source 风格 | Source Han Serif SC | | renderForwardLxgwFontPath | render-forward LXGW 风格 | LXGW WenKai Mono |

dump 指令配置

| 配置项 | 类型 | 默认值 | 说明 | |--------|------|--------|------| | dumpRenderMode | 'typst' \| 'markdown' | 'typst' | 默认渲染引擎 | | dumpMessageMode | 'forward' \| 'image' | 'forward' | 回复模式 | | dumpTypstRenderScale | number | 2.33 | Typst 渲染缩放倍率 | | dumpTypstPageBgColor | string | '#f9efe2' | 页面背景色 | | dumpTypstCodeBlockFillColor | string | '#ffffff' | 代码块背景色 |

render-forward 配置

| 配置项 | 类型 | 默认值 | 说明 | |--------|------|--------|------| | maxForwardNestDepth | number | 3 | 最大嵌套深度 | | renderForwardDefaultStyle | 'source' \| 'lxgw' | 'source' | 默认渲染风格 | | renderForwardSourceFontPath | string | - | Source 风格字体路径 | | renderForwardLxgwFontPath | string | - | LXGW 风格字体路径 | | renderForwardMaxImageSize | number | 50 | 图片最大尺寸 (px) |