Separate two forms of tag; support additional html attrs

Closes #154
This commit is contained in:
Matthew Tretter 2012-10-17 23:39:48 -04:00
parent 770a8cebf4
commit b0b466618f

View file

@ -1,5 +1,6 @@
from django import template
from django.utils.safestring import mark_safe
import re
from ..files import ImageSpecCacheFile
from .. import specs
@ -7,27 +8,86 @@ from .. import specs
register = template.Library()
class SpecNode(template.Node):
def __init__(self, spec_id, source_image, variable_name=None):
self.spec_id = spec_id
self.source_image = source_image
self.variable_name = variable_name
html_attr_pattern = r"""
(?P<name>\w+) # The attribute name
(
\s*=\s* # an equals sign, that may or may not have spaces around it
(?P<value>
("[^"]*") # a double-quoted value
| # or
('[^']*') # a single-quoted value
| # or
([^"'<>=\s]+) # an unquoted value
)
)?
"""
def render(self, context):
html_attr_re = re.compile(html_attr_pattern, re.VERBOSE)
class SpecResultNodeMixin(object):
def __init__(self, spec_id, source_file):
self._spec_id = spec_id
self._source_file = source_file
def get_spec(self, context):
from ..utils import autodiscover
autodiscover()
source_image = self.source_image.resolve(context)
spec_id = self.spec_id.resolve(context)
spec_id = self._spec_id.resolve(context)
spec = specs.registry.get_spec(spec_id)
if callable(spec):
spec = spec()
file = ImageSpecCacheFile(spec, source_image)
if self.variable_name is not None:
variable_name = str(self.variable_name)
context[variable_name] = file
return ''
return spec
return mark_safe(u'<img src="%s" />' % file.url)
def get_source_file(self, context):
return self._source_file.resolve(context)
def get_file(self, context):
spec = self.get_spec(context)
source_file = self.get_source_file(context)
return ImageSpecCacheFile(spec, source_file)
class SpecResultAssignmentNode(template.Node, SpecResultNodeMixin):
def __init__(self, spec_id, source_file, variable_name):
super(SpecResultAssignmentNode, self).__init__(spec_id, source_file)
self._variable_name = variable_name
def get_variable_name(self, context):
return unicode(self._variable_name)
def render(self, context):
variable_name = self.get_variable_name(context)
context[variable_name] = self.get_file(context)
return ''
class SpecResultImgTagNode(template.Node, SpecResultNodeMixin):
def __init__(self, spec_id, source_file, html_attrs):
super(SpecResultImgTagNode, self).__init__(spec_id, source_file)
self._html_attrs = html_attrs
def get_html_attrs(self, context):
attrs = []
for attr in self._html_attrs:
match = html_attr_re.search(attr)
if match:
attrs.append((match.group('name'), match.group('value')))
return attrs
def get_attr_str(self, k, v):
return k if v is None else '%s=%s' % (k, v)
def render(self, context):
file = self.get_file(context)
attrs = self.get_html_attrs(context)
attr_dict = dict(attrs)
if not 'width' in attr_dict and not 'height' in attr_dict:
attrs = attrs + [('width', '"%s"' % file.width),
('height', '"%s"' % file.height)]
attrs = [('src', '"%s"' % file.url)] + attrs
attr_str = ' '.join(self.get_attr_str(k, v) for k, v in attrs)
return mark_safe(u'<img %s />' % attr_str)
#@register.tag
@ -51,21 +111,26 @@ def spec(parser, token):
"""
args = token.split_contents()
arg_count = len(args)
bits = token.split_contents()
tag_name = bits.pop(0)
if (arg_count < 3 or arg_count > 5
or (arg_count > 3 and arg_count < 5)
or (args == 5 and args[3] != 'as')):
if len(bits) == 4 and bits[2] == 'as':
return SpecResultAssignmentNode(
parser.compile_filter(bits[0]), # spec id
parser.compile_filter(bits[1]), # source file
parser.compile_filter(bits[3]), # var name
)
elif len(bits) > 1:
return SpecResultImgTagNode(
parser.compile_filter(bits[0]), # spec id
parser.compile_filter(bits[1]), # source file
bits[2:], # html attributes
)
else:
raise template.TemplateSyntaxError('\'spec\' tags must be in the form'
' "{% spec spec_id image %}" or'
' "{% spec spec_id image'
' as varname %}"')
spec_id = parser.compile_filter(args[1])
source_image = parser.compile_filter(args[2])
variable_name = arg_count > 3 and args[4] or None
return SpecNode(spec_id, source_image, variable_name)
spec = spec_tag = register.tag(spec)