Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

assets: add backend support for asset management

  • Loading branch information...
commit 44e60b1e5c18e457751e04859acc18e1514a9d37 1 parent c334568
Yaniv Aknin yaniv-aknin authored
2  .gitignore
View
@@ -2,3 +2,5 @@
*.pyc
*.DS_Store
runcommands.local.sh
+frontend/gen
+frontend/.webassets-cache
2  backend/app.py
View
@@ -9,6 +9,8 @@ def initialize_app(settings):
# ORDER MIGHT BE IMPORTANT BELOW THIS LINE
# install extensions and import modules that do registrations
+ # the `import x; x` idiom silences pyflakes etc
import views ; views
+ import assets ; assets
return app
78 backend/assets.py
View
@@ -0,0 +1,78 @@
+from os import path
+from glob import glob
+from functools import partial
+from collections import defaultdict
+
+from flask.ext.assets import Environment, Bundle
+from webassets.filter import register_filter, get_filter
+
+from config.cdn import proxied
+
+from utils.flaskutils import RegisterJst
+from utils.ext.bunch import Bunch
+from utils.ext.path import Path
+
+from .app import app
+
+Coffee = partial(Bundle, filters='coffeescript', debug=False)
+SCSS = partial(Bundle, filters='pyscss', debug=False)
+JS = partial(Bundle, filters='yui_js')
+CSS = partial(Bundle, filters='yui_css')
+
+assets = Environment(app)
+assets.url = proxied('/static/')
+
+class Special(str): pass
+class Depends(Special): pass
+
+asset_spec = {}
+
+def get_rules(kind):
+ if kind == '.css':
+ return Bunch(
+ final_filter = ["yui_css", get_filter('cssrewrite', replace=proxied)],
+ compilers = {".scss": "pyscss"},
+ kwargs = defaultdict(dict)
+ )
+ elif kind == '.js':
+ return Bunch(final_filter="yui_js", compilers={".coffee": "coffeescript", ".jst": "register_jst"},
+ kwargs=defaultdict(dict))
+ raise RuntimeError("unknown bundle kind: %s" % (kind,))
+def yield_expanded(iterable):
+ already_yielded = set()
+ base = Path(app.static_folder)
+ for element in iterable:
+ if isinstance(element, Special):
+ yield element
+ continue
+ for atom in sorted(base.relpathto(expanded) for expanded in glob(base/element)):
+ if atom in already_yielded:
+ continue
+ already_yielded.add(atom)
+ yield atom
+def register_assets(spec):
+ for name, elements in spec.iteritems():
+ name, kind = path.splitext(name)
+ rules = get_rules(kind)
+ filemap = defaultdict(list)
+ for element in yield_expanded(elements):
+ _, extension = path.splitext(element)
+ if isinstance(element, Depends):
+ rules.kwargs[extension]['depends'] = element
+ continue
+ filemap[extension].append(element)
+
+ contents = list(filemap.get(kind, []))
+ for compiled_extension, compiled_filters in rules['compilers'].iteritems():
+ if compiled_extension in filemap:
+ kwargs = rules.kwargs.get(compiled_extension, {})
+ contents.append(Bundle(*filemap[compiled_extension], filters=compiled_filters, debug=False,
+ output="gen/%s.%%(version)s%s%s" % (name, compiled_extension, kind), **kwargs))
+ assets.register(
+ name + kind,
+ Bundle(*contents, filters=rules.final_filter, output="gen/%s.%%(version)s%s" % (name, kind),
+ **rules.kwargs[kind])
+ )
+register_filter(RegisterJst)
+register_assets(asset_spec)
+
4 requirements.txt
View
@@ -1,8 +1,12 @@
Flask==0.9
+Flask-Assets==0.8
Flask-Script==0.5.3
Jinja2==2.6
URLObject==2.3.1
Werkzeug==0.8.3
boto==2.8.0
+pyScss==1.1.4
readline==6.2.4.1
+webassets==0.8
wsgiref==0.1.2
+yuicompressor==2.4.7
26 utils/flaskutils.py
View
@@ -0,0 +1,26 @@
+import os
+import json
+
+from flask import current_app
+from webassets.filter import Filter
+
+class RegisterJst(Filter):
+ name = "register_jst"
+ def input(self, _in, out, source_path, **kwargs):
+ template_data = _in.read()
+ assert source_path.find(current_app.static_folder) == 0
+ source_path = source_path[len(current_app.static_folder):].lstrip(os.path.sep)
+ wrapped_template = "register_template(%s, %s);" %(json.dumps(source_path), json.dumps(template_data))
+ out.write(wrapped_template)
+
+ def output(self, _in, out, **kwargs):
+ out_data = _in.read()
+ out_data = """(function(){
+ window.jj = window.jj || {};
+ window.jj.jst = window.jj.jst || {};
+ var register_template = function(name, data){
+ window.jj.jst[name] = data;
+ };
+ %s
+ })();""" %(out_data,)
+ out.write(out_data)
Please sign in to comment.
Something went wrong with that request. Please try again.