Skip to content

Commit

Permalink
fix: Fix escaping of { and } in FormattableString (#3890)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Maxime Mangel <mangel.maxime@protonmail.com>
  • Loading branch information
roboz0r and MangelMaxime authored Sep 19, 2024
1 parent 49501d0 commit d61c993
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* [Python] Remove `$` sign when reporting an error from `assert_equal` and `assert_not_equal` (#3878) (by @joprice)

### Fixed

* [JS/TS] Fix escaping of `{` and `}` in FormattableString (#3890) (by @roboz0r)

## 4.20.0 - 2024-09-04

### Added
Expand Down
7 changes: 6 additions & 1 deletion src/Fable.Transforms/BabelPrinter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,12 @@ module PrinterExtensions =
| Literal.DirectiveLiteral(literal) -> printer.Print(literal)
| StringTemplate(tag, parts, values, loc) ->
let escape str =
Regex.Replace(str, @"(?<!\\)\\", @"\\").Replace("`", @"\`")
Regex
.Replace(str, @"(?<!\\)\\", @"\\")
.Replace("`", @"\`")
// FormattableString replaces { with {{
.Replace("{{", "{")
.Replace("}}", "}")

printer.AddLocation(loc)
printer.PrintOptional(tag)
Expand Down
4 changes: 4 additions & 0 deletions src/fable-library-ts/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* [JS/TS] Add support for `OrdinalIgnoreCase` overload for `String.EndsWith` (#3892) (by @goswinr)

### Fixed

* [JS/TS] Fix escaping of `{` and `}` in FormattableString (#3890) (by @roboz0r)

## 1.4.3 - 2024-09-04

* [JS/TS] Fixed Decimal comparisons (#3884) (by @ncave)
Expand Down
8 changes: 6 additions & 2 deletions src/fable-library-ts/String.ts
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,11 @@ export function fmtWith(fmts: string[]) {
}

export function getFormat(s: FormattableString) {
const strs = s.strs.map((value) => value.replace(/{/g, '{{').replace(/}/g, '}}'));

return s.fmts
? s.strs.reduce((acc, newPart, index) => acc + `{${String(index - 1) + s.fmts![index - 1]}}` + newPart)
: s.strs.reduce((acc, newPart, index) => acc + `{${index - 1}}` + newPart);
? strs
.reduce((acc, newPart, index) => acc + `{${String(index - 1) + s.fmts![index - 1]}}` + newPart)
: strs
.reduce((acc, newPart, index) => acc + `{${index - 1}}` + newPart);
}
40 changes: 40 additions & 0 deletions tests/Js/Main/StringTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,8 @@ let tests = testList "Strings" [
s4.Format |> equal "I have `backticks`"
let s5: FormattableString = $"I have {{escaped braces}} and %%percentage%%"
s5.Format |> equal "I have {{escaped braces}} and %percentage%"
let s6: FormattableString = $$$$"""I have {{escaped braces}} and %%percentage%%"""
s6.Format |> equal "I have {{{{escaped braces}}}} and %%percentage%%"
()

#if FABLE_COMPILER
Expand All @@ -1184,5 +1186,43 @@ let tests = testList "Strings" [
s2.GetStrings() |> toArray |> equal [|""; "This is \""; "\" awesome!"|]
let s3: FormattableString = $"""I have no holes"""
s3.GetStrings() |> toArray |> equal [|"I have no holes"|]

testCase "FormattableString fragments handle { and }" <| fun () ->
// TypeScript will complain because TemplateStringsArray is not equivalent to string[]
#if FABLE_COMPILER_TYPESCRIPT
let toArray = Seq.toArray
#else
let toArray = id
#endif
let classAttr = "item-panel"
let cssNew :FormattableString = $$""".{{classAttr}}:hover {background-color: #eee;}"""
let strs = cssNew.GetStrings() |> toArray
strs |> equal [|"."; ":hover {background-color: #eee;}"|]
let args = cssNew.GetArguments()
args |> equal [|classAttr|]

let cssNew :FormattableString = $""".{classAttr}:hover {{background-color: #eee;}}"""
let strs = cssNew.GetStrings() |> toArray
strs |> equal [|"."; ":hover {background-color: #eee;}"|]
let args = cssNew.GetArguments()
args |> equal [|classAttr|]

let cssNew :FormattableString = $".{classAttr}:hover {{background-color: #eee;}}"
let strs = cssNew.GetStrings() |> toArray
strs |> equal [|"."; ":hover {background-color: #eee;}"|]
let args = cssNew.GetArguments()
args |> equal [|classAttr|]

let another :FormattableString = $$"""{ { } {{classAttr}} } } }"""
let strs = another.GetStrings() |> toArray
strs |> equal [|"{ { } "; " } } }"|]
let args = another.GetArguments()
args |> equal [|classAttr|]

let another :FormattableString = $"""{{ {{{{ }}}}}} {classAttr} }}}} }} }}}}"""
let strs = another.GetStrings() |> toArray
strs |> equal [|"{ {{ }}} "; " }} } }}"|]
let args = another.GetArguments()
args |> equal [|classAttr|]
#endif
]

0 comments on commit d61c993

Please sign in to comment.