paste 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +0,0 @@
1
- module Paste
2
- module CSS
3
- class Base < Glue
4
- end
5
- end
6
- end
data/lib/paste/js/base.rb DELETED
@@ -1,26 +0,0 @@
1
- module Paste
2
- module JS
3
- class Base < Glue
4
-
5
- include Cache
6
- include Compress
7
-
8
- def initialize
9
- config.load_path << erb_path
10
- end
11
-
12
- def paste *sources
13
- raise 'Implement me!'
14
- end
15
-
16
- def result_name sources
17
- raise 'Implement me!'
18
- end
19
-
20
- def write_result result
21
- raise 'Implement me!'
22
- end
23
-
24
- end
25
- end
26
- end
@@ -1,111 +0,0 @@
1
- require 'active_support/core_ext/module/synchronization'
2
-
3
- require 'yaml'
4
-
5
- module Paste
6
- module JS
7
- module Cache
8
-
9
- def rebuild
10
- rebuild_if do |result, sources|
11
- needs_update? result
12
- end
13
- end
14
-
15
- def rebuild!
16
- rebuild_if { |r, s| true }
17
- end
18
-
19
- def rebuild_if &blk
20
- render_all_erb
21
- results.each_pair do |result, sources|
22
- begin
23
- if blk.call(result, sources[:sources])
24
- sources[:parser].reset!
25
- write_result result
26
- end
27
- rescue ResolveError
28
- results.delete result
29
- end
30
- end
31
- end
32
-
33
- def register sources, into_hash = nil
34
- into_hash ||= results
35
-
36
- if into_hash[result_name(sources)][:sources] != sources
37
- into_hash[result_name(sources)] = {
38
- :sources => sources,
39
- :parser => config.parser.new(self, sources)
40
- }
41
-
42
- write_cache_to_disk into_hash
43
- end
44
- end
45
-
46
- def registered? sources
47
- results.key? result_name(sources)
48
- end
49
-
50
- def needs_update? result
51
- needs_update_relative_to_sources result do
52
- results[result][:sources]
53
- end
54
- end
55
-
56
- def needs_dependency_update? result
57
- needs_update_relative_to_sources result do
58
- results[result][:parser].js_dependencies
59
- end
60
- end
61
-
62
- def results
63
- return @results if defined?(@results)
64
-
65
- @results = Hash.new { {} }
66
-
67
- begin
68
- cached = YAML.load_file tmp_path(config.cache_file)
69
-
70
- if cached
71
- cached.each do |sources|
72
- register sources, @results
73
- end
74
- end
75
- rescue
76
- end
77
-
78
- @results
79
- end
80
-
81
- @@results_lock = Mutex.new
82
- synchronize :results, :with => :@@results_lock
83
-
84
- protected
85
-
86
- def needs_update_relative_to_sources result
87
- path = destination result
88
- return true unless File.exists?(path) && results.key?(result)
89
-
90
- yield.inject(false) do |prev, source|
91
- prev || File.mtime(path) < File.mtime(find(source))
92
- end
93
- end
94
-
95
- def write_cache_to_disk cache
96
- file = tmp_path config.cache_file
97
- FileUtils.mkdir_p File.dirname(file)
98
-
99
- to_write = []
100
- cache.each do |result, hash|
101
- to_write << hash[:sources]
102
- end
103
-
104
- File.open(file, 'w') do |f|
105
- f << YAML.dump(to_write)
106
- end
107
- end
108
-
109
- end
110
- end
111
- end
@@ -1,55 +0,0 @@
1
- module Paste
2
- module JS
3
- class Chain < Base
4
-
5
- def paste *sources
6
- js_dependencies = []
7
- css_dependencies = []
8
-
9
- sources.each do |source|
10
- name = result_name [source]
11
- if registered? [source]
12
- if needs_update?(name) || needs_dependency_update?(name)
13
- results[name][:parser].reset!
14
- end
15
- else
16
- register [source]
17
- end
18
-
19
- source_deps = results[name][:parser].js_dependencies
20
- js_dependencies = source_deps | js_dependencies
21
- end
22
-
23
- js_dependencies.map! do |d|
24
- result = result_name [d]
25
- register [d] unless registered? [d] # implicit dependencies
26
- write_result result if needs_update?(result)
27
-
28
- css_dependencies = css_dependencies |
29
- results[result][:parser].css_dependencies
30
-
31
- result
32
- end
33
-
34
- {
35
- :javascript => js_dependencies,
36
- :css => css_dependencies
37
- }
38
- end
39
-
40
- def write_result result
41
- file = destination result
42
-
43
- FileUtils.mkdir_p File.dirname(file)
44
- FileUtils.cp find(result), file
45
- end
46
-
47
- def result_name sources
48
- result = sources.first
49
- result += '.js' unless result.end_with?('.js')
50
- result
51
- end
52
-
53
- end
54
- end
55
- end
@@ -1,46 +0,0 @@
1
- require 'closure-compiler'
2
- require 'active_support/core_ext/hash/except'
3
-
4
- module Paste
5
- module JS
6
- module Compress
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- alias_method_chain :rebuild!, :compression
11
- end
12
-
13
- def rebuild_with_compression! options = {}
14
- rebuild_without_compression!
15
-
16
- results.keys.each do |result|
17
- compress result, options
18
- end
19
- end
20
-
21
- def compress result, options = {}
22
- case options[:compress]
23
- when 'google'
24
- google_compress result, options.except(:compress)
25
- when nil, false
26
- # Compression not asked for
27
- else
28
- raise "Unknown compression technique: #{options[:compress]}"
29
- end
30
- end
31
-
32
- protected
33
-
34
- def google_compress result, options = {}
35
- file, output = destination(result), ''
36
- handle = File.open(file, 'a+')
37
- File.open(file, 'r') do |f|
38
- output = Closure::Compiler.new(options).compile f
39
- end
40
-
41
- File.open(file, 'w+') { |f| f << output.chomp }
42
- end
43
-
44
- end
45
- end
46
- end
@@ -1,55 +0,0 @@
1
- require 'erb'
2
-
3
- module Paste
4
- module JS
5
- module ERBRenderer
6
-
7
- def render_all_erb
8
- erb_sources.each { |s| render_erb s }
9
- end
10
-
11
- def render_erb source
12
- to_generate = erb_path source.sub(/\.erb$/, '')
13
- source = find source
14
-
15
- if !File.exists?(to_generate) ||
16
- File.mtime(source) > File.mtime(to_generate)
17
-
18
- FileUtils.mkdir_p File.dirname(to_generate)
19
- contents = PasteERBHelper.new(File.read(source)).result
20
- File.open(to_generate, 'w') { |f| f << contents }
21
- end
22
- end
23
-
24
- protected
25
-
26
- def erb_sources
27
- sources = load_path.map do |path|
28
- Dir[path + '/**/*.js.erb'].map do |erb|
29
- erb.gsub(path + '/', '')
30
- end
31
- end
32
- sources.flatten
33
- end
34
-
35
- end
36
- end
37
- end
38
-
39
- # This needs to be outside of the module because we don't want to
40
- # force templates to always do ::Rails
41
- class PasteERBHelper < ERB
42
- include ActionView::Helpers if defined?(ActionView::Helpers)
43
-
44
- def config
45
- Rails.application.config.action_controller if defined?(Rails)
46
- end
47
-
48
- def result *args
49
- super binding
50
- end
51
-
52
- def controller
53
- nil
54
- end
55
- end
@@ -1,38 +0,0 @@
1
- require 'digest/sha1'
2
-
3
- module Paste
4
- module JS
5
- class Unify < Base
6
-
7
- def paste *sources
8
- result = result_name sources
9
-
10
- register sources unless registered?(sources)
11
-
12
- if needs_update?(result) || needs_dependency_update?(result)
13
- results[result][:parser].reset!
14
- write_result result
15
- end
16
-
17
- {
18
- :javascript => [result],
19
- :css => results[result][:parser].css_dependencies
20
- }
21
- end
22
-
23
- def write_result result
24
- path = destination result
25
- FileUtils.mkdir_p File.dirname(path)
26
-
27
- results[result][:parser].reset!
28
- results[result][:parser].concatenation.save_to path
29
- end
30
-
31
- def result_name sources
32
- to_digest = sources.map{ |s| s.gsub /\.js$/, '' }.sort.join
33
- Digest::SHA1.hexdigest(to_digest)[0..12] + '.js'
34
- end
35
-
36
- end
37
- end
38
- end
@@ -1,29 +0,0 @@
1
- require 'spec_helper'
2
-
3
- shared_examples_for 'a css provider' do
4
- before :each do
5
- Paste::JS::Test.write 'foo', '//= require_css <foo>'
6
- Paste::CSS::Test.write 'foo', ''
7
- end
8
-
9
- it "should require the css" do
10
- result = subject.paste 'foo'
11
- result[:css].should == ['foo']
12
- end
13
-
14
- it "should not require multiple css twice" do
15
- Paste::JS::Test.write 'bar', '//= require_css <foo>'
16
-
17
- subject.paste('foo', 'bar')[:css].should == ['foo']
18
- end
19
- end
20
-
21
- describe 'Providing CSS from javascript' do
22
- describe Paste::JS::Unify do
23
- it_should_behave_like 'a css provider'
24
- end
25
-
26
- describe Paste::JS::Chain do
27
- it_should_behave_like 'a css provider'
28
- end
29
- end
@@ -1,47 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Paste::JS::Unify, 'building cached concatenations' do
4
-
5
- before :each do
6
- Paste::JS::Test.write 'foo', 'foo()'
7
- Paste::JS::Test.write 'bar', 'bar()'
8
- Paste::JS::Test.write 'foo/baz', 'baz()'
9
-
10
- @result = subject.paste('foo', 'bar', 'foo/baz')[:javascript].first
11
- Paste::JS::Test.delete @result
12
- end
13
-
14
- it "should rebuild within the same instance of the unifier" do
15
- subject.rebuild!
16
-
17
- subject.should have_in_result(@result, "foo()\nbar()\nbaz()")
18
- end
19
-
20
- it "should allow another watcher to rebuild it" do
21
- subject = Paste::JS::Unify.new
22
- subject.rebuild!
23
-
24
- subject.should have_in_result(@result, "foo()\nbar()\nbaz()")
25
- end
26
-
27
- it "should rebuild pre-existing results despite modification times" do
28
- # Make the file exist and have the last modified time of the sources
29
- # to be previous to now
30
- subject.paste('foo', 'bar', 'foo/baz')
31
- Paste::JS::Test.write 'foo', 'foo2()', Time.now - 42
32
- Paste::JS::Test.write 'bar', 'bar2()', Time.now - 42
33
- Paste::JS::Test.write 'foo/baz', 'baz2()', Time.now - 42
34
-
35
- subject.rebuild!
36
-
37
- subject.should have_in_result(@result, "foo2()\nbar2()\nbaz2()")
38
- end
39
-
40
- it "should ignore cached results which no longer exist" do
41
- Paste::JS::Test.delete_source 'foo'
42
- Paste::JS::Test.delete_source 'bar'
43
-
44
- subject.rebuild!
45
- subject.destination(@result).should_not exist
46
- end
47
- end
@@ -1,133 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Paste::JS::Chain do
4
- before :each do
5
- Paste::JS::Test.write 'foo', 'foo()'
6
- Paste::JS::Test.write 'bar', 'bar()'
7
- Paste::JS::Test.write 'foo/baz', 'baz()'
8
- end
9
-
10
- it "should return the sources given" do
11
- results = subject.paste('foo', 'bar', 'foo/baz')[:javascript]
12
-
13
- results.sort.should == ['bar.js', 'foo.js', 'foo/baz.js']
14
- end
15
-
16
- it "should generate the concatenation when the destination doesn't exist" do
17
- subject.paste('foo', 'bar', 'foo/baz')
18
-
19
- subject.should have_in_result('foo', 'foo()')
20
- subject.should have_in_result('bar', 'bar()')
21
- subject.should have_in_result('foo/baz', 'baz()')
22
- end
23
-
24
- it "should return the sources with dependencies satisfied" do
25
- Paste::JS::Test.write 'foo', "//= require <foo/bar>\n//= require <bar>"
26
- Paste::JS::Test.write 'bar', '//= require <foo/bar>'
27
- Paste::JS::Test.write 'foo/bar', 'foobar()'
28
-
29
- subject.paste('foo', 'bar', 'foo/bar')[:javascript].should == ['foo/bar.js', 'bar.js', 'foo.js']
30
- end
31
-
32
- it "should raise an exception on circular dependencies" do
33
- Paste::JS::Test.write 'foo', '//= require <bar>'
34
- Paste::JS::Test.write 'bar', '//= require <foo>'
35
-
36
- lambda {
37
- subject.paste('foo', 'bar')
38
- }.should raise_exception(/circular dependency/i)
39
- end
40
-
41
- describe "regenerating files" do
42
- it "should only regenerate modified files" do
43
- subject.paste('foo', 'bar', 'foo/baz')
44
-
45
- Paste::JS::Test.write 'foo', 'foo(foo)', Time.now - 42
46
- Paste::JS::Test.write 'bar', 'bar(bar)', Time.now + 42
47
-
48
- subject.paste('foo', 'bar', 'foo/baz')
49
-
50
- subject.should have_in_result('foo', 'foo()')
51
- subject.should have_in_result('bar', 'bar(bar)')
52
- subject.should have_in_result('foo/baz', 'baz()')
53
- end
54
-
55
- it "should update the results only if the sources have changed" do
56
- subject = described_class.new
57
-
58
- subject.paste('foo')
59
- subject.paste('bar')
60
- Paste::JS::Test.write 'foo', 'foobar()', Time.now - 42
61
- Paste::JS::Test.write 'bar', 'barbar()', Time.now + 42
62
-
63
- subject.rebuild
64
-
65
- subject.should have_in_result('foo', 'foo()')
66
- subject.should have_in_result('bar', 'barbar()')
67
- end
68
-
69
- it "should watch for changes in dependencies as well" do
70
- Paste::JS::Test.write 'foo', '//= require <bar>'
71
- Paste::JS::Test.write 'bar', ''
72
- Paste::JS::Test.write 'baz', ''
73
- subject.paste('foo')
74
-
75
- Paste::JS::Test.write 'bar', '//= require <baz>', Time.now + 42
76
-
77
- subject.paste('foo')[:javascript].should == ['baz.js', 'bar.js', 'foo.js']
78
- end
79
-
80
- it "should watch for changes in dependencies as well" do
81
- Paste::JS::Test.write 'foo', '//= require <bar>'
82
- Paste::JS::Test.write 'bar', ''
83
- Paste::JS::Test.write 'baz', ''
84
- subject.paste('foo')
85
-
86
- Paste::JS::Test.write 'bar', '//= require <baz>', Time.now + 42
87
-
88
- subject.paste('foo')[:javascript].should == ['baz.js', 'bar.js', 'foo.js']
89
- end
90
-
91
- it "should watch for changes in very deep dependencies" do
92
- Paste::JS::Test.write 'foo', ''
93
- Paste::JS::Test.write 'bar', ''
94
- subject.paste('foo')
95
-
96
- Paste::JS::Test.write 'foo', '//= require <bar>', Time.now + 42
97
-
98
- subject.paste('foo')[:javascript].should == ['bar.js', 'foo.js']
99
- end
100
-
101
- it "should update dependencies when they've been rewritten using rebuild" do
102
- Paste::JS::Test.write 'foo', ''
103
- Paste::JS::Test.write 'baz', 'foobar'
104
-
105
- subject.paste('foo')
106
- Paste::JS::Test.write 'foo', '//= require <baz>', Time.now + 42
107
- subject.rebuild
108
- Paste::JS::Test.touch 'foo', Time.now - 1
109
-
110
- @result = subject.paste('foo')[:javascript].should == ['baz.js', 'foo.js']
111
- end
112
- end
113
-
114
- describe "implicit dependencies" do
115
- before :each do
116
- Paste::JS::Test.write 'foo', ''
117
- Paste::JS::Test.write 'bar', '//= require <foo>'
118
- end
119
-
120
- it "should be included when pasting" do
121
- subject.paste('bar')[:javascript].should == ['foo.js', 'bar.js']
122
- end
123
-
124
- it "should be regenerated" do
125
- result = subject.paste('bar')[:javascript].first
126
-
127
- Paste::JS::Test.write 'foo', 'foobar()', Time.now + 42
128
-
129
- subject.paste('bar')
130
- subject.should have_in_result(result, 'foobar()')
131
- end
132
- end
133
- end
@@ -1,43 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Paste::JS::Unify, 'compression' do
4
- before :each do
5
- Paste::JS::Test.write 'foo', "function foo() {};\n foo()"
6
- Paste::JS::Test.write 'bar', "function bar() {};\n bar()"
7
- end
8
-
9
- it "should not compress the files when pasting" do
10
- result = subject.paste('foo')[:javascript].first
11
-
12
- subject.should have_in_result(result, "function foo() {};\n foo()")
13
- end
14
-
15
- it "should compress the previously generated result" do
16
- result = subject.paste('foo', 'bar')[:javascript].first
17
-
18
- begin
19
- subject.rebuild! :compress => 'google'
20
- rescue SocketError
21
- pending 'Error connecting to google'
22
- end
23
-
24
- contents = File.read subject.destination(result)
25
- contents.should_not contain("\n")
26
- contents.should =~ /function/
27
- end
28
-
29
- it "should allow the compilation level to be specified" do
30
- result = subject.paste('foo', 'bar')[:javascript].first
31
-
32
- begin
33
- subject.rebuild! :compress => 'google',
34
- :compilation_level => 'ADVANCED_OPTIMIZATIONS'
35
- rescue SocketError
36
- pending 'Error connecting to google'
37
- end
38
-
39
- # Everything should be optimized out
40
- subject.should have_in_result(result, '')
41
- end
42
-
43
- end