@@ -3,7 +3,6 @@ package hclparse
33import (
44 "bytes"
55 "slices"
6- "strings"
76
87 "github.com/hashicorp/hcl/v2"
98 "github.com/hashicorp/hcl/v2/hclsyntax"
@@ -136,15 +135,15 @@ func partialEvalTemplate(e *hclsyntax.TemplateExpr, args *EvalArgs) []byte {
136135
137136 for _ , part := range e .Parts {
138137 if lit , ok := part .(* hclsyntax.LiteralValueExpr ); ok {
139- buf .WriteString ( escapeHCLStringLit (lit .Val .AsString ()))
138+ buf .Write ( hclStringContent (lit .Val .AsString ()))
140139
141140 continue
142141 }
143142
144143 if IsPure (part , args .Deferred ) {
145144 val , diags := part .Value (args .EvalCtx )
146145 if ! diags .HasErrors () && val .Type () == cty .String {
147- buf .WriteString ( escapeHCLStringLit (val .AsString ()))
146+ buf .Write ( hclStringContent (val .AsString ()))
148147
149148 continue
150149 }
@@ -161,6 +160,20 @@ func partialEvalTemplate(e *hclsyntax.TemplateExpr, args *EvalArgs) []byte {
161160 return buf .Bytes ()
162161}
163162
163+ // hclStringContent returns the inner content of an HCL-escaped string
164+ // (without surrounding quotes). Uses hclwrite.TokensForValue for correct
165+ // escaping of all HCL special characters.
166+ func hclStringContent (s string ) []byte {
167+ raw := hclwrite .TokensForValue (cty .StringVal (s )).Bytes ()
168+
169+ // TokensForValue produces `"escaped content"` — strip the quotes.
170+ if len (raw ) >= 2 {
171+ return raw [1 : len (raw )- 1 ]
172+ }
173+
174+ return raw
175+ }
176+
164177func partialEvalObject (e * hclsyntax.ObjectConsExpr , args * EvalArgs ) []byte {
165178 var buf bytes.Buffer
166179
@@ -213,34 +226,6 @@ func partialEvalTuple(e *hclsyntax.TupleConsExpr, args *EvalArgs) []byte {
213226 return buf .Bytes ()
214227}
215228
216- func escapeHCLStringLit (s string ) string {
217- var buf strings.Builder
218-
219- buf .Grow (len (s ))
220-
221- for _ , r := range s {
222- switch r {
223- case '\\' :
224- buf .WriteString (`\\` )
225- case '"' :
226- buf .WriteString (`\"` )
227- case '\n' :
228- buf .WriteString (`\n` )
229- case '\r' :
230- buf .WriteString (`\r` )
231- case '\t' :
232- buf .WriteString (`\t` )
233- default :
234- buf .WriteRune (r )
235- }
236- }
237-
238- result := buf .String ()
239- result = strings .ReplaceAll (result , "${" , "$${" )
240- result = strings .ReplaceAll (result , "%{" , "%%{" )
241-
242- return result
243- }
244229
245230func valueToHCLBytes (val cty.Value ) []byte {
246231 tokens := hclwrite .TokensForValue (val )
0 commit comments