jbundle 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ spec/dist/*
5
+ .rvmrc
6
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in jbundle.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ jbundle (0.0.1)
5
+ closure-compiler
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ closure-compiler (0.3.3)
11
+ rspec (1.3.1)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ bundler (>= 1.0.0)
18
+ closure-compiler
19
+ jbundle!
20
+ rspec (= 1.3.1)
data/README.md ADDED
@@ -0,0 +1,107 @@
1
+ ## JBundle (in progress)
2
+
3
+ Define a set of javascript files to bundle and minify
4
+
5
+ JBundle.config do
6
+ version '1.6.1'
7
+
8
+ src_dir File.dirname(__FILE__) + '/src'
9
+
10
+ bundle 'foo.js' do
11
+ file 'file1.js'
12
+ file 'file2.js'
13
+ end
14
+
15
+ bundle 'foo2.js' do
16
+ file 'file3.js'
17
+ file 'file4.js'
18
+ end
19
+
20
+ file 'file4.js'
21
+
22
+ file 'text.txt'
23
+
24
+ # Filters can be use for string substitution
25
+ filter do |src, config|
26
+ src.gsub!(/<VERSION>/, config.version)
27
+ end
28
+
29
+ end
30
+
31
+ Then write them to a directory
32
+
33
+ JBundle.write_to './dist'
34
+
35
+ This will write the following files:
36
+
37
+ 'dist/1.6.1/foo.js'
38
+ 'dist/1.6.1/foo.min.js'
39
+ 'dist/1.6.1/foo2.js'
40
+ 'dist/1.6.1/foo2.min.js'
41
+ 'dist/1.6.1/file4.js'
42
+ 'dist/1.6.1/file4.min.js'
43
+ 'dist/1.6.1/text.txt'
44
+
45
+ 'dist/1.6/foo.js'
46
+ 'dist/1.6/foo.min.js'
47
+ 'dist/1.6/foo2.js'
48
+ 'dist/1.6/foo2.min.js'
49
+ 'dist/1.6/file4.js'
50
+ 'dist/1.6/file4.min.js'
51
+ 'dist/1.6/text.txt'
52
+
53
+ Or you can build a single bundle/file dinamically (ie. for testing, or for serving and caching dinamically)
54
+
55
+ JBundle.build('foo.js').src
56
+
57
+ Or
58
+
59
+ JBundle.build('foo.js').min
60
+
61
+ You can bundle licenses in bundles. Licenses will not be minified even if though they end up as part of minified files
62
+
63
+ bundle 'foo2.js' do
64
+ license 'license.txt'
65
+ file 'file3.js'
66
+ file 'file4.js'
67
+ end
68
+
69
+ All defined filters will run on the src for all these cases.
70
+
71
+ ## JBundlefile
72
+
73
+ You can add configuration in a JBundlefile in the root of your project.
74
+
75
+ version '1.0.1'
76
+
77
+ src_dir './'
78
+
79
+ bundle 'foo.js' do
80
+ license 'license.txt'
81
+ file 'file1.js'
82
+ file 'file2.js'
83
+ end
84
+
85
+ file 'page.html'
86
+
87
+ filter do |src, config|
88
+ src.gsub! /<VERSION>/, config.version
89
+ end
90
+
91
+ target_dir 'dist'
92
+
93
+ Then you can bundle everything up with the command line tool
94
+
95
+ $ jbundle
96
+
97
+ ## Pre-releases
98
+
99
+ If you want a prerelease not to overwrite the previous point release, suffix it with "-pre", as in:
100
+
101
+ version '1.0.1-pre'
102
+
103
+
104
+ ## TODO
105
+
106
+ - DRY up stuff, better error handling for missing config
107
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'spec/rake/spectask'
5
+ Spec::Rake::SpecTask.new(:spec) do |t|
6
+ t.spec_files = FileList["spec/**/*_spec.rb"]
7
+ t.spec_opts = %w{-f s -c -L mtime}
8
+ end
9
+
10
+ task :default => :spec
data/bin/jbundle ADDED
@@ -0,0 +1,9 @@
1
+ require 'jbundle'
2
+
3
+ JBUNDLE_FILE = 'JBundlefile'
4
+
5
+ if ::File.exists?(JBUNDLE_FILE)
6
+ JBundle.run( ::File.read(JBUNDLE_FILE) )
7
+ else
8
+ puts "You need to define ./#{JBUNDLE_FILE}"
9
+ end
data/jbundle.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/jbundle/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "jbundle"
6
+ s.version = JBundle::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ['Ismael Celis']
9
+ s.email = ['ismaelct@gmail.com']
10
+ s.homepage = "http://github.com/ismasan/jbundle"
11
+ s.summary = "Writes versioned, bundled and minified javascript files and dependencies"
12
+ s.description = "Good for releasing javascript libraries composed of many files. Writes files apt for deploying to CDNs."
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+ s.rubyforge_project = "jbundle"
16
+
17
+ s.add_development_dependency "bundler", ">= 1.0.0"
18
+ s.add_development_dependency "rspec", '1.3.1'
19
+ s.add_dependency 'closure-compiler'
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
23
+ s.require_path = 'lib'
24
+ end
@@ -0,0 +1,88 @@
1
+ require 'closure-compiler'
2
+
3
+ module JBundle
4
+
5
+ class Compiler
6
+
7
+ BUILDABLE_FILES = ['.js']
8
+
9
+ attr_reader :name, :src_dir
10
+
11
+ def initialize(name, file_list, src_dir = 'src')
12
+ @name, @file_list, @src_dir = name.to_s, file_list, src_dir
13
+ end
14
+
15
+ def buildable?
16
+ BUILDABLE_FILES.include?(::File.extname(name))
17
+ end
18
+
19
+ # This only makes sense for one-file objects
20
+ def src_path
21
+ ::File.join(@src_dir, name)
22
+ end
23
+
24
+ def src
25
+ @src ||= licenses + raw_src
26
+ end
27
+
28
+ def min
29
+ @min ||= licenses + Closure::Compiler.new.compile(raw_src)
30
+ end
31
+
32
+ def min_name
33
+ @min_name ||= (
34
+ ext = ::File.extname(name)
35
+ name.sub(ext, '') + '.min' + ext
36
+ )
37
+ end
38
+
39
+ def licenses
40
+ @licenses ||= if @file_list.respond_to?(:licenses)
41
+ read_files @file_list.licenses
42
+ else
43
+ ''
44
+ end
45
+ end
46
+
47
+ def raw_src
48
+ @raw_src ||= read_files(@file_list)
49
+ end
50
+
51
+ protected
52
+
53
+ def read_files(file_names)
54
+ file_names.inject('') do |mem, file_name|
55
+ mem << ::File.read(::File.join(src_dir, file_name))
56
+ mem << "\n"
57
+ mem
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+
64
+ class Builder
65
+
66
+ def initialize(config)
67
+ @config = config
68
+ @sources = []
69
+ end
70
+
71
+ def build!
72
+ @sources = @config.bundles_and_files.map do |b|
73
+ build_one b
74
+ end
75
+ end
76
+
77
+ def build_one(f)
78
+ compiler = Compiler.new(f.name, f, @config.src_dir)
79
+ @config.filters.each do |filter|
80
+ filter.call(compiler.licenses, @config)
81
+ filter.call(compiler.raw_src, @config)
82
+ end
83
+ compiler
84
+ end
85
+
86
+ end
87
+
88
+ end
@@ -0,0 +1,29 @@
1
+ module JBundle
2
+
3
+ class Bundle
4
+
5
+ include Enumerable
6
+
7
+ attr_reader :name, :licenses
8
+
9
+ def initialize(name)
10
+ @name = name.to_s
11
+ @files = []
12
+ @licenses = []
13
+ end
14
+
15
+ def file(f)
16
+ @files << f
17
+ end
18
+
19
+ def license(license_file)
20
+ @licenses << license_file
21
+ end
22
+
23
+ def each(&block)
24
+ @files.each &block
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,51 @@
1
+ module JBundle
2
+
3
+ class Config
4
+
5
+ attr_reader :bundles, :files, :src_dir, :filters
6
+
7
+ def initialize
8
+ @bundles = []
9
+ @files = []
10
+ @filters = []
11
+ end
12
+
13
+ def version(v = nil)
14
+ @version = v if v
15
+ @version
16
+ end
17
+
18
+ def src_dir(dir = nil)
19
+ @src_dir = dir if dir
20
+ @src_dir
21
+ end
22
+
23
+ def target_dir(dir = nil)
24
+ @target_dir = dir if dir
25
+ @target_dir
26
+ end
27
+
28
+ def bundle(name, &block)
29
+ name = name.to_sym
30
+ if !b = @bundles.detect{|a| a.name == name}
31
+ b = Bundle.new(name)
32
+ @bundles << b
33
+ end
34
+ b.instance_eval &block
35
+ b
36
+ end
37
+
38
+ def file(f)
39
+ @files << JBundle::File.new(f)
40
+ end
41
+
42
+ def filter(&block)
43
+ filters << block
44
+ end
45
+
46
+ def bundles_and_files
47
+ @bundles + @files
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,19 @@
1
+ module JBundle
2
+
3
+ class File
4
+
5
+ include Enumerable
6
+
7
+ attr_reader :name
8
+
9
+ def initialize(name)
10
+ @name = name.to_s
11
+ end
12
+
13
+ def each(&block)
14
+ yield name
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,3 @@
1
+ module JBundle
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,69 @@
1
+ module JBundle
2
+
3
+ class Version
4
+
5
+ def initialize(string)
6
+ @major, @minor, @patch = string.split('.')
7
+ raise "require (major.minor.patch) eg: 1.3.1" unless @major && @minor && @patch
8
+ end
9
+
10
+ def full
11
+ [@major, @minor, @patch].join('.')
12
+ end
13
+
14
+ def major_minor
15
+ [@major, @minor].join('.')
16
+ end
17
+
18
+ def releaseable
19
+ prerelease? ? [full] : [full, major_minor]
20
+ end
21
+
22
+ def to_s
23
+ full
24
+ end
25
+
26
+ protected
27
+
28
+ def prerelease?
29
+ @patch =~ /-pre/
30
+ end
31
+
32
+ end
33
+
34
+ class Writer
35
+
36
+ def initialize(compiler, version, target_dir)
37
+ @compiler, @version, @target_dir = compiler, Version.new(version), target_dir
38
+ end
39
+
40
+ def write
41
+ @version.releaseable.each do |version_dir|
42
+ if @compiler.buildable?
43
+ write_file @compiler.src, ::File.join(@target_dir, version_dir), @compiler.name
44
+ write_file @compiler.min, ::File.join(@target_dir, version_dir), @compiler.min_name
45
+ else
46
+ copy_file @compiler.src_path, ::File.join(@target_dir, version_dir, @compiler.name)
47
+ end
48
+ end
49
+ end
50
+
51
+ protected
52
+
53
+ def copy_file(src, target)
54
+ JBundle.log("Copying to #{target}")
55
+ FileUtils.cp src, target
56
+ end
57
+
58
+ def write_file(content, dir_name, file_name)
59
+ FileUtils.mkdir_p dir_name
60
+ path = ::File.join(dir_name, file_name)
61
+ JBundle.log("Writing to #{path}")
62
+ ::File.open(path, 'w') do |f|
63
+ f.write content
64
+ end
65
+ end
66
+
67
+ end
68
+
69
+ end
data/lib/jbundle.rb ADDED
@@ -0,0 +1,55 @@
1
+ require 'fileutils'
2
+ require 'jbundle/config'
3
+ require 'jbundle/file'
4
+ require 'jbundle/bundle'
5
+ require 'jbundle/builder'
6
+ require 'jbundle/writer'
7
+
8
+ module JBundle
9
+
10
+ class << self
11
+
12
+ attr_accessor :logger
13
+
14
+ def log(msg)
15
+ logger.call(msg)
16
+ end
17
+
18
+ def config(&block)
19
+ @current_config ||= JBundle::Config.new
20
+ @current_config.instance_eval(&block) if block_given?
21
+ @current_config
22
+ end
23
+
24
+ def output
25
+ @output ||= Builder.new(config).build!
26
+ end
27
+
28
+ def reset!
29
+ @current_config = nil
30
+ @output = nil
31
+ self
32
+ end
33
+
34
+ def write_to(target_dir)
35
+ output.each do |compiler|
36
+ Writer.new(compiler, config.version, target_dir).write
37
+ end
38
+ end
39
+
40
+ def build(name)
41
+ found = config.bundles_and_files.detect {|f| f.name == name}
42
+ raise "No bundle or file found with name #{name}" unless found
43
+ Builder.new(config).build_one found
44
+ end
45
+
46
+ def run(content)
47
+ config.instance_eval content
48
+ write_to config.target_dir || './dist'
49
+ end
50
+
51
+ end
52
+
53
+ self.logger = lambda {|msg| puts "#{msg}\n"}
54
+
55
+ end
data/spec/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,98 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'fileutils'
3
+
4
+ describe "JBundle" do
5
+
6
+ before do
7
+
8
+ JBundle.reset!
9
+
10
+ JBundle.config do
11
+ version '1.6.1'
12
+
13
+ src_dir File.dirname(__FILE__) + '/test_src'
14
+
15
+ bundle 'foo.js' do
16
+ file 'file1.js'
17
+ file 'file2.js'
18
+ end
19
+
20
+ bundle 'foo2.js' do
21
+ license 'license.txt'
22
+ file 'file3.js'
23
+ file 'file4.js'
24
+ end
25
+
26
+ file 'file4.js'
27
+
28
+ file 'text.txt'
29
+
30
+ filter do |src, config|
31
+ src.gsub!(/<VERSION>/, config.version)
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ it 'should have a version' do
39
+ JBundle.config.version.to_s.should == '1.6.1'
40
+ end
41
+
42
+ it 'should have bundles' do
43
+ JBundle.config.bundles[0].name.should == 'foo.js'
44
+ JBundle.config.bundles[1].name.should == 'foo2.js'
45
+ end
46
+
47
+ context 'bundling' do
48
+
49
+ it 'should build single bundles' do
50
+ JBundle.build('foo.js').src.should == "var VERSION = '1.6.1';\nvar a1 = 1;\nvar a2 = 2;\n"
51
+ JBundle.build('file4.js').min.should == "var a4=4;\n"
52
+ end
53
+
54
+ it 'should bundle bundles' do
55
+ JBundle.output.size.should == 4
56
+ JBundle.output[0].name.should == 'foo.js'
57
+ JBundle.output[0].src.should == "var VERSION = '1.6.1';\nvar a1 = 1;\nvar a2 = 2;\n"
58
+ JBundle.output[0].min.should == "var VERSION=\"1.6.1\",a1=1,a2=2;\n"
59
+ end
60
+
61
+ it 'should not minify licenses' do
62
+ JBundle.build('foo2.js').src.should == "/* Version: 1.6.1\nThis is a license\n-----------------------*/\nvar a3 = 3;\nvar a4 = 4;\n"
63
+ JBundle.build('foo2.js').min.should == "/* Version: 1.6.1\nThis is a license\n-----------------------*/\nvar a3=3,a4=4;\n"
64
+ end
65
+
66
+ end
67
+
68
+ context 'writing' do
69
+
70
+ before do
71
+ @dist = File.dirname(__FILE__)+'/dist'
72
+ FileUtils.rm_rf @dist
73
+ end
74
+
75
+ it 'should write files' do
76
+ JBundle.write_to(@dist)
77
+
78
+ File.exist?(@dist + '/1.6.1/foo.js').should be_true
79
+ File.exist?(@dist + '/1.6.1/foo.min.js').should be_true
80
+ File.exist?(@dist + '/1.6.1/foo2.js').should be_true
81
+ File.exist?(@dist + '/1.6.1/foo2.min.js').should be_true
82
+ File.exist?(@dist + '/1.6.1/file4.js').should be_true
83
+ File.exist?(@dist + '/1.6.1/file4.min.js').should be_true
84
+ File.exist?(@dist + '/1.6.1/text.txt').should be_true
85
+ File.exist?(@dist + '/1.6.1/text.min.txt').should be_false
86
+
87
+ File.exist?(@dist + '/1.6/foo.js').should be_true
88
+ File.exist?(@dist + '/1.6/foo.min.js').should be_true
89
+ File.exist?(@dist + '/1.6/foo2.js').should be_true
90
+ File.exist?(@dist + '/1.6/foo2.min.js').should be_true
91
+ File.exist?(@dist + '/1.6/file4.js').should be_true
92
+ File.exist?(@dist + '/1.6/file4.min.js').should be_true
93
+ File.exist?(@dist + '/1.6/text.txt').should be_true
94
+ File.exist?(@dist + '/1.6/text.min.txt').should be_false
95
+ end
96
+ end
97
+
98
+ end
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup
4
+
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ require 'jbundle'
8
+ begin
9
+ require 'spec'
10
+ rescue LoadError
11
+ require 'rubygems'
12
+ gem 'rspec'
13
+ require 'spec'
14
+ end
@@ -0,0 +1,2 @@
1
+ var VERSION = '<VERSION>';
2
+ var a1 = 1;
@@ -0,0 +1 @@
1
+ var a2 = 2;
@@ -0,0 +1 @@
1
+ var a3 = 3;
@@ -0,0 +1 @@
1
+ var a4 = 4;
@@ -0,0 +1,3 @@
1
+ /* Version: <VERSION>
2
+ This is a license
3
+ -----------------------*/
@@ -0,0 +1 @@
1
+ Foo
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jbundle
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Ismael Celis
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-03 00:00:00 -03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: bundler
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 0
34
+ version: 1.0.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rspec
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - "="
44
+ - !ruby/object:Gem::Version
45
+ hash: 25
46
+ segments:
47
+ - 1
48
+ - 3
49
+ - 1
50
+ version: 1.3.1
51
+ type: :development
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: closure-compiler
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ type: :runtime
66
+ version_requirements: *id003
67
+ description: Good for releasing javascript libraries composed of many files. Writes files apt for deploying to CDNs.
68
+ email:
69
+ - ismaelct@gmail.com
70
+ executables:
71
+ - jbundle
72
+ extensions: []
73
+
74
+ extra_rdoc_files: []
75
+
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - Gemfile.lock
80
+ - README.md
81
+ - Rakefile
82
+ - bin/jbundle
83
+ - jbundle.gemspec
84
+ - lib/jbundle.rb
85
+ - lib/jbundle/builder.rb
86
+ - lib/jbundle/bundle.rb
87
+ - lib/jbundle/config.rb
88
+ - lib/jbundle/file.rb
89
+ - lib/jbundle/version.rb
90
+ - lib/jbundle/writer.rb
91
+ - spec/.rspec
92
+ - spec/jbundle_spec.rb
93
+ - spec/spec_helper.rb
94
+ - spec/test_src/file1.js
95
+ - spec/test_src/file2.js
96
+ - spec/test_src/file3.js
97
+ - spec/test_src/file4.js
98
+ - spec/test_src/license.txt
99
+ - spec/test_src/text.txt
100
+ has_rdoc: true
101
+ homepage: http://github.com/ismasan/jbundle
102
+ licenses: []
103
+
104
+ post_install_message:
105
+ rdoc_options: []
106
+
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ hash: 3
115
+ segments:
116
+ - 0
117
+ version: "0"
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ hash: 23
124
+ segments:
125
+ - 1
126
+ - 3
127
+ - 6
128
+ version: 1.3.6
129
+ requirements: []
130
+
131
+ rubyforge_project: jbundle
132
+ rubygems_version: 1.3.7
133
+ signing_key:
134
+ specification_version: 3
135
+ summary: Writes versioned, bundled and minified javascript files and dependencies
136
+ test_files: []
137
+