Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom Template class with tojavascript filter #1912

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions folium/template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import json
from typing import Union

import jinja2
from branca.element import Element

from folium.utilities import JsCode, TypeJsonValue, camelize


def tojavascript(obj: Union[str, JsCode, dict, list, Element]) -> str:
if isinstance(obj, JsCode):
return obj.js_code
elif isinstance(obj, Element):
return obj.get_name()
elif isinstance(obj, dict):
out = ["{\n"]
for key, value in obj.items():
out.append(f' "{camelize(key)}": ')
out.append(tojavascript(value))
out.append(",\n")
out.append("}")
return "".join(out)
elif isinstance(obj, list):
out = ["[\n"]
for value in obj:
out.append(tojavascript(value))
out.append(",\n")
out.append("]")
return "".join(out)
else:
return _to_escaped_json(obj)


def _to_escaped_json(obj: TypeJsonValue) -> str:
return (
json.dumps(obj)
.replace("<", "\\u003c")
.replace(">", "\\u003e")
.replace("&", "\\u0026")
.replace("'", "\\u0027")
)


class Environment(jinja2.Environment):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.filters["tojavascript"] = tojavascript


class Template(jinja2.Template):
environment_class = Environment
68 changes: 68 additions & 0 deletions tests/test_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from branca.element import Element

from folium import JsCode
from folium.template import Environment, Template, _to_escaped_json, tojavascript


def test_tojavascript_with_jscode():
js_code = JsCode("console.log('Hello, World!')")
assert tojavascript(js_code) == "console.log('Hello, World!')"


def test_tojavascript_with_element():
element = Element()
assert tojavascript(element) == element.get_name()


def test_tojavascript_with_dict():
dict_obj = {"key": "value"}
assert tojavascript(dict_obj) == '{\n "key": "value",\n}'


def test_tojavascript_with_list():
list_obj = ["value1", "value2"]
assert tojavascript(list_obj) == '[\n"value1",\n"value2",\n]'


def test_tojavascript_with_string():
assert tojavascript("Hello, World!") == _to_escaped_json("Hello, World!")


def test_tojavascript_with_combined_elements():
js_code = JsCode("console.log('Hello, World!')")
element = Element()
combined_dict = {
"key": "value",
"list": ["value1", "value2", element, js_code],
"nested_dict": {"nested_key": "nested_value"},
}
result = tojavascript(combined_dict)
expected_lines = [
"{",
' "key": "value",',
' "list": [',
'"value1",',
'"value2",',
element.get_name() + ",",
"console.log('Hello, World!'),",
"],",
' "nestedDict": {',
' "nestedKey": "nested_value",',
"},",
"}",
]
for result_line, expected_line in zip(result.splitlines(), expected_lines):
assert result_line == expected_line


def test_to_escaped_json():
assert _to_escaped_json("hi<>&'") == '"hi\\u003c\\u003e\\u0026\\u0027"'


def test_environment_filter():
env = Environment()
assert "tojavascript" in env.filters


def test_template_environment_class():
assert Template.environment_class == Environment