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

hexo-text-pipeline

v0.4.0

Published

A general-purpose hooks bus for Hexo's render pipeline: hang your own scripts/commands on any text stage (text in, text out, edit-and-use), with a checker system as the safety net. Ships an Obsidian Flavored Markdown preset.

Readme

English | 简体中文

hexo-text-pipeline

Hexo 渲染管线的通用 hooks 总线。

Hexo 渲染过程中所有"文本进、文本出"的执行点都被暴露为 stage。你用纯声明式配置往 stage 上挂东西——自己的脚本、shell 命令、或打包好的 preset。checker 系统全程兜底:配置错误在第一篇文章被处理之前就被发现,单个节点失败只会被跳过,构建永远不炸。

设计目标:绝大多数小型 Hexo 插件做的事,本质都是"在管线的某个点变换一段文本"。这不该需要发包、不该需要配置——写插件就是写一个文件。在站点根目录建 text-pipeline/,丢进去:

// text-pipeline/arrow.js —— 这就是一个完整插件
module.exports = {
  replace: [[/-->/g, '→']]
};

下一次 hexo generate 它就在跑了:零配置自动发现,markdown 阶段自动跳过代码块,逻辑改动即改即用,坏了只会被跳过、构建永远不炸。完整契约见 docs/PLUGINS.zh-CN.md

Stage 表

| Stage | 流经的文本 | |-------|-----------| | before_post_render | 单篇文章的 markdown(渲染前) | | after_post_render | 单篇文章的 HTML 片段(渲染后) | | after_render:html | 模板套完后的完整页面 HTML | | after_render:css / after_render:js | 生成的静态资源 |

Hexo filter API 一一对应。非文本的 filter(template_localsserver_middleware 等)刻意不在范围内。

四种挂载方式

1. 单文件插件(默认答案) —— text-pipeline/ 目录里每个 .js 文件自动挂载。导出与统一契约同形的 node 对象(name 缺省取文件名),replace 规则表是 convert 的声明式写法;_config.yml 可按插件名覆盖 enable / slot / priority,其余子配置进 ctx.config。详见 docs/PLUGINS.zh-CN.md

// text-pipeline/ruby.js
module.exports = {
  stage: 'before_post_render',
  match: '\\{ruby',
  convert: (text, ctx) => text.replace(/\{ruby (.+?)\}/g, '<ruby>$1</ruby>')
};

2. 本地脚本(hook) —— module.exports = (text, ctx) => text,相对 Hexo 根目录解析,每次执行重新加载。改完文件,下一次渲染就生效。想要纯函数形态、placement 写在 YAML 里时用它。

hooks:
  - script: scripts/minify.js
    stage: after_render:html

3. 外部命令 —— 正文从 stdin 进,变换结果从 stdout 出,任何语言。上下文走环境变量:HTP_STAGE / HTP_SLOT 恒有,post 类 stage 给 HTP_POST_SOURCE / HTP_POST_PATH / HTP_POST_TITLE,string 类给 HTP_FILE_PATH

hooks:
  - command: python scripts/furigana.py
    stage: before_post_render   # 默认 stage
    name: furigana              # 可选,日志标识
    priority: 20                # 可选,默认 10,小者先跑
    timeout: 10000              # 可选,毫秒
    match: '\\{furigana'        # 可选正则:文本不命中直接跳过(command 可省一次 spawn)
    slot: late                  # 可选:late(默认,看到该 stage 最终文本)| early(原始文本)

4. 程序化注册 —— 其他插件(或站点 scripts/ 目录里的脚本)可以直接注册 node:

hexo.textPipeline.register({
  name: 'exclaim',
  stage: 'before_post_render',
  priority: 5,
  convert: (text, ctx) => text + '!'
});

注册的默认值与校验和 hooks 同一套规则(slot 默认 late,也支持 match 正则预判)。ctx{ hexo, stage, pluginConfig, utils, log },post 类 stage 另有 ctx.post、string 类有 ctx.filectx.utils 自带 replaceOutsideCode / segmentInlineCode,在 markdown 阶段做行内替换时安全跳过代码块。

执行顺序:每个 stage 两个挂点

每个 stage 有两个挂点,注册在 Hexo 自己的 filter 前后:

[5]   early 挂点 —— preset node 默认在这里(它们需要原始文本,
      比如 mermaid 必须在高亮器吃掉围栏代码块之前看到它)
[10]  hexo 内置 filter(代码高亮等)和其他插件
[100] late 挂点 —— 你的 hook 默认在这里(看到该 stage 的最终文本)

hook 加 slot: early 可以抢到所有人之前;preset node 加 slot: late 可以压到最后。同一挂点内按 priority 升序(默认 10),同级按声明顺序。hexo pipeline 会打印最终解析出的精确顺序,永远不用猜。

Checker 系统(兜底)

  1. 注册期静态检查——在任何文章被处理之前:未知配置键(带 did-you-mean 建议)、非法 stage、node 重名、priority 类型错误、脚本文件缺失、不同来源的 node 共享同一 priority 的顺序歧义提示。
  2. 运行期防护——每次执行都过守卫:抛错或返回非字符串的 node 被跳过并告警,原文继续流向下一环;连续失败 3 次的 node 整轮熔断;可疑输出(非空输入被清空、体积膨胀 20 倍)会被标记但放行。
  3. hexo pipeline 诊断命令——打印每个 stage 解析后的 node 顺序(priority + 来源)和全部检查结果,冲突在部署前就能看见。

默认策略是 warn-and-skip:构建永远不会因为一个坏 hook 失败。strict: true(给 CI 用)则把配置错误和节点失败变成构建失败。

开发 hook(调试模式)

两个工具回答"我的 hook 在这个 stage 到底收到什么":

hexo pipeline --dry-run source/_posts/x.md——对单个文件跑 before_post_render 链,逐 node 打印效果(跳过 / 无变化 / 变更行级 diff / 失败),不生成任何东西。

tap(管线抽头)——在真实 hexo generate / hexo s 过程中,把每个 stage 流过的文本落盘成快照:

text_pipeline:
  tap:
    enable: true
    match: my-post        # 强烈建议设置:只抓匹配的文章/页面
    dir: .text-pipeline-tap
.text-pipeline-tap/_posts_my-post.md/after_post_render.late/
├── 00-input.txt              ← 挂在该 stage(late 挂点)的 hook 收到的就是这个
├── 01-hook_my-hook.txt       ← 每个改动了文本的 node 改完后的样子
└── …                         ← 最后一个文件即该挂点的最终输出

每个 stage 的每个挂点一个快照目录(<stage>.early / <stage>.late)。

每轮渲染替换上一轮快照。tap 目录记得加进 .gitignore,正常构建时关掉 enable

内置 preset:obsidian

把 Obsidian Flavored Markdown 编译为 Hexo 友好输出。在 text_pipeline: 键下写 presets: [obsidian] 启用——完整使用指南见 docs/USING-PRESETS.zh-CN.md

| Node | 语法 | 默认 | 行为 | |------|------|------|------| | comment | %%行内%%、跨行 %% … %% | 开 | 渲染前剥离(代码内为字面量) | | embed | ![[图片.png\|300]]![[笔记]] | 开 | 图片 → markdown 图片 / <img width>asset_prefix 配置);可解析的笔记嵌入 → 链接;其他原样保留 | | wikilink | [[目标#锚点\|别名]][[#标题]] | 开 | 重写为文章永久链接(abbrlink 优先,回退 post.path);同页标题 → #锚点;块引用锚点(#^id)降级为文章链接 | | highlight | ==文本== | 开 | <mark>文本</mark> | | blockid | 行尾 ^block-id | 开 | 剥离(Obsidian 阅读视图里同样不可见) | | mdlink | HTML 里残留的 .md 链接 | 开 | 兜底重写为文章永久链接 | | mermaid | ```mermaid 围栏块 | 开 | 换成 <pre class="mermaid"> 绕开语法高亮;按需注入懒加载 CDN 脚本 | | callout | > [!type] 标题 | | <div class="callout callout-type">;主流渲染器/主题已多自带支持,所以默认关 |

text_pipeline:
  presets:
    - name: obsidian
      config:
        domain_prefix: ''                  # wikilink/mdlink/embed 的链接前缀
        callout:
          enable: true                     # 按需打开
          css: ./source/css/callout.css    # 可选:用自己的样式文件整体替换内置样式
        embed: { asset_prefix: /images }   # 嵌入图片路径的前缀
        mermaid: { theme: dark, priority: 15 }   # 任意 node:子配置 + priority 覆盖

安装

npm install hexo-text-pipeline --save

完整配置参考

text_pipeline:
  enable: true       # 总开关
  debug: false       # 详细日志
  strict: false      # 配置错误 / 节点失败让构建失败(CI 用)
  inject_css: true   # node 的默认样式(如 callout);node 子配置 css: <文件|列表> 可换成自己的
  inject_js: true    # node 的前端脚本(如 mermaid 加载器)
  presets: []        # 内置名 | npm 包 | ./本地路径 | { name, config }
  hooks: []          # { script | command, stage, slot, priority, name, timeout, match, enable }
  plugins_dir: text-pipeline   # 单文件插件目录;false 关闭自动发现
  plugins: {}        # 按插件名覆盖:{ <name>: { enable, slot, priority, ...其余进 ctx.config } }
  tap:               # 调试模式:落盘每个 stage 的文本快照(见"开发 hook")
    enable: false
    match: ''
    dir: .text-pipeline-tap

开发

唯一运行时依赖是 hexo-util(Hexo 本体自带,npm 会直接复用站点已有的那份,零额外安装成本)。Node >= 16。

npm test   # node --test

许可证

MIT