diff --git a/src/webassets/bundle.py b/src/webassets/bundle.py index d4322083..c1bdaa98 100644 --- a/src/webassets/bundle.py +++ b/src/webassets/bundle.py @@ -713,7 +713,7 @@ def _make_output_url(self, ctx): url = "%s?%s" % (url, version) return url - def _urls(self, ctx, extra_filters, *args, **kwargs): + def _urls(self, ctx, extra_filters, with_bodies, *args, **kwargs): """Return a list of urls for this bundle, and all subbundles, and, when it becomes necessary, start a build process. """ @@ -744,7 +744,13 @@ def _urls(self, ctx, extra_filters, *args, **kwargs): if ctx.auto_build: self._build(ctx, extra_filters=extra_filters, force=False, *args, **kwargs) - return [self._make_output_url(ctx)] + if with_bodies: + # The hunks returned by the _build() method aren't useful as + # they sometimes have %(version)s in them. Can this be changed? + hunk = FileHunk(self.resolve_output(ctx)) + return [(self._make_output_url(ctx), hunk.data())] + else: + return [self._make_output_url(ctx)] else: # We either have no files (nothing to build), or we are # in debug mode: Instead of building the bundle, we @@ -755,10 +761,15 @@ def _urls(self, ctx, extra_filters, *args, **kwargs): urls.extend(org._urls( wrap(ctx, cnt), merge_filters(extra_filters, self.filters), + with_bodies, *args, **kwargs)) elif is_url(cnt): - urls.append(cnt) + if with_bodies: + urls.append((cnt, UrlHunk(cnt, ctx).data())) + else: + urls.append(cnt) else: + external = None try: url = ctx.resolver.resolve_source_to_url(ctx, cnt, org) except ValueError: @@ -768,7 +779,10 @@ def _urls(self, ctx, extra_filters, *args, **kwargs): external = pull_external(ctx, cnt) url = ctx.resolver.resolve_source_to_url(ctx, external, org) - urls.append(url) + if with_bodies: + urls.append((url, FileHunk(external or cnt).data())) + else: + urls.append(url) return urls def urls(self, *args, **kwargs): @@ -784,9 +798,21 @@ def urls(self, *args, **kwargs): ctx = wrap(self.env, self) urls = [] for bundle, extra_filters, new_ctx in self.iterbuild(ctx): - urls.extend(bundle._urls(new_ctx, extra_filters, *args, **kwargs)) + urls.extend(bundle._urls(new_ctx, extra_filters, False, *args, **kwargs)) return urls + def urls_with_bodies(self, *args, **kwargs): + """Returns a list of tuples containing urls and their content. + + Works just like urls() except that it returns tuples of the urls + and their respective content. + """ + ctx = wrap(self.env, self) + urls_contents = [] + for bundle, extra_filters, new_ctx in self.iterbuild(ctx): + urls_contents.extend(bundle._urls(new_ctx, extra_filters, True, *args, **kwargs)) + return urls_contents + def pull_external(ctx, filename): """Helper which will pull ``filename`` into diff --git a/src/webassets/ext/jinja2.py b/src/webassets/ext/jinja2.py index fcfb321d..2d9e8e8a 100644 --- a/src/webassets/ext/jinja2.py +++ b/src/webassets/ext/jinja2.py @@ -142,6 +142,7 @@ def parse(self, parser): # # Summary: We have to be satisfied with a single EXTRA variable. args = [nodes.Name('ASSET_URL', 'store'), + nodes.Name('ASSET_CONTENTS', 'store'), nodes.Name('EXTRA', 'store')] # Return a ``CallBlock``, which means Jinja2 will call a Python method @@ -183,13 +184,13 @@ def _render_assets(self, filter, output, dbg, depends, files, caller=None): # Retrieve urls (this may or may not cause a build) with bundle.bind(env): - urls = bundle.urls() + urls = bundle.urls_with_bodies() # For each url, execute the content of this template tag (represented # by the macro ```caller`` given to use by Jinja2). result = u"" - for url in urls: - result += caller(url, bundle.extra) + for url, body in urls: + result += caller(url, body, bundle.extra) return result diff --git a/tests/test_ext/test_jinja2.py b/tests/test_ext/test_jinja2.py index 69877f7e..4fffe1ea 100644 --- a/tests/test_ext/test_jinja2.py +++ b/tests/test_ext/test_jinja2.py @@ -27,6 +27,7 @@ def setup(self): test_instance = self class MockBundle(Bundle): urls_to_fake = ['foo'] + content_to_fake = ['bar'] def __init__(self, *a, **kw): Bundle.__init__(self, *a, **kw) self.env = assets_env @@ -38,6 +39,9 @@ def __init__(self, *a, **kw): test_instance.the_bundle = self def urls(self, *a, **kw): return self.urls_to_fake + def urls_with_bodies(self, *a, **kw): + return zip(self.urls_to_fake, self.content_to_fake) + self._old_bundle_class = AssetsExtension.BundleClass AssetsExtension.BundleClass = self.BundleClass = MockBundle @@ -87,8 +91,14 @@ def test_output_urls(self): """Ensure the tag correctly spits out the urls the bundle returns. """ self.BundleClass.urls_to_fake = ['foo', 'bar'] + self.BundleClass.content_to_fake = ['as', 'df'] assert self.render_template('"file1" "file2" "file3"') == 'foo;bar;' + def test_asset_contents(self): + output = self.jinja_env.from_string( + '{% assets "bundle" %}{{ ASSET_CONTENTS }}{% endassets %}').render({}) + assert output == 'bar' + def test_debug_on_tag(self): content = self.jinja_env.from_string( '{% assets debug="True", "debug1.txt" %}{{ ASSET_URL }};{% endassets %}').render({})