~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/scripts/utilities/js/combo.py

[r=deryck][bug=803954] Bring lazr-js source into lp tree and package
        yui as a dependency

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import os
 
2
import cgi
 
3
import urlparse
 
4
 
 
5
from jsbuild import CSSComboFile, JSComboFile
 
6
 
 
7
 
 
8
def parse_url(url):
 
9
    """Parse a combo URL.
 
10
 
 
11
    Returns the list of arguments in the original order.
 
12
    """
 
13
    scheme, loc, path, query, frag = urlparse.urlsplit(url)
 
14
    return parse_qs(query)
 
15
 
 
16
 
 
17
def parse_qs(query):
 
18
    """Parse a query string.
 
19
 
 
20
    Returns the list of arguments in the original order.
 
21
    """
 
22
    params = cgi.parse_qsl(query, keep_blank_values=True)
 
23
    return tuple([param for param, value in params])
 
24
 
 
25
 
 
26
def combine_files(fnames, root, resource_prefix="",
 
27
                  minify_css=True, rewrite_urls=True):
 
28
    """Combine many files into one.
 
29
 
 
30
    Returns an iterator with the combined content of all the
 
31
    files. The relative path to root will be included as a comment
 
32
    between each file.
 
33
    """
 
34
 
 
35
    combo_by_kind = {
 
36
        ".css": CSSComboFile([], os.path.join(root, "combo.css"),
 
37
                             resource_prefix, minify_css, rewrite_urls),
 
38
        ".js": JSComboFile([], os.path.join(root, "combo.js")),
 
39
    }
 
40
 
 
41
    for fname in fnames:
 
42
        combo = combo_by_kind.get(os.path.splitext(fname)[-1])
 
43
        if combo is None:
 
44
            continue
 
45
        full = os.path.abspath(os.path.join(root, fname))
 
46
        yield combo.get_file_header(full)
 
47
        if not full.startswith(root) or not os.path.exists(full):
 
48
            yield combo.get_comment("[missing]")
 
49
        else:
 
50
            f = open(full, "r")
 
51
            content = f.read()
 
52
            f.close()
 
53
            yield combo.filter_file_content(content, full)
 
54
 
 
55
 
 
56
def combo_app(root, resource_prefix="", minify_css=True, rewrite_urls=True):
 
57
    """A simple YUI Combo Service WSGI app.
 
58
 
 
59
    Serves any files under C{root}, setting an appropriate
 
60
    C{Content-Type} header.
 
61
    """
 
62
    root = os.path.abspath(root)
 
63
    def app(environ, start_response, root=root):
 
64
        fnames = parse_qs(environ["QUERY_STRING"])
 
65
        content_type = "text/plain"
 
66
        if fnames:
 
67
            if fnames[0].endswith(".js"):
 
68
                content_type = "text/javascript"
 
69
            elif fnames[0].endswith(".css"):
 
70
                content_type = "text/css"
 
71
        else:
 
72
            start_response("404 Not Found", [("Content-Type", content_type)])
 
73
            return ("Not Found",)
 
74
        start_response("200 OK", [("Content-Type", content_type)])
 
75
        return combine_files(fnames, root, resource_prefix,
 
76
                             minify_css, rewrite_urls)
 
77
    return app