Files
edx-platform/openedx/core/djangolib/js_utils.py
Robert Raposa f555ffd585 Refactor and improve js_utils helpers
- Rename escape_json_dumps to dump_js_escaped_json
- Rename escape_js_string to js_escaped_string
- Update js_escaped_string to output empty string for None
- Introduce dump_html_escaped_json
- Move dump_js_escaped_json after the pipe as new best practice
- Introduce additional uses of helpers
- Introduce new djangolib directory and move js_utils
2016-02-03 17:13:21 -05:00

150 lines
4.7 KiB
Python

"""
Utilities for dealing with Javascript and JSON.
"""
import json
from django.utils.html import escapejs
from mako.filters import decode
from markupsafe import escape
from xmodule.modulestore import EdxJSONEncoder
def _escape_json_for_js(json_dumps_string):
"""
Escape output of JSON dumps that is safe to be embedded in a <SCRIPT> tag.
This implementation is based on escaping performed in
simplejson.JSONEncoderForHTML.
Arguments:
json_dumps_string (string): A JSON string to be escaped.
This must be the output of json.dumps to ensure:
1. The string contains valid JSON, and
2. That non-ascii characters are properly escaped
Returns:
(string) Escaped JSON that is safe to be embedded in HTML.
"""
json_dumps_string = json_dumps_string.replace("&", "\\u0026")
json_dumps_string = json_dumps_string.replace(">", "\\u003e")
json_dumps_string = json_dumps_string.replace("<", "\\u003c")
return json_dumps_string
def dump_js_escaped_json(obj, cls=EdxJSONEncoder):
"""
JSON dumps and escapes objects that are safe to be embedded in JavaScript.
Use this for anything but strings (e.g. dicts, tuples, lists, bools, and
numbers). For strings, use js_escaped_string.
The output of this method is also usable as plain-old JSON.
Usage:
Used as follows in a Mako template inside a <SCRIPT> tag::
var json_obj = ${obj | n, dump_js_escaped_json}
If you must use the cls argument, then use as follows::
var json_obj = ${dump_js_escaped_json(obj, cls) | n}
Use the "n" Mako filter above. It is possible that the default filter
may include html escaping in the future, and this ensures proper
escaping.
Ensure ascii in json.dumps (ensure_ascii=True) allows safe skipping of
Mako's default filter decode.utf8.
Arguments:
obj: The object soon to become a JavaScript escaped JSON string. The
object can be anything but strings (e.g. dicts, tuples, lists, bools, and
numbers).
cls (class): The JSON encoder class (defaults to EdxJSONEncoder).
Returns:
(string) Escaped encoded JSON.
"""
json_string = json.dumps(obj, ensure_ascii=True, cls=cls)
json_string = _escape_json_for_js(json_string)
return json_string
def dump_html_escaped_json(obj, cls=EdxJSONEncoder):
"""
JSON dumps and escapes objects that are safe to be embedded in HTML.
Use this for anything but strings (e.g. dicts, tuples, lists, bools, and
numbers). For strings, just used the default html filter.
Usage:
Used as follows in a Mako template inside a HTML, like in
a data attribute::
data-obj='${obj | n, dump_html_escaped_json}'
If you must use the cls argument, then use as follows::
data-obj='${dump_html_escaped_json(obj, cls) | n}'
Use the "n" Mako filter above. The default filter will include
html escaping in the future, and this ensures proper ordering of
these calls.
Ensure ascii in json.dumps (ensure_ascii=True) allows safe skipping of
Mako's default filter decode.utf8.
Arguments:
obj: The object soon to become an HTML escaped JSON string. The object
can be anything but strings (e.g. dicts, tuples, lists, bools, and
numbers).
cls (class): The JSON encoder class (defaults to EdxJSONEncoder).
Returns:
(string) Escaped encoded JSON.
"""
json_string = json.dumps(obj, ensure_ascii=True, cls=cls)
json_string = escape(json_string)
return json_string
def js_escaped_string(string_for_js):
"""
Mako filter that escapes text for use in a JavaScript string.
If None is provided, returns an empty string.
Usage:
Used as follows in a Mako template inside a <SCRIPT> tag::
var my_string_for_js = "${my_string_for_js | n, js_escaped_string}"
The surrounding quotes for the string must be included.
Use the "n" Mako filter above. It is possible that the default filter
may include html escaping in the future, and this ensures proper
escaping.
Mako's default filter decode.utf8 is applied here since this default
filter is skipped in the Mako template with "n".
Arguments:
string_for_js (string): Text to be properly escaped for use in a
JavaScript string.
Returns:
(string) Text properly escaped for use in a JavaScript string as
unicode. Returns empty string if argument is None.
"""
if string_for_js is None:
string_for_js = ""
string_for_js = decode.utf8(string_for_js)
string_for_js = escapejs(string_for_js)
return string_for_js