1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
9 RE_REPLACEMENT_FIELD
= re
.compile(r
'{{(?P<field_spec>[^}]*)}}')
10 RE_FIELD_IDENTIFIER
= re
.compile(r
'(?P<modifier>[@*])?(?P<name>\w+)$')
13 def RenderValue(value
):
14 """Convert a Python value to a string with its JavaScript representation."""
15 return json
.dumps(value
, sort_keys
=True)
18 def Render(template
, **kwargs
):
19 """Helper method to interpolate Python values into JavaScript snippets.
21 Placeholders in the template, field names enclosed in double curly braces,
22 are replaced with the value of the corresponding named argument.
24 Prefixing a field name with '*' causes the value, expected to be a
25 sequence of individual values, to be all interpolated and separated by
28 Prefixing a field name with '@' causes the value to be inserted literally.
34 'var {{ @var_name }} = f({{ x }}, {{ *args }});',
35 var_name='foo', x=42, args=('hello', 'there'))
39 'var foo = f(42, "hello", "there");'
42 template: A string with a JavaScript template, tagged with {{ fields }}
43 to interpolate with values.
44 **kwargs: Values to be interpolated in the template.
49 field_spec
= m
.group('field_spec').strip()
50 field
= RE_FIELD_IDENTIFIER
.match(field_spec
)
52 raise KeyError(field_spec
)
53 key
= field
.group('name')
56 if field
.group('modifier') == '@':
57 if not isinstance(value
, str):
58 raise ValueError('Literal value for %s must be a string' % field_spec
)
60 elif field
.group('modifier') == '*':
61 return ', '.join(RenderValue(v
) for v
in value
)
63 return RenderValue(value
)
65 result
= RE_REPLACEMENT_FIELD
.sub(interpolate
, template
)
67 raise TypeError('Unexpected arguments not used in template: %s.' % (
68 ', '.join(repr(str(k
)) for k
in sorted(unused
))))