You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Handlebars生成YAML时如何避免引号被转义为"?

解决Handlebars生成YAML时双引号被过度转义的问题

问题背景

使用Handlebars编译模板生成Argo CD ApplicationSet的YAML文件时,原本的双引号"被转义成",连=也被转成=,导致生成的YAML无法正常使用。不想采用二次替换这种临时方案,需要更高效的解决办法。

核心原因

Handlebars默认会自动转义HTML实体(比如把"转成",嵌套渲染时会进一步变成"),这是因为它最初是为HTML场景设计的。但YAML不需要这种转义,因此要禁用该自动转义行为。

解决方案

方案1:使用三重大括号输出不转义内容

在主模板中,将{{templatePlaceholder}}改为{{{templatePlaceholder}}},三重大括号会让Handlebars直接输出变量的原始内容,不会转义其中的任何字符。

修改后的主模板:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: {{serviceName}}
  namespace: argocd-prod
spec:
  generators:
    - list:
{{#application}}
        - namespace: {{namespace}}
          environment: {{env}}
          region: {{region}}
          path: {{path}}
          clusterurl: {{clusterUrl}}
{{/application}}
{{! BEGIN template block }}
{{{templatePlaceholder}}}
{{! END template block }}

该方案无需修改JS代码,仅调整主模板的占位符语法即可解决转义问题。

方案2:编译模板时开启全局不转义选项

编译Handlebars模板时,添加noEscape: true参数,全局禁用自动转义。注意:此选项会让所有{{variable}}的输出都不转义,需确保所有变量内容安全(无恶意HTML字符)后再使用。

修改JS代码中的编译逻辑:

const compiledTemplate = Handlebars.compile(yamlData, { noEscape: true });

方案3:用Handlebars局部模板重构(更规范)

将template块单独做成Handlebars模板文件,注册为局部模板,避免字符串嵌套替换的问题,更符合Handlebars的最佳实践。

  1. 创建局部模板文件templates/appset-template-partial.hbs:
template:
    metadata:
      name: "{{environment}}-{{region}}-{{namespace}}-{{serviceName}}"
      labels:
        service: {{serviceName}}-{{environment}}
        tribe: {{tribe}}
        squad: {{squad}}
        environment: "{{environment}}"
        region: "{{region}}"
    spec:
      project: {{squad}}
      source:
        targetRevision: HEAD
        path: "{{path}}"
      destination:
        server: "{{clusterurl}}"
        namespace: "{{namespace}}"
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
          allowEmpty: true
        syncOptions:
          - CreateNamespace=true
  1. 修改JS代码,注册并使用局部模板:
import 'core-js/features/string/replace-all';
import { ApplicationSet, Owner } from './interfaces/types';
import * as fs from 'fs';
import * as Handlebars from 'handlebars';

const yamlTemplate = 'templates/argocd-appset.yaml';
// 注册局部模板
const partialTemplate = fs.readFileSync('templates/appset-template-partial.hbs', 'utf8');
Handlebars.registerPartial('appsetTemplate', partialTemplate);

export function generateApp(appset: ApplicationSet, owner: Owner): string {
  const yamlData = fs.readFileSync(yamlTemplate, 'utf8');
  const compiledTemplate = Handlebars.compile(yamlData);
  // 合并所有数据,无需单独处理template块
  const merged = {...appset,...owner};
  const renderedYAML = compiledTemplate(merged);
  return renderedYAML;
}
  1. 修改主模板,调用局部模板:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: {{serviceName}}
  namespace: argocd-prod
spec:
  generators:
    - list:
{{#application}}
        - namespace: {{namespace}}
          environment: {{env}}
          region: {{region}}
          path: {{path}}
          clusterurl: {{clusterUrl}}
{{/application}}
{{! BEGIN template block }}
{{> appsetTemplate}}
{{! END template block }}

该方案彻底避免了字符串嵌套替换的问题,代码结构更清晰,维护性更强。

内容的提问来源于stack exchange,提问作者Vini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:35:26