Skip to content
This repository
tree: 8c1d899ac5
Fetching contributors…

Cannot retrieve contributors at this time

file 150 lines (129 sloc) 5.407 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
import os
from fnmatch import fnmatch
import yaml
from django.conf import settings

DATA_URI_START = "<!--[if (!IE)|(gte IE 8)]><!-->"
DATA_URI_END = "<!--<![endif]-->"
MHTML_START = "<!--[if lte IE 7]>"
MHTML_END = "<![endif]-->"

class JammitAssets:

    ASSET_FILENAME = 'assets.yml'
    
    def __init__(self, assets_dir):
        """
Initializes the Jammit object by reading the assets.yml file and
stores all javascripts and stylesheets in memory for easy lookup
in templates.
"""
        self.assets_dir = assets_dir
        self.assets = self.read_assets()
        
    def read_assets(self):
        """
Read the assets from the YAML and store it as a lookup dictionary.
"""
        filepath = os.path.join(self.assets_dir, self.ASSET_FILENAME)
        f = open(filepath, 'r')
        return yaml.load(f.read())
    
    def render_tags(self, asset_type, asset_package):
        """
Returns rendered <script> and <link> tags for the given package name. Will
either be a single tag or a list of tags as a string, depending on
`use_compressed_assets` profile setting.
"""
        tags = []
        if not getattr(settings, 'DEBUG_ASSETS', settings.DEBUG):
            if asset_type == 'javascripts':
                asset_type_ext = 'js'
            elif asset_type == 'stylesheets':
                asset_type_ext = 'css'
            if asset_type == 'javascripts':
                tag = self.javascript_tag_compressed(asset_package, asset_type_ext)
            elif asset_type == 'stylesheets':
                tag = self.stylesheet_tag_compressed(asset_package, asset_type_ext)
            tags.append(tag)
        else:
            patterns = self.assets[asset_type][asset_package]
            for pattern in patterns:
                paths = FileFinder.filefinder(pattern)
                for path in paths:
                    if asset_type == 'javascripts':
                        tag = self.javascript_tag(path)
                    elif asset_type == 'stylesheets':
                        tag = self.stylesheet_tag(path)
                    tags.append(tag)
        tags = self.uniquify(tags)
        return '\n'.join(tags)
    
    def render_code(self, asset_type, asset_package):
        text = []
        patterns = self.assets[asset_type][asset_package]
        
        for pattern in patterns:
            paths = FileFinder.filefinder(pattern)
            for path in paths:
                newsblur_dir = settings.NEWSBLUR_DIR
                abs_filename = os.path.join(newsblur_dir, path)
                f = open(abs_filename, 'r')
                code = f.read()
                if asset_type == 'stylesheets':
                    code = code.replace('\"', '\\"').replace('\n', ' ')
                text.append(code)
        
        return ''.join(text)
    
    def uniquify(self, tags):
        """
Returns a uniquified list of script/link tags, preserving order.
"""
        seen = set()
        unique = []
        
        for tag in tags:
            if tag not in seen:
                unique.append(tag)
                seen.add(tag)

        return unique
    
    def javascript_tag(self, path):
        return '<script src="/%s" type="text/javascript" charset="utf-8"></script>' % path
    
    def javascript_tag_compressed(self, asset_package, asset_type_ext):
        filename = 'static/%s.%s' % (asset_package, asset_type_ext)
        asset_mtime = int(os.path.getmtime(filename))
        path = '%s?%s' % (filename, asset_mtime)
        return self.javascript_tag(path)
    
    def stylesheet_tag(self, path):
        return '<link rel="stylesheet" href="/%s" type="text/css" charset="utf-8">' % path

    def stylesheet_tag_compressed(self, asset_package, asset_type_ext):
        datauri_filename = 'static/%s-datauri.%s' % (asset_package, asset_type_ext)
        original_filename = 'static/%s.%s' % (asset_package, asset_type_ext)
        asset_mtime = int(os.path.getmtime(datauri_filename))
        datauri_path = '%s?%s' % (datauri_filename, asset_mtime)
        original_path = '%s?%s' % (original_filename, asset_mtime)
        
        return '\n'.join([
            DATA_URI_START,
            self.stylesheet_tag(datauri_path),
            DATA_URI_END,
            MHTML_START,
            self.stylesheet_tag(original_path),
            MHTML_END,
        ])

class FileFinder:

    @classmethod
    def filefinder(cls, pattern):
        paths = []
        if '**' in pattern:
            folder, wild, pattern = pattern.partition('/**/')
            for f in cls.recursive_find_files(folder, pattern):
                paths.append(f)
        else:
            folder, pattern = os.path.split(pattern)
            for f in cls.find_files(folder, pattern):
                # print f, paths
                paths.append(f)
        return paths

    @classmethod
    def recursive_find_files(cls, folder, pattern):
        for root, dirs, files in os.walk(folder):
            for f in files:
                if fnmatch(f, pattern):
                    yield os.path.join(root, f)

    @classmethod
    def find_files(cls, folder, pattern):
        listdir = os.listdir(folder)
        listdir.sort()
        for entry in listdir:
            if not os.path.isdir(entry) and fnmatch(entry, pattern):
                yield os.path.join(folder, entry)
Something went wrong with that request. Please try again.