jbundle 0.0.1

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.
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
+