Skip to content

Commit b4dbe1c

Browse files
committed
vega: Escape special characters in field and title.
Closes #80
1 parent c6f6abc commit b4dbe1c

File tree

4 files changed

+32
-0
lines changed

4 files changed

+32
-0
lines changed

src/dvc_render/vega.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ def get_filled_template(
8181
f"Template '{self.template.name}' "
8282
f"is not using '{anchor}' anchor"
8383
)
84+
else:
85+
value = self.template.escape_special_characters(value)
8486
content = self.template.fill_anchor(content, name, value)
8587

8688
return content

src/dvc_render/vega_templates.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ def fill_anchor(cls, content, name, value) -> str:
7272
)
7373
return content.replace(cls.anchor_str(name), value_str)
7474

75+
@classmethod
76+
def escape_special_characters(cls, value: str) -> str:
77+
"Escape special characters in `value`"
78+
for character in (".", "[", "]"):
79+
value = value.replace(character, "\\" + character)
80+
return value
81+
7582
@classmethod
7683
def anchor_str(cls, name) -> str:
7784
"Get string wrapping ANCHOR formatted with name."

tests/test_templates.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
TEMPLATES,
77
LinearTemplate,
88
ScatterTemplate,
9+
Template,
910
TemplateContentDoesNotMatch,
1011
TemplateNotFoundError,
1112
dump_templates,
@@ -76,3 +77,8 @@ def test_raise_on_init_modified(tmp_dir):
7677

7778
with pytest.raises(TemplateContentDoesNotMatch):
7879
dump_templates(output=".", targets=["linear"])
80+
81+
82+
def test_escape_special_characters():
83+
value = "foo.bar[2]"
84+
assert Template.escape_special_characters(value) == "foo\\.bar\\[2\\]"

tests/test_vega.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,20 @@ def test_invalid_generate_markdown():
159159
match="`generate_markdown` can only be used with `LinearTemplate`",
160160
):
161161
renderer.generate_markdown("output")
162+
163+
164+
def test_escape_special_characters():
165+
datapoints = [
166+
{"foo.bar[0]": 0, "foo.bar[1]": 3},
167+
{"foo.bar[0]": 1, "foo.bar[1]": 4},
168+
]
169+
props = {"template": "simple", "x": "foo.bar[0]", "y": "foo.bar[1]"}
170+
renderer = VegaRenderer(datapoints, "foo", **props)
171+
filled = json.loads(renderer.get_filled_template())
172+
# data is not escaped
173+
assert filled["data"]["values"][0] == datapoints[0]
174+
# field and title yes
175+
assert filled["encoding"]["x"]["field"] == "foo\\.bar\\[0\\]"
176+
assert filled["encoding"]["x"]["title"] == "foo\\.bar\\[0\\]"
177+
assert filled["encoding"]["y"]["field"] == "foo\\.bar\\[1\\]"
178+
assert filled["encoding"]["y"]["title"] == "foo\\.bar\\[1\\]"

0 commit comments

Comments
 (0)