Skip to content

Commit

Permalink
Inject CSS/JSSource only once.
Browse files Browse the repository at this point in the history
  • Loading branch information
Cito committed Oct 8, 2012
1 parent cbf6032 commit ae13c36
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 14 deletions.
38 changes: 33 additions & 5 deletions tests/test_resources.py
Expand Up @@ -32,13 +32,13 @@ def setUp(self):
def test_res_collection(self):
rl = testapi.request(1, mw)
wa = TestWidget(id='a')
wb = TestWidget(id='b', resources=[js,css])
wb = TestWidget(id='b', resources=[js, css])
wa.display()
rl = twc.core.request_local()
assert(len(rl.get('resources', [])) == 0)
wb.display()
for r in rl['resources']:
assert(any(isinstance(r, b) for b in [js,css]))
assert(any(isinstance(r, b) for b in [js, css]))
rl = testapi.request(2)
r = rl.get('resources', [])
assert len(r) == 0, r
Expand Down Expand Up @@ -187,6 +187,34 @@ def test_inject_both(self):
<title>a</title></head><body>hello<script type="text/javascript">bob</script>\
</body></html>')

def test_inject_js_twice(self):
rl = testapi.request(1, mw)
js.inject()
js.inject()
out = twc.inject_resources(html)
print out
assert eq_xhtml(out, '<html><head>\
<script type="text/javascript" src="paj"></script>\
<title>a</title></head><body>hello</body></html>')

def test_inject_jssrc_twice(self):
rl = testapi.request(1, mw)
jssrc.inject()
jssrc.inject()
out = twc.inject_resources(html)
assert eq_xhtml(out, '<html><head>\
<title>a</title></head><body>hello<script type="text/javascript">bob</script>\
</body></html>')

def test_inject_csssrc_twice(self):
rl = testapi.request(1, mw)
csssrc.inject()
csssrc.inject()
out = twc.inject_resources(html)
assert eq_xhtml(out, '<html><head>\
<style type="text/css">.bob { font-weight: bold; }</style>\
<title>a</title></head><body>hello</body></html>')

def test_detect_clear(self):
widget = twc.Widget(id='a', template='genshi:tw2.core.test_templates.inner_genshi', test='test', resources=[js])
rl = testapi.request(1, mw)
Expand Down Expand Up @@ -286,7 +314,7 @@ def test_display(self):
displays.append(r.display(template='%s:%s' % (e, twr.JSSource.template)))

compare_to = str(displays[0]).strip()
equal_displays = filter(lambda x:str(x).strip()==compare_to, displays)
equal_displays = filter(lambda x: str(x).strip() == compare_to, displays)
assert len(displays) == len(equal_displays), equal_displays

class TestCSSSourceEscaping(tb.WidgetTest):
Expand All @@ -310,7 +338,7 @@ def test_display(self):
displays.append(r.display(template='%s:%s' % (e, twr.CSSSource.template)))

compare_to = str(displays[0]).strip()
equal_displays = filter(lambda x:str(x).strip()==compare_to, displays)
equal_displays = filter(lambda x: str(x).strip() == compare_to, displays)
assert len(displays) == len(equal_displays), equal_displays

from pkg_resources import Requirement
Expand Down Expand Up @@ -338,7 +366,7 @@ def testJSSymbol(self):
should set the src attribute
"""
s = twr.JSSymbol("source")
self.assert_(s.src=="source")
self.assert_(s.src == "source")

def testEncoderDefault(self):
enc = twc.encoder
Expand Down
18 changes: 12 additions & 6 deletions tw2/core/resources.py
Expand Up @@ -176,11 +176,9 @@ def __hash__(self):
)

def __eq__(self, other):
attrs = ['link', 'modname', 'filename']
return all([
getattr(self, attr, None) == getattr(other, attr, None)
for attr in attrs
])
return (isinstance(other, Link) and self.link == other.link
and self.modname == other.modname
and self.filename == other.filename)

def __repr__(self):
return "%s('%s')" % (
Expand Down Expand Up @@ -227,6 +225,9 @@ class JSSource(Resource):
location = 'bodybottom'
template = 'tw2.core.templates.jssource'

def __eq__(self, other):
return isinstance(other, JSSource) and self.src == other.src

def __repr__(self):
return "%s('%s')" % (self.__class__.__name__, self.src)

Expand All @@ -236,6 +237,7 @@ def prepare(self):
raise ValueError("%r must be provided a 'src' attr" % self)
self.src = Markup(self.src)


class CSSSource(Resource):
"""
Inline Cascading Style-Sheet code.
Expand All @@ -244,6 +246,9 @@ class CSSSource(Resource):
location = 'head'
template = 'tw2.core.templates.csssource'

def __eq__(self, other):
return isinstance(other, CSSSource) and self.src == other.src

def __repr__(self):
return "%s('%s')" % (self.__class__.__name__, self.src)

Expand All @@ -253,6 +258,7 @@ def prepare(self):
raise ValueError("%r must be provided a 'src' attr" % self)
self.src = Markup(self.src)


class _JSFuncCall(JSSource):
"""
Internal use inline JavaScript function call.
Expand Down Expand Up @@ -445,7 +451,7 @@ class _ResourceInjector(util.MultipleReplacer):
cannot be injected again (in the same request). This is useful in case
:class:`injector_middleware` is stacked so it doesn't inject them again.
Injecting them explicitly is neccesary if the response's body is being
Injecting them explicitly is necessary if the response's body is being
cached before the middleware has a chance to inject them because when the
cached version is served no widgets are being rendered so they will not
have a chance to register their resources.
Expand Down
6 changes: 3 additions & 3 deletions tw2/core/util.py
Expand Up @@ -47,7 +47,7 @@ class MultipleReplacer(object):
"""Performs several regexp substitutions on a string with a single pass.
``dct`` is a dictionary keyed by a regular expression string and with a
callable as value that will get called to produce a subsituted value.
callable as value that will get called to produce a substituted value.
The callable takes the matched text as first argument and may take any
number of positional and keyword arguments. These arguments are any extra
Expand Down Expand Up @@ -79,7 +79,7 @@ def __repr__(self):
return "<%s at %d (%r)>" % (self.__class__.__name__, id(self),
self._raw_regexp)

def _subsitutor(self, *args, **kw):
def _substitutor(self, *args, **kw):
def substitutor(match):
tuples = itertools.izip(self._substitutors, match.groups())
for substitutor, group in tuples:
Expand All @@ -88,7 +88,7 @@ def substitutor(match):
return substitutor

def __call__(self, string, *args, **kw):
return self._regexp.sub(self._subsitutor(*args, **kw), string)
return self._regexp.sub(self._substitutor(*args, **kw), string)


def abort(req, status):
Expand Down

0 comments on commit ae13c36

Please sign in to comment.