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

dsh-template-render

v0.1.0

Published

Template rendering for DeepSeek Harness: render `{{ var }}` placeholders with filters, `{% if %}` branches and `{% each %}` loops into text; validate templates for syntax and undefined variables; extract required data fields. Zero runtime dependencies, re

Readme

dsh-template-render

DeepSeek Harness 的模板渲染工具箱:render_template 用数据把 {{ var }}、{% if %}、{% each %} 渲染成文本,validate_template 在发布前静态检查语法与未定义变量,extract_vars 列出模板需要哪些数据字段。只读、零运行时依赖,不 eval、不执行代码。

  • 源码:https://github.com/geeklei/dsh-plugins/tree/main/dsh-template-render
  • npm:https://www.npmjs.com/package/dsh-template-render

功能说明

很多文本是「骨架 + 变量」:发一封邮件、生成一段配置、拼一条上报,正文基本固定,只有姓名、数值、状态在变。手写字符串拼接容易错、难维护,正则替换又处理不了「有就列出来、没有就换句话」的分支。

本插件用一套极小的模板语法把「文本」和「数据」分开:

  • 变量占位 {{ name }}:用数据里的值替换,支持点路径({{ a.b.c }})、数组下标({{ items.1 }}),还能套过滤器({{ n | round:1 }})。
  • 条件分支 {% if 条件 %} … {% else %} … {% endif %}:条件可以是任意变量(真/假),也支持 ==、!=、>、>=、<、<= 比较。
  • 循环 {% each 列表 as 项 %} … {% empty %} … {% endeach %}:按列表逐项重复,空列表走 empty 分支;循环内可用 {{ item }}、{{ item.字段 }} 和 {{ for.index }} / {{ for.first }} / {{ for.last }}。
  • 注释 {# 说明 #}:渲染时直接移除,适合在模板里留说明。
  • 转义 \{{:想输出字面 {{ 时用反斜杠转义。
  • 过滤器:upper、lower、trim、length、json、number、round:n、default:x、join:分隔、first、last。

解析器是自写分词 + 递归渲染,不做 eval,不加载模块,模板里的内容只是字符串和数据,不会被执行。

安装

npm install dsh-template-render

安装后在 cordis.patch.yml 中加入:

- insert:
    - id: template-render
      name: "dsh-template-render"

使用说明

render_template

把模板和一份数据渲染成文本。模板用 text 传正文或 path 传文件,数据用 data 传 JSON 字符串或 data_path 传 JSON 文件(缺省为空对象 {})。strict=true 时遇到未定义变量会报错,否则渲染为空串。

参数:text / path(模板,二选一,text 优先);data / data_path(数据,二选一,data 优先);strict(默认 false);max_chars / max_size。

模板来源:(内联模板);数据来源:(内联数据)
--- 渲染结果(4 行)---
报告:智慧城市一期
姓名:甲(架构)
规模较大
无备注
--- 统计 ---
已替换变量 4 个
模式:宽松(未定义变量渲染为空)

用户:用这套模板和数据生成项目周报正文

助手:调用 render_template,text 传模板、data 传 JSON

用户:严格一点,漏了变量就报错,别静默留空

助手:调用 render_template,加 strict=true

用户:从 data.json 文件读数据渲染 tpl.txt

助手:调用 render_template,path=tpl.txt、data_path=data.json

validate_template

发布模板前做静态检查:语法(未闭合标签、未知标签、非法过滤器、非法变量名)、标签数量、在给定数据下未定义的变量、以及数据里未被引用的顶层键。语法或渲染期问题会以「检查报告」返回,而不是直接抛错中断。

模板来源:(内联模板);数据来源:(内联数据)
语法检查:通过(无未闭合标签、未知标签、非法过滤器)
标签统计:变量 4;if 1;each 1;注释 0
未定义变量:无
未使用的数据键:members、total

用户:发布前帮我检查下这个模板有没有语法问题和漏变量

助手:调用 validate_template,text 传模板、data 传一份真实数据

用户:只查语法,不关心数据是否齐全

助手:调用 validate_template,只传 text(不传 data,未定义变量会全量列出)

extract_vars

扫描模板,列出所有引用的变量路径(含 each 列表路径、if 条件路径)与使用的过滤器,并统计 if / each / 注释 数量。适合在写模板前先确认「需要准备哪些数据字段」。

模板来源:(内联模板)
标签统计:变量 4;if 1;each 1;注释 0
引用变量(4):note、project、u.name、u.role
使用的过滤器(1):default

用户:我要写一个模板,先告诉我需要准备哪些数据字段

助手:调用 extract_vars,text 传草稿模板,根据返回的变量清单准备数据

典型场景

  • 批量生成:同一模板配多份数据,生成报告、邮件、公告、配置片段,不用每次手写。
  • 配置注入:把 {{ 环境 }}、{{ 端口 }} 之类的占位符填进部署脚本、连接串、yaml。
  • 结构化文本:生成用户列表、工单清单,用 {% each %} 循环展开,{% empty %} 处理「暂无」。
  • 文案分级:用 {% if %} 按数值 / 状态走不同措辞,避免在代码里堆 if-else 拼字符串。
  • 发布前质检:validate_template 先查出漏变量、未闭合标签、多余数据键,避免生成一半再发现。
  • 数据契约先行:写模板前先 extract_vars,把需要的字段列给上游,减少返工。
  • 脚本与注释:{# … #} 把说明留在模板里,渲染输出自动去干净。
  • 只读安全:所有操作不写文件、不联网,模板里的内容只当字符串处理,不会被执行。

安全边界

  • 只读:三个工具都不写入、不修改、不删除文件;测试含源文件 size/mtime 不变的只读性断言。
  • 不访问网络:分词、校验、渲染全部在本地完成,无任何外部请求。
  • 不执行代码:模板是纯文本 + 数据查找,不用 eval、不加载模块、不解析表达式函数;{% if %} 只支持变量与简单比较,不支持任意代码。
  • 二进制拒绝:读取模板或数据文件时检测 NUL 字节,疑似二进制文件直接拒绝。
  • 多层上限:文件大小上限 51200 KB(默认 10240 KB)、输出字符上限 200000(默认 20000)。超限即截断或拒绝并显式提示。
  • 不做任意外部调用:过滤器只做字符串 / 数值 / 集合的纯函数变换,不发起请求、不访问文件系统。
  • 不脱敏:数据中的字段原样进入渲染结果。模板或数据里可能含密钥、路径、个人信息,分享前请先用 dsh-credential-scan 检查。

其他插件集成说明

| 协作插件 | 集成方式 | |---|---| | dsh-json-toolkit | 先用 JSON 工具取到对象,再交给本插件渲染成文本 | | dsh-csv-inspect | 把 CSV 的列映射成 JSON 数据后,用模板生成逐行文本 | | dsh-text-stats | 渲染结果交给 text-stats 看长度、词频等统计 | | dsh-chart-ascii | 模板生成文字列表,chart-ascii 把其中的数值画成图 | | dsh-markdown-lint | 模板产出的 Markdown 文本再过一遍 markdown-lint 检查格式 | | dsh-credential-scan | 分享渲染结果前扫描是否混入密钥、令牌 | | dsh-config-merge | 从多个配置源合并数据后,用模板统一生成目标配置 |

版本说明

  • 0.1.0(2026-10-05):初始版本。
    • render_template:{{ var }} 点路径与过滤器、{% if %} 条件、{% each %} 循环(含 {% empty %}、for.index/first/last)、{# 注释 #}、\{{ 转义、strict 模式
    • validate_template:语法与标签结构检查、未定义变量检测、未使用数据键检测
    • extract_vars:变量路径(含 each 列表、if 条件)与过滤器清单、标签统计
    • 过滤器:upper / lower / trim / length / json / number / round / default / join / first / last
    • 自写分词 + 递归渲染,不做 eval,未闭合标签 / 未知标签 / 非法变量名 / 非法过滤器均显式报错
    • 二进制拒绝、多层上限与截断提示

RoadMap

v0.2(计划)

  • 增加 {% set %}:模板内定义中间变量,减少重复表达式
  • 增加 {% include %}:引用片段模板,支持复用公共头尾
  • 过滤器扩充:replace、split、slice、date(格式化时间字段)
  • 输出可选 JSON 结构(变量清单、渲染耗时、每处未定义变量的位置)

v0.3(展望)

  • 循环支持 {% each key,value in 对象 %},遍历对象键值对
  • 增加「渲染预览」工具:高亮所有未定义变量位置,便于排查长模板
  • 与 dsh-doc-outline 联动,把模板渲染出的标题结构画成大纲
  • 增加 linter 风格建议:重复变量、可提取的子串等

FAQ

Q:为什么变量没渲染出来,直接变成空串? 默认(宽松模式)下未定义变量渲染为空串,因为输入数据里没有对应的键。可先用 extract_vars 看需要哪些字段,或用 validate_template 查出未定义变量,或在 render_template 加 strict=true 让它直接报错。

Q:{{ a.b.c }} 找不到会怎样? 逐级查找,任何一级为 null / undefined 就视为未定义。路径第一段会尝试从最内层 each 的循环变量解析,找不到再回退到根数据。

Q:{% if %} 支持哪些条件? 任意变量(真值:非零、非空串、非空数组、非 null)或形如 变量 == 值、变量 > 值 的比较,右侧支持数字、带引号的字符串、true / false。不支持函数调用、运算式、正则。

Q:{% each %} 里怎么拿循环变量? {% each list as item %} 中可用 {{ item }} 或 {{ item.字段 }};缺省 as 时变量名默认为 item。另可用 {{ for.index }}(0 起)、{{ for.first }}、{{ for.last }}。

Q:列表是空的时候想显示「暂无」怎么处理? 用 {% each list as item %}{{ item }}{% empty %}暂无{% endeach %}。列表为空时只渲染 empty 分支;列表非空且没有 empty 标签则正常循环。

Q:过滤器参数要不要带引号? 带不带都可以:{{ n | round:1 }} 与 {{ s | default:"暂无" }} 都会去掉两端引号。default 的值含引号或特殊字符时建议带上引号避免歧义。

Q:\{{ 是什么? 模板里想输出字面 {{ 时用 \{{ 转义,渲染结果是 {{(不含反斜杠)。偶数个反斜杠时后一个为字面反斜杠,奇数个才视为转义。

Q:模板里能不能执行代码或调用函数? 不能。这是刻意的安全边界——解析器只认变量、条件、循环、注释和过滤器,内容当字符串处理,不做 eval。需要复杂逻辑请在数据里预先算好,或用专门的代码插件。

Q:未闭合标签会怎样? 分词或渲染时会抛错,validate_template 会把「缺 {% endif %} / {% endeach %}」等作为检查报告列出,不会生成一半的输出。

Q:数据里很多键模板没用上,会警告吗? validate_template 会列出「未使用的数据键」。注意循环变量(item 等)和路径首段属于局部引用,不会被误判为数据键。

Q:输出很长会被截断吗? 超过 max_chars(默认 20000,上限 200000)时截断并提示总字符数;也可用 {% each %} 配 for.index 自己控制条数,或用工具端 limit 思路先缩窄输入。

源码与发布地址

  • 源码:https://github.com/geeklei/dsh-plugins/tree/main/dsh-template-render
  • npm:https://www.npmjs.com/package/dsh-template-render

许可证

MIT