def to_python(self, value): """ The data is serialized as JSON with the keys `raw` and `html` where `raw` is the entered string with LaTeX and `html` is the html string generated by KaTeX. If this function gets just a string, then we need to generate the LaTeX. WARNING: Generating the LaTeX server-side requires Node.js to be installed. To generate the LaTeX client-side, make sure that you specify that the MathFields that you use are assigned to the widget `MathFieldWidget` in your app's admin.py. """ if value is None: return None if value == "": return {'raw': '', 'html': ''} if isinstance(value, basestring): try: return dict(json.loads(value)) except (ValueError, TypeError): # the value was stored as just a string. Try to compile it to # LaTeX and return a dictionary, or raise a NodeError return store_math(value) if isinstance(value, dict): return value return {'raw': '', 'html': ''}
def get_prep_value(self, value): if not value: return json.dumps({'raw': '', 'html': ''}) if isinstance(value, basestring): try: dictval = json.loads(value) except (ValueError, TypeError): # This means the user tried to pass just a string of text in. # The HTML will be generated manually, but this will only work # if node.js is installed on the server. Otherwise, a NodeError # will be raised. return json.dumps(store_math(value)) else: if {'raw', 'html'} == set(dictval.keys()): return value else: raise MathFieldValidationError(self, value) if isinstance(value, dict): if {'raw', 'html'} == set(value.keys()): return json.dumps(value) else: raise MathFieldValidationError(self, value) return json.dumps({'raw': '', 'html': ''})
def test_store_math_escaped_html(self): self.assertEqual( api.store_math('<script>alert(1);</script>$x=2$'), { 'raw': '<script>alert(1);</script>$x=2$', 'html': """<script>alert(1);</script><span class="katex"><span class="katex-inner"><span class="strut" style="height:0.64444em;"></span><span class="strut bottom" style="height:0.64444em;vertical-align:0em;"></span><span class="base textstyle uncramped"><span class="mord mathit">x</span><span class="mrel">=</span><span class="mord">2</span></span></span></span>""" })
def test_store_math_escaped_dollars(self): self.assertEqual( api.store_math('\\$foo$x=\\$ 2$bar\\$'), { 'raw': '\\$foo$x=\\$ 2$bar\\$', 'html': """$foo<span class="katex"><span class="katex-inner"><span class="strut" style="height:0.75em;"></span><span class="strut bottom" style="height:0.80556em;vertical-align:-0.05556em;"></span><span class="base textstyle uncramped"><span class="mord mathit">x</span><span class="mrel">=</span><span class="mord">$</span><span class="mord">2</span></span></span></span>bar$""" })
def test_store_math_latex_at_start(self): self.assertEqual( api.store_math('$x=2$'), { 'raw': '$x=2$', 'html': """<span class="katex"><span class="katex-inner"><span class="strut" style="height:0.64444em;"></span><span class="strut bottom" style="height:0.64444em;vertical-align:0em;"></span><span class="base textstyle uncramped"><span class="mord mathit">x</span><span class="mrel">=</span><span class="mord">2</span></span></span></span>""" })
def render(self, name, value, attrs=None): output = super(MathFieldWidget, self).render(name, value, attrs) output = '<div id="{0}-container"><span>{1}</span></div>'.format( attrs['id'], output) if value: if isinstance(value, basestring): try: value = dict(json.loads(value)) except (ValueError, TypeError): # the value was stored as just a string. Try to compile it to # LaTeX and return a dictionary, or raise a NodeError value = store_math(value) if isinstance(value, dict): raw = value['raw'] if 'raw' in value else '' html = value['html'] if 'html' in value else '' html = html.replace('"', '\\"').replace("'", "\\'") raw = raw.replace('\n', '\\n').replace("\n", "\\n") html = html.replace('\n', '<br />').replace("\n", "<br />") elif isinstance(value, basestring): raw = value html = '' raw = cgi.escape(raw.replace('\\', '\\\\')) else: raw = html = '' if hasattr(settings, 'STATIC_URL'): static_url = getattr(settings, 'STATIC_URL', {}) else: static_url = '/static/' output += textwrap.dedent(""" <link rel="stylesheet" type="text/css" href="{static}mathfield/css/mathfield.css"/> <script type="text/javascript" src="{static}mathfield/js/mathfield.min.js"></script> <script type="text/javascript"> renderMathFieldForm("{id}", "{raw}", "{html}"); </script> """.format(static=static_url, id=attrs['id'], raw=raw, html=html)) return mark_safe(output)
def test_store_math_blank(self): self.assertEqual(api.store_math(), {'raw': '', 'html': '',})
def test_store_math_escaped_html(self): self.assertEqual(api.store_math('<script>alert(1);</script>$x=2$'), { 'raw': '<script>alert(1);</script>$x=2$', 'html': """<script>alert(1);</script><span class="katex"><span class="katex-inner"><span class="strut" style="height:0.64444em;"></span><span class="strut bottom" style="height:0.64444em;vertical-align:0em;"></span><span class="base textstyle uncramped"><span class="mord mathit">x</span><span class="mrel">=</span><span class="mord">2</span></span></span></span>""" })
def test_store_math_escaped_dollars(self): self.assertEqual(api.store_math('\\$foo$x=\\$ 2$bar\\$'), { 'raw': '\\$foo$x=\\$ 2$bar\\$', 'html': """$foo<span class="katex"><span class="katex-inner"><span class="strut" style="height:0.75em;"></span><span class="strut bottom" style="height:0.80556em;vertical-align:-0.05556em;"></span><span class="base textstyle uncramped"><span class="mord mathit">x</span><span class="mrel">=</span><span class="mord">$</span><span class="mord">2</span></span></span></span>bar$""" })
def test_store_math_no_math(self): self.assertEqual(api.store_math('no math'), { 'raw': 'no math', 'html': 'no math', })
def test_store_math_no_math(self): self.assertEqual(api.store_math('no math'), {'raw': 'no math', 'html': 'no math',})
def test_store_math_html_given(self): self.assertEqual(api.store_math('foo', 'bar'), {'raw': 'foo', 'html': 'bar',})
def test_store_math_blank(self): self.assertEqual(api.store_math(), { 'raw': '', 'html': '', })
def test_store_math_latex_at_start(self): self.assertEqual(api.store_math('$x=2$'), { 'raw': '$x=2$', 'html': """<span class="katex"><span class="katex-inner"><span class="strut" style="height:0.64444em;"></span><span class="strut bottom" style="height:0.64444em;vertical-align:0em;"></span><span class="base textstyle uncramped"><span class="mord mathit">x</span><span class="mrel">=</span><span class="mord">2</span></span></span></span>""" })
def test_store_math_html_given(self): self.assertEqual(api.store_math('foo', 'bar'), { 'raw': 'foo', 'html': 'bar', })