Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: src/site/_plugins/asset_bundler.rb

Issue 10700168: massive CL is massive (Closed) Base URL: https://code.google.com/p/dartlang-site/@master
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/site/_plugins/articles_tag.rb ('k') | src/site/_plugins/pygments_cache.rb » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #
2 # Jekyll Asset Bundler
3 #
4 # Author : Colin Kennedy
5 # Repo : http://github.com/moshen/jekyll-asset_bundler
6 # License: MIT, see LICENSE file
7 #
8
9 require 'yaml'
10 require 'digest/md5'
11 require 'net/http'
12 require 'uri'
13
14 module Jekyll
15
16 class BundleTag < Liquid::Block
17 @@supported_types = ['js', 'css']
18
19 def initialize(tag_name, text, tokens)
20 super
21 @text = text
22 @files = {}
23 end
24
25 def render(context)
26 src = context.registers[:site].source
27 raw_markup = super(context)
28 begin
29 @assets = YAML::load(raw_markup)
30 rescue
31 puts <<-END
32 Asset Bundler - Error: Problem parsing a YAML bundle
33 #{raw_markup}
34
35 #{$!}
36 END
37 end
38
39 if @assets.class != Array
40 puts "Asset Bundler - Error: YAML bundle is not an Array\n#{raw_markup}"
41 @assets = []
42 end
43
44 add_files_from_list(src, @assets)
45
46 markup = ""
47
48 @files.each {|k,v|
49 markup.concat(Bundle.new(v, k, context).markup())
50 }
51
52 markup
53 end
54
55 def add_files_from_list(src, list)
56 list.each {|a|
57 path = File.join(src, a)
58 if (File.basename(a) !~ /^\.+/ and File.file?(path)) or a =~ /^(https?:) ?\/\//i
59 add_file_by_type(a)
60 else
61 puts "Asset Bundler Error - File: #{path} not found, ignoring..."
62 end
63 }
64 end
65
66 def add_file_by_type(file)
67 if file =~ /\.([^\.]+)$/
68 type = $1.downcase()
69 return if @@supported_types.index(type).nil?
70 if !@files.key?(type)
71 @files[type] = []
72 end
73
74 @files[type].push(file)
75 end
76 end
77
78 end
79
80 class BundleGlobTag < BundleTag
81 def add_files_from_list(src, list)
82 list.each {|a|
83 Dir.glob(File.join(src, a)) {|f|
84 if f !~ /^\.+/ and File.file?(f)
85 add_file_by_type(f.sub(src,''))
86 end
87 }
88 }
89 end
90
91 end
92
93 class DevAssetsTag < BundleTag
94 def render(context)
95 if Bundle.config(context)['dev']
96 super(context)
97 else
98 ''
99 end
100 end
101
102 def add_files_from_list(src, list)
103 list.each {|a|
104 add_file_by_type(a)
105 }
106 end
107 end
108
109 class Bundle
110 @@bundles = {}
111 @@default_config = {
112 'compile' => { 'coffee' => false, 'less' => false },
113 'compress' => { 'js' => false, 'css' => false },
114 'base_path' => '/bundles/',
115 'remove_bundled' => false,
116 'dev' => false
117 }
118 attr_reader :content, :hash, :filename, :base
119
120 def initialize(files, type, context)
121 @files = files
122 @type = type
123 @context = context
124 @content = ''
125 @hash = ''
126 @filename = ''
127
128 @config = Bundle.config(@context)
129 @base = @config['base_path']
130
131 @filename_hash = Digest::MD5.hexdigest(@files.join())
132 if @@bundles.key?(@filename_hash)
133 @filename = @@bundles[@filename_hash].filename
134 @base = @@bundles[@filename_hash].base
135 else
136 load_content()
137 end
138 end
139
140 def self.config(context)
141 ret_config = nil
142 if context.registers[:site].config.key?("asset_bundler")
143 ret_config = @@default_config.deep_merge(context.registers[:site].config ["asset_bundler"])
144 else
145 ret_config = @@default_config
146 end
147
148 if context.registers[:site].config.key?("dev")
149 ret_config['dev'] = context.registers[:site].config["dev"] ? true : fals e
150 end
151
152 if context.registers[:site].config['server']
153 ret_config['dev'] = true
154 end
155
156 ret_config
157 end
158
159 def load_content()
160 if @config['dev']
161 @@bundles[@filename_hash] = self
162 return
163 end
164
165 src = @context.registers[:site].source
166
167 @files.each {|f|
168 if f =~ /^(https?:)?\/\//i
169 # Make all requests via http
170 f = "http:#{f}" if !$1
171 f.sub!( /^https/i, "http" ) if $1 =~ /^https/i
172 @content.concat(remote_asset_cache(URI(f)))
173 else
174 @content.concat(File.read(File.join(src, f)))
175 end
176 }
177
178 @hash = Digest::MD5.hexdigest(@content)
179 @filename = "#{@hash}.#{@type}"
180 cache_file = File.join(cache_dir(), @filename)
181
182 if File.readable?(cache_file) and @config['compress'][@type]
183 @content = File.read(cache_file)
184 elsif @config['compress'][@type]
185 # TODO: Compilation of Less and CoffeeScript would go here
186 compress()
187 File.open(cache_file, "w") {|f|
188 f.write(@content)
189 }
190 end
191
192 @context.registers[:site].static_files.push(self)
193 remove_bundled() if @config['remove_bundled']
194
195 @@bundles[@filename_hash] = self
196 end
197
198 def cache_dir()
199 cache_dir = File.expand_path( "../_asset_bundler_cache",
200 @context.registers[:site].plugins )
201 if( !File.directory?(cache_dir) )
202 FileUtils.mkdir_p(cache_dir)
203 end
204
205 cache_dir
206 end
207
208 def remote_asset_cache(uri)
209 cache_file = File.join(cache_dir(),
210 "remote.#{Digest::MD5.hexdigest(uri.to_s)}.#{@type} ")
211 content = ""
212
213 if File.readable?(cache_file)
214 content = File.read(cache_file)
215 else
216 begin
217 puts "Asset Bundler - Downloading: #{uri.to_s}"
218 content = Net::HTTP.get(uri)
219 File.open(cache_file, "w") {|f|
220 f.write( content )
221 }
222 rescue
223 puts "Asset Bundler - Error: There was a problem downloading #{f}\n # {$!}"
224 end
225 end
226
227 return content
228 end
229
230 # Removes StaticFiles from the _site if they are bundled
231 # and the remove_bundled option is true
232 # which... it isn't by default
233 def remove_bundled()
234 src = @context.registers[:site].source
235 @files.each {|f|
236 @context.registers[:site].static_files.select! {|s|
237 if s.class == StaticFile
238 s.path != File.join(src, f)
239 else
240 true
241 end
242 }
243 }
244 end
245
246 def compress()
247 return if @config['dev']
248
249 case @config['compress'][@type]
250 when 'yui'
251 compress_yui()
252 when 'closure'
253 compress_closure()
254 else
255 compress_command()
256 end
257 end
258
259 def compress_command()
260 temp_path = cache_dir()
261 command = String.new(@config['compress'][@type])
262 infile = false
263 outfile = false
264 used_files = []
265
266 if command =~ /:infile/
267 File.open(File.join(temp_path, "infile.#{@filename_hash}.#{@type}"), mod e="w") {|f|
268 f.write(@content)
269 used_files.push( f.path )
270 infile = f.path
271 }
272 command.sub!( /:infile/, "\"#{infile.gsub(File::SEPARATOR,
273 File::ALT_SEPARATOR || File::SEPARATOR)}\"")
274 end
275 if command =~ /:outfile/
276 outfile = File.join(temp_path, "outfile.#{@filename_hash}.#{@type}")
277 used_files.push( outfile )
278 command.sub!( /:outfile/, "\"#{outfile.gsub(File::SEPARATOR,
279 File::ALT_SEPARATOR || File::SEPARATOR)}\"")
280 end
281
282 if infile and outfile
283 `#{command}`
284 else
285 mode = "r"
286 mode = "r+" if !infile
287 IO.popen(command, mode) {|i|
288 if !infile
289 i.puts(@content)
290 i.close_write()
291 end
292 @content = i.gets() if !outfile
293 }
294 end
295
296 if outfile
297 @content = File.read( outfile )
298 end
299
300 used_files.each {|f|
301 File.unlink( f )
302 }
303 end
304
305 def compress_yui()
306 require 'yui/compressor'
307 case @type
308 when 'js'
309 @content = YUI::JavaScriptCompressor.new.compress(@content)
310 when 'css'
311 @content = YUI::CssCompressor.new.compress(@content)
312 end
313 end
314
315 def compress_closure()
316 require 'closure-compiler'
317 case @type
318 when 'js'
319 @content = Closure::Compiler.new.compile(@content)
320 end
321 end
322
323 def markup()
324 return dev_markup() if @config['dev']
325 case @type
326 when 'js'
327 "<script type='text/javascript' src='#{@base}#{@filename}'></script>\n "
328 when 'coffee'
329 "<script type='text/coffeescript' src='#{@base}#{@filename}'></script> \n"
330 when 'css'
331 "<link rel='stylesheet' type='text/css' href='#{@base}#{@filename}' /> \n"
332 when 'less'
333 "<link rel='stylesheet/less' type='text/css' href='#{@base}#{@filename }' />\n"
334 end
335 end
336
337 def dev_markup()
338 output = ''
339 @files.each {|f|
340 case @type
341 when 'js'
342 output.concat("<script type='text/javascript' src='#{f}'></script>\n ")
343 when 'coffee'
344 output.concat("<script type='text/coffeescript' src='#{f}'></script> \n")
345 when 'css'
346 output.concat("<link rel='stylesheet' type='text/css' href='#{f}' /> \n")
347 when 'less'
348 output.concat("<link rel='stylesheet/less' type='text/css' href='#{f }' />\n")
349 end
350 }
351
352 return output
353 end
354
355 # Methods required by Jekyll::Site to write out the bundle
356 # This is where we give Jekyll::Bundle a Jekyll::StaticFile
357 # duck call and send it on its way.
358 def destination(dest)
359 File.join(dest, @base, @filename)
360 end
361
362 def write(dest)
363 dest_path = destination(dest)
364 return false if File.exists?(dest_path)
365
366 FileUtils.mkdir_p(File.dirname(dest_path))
367 File.open(dest_path, "w") {|o|
368 o.write(@content)
369 }
370
371 true
372 end
373 # End o' the duck call
374
375 end
376
377 end
378
379 Liquid::Template.register_tag('bundle' , Jekyll::BundleTag )
380 Liquid::Template.register_tag('bundle_glob', Jekyll::BundleGlobTag)
381 Liquid::Template.register_tag('dev_assets' , Jekyll::DevAssetsTag )
OLDNEW
« no previous file with comments | « src/site/_plugins/articles_tag.rb ('k') | src/site/_plugins/pygments_cache.rb » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698