ESLint template-curly-spacing 规则深度解析:统一模板字符串 `${}` 内部空格的布局规则

发布时间:2026/11/13 8:10:32

ESLint template-curly-spacing 规则深度解析:统一模板字符串 `${}` 内部空格的布局规则 ESLint template-curly-spacing 规则深度解析统一模板字符串${}内部空格的布局规则【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint导读本文围绕 ESLint 核心规则template-curly-spacing展开它是用于统一 JavaScript 模板字符串Template Literal中${ ... }内嵌表达式内部空格风格的 layout布局类规则。文章将以官方文档 docs/src/rules/template-curly-spacing.md 为主体骨架结合仓库内 规则实现源码、单元测试 与 规则元数据讲清两种选项never/always的语义、可自动修复行为、边界情况多行表达式、注释、带标签模板以及该规则的弃用与迁移路径使读者能直接在自己的 ESLint 配置中落地使用。一、规则背景模板字符串中的表达式占位符ES6 模板字符串允许通过一对${与}在字符串中嵌入 JavaScript 表达式例如let hello hello, ${people.name}!;这里的${people.name}就是模板字符串中的嵌入式表达式embedded expression。虽然写法自由但占位符内部的空格风格在不同的风格指南style guides中并不一致有的团队习惯${ people.name }两侧留空格有的则坚持${people.name}紧贴。template-curly-spacing规则正是为这一细节而生它根据配置强制约束花括号对内部的空格使用方式从而让整个代码库的模板字符串保持一致的排版。注意它只关注${与}内部的空格不会管表达式内部自身的格式也不管模板字符串之外的内容。从仓库的 rule_versions.json 可以看到该规则自 ESLint2.0.0-rc.0版本起引入属于历史悠久的核心规则之一。二、Rule Details规则到底检查什么官方文档docs/src/rules/template-curly-spacing.md对本规则的目标给出了明确定义This rule aims to maintain consistency around the spacing inside of template literals.即维护模板字符串内部空格的全局一致性。具体到实现层面lib/rules/template-curly-spacing.js 中的create(context)函数遍历 AST 中的TemplateElement节点对每个模板元素 token 执行两个方向的检查checkSpacingBefore(token)检查}之前是否有空格实现位置checkSpacingAfter(token)检查${之后是否有空格实现位置。两个检查函数都调用了sourceCode.isSpaceBetween()判断两个 token 之间是否存在空白字符并通过astUtils.isTokenOnSameLine()判断是否处于同一行——这两个细节决定了下文要讲的多行表达式豁免行为。规则在meta中声明为layout 类型且fixable: whitespacemeta 定义意味着所有违规都可以通过eslint --fix自动修复。三、Optionsnever与always两种模式规则的配置方式与参数约束在源码 schema 中写得非常清楚lib/rules/template-curly-spacing.js#L54schema: [{ enum: [always, never] }],即只接受一个选项取值只能是always或never二选一传入其他值会在配置校验阶段由共享的 ajv 校验 负责直接报配置错误。默认配置示例{ template-curly-spacing: [error, never] }两种选项的官方语义选项含义源码判定never默认禁止${与}内部出现空格always context.options[0] always为false源码always要求${与}内部至少一个空格always为true需要特别说明默认值是never。从源码const always context.options[0] alwayslib/rules/template-curly-spacing.js#L65可以推断只要未显式传入always规则一律按never处理——这与官方文档never(by default)的描述完全一致。该规则recommended: falsemeta 定义因此它既不在eslint:recommended中也不在 tests/conf/eslint-recommended.js 所列规则之列需要使用者显式开启。3.1 never禁止花括号内部空格不正确的代码默认never选项下会报错/*eslint template-curly-spacing: error*/ hello, ${ people.name}!; hello, ${people.name }!; hello, ${ people.name }!;正确的代码/*eslint template-curly-spacing: error*/ hello, ${people.name}!; hello, ${ people.name }!;注意最后一个多行例子表达式换行书写时${\n与\n}之间是换行而非空格规则同样放行原因见下文多行表达式豁免。3.2 always要求花括号内部至少一个空格不正确的代码always选项下会报错/*eslint template-curly-spacing: [error, always]*/ hello, ${ people.name}!; hello, ${people.name }!; hello, ${people.name}!;正确的代码/*eslint template-curly-spacing: [error, always]*/ hello, ${ people.name }!; hello, ${ people.name }!;可以看出always只要求${与表达式、表达式与}之间各至少一个空格多行写法同样不受影响。3.3 两种模式下的错误消息规则共定义了 4 条 messageIdlib/rules/template-curly-spacing.js#L55-L60在--fix之外使用--format json等格式化器或断言测试时可以直接引用messageId触发条件文本expectedAfteralways下${后缺空格Expected space(s) after ${.expectedBeforealways下}前缺空格Expected space(s) before }.unexpectedAfternever下${后有空格Unexpected space(s) after ${.unexpectedBeforenever下}前有空格Unexpected space(s) before }.四、源码实现三个关键行为细节只讲怎么配还不够结合 lib/rules/template-curly-spacing.js 的实现可以看清规则在三个边界场景下的真实行为这些细节直接影响落地效果。4.1 仅检查紧邻占位符的模板元素checkSpacingBefore首先判断token.value.startsWith(})源码checkSpacingAfter则判断token.value.endsWith(${)源码两者不满足就提前返回。这是因为模板字符串会被解析为若干TemplateElement纯文本段与表达式段交替出现只有恰好以${结束紧邻嵌入表达式之前或以}开始紧邻嵌入表达式之后的模板元素才是本规则关注的对象——首尾以反引号收尾的普通文本段直接被跳过。4.2 多行表达式豁免规则通过astUtils.isTokenOnSameLine(prevToken, token)源码判断${之后 /}之前的 token 是否与占位符位于同一行。只要不在同一行就直接 return不做任何检查。这正是官方示例中以下多行写法在两种模式下都正确的原因hello, ${ people.name }!;换言之本规则只约束同一行内的内联空格多行书写不受影响。这一设计避免了规则与换行缩进风格互相干扰。4.3 注释参与空格判定两个检查函数在取相邻 token 时都传入了includeComments: true源码 与 L123-L125意味着${ /* 注释 */ foo }这类带注释的写法中注释会被当作相邻 token参与isSpaceBetween判定。从 单元测试 可以看到never下${/* */ foo} ${bar /* */}是合法代码而always下${ /* */ foo } ${ bar /* */ }才是合法代码——注释两侧的空格同样受规则约束。4.4 自动修复逻辑规则的fixable: whitespace决定了它支持eslint --fix自动修复never模式下违规时通过fixer.removeRange([...])删除${后或}前的多余空格源码 与 L153-L155always模式下通过fixer.insertTextAfter/insertTextBefore插入一个空格源码 与 L142。注意由于多行场景被豁免修复操作只会发生在同一行内不会把多行表达式强行压平。五、测试验证RuleTester 覆盖的行为矩阵仓库在 tests/lib/rules/template-curly-spacing.js 中为该规则编写了非常详尽的 RuleTester 用例测试运行环境为ecmaVersion: 6即模板字符串的最低支持版本可以作为行为矩阵的权威依据普通模板字符串${foo} ${bar}never合法、${ foo } ${ bar }always合法以及两者互判为违规并给出精确的修复输出如${ foo } ${ bar }→${foo} ${bar}带标签模板tagged templatetag\${foo} ${bar} 等用例与普通模板行为完全一致说明规则对带标签调用同样生效多个空格/制表符${ foo } ${ bar }、${foo }${ bar}、${ foo \t}${\t\tbar }均在never下被逐处报告unexpectedAfter/unexpectedBefore并修复为无空格形式证明规则处理的是任意数量的空白而非仅单个空格注释场景块注释、行注释、跨行注释穿插在占位符内的各种组合均有 valid/invalid 用例且never与always下注释两侧空格规则对称跨行模板\n${foo}\n在always下修复为\n${ foo }\n验证了自动修复对换行场景的处理。测试同时精确断言了每次报告的line/column/endLine/endColumn定位例如${ foo } ${ bar }在never下第一次报告的unexpectedAfter位于第 1 行第 45 列tests/lib/rules/template-curly-spacing.js#L86-L118这为依赖 ESLint 位置的编辑器集成提供了稳定预期。六、在项目配置中启用该规则该规则可通过传统的.eslintrc风格与新版 flat config 两种方式启用。.eslintrc风格JSON{ rules: { template-curly-spacing: [error, never] } }新版 flat configeslint.config.js 风格export default [ { rules: { template-curly-spacing: [error, never] } } ];关于 flat config 的完整迁移说明可参考 docs/src/extend/plugin-migration-flat-config.md。由于该规则recommended: false两种方式下都必须显式声明才会生效。七、When Not To Use It何时关闭该规则官方文档的结论非常直白If you dont want to be notified about usage of spacing inside of template strings, then its safe to disable this rule.即如果你不希望被模板字符串内部的空格问题打扰完全可以安全地关闭它。这背后有两层原因空格属于纯样式问题不影响程序行为关闭不会带来任何功能风险该规则是布局类layout规则从 rules_meta.json 可以看到ESLint 官方从 v8.53.0 起已开始将格式化类规则移出核心template-curly-spacing标记为deprecateddeprecatedSince: 8.53.0availableUntil: 11.0.0其维护工作交由stylistic/eslint-plugin插件接管。因此如果项目已使用stylistic/eslint-plugin应改由该插件的同名template-curly-spacing规则负责此项检查如果项目仅需在 ESLint v11 之前锁定现状继续使用核心内置规则也完全可行如果团队根本不关心这类细节排版直接不启用即可。八、小结template-curly-spacing是 ESLint 中一个小而精的布局规则它以never默认禁止${}内部空格和always要求内部至少一个空格两个选项统一了模板字符串嵌入表达式的排版其实现基于TemplateElementtoken 的成对检查天然豁免多行表达式并支持eslint --fix自动修复与注释感知。结合本文引用的 官方文档、实现源码 与 测试用例开发者可以准确判断该规则在本项目的取舍——包括其自 v8.53.0 起的弃用状态与迁移到 Stylistic 插件的时机。/DSMLparameter /DSMLinvoke /DSMLtool_calls【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/12 11:29:29

i-have-adhd:神经多样性时代的数字生存协议

1. 这不是标签,是真实存在的神经多样性体验“i-have-adhd”——最近在社交平台、创意社区甚至职场讨论区高频出现的短句,表面看像一句自述,实则已演变为一种轻量级身份标识、一种群体共鸣信号、一种对主流节奏的温和抵抗宣言。它不带诊断书&a…

2026/11/5 1:40:36

AI原生SDLC操作手册:重塑软件交付全流程

AI 原生 SDLC 操作手册(The AI-Native SDLC playbook)这两年我团队最大的变化,不是用了多少 AI 工具,而是整个软件交付的流程被重塑了一遍。如果你还停留在“用 Copilot 补全代码”的阶段,那接下来的内容可能会颠覆你对…

2026/10/21 13:41:59

论文降重与文本改写服务避坑指南:如何识别不靠谱的改写工具

引言:为什么降重服务频频踩坑 毕业论文写作中,降重与文本改写几乎是每位毕业生绕不开的环节。面对知网、维普、格子达等查重系统的严格检测,不少同学选择借助第三方改写服务来降低重复率。然而,市面上的改写服务鱼龙混杂&#xf…

2026/11/13 8:07:30

电工证要什么学历怎么报名多少钱全知道

电工证要什么学历怎么报名多少钱全知道 你是不是也觉得学历不高就报不了电工证?别急,我来给你说说真实情况,包括报名流程、费用以及你最关心的学历门槛,别让学历拦住了你的路。 一、电工证要什么学历才能报考?…

2026/11/13 8:07:30

三个电工证用途到期换证流程网上查询全攻略

三个电工证用途到期换证流程网上查询全攻略 之前考的证在外省能不能转过来?这是很多电工朋友在换证或复审时最关心的问题,尤其是像你这种在开封从事房建工程的朋友,经常需要跨省作业,证书的流动性和认可度就显得特别重要。通过【网上查询】平台,你可以轻…

2026/11/13 8:07:30

中江电工证怎么考 你知道郑州报考避坑指南吗

中江电工证怎么考 你知道郑州报考避坑指南吗 之前考的证在外省能不能转过来?这个问题几乎是每个打算报考或正在准备转证的电工朋友心中的头等大事。特别是像南阳这样的地方,水利工程从业者越来越多,电工证不仅关系到日常工作,还直接影响到能否参与项目投…

2026/11/12 20:35:13

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/13 0:01:06

办上海高压电工证良心建议:别被中介坑了,自己看这篇就够了

办上海高压电工证良心建议:别被中介坑了,自己看这篇就够了 你是不是也像我一样,第一次听说“高压电工证”这个名词,就感觉一头雾水?其实很多人都跟我一样,不知道去哪报名、怕被中介坑,结果花了冤枉钱还考不上。今天我就从一个在商丘培训过的学员角度,…

2026/11/13 0:01:06

黎里考电工证在哪里值不值得考

黎里考电工证在哪里值不值得考 之前考的证在外省能不能转过来?这是很多在外地工作、准备回老家发展的朋友最关心的问题。特别是在黎里地区,很多从事电力相关工作的朋友,都面临这样一个难题: 外省的电工证能否在本地使用?值不值得考?…

2026/11/13 0:01:06

毕节哪里考电工证 怎么报名学历不高也能上手

毕节哪里考电工证 怎么报名学历不高也能上手 你是不是也和我一样,学历不高,想着考个电工证,但又担心自己条件不够,怕报不上名?其实不然,只要符合条件,学历不高也能考电工证。今天就来聊聊【毕节哪里考电工证】这个问题,还有怎么报名,让你一步到位不…

2026/11/12 22:10:13

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/12 9:51:42

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑