format_dict: only unescape quotes when removing outer quotes (#1609)

This commit is contained in:
Masen Furer 2023-08-17 09:45:25 -07:00 committed by GitHub
parent 8c4183f500
commit 26e45c1f18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 3 deletions

View File

@ -473,10 +473,22 @@ def format_dict(prop: ComponentStyle) -> str:
# Dump the dict to a string.
fprop = json_dumps(prop)
def unescape_double_quotes_in_var(m: re.Match) -> str:
# Since the outer quotes are removed, the inner escaped quotes must be unescaped.
return re.sub('\\\\"', '"', m.group(1))
# This substitution is necessary to unwrap var values.
fprop = re.sub('"{', "", fprop)
fprop = re.sub('}"', "", fprop)
fprop = re.sub('\\\\"', '"', fprop)
fprop = re.sub(
pattern=r"""
(?<!\\) # must NOT start with a backslash
" # match opening double quote of JSON value
{(.*?)} # extract the value between curly braces (non-greedy)
" # match must end with an unescaped double quote
""",
repl=unescape_double_quotes_in_var,
string=fprop,
flags=re.VERBOSE,
)
# Return the formatted dict.
return fprop

View File

@ -4,6 +4,7 @@ import pytest
from reflex.components.tags import CondTag, Tag, tagless
from reflex.event import EVENT_ARG, EventChain, EventHandler, EventSpec
from reflex.style import Style
from reflex.vars import BaseVar, Var
@ -23,6 +24,14 @@ def mock_event(arg):
([1, 2, 3], "{[1, 2, 3]}"),
(["a", "b", "c"], '{["a", "b", "c"]}'),
({"a": 1, "b": 2, "c": 3}, '{{"a": 1, "b": 2, "c": 3}}'),
({"a": 'foo "bar" baz'}, r'{{"a": "foo \"bar\" baz"}}'),
(
{
"a": 'foo "{ "bar" }" baz',
"b": BaseVar(name="val", type_="str"),
},
r'{{"a": "foo \"{ \"bar\" }\" baz", "b": val}}',
),
(
EventChain(events=[EventSpec(handler=EventHandler(fn=mock_event))]),
'{_e => Event([E("mock_event", {})], _e)}',
@ -57,6 +66,13 @@ def mock_event(arg):
{"a": BaseVar(name='state.colors["val"]', type_="str")},
'{{"a": state.colors["val"]}}',
),
# tricky real-world case from markdown component
(
{
"h1": f"{{({{node, ...props}}) => <Heading {{...props}} {''.join(Tag(name='', props=Style({'as_': 'h1'})).format_props())} />}}"
},
'{{"h1": ({node, ...props}) => <Heading {...props} as={`h1`} />}}',
),
],
)
def test_format_prop(prop: Var, formatted: str):