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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@scvzerng/template-parser

v0.1.0

Published

面向打印/报表场景的轻量级 HTML 模板解析与渲染库。通过在 HTML 表格中书写变量表达式,并提供业务上下文(Context),可完成变量替换、循环行扩展与统计汇总,最终输出可直接用于打印或导出的 HTML。

Readme

template-parser

面向打印/报表场景的轻量级 HTML 模板解析与渲染库。通过在 HTML 表格中书写变量表达式,并提供业务上下文(Context),可完成变量替换、循环行扩展与统计汇总,最终输出可直接用于打印或导出的 HTML。

功能特性

  • 所见即所得模板:直接使用标准 HTML(通常是 table)作为模板,易于维护
  • 表达式解析:支持 ${变量名} 与表达式语法,支持多表达式拼接
  • 上下文驱动:通过 Context 提供变量值;支持自定义 Context 扩展集合与派生值
  • 行模型:将表格解析为行/单元格模型,逐行渲染
  • 循环/汇总:按约定识别「循环行」并扩展;支持专用统计语法与表达式汇总
  • 轻量可扩展:核心抽象清晰,便于二次封装

安装

npm install template-parser

使用方式(ESM):

import { NormalContext, Expression } from 'template-parser'

快速开始

1) 表达式解析与求值

import { NormalContext, Expression } from 'template-parser'

const tpl = 'Hello ${name}, your balance is ${amount.toFixed(2)}'
const context = new NormalContext({ name: 'John', amount: 100.5 })

const exps = Expression.parse(tpl) // 提取到 ["${name}", "${amount.toFixed(2)}"]

// 将表达式替换回字符串(示例化简实现)
let i = 0
let result = ''
for (const exp of exps) {
  result += tpl.slice(i, exp.getStartIndex())
  result += String(exp.eval(context))
  i = exp.getEndIndex()
}
result += tpl.slice(i)
// => Hello John, your balance is 100.50

2) 表格模板渲染(概念示例)

库中提供 HTML 表格到行/单元格模型的解析与渲染基类 HtmlTemplate,适合二次封装成你的业务模板。

HTML 模板(片段):

<table data-type="luckysheet_copy_action_table">
  <tbody>
    <tr>
      <td>客户</td>
      <td>${customerName}</td>
    </tr>
    <!-- 目标行(含集合变量) -->
    <tr>
      <td>${index + 1}</td>
      <td>${item.name}</td>
      <td>${item.qty}</td>
    </tr>
    <!-- 占位空行(用于循环复制) -->
    <tr>
      <td></td><td></td><td></td>
    </tr>
    <!-- 合计:专用语法 “字段,小数位” 或表达式 -->
    <tr>
      <td>合计</td>
      <td colspan="2">qty,2</td>
    </tr>
  </tbody>
</table>

简单的模板解析器实现:

import { HtmlTemplate, NormalContext } from 'template-parser'

class MyTableTemplate extends HtmlTemplate<NormalContext> {
  parse(ctx: NormalContext): string {
    // 逐行渲染(ExpressionCell 会用 ctx 替换表达式)
    let row = (this as any).rows[0] // rows 为受保护字段,示例中直接访问;在你的项目中可封装更友好的 API
    while (row) {
      row.eval(ctx)
      row = row.getNext()
    }
    // 返回模板根节点 HTML。此处 domFragment 为基类中的片段
    // 可根据需要改为 outerHTML 或 innerHTML
    return (this as any).domFragment.firstElementChild?.outerHTML ?? ''
  }
}

关于循环与占位:

  • 目标行:包含集合相关变量(如 ${item.name}),用于被复制
  • 占位空行:目标行之后紧邻的“全空”行作为占位,渲染时按集合长度复制目标行并覆盖/追加

注意:集合与统计依赖 Context.getVector 提供集合数据;默认 NormalContext 未实现集合向量(会抛出异常)。你需要实现自定义 Context 以支持集合渲染与统计。

统计单元格(SummeryCell)

  • 写法:字段,小数位(如 qty,2),等价于 ${qty.reduce((t,e)=>t+e,0).toFixed(2)}。依赖 Context.getVector(field) 提供数组。

核心 API 速查

template-parser 导出的主要成员:

  • 上下文
    • Context 接口:set/get/merge/has/getVariables/getVector
    • NormalContext:基础实现(未实现集合 getVector)
  • 表达式
    • Expressionparse(input: string)eval(context)
    • 常量:EXP_START = '\${'EXP_END = '}'
  • 模板与表格
    • Template<T extends Context>parse(context: T): string
    • HtmlTemplate<T extends Context>:HTML 表格模板基类
    • HtmlTableRow/TemplateRow:行级操作(eval/append/remove/override/clone/isEmpty 等)
    • TemplateCell 及实现:NormalCellExpressionCellEmptyCellSummeryCell
    • CellUtils:辅助判断单元格类型(空/普通/表达式/统计)

自定义 Context(支持集合/循环)

import { NormalContext } from 'template-parser'

class ListContext extends NormalContext {
  getVector(key: string): (string | number)[] {
    const v = this.get(key)
    return Array.isArray(v) ? (v as any[]) : []
  }
}

开发指南

  • 本地开发:npm run dev
  • 构建:npm run build(会先跑测试,再打包 Vite 和类型)
  • 测试:npm run test(Vitest + jsdom)
  • Lint:npm run lint / npm run lint:fix

打包产物(见 package.json exports):

  • ESM:dist/template-parser.es.js
  • UMD:dist/template-parser.umd.js
  • 类型:dist/types/index.d.ts

兼容性与限制

  • 需要 DOM 环境(浏览器或 jsdom)。Node 端纯字符串渲染可仅使用 Expression/Context。
  • HtmlTemplate 解析要求根 table ,tbody 必须存在。
  • 循环/统计依赖你提供的集合 Context 实现。