☰
ts-jest 的 stringifyContentPathRegex 选项:将匹配文件原样字符串化导出
2026/10/7 9:39:00 网站建设 项目流程
  • 测试
  • 开发工具

【免费下载链接】ts-jest

A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript.

项目地址:https://gitcode.com/gh_mirrors/ts/ts-jest
点击查看免费下载

stringifyContentPathRegex是 ts-jest 提供的一个正则表达式配置项,用于把匹配到的文件(典型场景是 HTML 模板)当作纯文本字符串导出,而不是当作 TypeScript/JavaScript 源码进行编译。本文以 ts-jest 仓库(当前版本 29.0 文档)为基准,完整讲解该选项的语义、三种配置写法、正则匹配细节、源码实现原理与历史兼容性,帮助你安全地在 Jest 中完成「HTML 模板字符串化」类需求。

选项是什么:为__HTML_TRANSFORM__保留的字符串化能力

stringifyContentPathRegex选项最初是为了向后兼容旧版 ts-jest 的__HTML_TRANSFORM__全局配置而保留的(详见下文「历史迁移」一节)。它的作用非常明确:

  • 它是一个正则表达式模式,用来匹配将被转换的文件路径;
  • 一旦匹配成功,该文件不会被当作源码编译,而是被导出为一个导出其文件内容的模块。

也就是说,当正则命中某个文件后,ts-jest 完全跳过 TypeScript 编译管线,直接生成类似下面的模块代码:

module.exports = "文件原始内容字符串"

一个直观的例子

假设你有一个文件foo.ts,内容为:

export default "bar"

并且你的stringifyContentPathRegex被设置为foo\\.ts$。那么最终得到的模块不是编译foo.ts源码的结果,而是一个导出了字符串"export default \"bar\""的模块——文件内容被整体「字符串化」了。

注意这里的正则需要转义:foo\\.ts$中的\\.匹配一个字面量点号.,$锚定文件路径结尾。如果你直接在jest.config.ts中书写,也可以使用 JavaScript 正则字面量/foo\.ts$/,二者语义一致(具体类型与规范化见下文源码分析)。

关键注意事项(CAUTION)

无论你想让哪些文件被stringifyContentPathRegex命中,都必须同时满足两个前提,否则匹配不会生效:

  1. Jest 的transform选项中指向ts-jest的规则必须能匹配到这些文件。也就是说,ts-jest 只会处理被transform交给它的文件;stringifyContentPathRegex只能在 ts-jest 已经接管的文件范围内生效。
  2. 可能还需要把这些文件的扩展名加入 Jest 的moduleFileExtensions选项。例如你希望foo.html被处理,就应把html加入moduleFileExtensions,否则 Jest 在模块解析阶段可能根本不会把该文件交给 transform 管线。

这两点共同决定了「正则写了却不起作用」的绝大多数排查方向:先确认transform规则覆盖了目标扩展名,再确认moduleFileExtensions包含该扩展名。

配置示例:三种写法完整继承

写法一:jest.config.js(推荐基于 preset 扩展)

// jest.config.js const { defaults: tsjPreset } = require('ts-jest/presets') /** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { // [...] moduleFileExtensions: [...tsjPreset.moduleFileExtensions, 'html'], transform: { ...tsjPreset.transform, '\\.html$': [ 'ts-jest', { stringifyContentPathRegex: /\.html$/, }, ], }, }

写法二:jest.config.ts

// jest.config.ts import type { JestConfigWithTsJest } from 'ts-jest' import tsJestPresets from 'ts-jest/presets' const jestConfig: JestConfigWithTsJest = { // [...] moduleFileExtensions: [...tsJestPresets.defaults.moduleFileExtensions, 'html'], transform: { ...tsJestPresets.defaults.transform, '\\.html$': [ 'ts-jest', { stringifyContentPathRegex: /\.html$/, }, ], }, }

写法三:package.json中的内联 Jest 配置

// package.json { // [...] "jest": { "moduleFileExtensions": ["js", "ts", "html"], "transform": { "\\.(html|ts|js)$": [ "ts-jest", { "stringifyContentPathRegex": "\\.html$" } ] } } }

文档原文特别说明:在jest.config.js版本中,你可以像package.json版本那样书写,但从 preset(ts-jest/presets)扩展会带来更强的兼容性——升级 ts-jest 版本时无需改动配置即可保持行为一致。

关于示例的补充说明

  • 示例中transform的 key'\\.html$'是 Jest 用来匹配待转换文件路径的正则;stringifyContentPathRegex: /\.html$/则是 ts-jest 内部用来决定「文件内容是否字符串化」的正则。二者作用层面不同,但示例中刻意保持一致(都匹配.html结尾),这也是最常见的组合。
  • 在package.json版本中"\\.(html|ts|js)$"同时覆盖了 html/ts/js 三种扩展名,确保.html文件能被 ts-jest 接管;此时moduleFileExtensions也必须包含html。
  • 正则在 JSON 配置中必须写成字符串(如"\\.html$"),在jest.config.js/ts中则推荐使用原生正则字面量/.html$/。

源码级解析:正则如何被规范化与使用

类型定义

在 src/types.ts 中,该选项的类型被定义为:

stringifyContentPathRegex?: string | RegExp

即既接受字符串形式,也接受 RegExp 对象形式,这解释了为什么 JSON 配置(只能存字符串)和 JS/TS 配置文件(可用字面量正则)都能正常工作。

规范化流程

在 src/legacy/config/config-set.ts 中,ConfigSet 构造时会对该选项做归一化处理:

// stringifyContentPathRegex if (options.stringifyContentPathRegex) { this._stringifyContentRegExp = typeof options.stringifyContentPathRegex === 'string' ? new RegExp(normalizeRegex(options.stringifyContentPathRegex)!) // eslint-disable-line @typescript-eslint/no-non-null-assertion : options.stringifyContentPathRegex this.logger.debug( { stringifyContentPathRegex: this._stringifyContentRegExp }, 'normalized stringifyContentPathRegex config via ts-jest option', ) }

从源码结构可以看到:

  • 传入的字符串会经过normalizeRegex处理后用new RegExp(...)编译为正则对象;
  • 传入的正则对象会被直接使用;
  • 归一化结果保存在内部属性_stringifyContentRegExp中,并输出 debug 日志便于排查。

匹配判定

在 src/legacy/config/config-set.ts 中,判定逻辑非常简洁:

shouldStringifyContent(filePath: string): boolean { return this._stringifyContentRegExp ? this._stringifyContentRegExp.test(filePath) : false }

未配置该选项时恒返回false,即所有文件照常走编译流程;配置后则用正则测试传入的文件路径。

字符串化输出

在 src/legacy/ts-jest-transformer.ts 中,processWithTs首先调用configs.shouldStringifyContent(sourcePath)判断,命中后直接短路编译流程:

const shouldStringifyContent = configs.shouldStringifyContent(sourcePath) const babelJest = shouldStringifyContent ? undefined : configs.babelJestTransformer // ... if (shouldStringifyContent) { // handles here what we should simply stringify result = { code: `module.exports=${stringify(sourceText)}`, } }

注意两个细节:

  • 命中字符串化的文件不会再走 babel 转换(babelJest被置为undefined);
  • 输出代码为module.exports=<JSON.stringify后的源码文本>,即把整个文件内容序列化为一个字符串并导出。

测试用例印证

在 src/legacy/ts-jest-transformer.spec.ts 中有一个直接验证该行为的测试:对foo.html(内容为<h1>Hello World</h1>)配置stringifyContentPathRegex: '\\.html$'后调用tr.process,期望产物为:

{ "code": "module.exports=\"<h1>Hello World</h1>\"" }

这与文档描述完全一致:HTML 内容没有被 TypeScript 编译,而是被转义后作为字符串导出。另外,src/legacy/config/config-set.spec.ts 还验证了该选项同时支持字符串('\\.str$')与正则对象(/\.str$/)两种形式,以及未配置时的默认行为。

历史迁移:从__TRANSFORM_HTML__到stringifyContentPathRegex

文档明确指出该选项是为__HTML_TRANSFORM__的向后兼容而保留。在 src/utils/backports.ts 中可以看到对应的迁移逻辑:

if ('__TRANSFORM_HTML__' in globals) { warnConfig('globals.__TRANSFORM_HTML__', 'globals.ts-jest.stringifyContentPathRegex') if (globals.__TRANSFORM_HTML__) { mergeTsJest.stringifyContentPathRegex = '\\.html?$' } delete globals.__TRANSFORM_HTML__ }

含义是:如果旧配置中启用了globals.__TRANSFORM_HTML__,ts-jest 会打印弃用警告(提示改用globals.ts-jest.stringifyContentPathRegex),并自动把等效正则\\.html?$写入新的选项位置,最后删除旧键。\\.html?$中的?让l可省略,因此同时覆盖.html与.htm。相关警告文案可在 src/utils/snapshots/backports.spec.ts.snap 的快照中看到。

如果你正在从旧版本升级,请检查配置中是否残留globals.__TRANSFORM_HTML__,并替换为本文所述的stringifyContentPathRegex写法。

实战要点与最佳实践

  1. 正则只匹配路径,不匹配内容。stringifyContentPathRegex测试的是传入 ts-jest 的文件路径(如foo.html),因此写\.html$即可覆盖所有.html文件;若只针对某个目录,可写成^src/templates/.*\.html$之类带锚点的模式。
  2. transform与moduleFileExtensions是生效前提。stringifyContentPathRegex只在 ts-jest 被 Jest 指定的 transform 规则接管文件后才生效;moduleFileExtensions中缺少对应扩展名会导致 Jest 根本不解析该类文件。二者缺一不可。
  3. 字符串化后文件内容可被require/import直接读取。因为产物是module.exports="...",测试代码中可以import html from './template.html'拿到模板原文,适用于需要把 HTML 片段注入 DOM 或做快照断言的场景。
  4. 字符串形式需注意转义。JSON 配置中必须写成"\\.html$"(两个反斜杠表示一个正则中的字面量点);而在jest.config.js/ts中直接使用/\.html$/更直观,且与源码内部new RegExp归一化后的对象等价。
  5. 不要用该选项匹配 TS 业务源码。它会让匹配到的.ts/.js文件跳过编译直接变成字符串模块(如文档中的foo.ts示例所示),绝大多数情况下这不是你想要的;它最适合的是模板类资源文件。

参考文件索引

  • 选项类型定义:src/types.ts
  • 字符串/正则归一化与匹配判定:src/legacy/config/config-set.ts、src/legacy/config/config-set.ts
  • 字符串化输出实现:src/legacy/ts-jest-transformer.ts
  • 行为验证测试:src/legacy/ts-jest-transformer.spec.ts、src/legacy/config/config-set.spec.ts
  • 旧配置迁移逻辑:src/utils/backports.ts
  • 测试
  • 开发工具

【免费下载链接】ts-jest

A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript.

项目地址:https://gitcode.com/gh_mirrors/ts/ts-jest
点击查看免费下载

相关推荐

上一篇:Markdown Preview Enhanced:电子书制作终极完整指南
下一篇:AutoHotkey鼠标轨迹记录终极指南:5分钟掌握精准操作回放

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询