jekyll-minibundle 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YmU4ZTUwM2ZlNTlhNGI1OGFjMTg4OGRhNDEyNWYwOWUyYjI1OWUwMQ==
5
+ data.tar.gz: !binary |-
6
+ ZDdiN2RjN2JiMDY3Yjc4ODA4MTI2YTA5YWVlY2RkMzM3NGFhOTMzYg==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ MGFiYmJhNGY1MTRhOTRiYWYxM2FkOWQxYmE5YzU0ZGM5NjMwMTkxNDRlY2Q0
10
+ MWQxZmIwZTY5NWY5YTg5ZGIzYjkyMjlkNzk4Yjg1NTNlN2QzMzA5ZjU3NDZl
11
+ OTcwODM2ZjU3YjQ1NGFjNmRlYzcyNDU0NDg5Y2I4YTQ2YWZiYmE=
12
+ data.tar.gz: !binary |-
13
+ ZWZjNmNlZmMxZTQ3MmFkNGY0YzExYmY1NGFjM2VmZjVkMzFiZjQxMTY1ODNi
14
+ OWVhODdjNTIzM2E5NjRkMDNjMDA4Njc1NjI4MmVjOTZjMjlkNjVlZWJhZWIx
15
+ MWE3YzVmZThlMmQ0YzIxODgxZmFiZmQ2ODg4NzQ2M2Q0YmE4M2E=
@@ -1,17 +1,25 @@
1
- ### 1.0.0 / 2013-02-15
1
+ # 1.1.0 / 2013-02-27
2
+
3
+ * `ministamp` tag omits fingerprint in development mode
4
+ * Clarify documentation
5
+ * Comply with (Gemnasium) conventions for changelogs (@tmatilai)
6
+ * Bug fix: do not bundle assets when nonrelated files change
7
+ * Bug fix: do not bundle assets twice upon startup
8
+
9
+ # 1.0.0 / 2013-02-15
2
10
 
3
11
  * Add development mode, where `minibundle` block will copy each asset
4
12
  as-is to the destination directory
5
13
  * Clarify documentation
6
14
  * Increase test coverage
7
15
 
8
- ### 0.2.0 / 2012-12-15
16
+ # 0.2.0 / 2012-12-15
9
17
 
10
18
  * Escape the values of custom attributes given in `minibundle` block
11
19
  * Add semicolons between each JavaScript asset in bundling
12
20
  * Show error in page output if asset bundling command failed
13
21
 
14
- ### 0.1.0 / 2012-12-07
22
+ # 0.1.0 / 2012-12-07
15
23
 
16
24
  * Add `ministamp` tag and `minibundle` block for Jekyll
17
25
  * First release
File without changes
data/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # Jekyll Minibundle plugin
2
+
3
+ A minimalistic plugin for bundling assets to
4
+ [Jekyll](https://github.com/mojombo/jekyll)'s site generation
5
+ directory.
6
+
7
+ In addition to the plugin itself, you need a minification tool
8
+ supporting standard unix input and output. There are no gem
9
+ dependencies at runtime.
10
+
11
+ Tested with Ruby MRI 1.9.3. Ruby 1.8 is *not* supported.
12
+
13
+ [![Build Status](https://secure.travis-ci.org/tkareine/jekyll-minibundle.png)](http://travis-ci.org/tkareine/jekyll-minibundle)
14
+
15
+ # Features
16
+
17
+ There are two features: asset fingerprinting with MD5 digest over the
18
+ contents of the asset, and asset bundling combined with the first
19
+ feature.
20
+
21
+ Asset bundling consists of concatenation and minification. The plugin
22
+ implements concatenation and leaves up to you to choose the
23
+ minification tool. [UglifyJS2](https://github.com/mishoo/UglifyJS2) is
24
+ a good and fast minifier. The plugin connects to the minifier with
25
+ standard unix pipe, feeding asset file contents to it in desired order
26
+ via standard input, and reads the result from standard output.
27
+
28
+ Why is this good? Well, a fingerprint in asset's path is the
29
+ [recommended way](https://developers.google.com/speed/docs/best-practices/caching)
30
+ to handle caching of static resources, because you can allow caching
31
+ the asset forever. Calculating MD5 digest over the contents of the
32
+ asset is fast and the resulting digest is reasonably unique to be
33
+ generated automatically.
34
+
35
+ Asset bundling is good for reducing the number of requests to the
36
+ backend upon page load. The minification of stylesheets and JavaScript
37
+ sources makes asset sizes smaller and thus faster to load over
38
+ network.
39
+
40
+ # Usage
41
+
42
+ The plugin is shipped as a
43
+ [RubyGem](https://rubygems.org/gems/jekyll-minibundle):
44
+
45
+ ``` bash
46
+ $ gem install jekyll-minibundle
47
+ ```
48
+
49
+ Add file `_plugins/minibundle.rb` to your Jekyll site project with
50
+ this line:
51
+
52
+ ``` ruby
53
+ require 'jekyll/minibundle'
54
+ ```
55
+
56
+ ## Asset fingerprinting
57
+
58
+ Asset fingerprinting is intended to be used together with
59
+ [Compass](http://compass-style.org/) and other similar asset
60
+ generation tools that have their own configuration for input sources.
61
+
62
+ Configure Compass to take inputs from `_assets/styles/*.scss` and to
63
+ put output to `_tmp/site.css`. Use `ministamp` tag to copy the
64
+ processed style asset to the generated site:
65
+
66
+ ``` html
67
+ <link href="{% ministamp _tmp/site.css assets/site.css %}" rel="stylesheet" media="screen, projection">
68
+ ```
69
+
70
+ Output, containing the MD5 digest of the file in the filename:
71
+
72
+ ``` html
73
+ <link href="assets/site-390be921ee0eff063817bb5ef2954300.css" rel="stylesheet" media="screen, projection">
74
+ ```
75
+
76
+ This feature does not require any external tools.
77
+
78
+ ## Asset bundling
79
+
80
+ This is a straightforward way to bundle assets with any minification
81
+ tool that supports reading input from STDIN and writing the output to
82
+ STDOUT. You write the configuration for input sources directly into
83
+ the content file where you want the markup tag for the bundle file to
84
+ appear. The outcome will be a markup tag containing the path to the
85
+ bundle file, and the generated site will have the bundle file in that
86
+ path. The MD5 digest of the file will be included in the filename.
87
+
88
+ Place `minibundle` block with configuration into your content file
89
+ where you want the generated markup to appear. For example, to bundle
90
+ a set of JavaScript sources:
91
+
92
+ ``` text
93
+ {% minibundle js %}
94
+ source_dir: _assets/scripts
95
+ destination_path: assets/site
96
+ assets:
97
+ - dependency
98
+ - app
99
+ attributes:
100
+ id: my-scripts
101
+ {% endminibundle %}
102
+ ```
103
+
104
+ Then, specify the command for launching your favorite minifier in
105
+ `$JEKYLL_MINIBUNDLE_CMD_JS` environment variable. For example, when
106
+ launching Jekyll:
107
+
108
+ ``` bash
109
+ $ JEKYLL_MINIBUNDLE_CMD_JS='./node_modules/.bin/uglifyjs --' jekyll
110
+ ```
111
+
112
+ You can pass custom attributes to the generated markup with
113
+ `attributes` map in the configuration.
114
+
115
+ Output in the content file:
116
+
117
+ ``` html
118
+ <script src="assets/site-8e764372a0dbd296033cb2a416f064b5.js" type="text/javascript" id="my-scripts"></script>
119
+ ```
120
+
121
+ For bundling CSS assets, you use `css` as the argument to `minibundle` block:
122
+
123
+ ``` text
124
+ {% minibundle css %}
125
+ source_dir: _assets/styles
126
+ destination_path: assets/site
127
+ assets:
128
+ - reset
129
+ - common
130
+ attributes:
131
+ media: screen
132
+ {% endminibundle %}
133
+ ```
134
+
135
+ And then specify the command for launching bundling in
136
+ `$JEKYLL_MINIBUNDLE_CMD_CSS` environment variable.
137
+
138
+ ## Development mode
139
+
140
+ The plugin has one more trick in its sleeves. If you set environment
141
+ variable `JEKYLL_MINIBUNDLE_MODE` to `development`, then the plugin
142
+ will copy asset files as is to the destination directory (using
143
+ `destination_path` as directory for `minibundle` block), and omit
144
+ fingerprinting. This is useful in development workflow, where you need
145
+ the filenames and line numbers of the original asset sources.
146
+
147
+ ``` bash
148
+ $ JEKYLL_MINIBUNDLE_MODE=development jekyll --auto --server
149
+ ```
150
+
151
+ # Example site
152
+
153
+ See the contents of `test/fixture/site` directory.
154
+
155
+ # License
156
+
157
+ MIT. See `LICENSE.txt`.
data/RELEASING.txt ADDED
@@ -0,0 +1,11 @@
1
+ In order to release, do
2
+
3
+ $EDITOR lib/jekyll/minibundle/version.rb # update version number
4
+ $EDITOR CHANGELOG.md # describe a summary of changes since last release
5
+ git diff # review the changes
6
+ rake gem:build # check that tests pass
7
+ git add -p
8
+ git commit -m 'Release <version>'
9
+ git tag <version>
10
+ git push --tags origin master
11
+ gem push jekyll-minibundle-<version>.gem
data/Rakefile CHANGED
@@ -38,7 +38,7 @@ task :test do
38
38
  tests = Dir['test/**/*_test.rb'].
39
39
  map { |file| %r{^test/(.+)\.rb$}.match(file)[1] }.
40
40
  shelljoin
41
- test_cmd = %{bundle exec ruby -e 'ARGV.each { |f| require f }' #{tests}}
41
+ test_cmd = %{ruby -e 'ARGV.each { |f| require f }' #{tests}}
42
42
  sh(get_minibundle_env('RUBYLIB' => 'lib:test'), test_cmd)
43
43
  end
44
44
 
@@ -0,0 +1,70 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'lib/jekyll/minibundle/version'))
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'jekyll-minibundle'
5
+ s.version = Jekyll::Minibundle::VERSION
6
+ s.summary = 'A minimalistic asset bundling plugin for Jekyll'
7
+ s.authors = ['Tuomas Kareinen']
8
+ s.email = 'tkareine@gmail.com'
9
+ s.homepage = 'https://github.com/tkareine/jekyll-minibundle'
10
+ s.licenses = %w{MIT}
11
+
12
+ s.description = <<-END
13
+ A minimalistic asset bundling plugin for Jekyll, requiring only your
14
+ bundling tool of choice (no other dependencies, not even other gems).
15
+ Provides asset bundling and filename stamping with MD5 digest.
16
+ END
17
+
18
+ s.files = %w{
19
+ CHANGELOG.md
20
+ LICENSE.txt
21
+ README.md
22
+ RELEASING.txt
23
+ Rakefile
24
+ jekyll-minibundle.gemspec
25
+ lib/jekyll/minibundle/asset_bundle.rb
26
+ lib/jekyll/minibundle/asset_file_operations.rb
27
+ lib/jekyll/minibundle/asset_file_paths.rb
28
+ lib/jekyll/minibundle/asset_stamp.rb
29
+ lib/jekyll/minibundle/asset_tag_markup.rb
30
+ lib/jekyll/minibundle/bundle_file.rb
31
+ lib/jekyll/minibundle/development_file.rb
32
+ lib/jekyll/minibundle/development_file_collection.rb
33
+ lib/jekyll/minibundle/environment.rb
34
+ lib/jekyll/minibundle/mini_bundle_block.rb
35
+ lib/jekyll/minibundle/mini_stamp_tag.rb
36
+ lib/jekyll/minibundle/stamp_file.rb
37
+ lib/jekyll/minibundle/version.rb
38
+ lib/jekyll/minibundle.rb
39
+ }
40
+
41
+ s.test_files = %w{
42
+ test/fixture/site/_assets/scripts/app.js
43
+ test/fixture/site/_assets/scripts/dependency.js
44
+ test/fixture/site/_assets/styles/common.css
45
+ test/fixture/site/_assets/styles/reset.css
46
+ test/fixture/site/_bin/remove_comments
47
+ test/fixture/site/_bin/with_count
48
+ test/fixture/site/_plugins/minibundle.rb
49
+ test/fixture/site/_tmp/site.css
50
+ test/fixture/site/index.html
51
+ test/integration/minibundle_development_mode_test.rb
52
+ test/integration/minibundle_production_mode_test.rb
53
+ test/integration/ministamp_test.rb
54
+ test/support/fixture_config.rb
55
+ test/support/test_case.rb
56
+ test/unit/asset_bundle_test.rb
57
+ test/unit/asset_tag_markup_test.rb
58
+ test/unit/bundle_file_test.rb
59
+ test/unit/stamp_file_test.rb
60
+ }
61
+
62
+ s.add_development_dependency 'jekyll', '~> 0.12.0'
63
+ s.add_development_dependency 'minitest', '~> 4.6.0'
64
+ s.add_development_dependency 'nokogiri', '~> 1.5.6'
65
+ s.add_development_dependency 'rake', '~> 10.0.2'
66
+
67
+ s.required_ruby_version = '>= 1.9.3'
68
+
69
+ s.rdoc_options << '--line-numbers' << '--title' << s.name << '--exclude' << 'test'
70
+ end
@@ -1,4 +1,5 @@
1
1
  require 'tempfile'
2
+ require 'jekyll/minibundle/environment'
2
3
 
3
4
  module Jekyll::Minibundle
4
5
  class AssetBundle
@@ -27,10 +28,7 @@ module Jekyll::Minibundle
27
28
  private
28
29
 
29
30
  def bundling_cmd
30
- key = "JEKYLL_MINIBUNDLE_CMD_#{@type.upcase}"
31
- cmd = ENV[key]
32
- raise "You need to set bundling command in $#{key}" if !cmd
33
- cmd
31
+ Environment.command_for @type
34
32
  end
35
33
 
36
34
  def pipe_bundling_to_temp_file(cmd)
@@ -4,12 +4,12 @@ module Jekyll::Minibundle
4
4
  asset_source_path
5
5
  end
6
6
 
7
- def asset_path
7
+ def asset_destination_path
8
8
  File.join asset_destination_dir, asset_destination_basename
9
9
  end
10
10
 
11
11
  def destination(site_destination_dir)
12
- File.join site_destination_dir, asset_destination_dir, asset_destination_basename
12
+ File.join site_destination_dir, asset_destination_path
13
13
  end
14
14
 
15
15
  def destination_exists?(site_destination_dir)
@@ -7,72 +7,88 @@ module Jekyll::Minibundle
7
7
  class BundleFile
8
8
  include AssetFileOperations
9
9
 
10
- @@mtimes = {}
10
+ def self.clear_cache
11
+ @@mtimes = {}
12
+ @@writes_after_mtime_updates = Hash.new false
13
+ @@asset_bundles = {}
14
+ end
15
+
16
+ clear_cache
11
17
 
12
18
  def initialize(config)
13
19
  @type = config['type']
14
20
  @site_source_dir = config['site_dir']
15
21
  asset_source_dir = File.join @site_source_dir, config['source_dir']
16
22
  @assets = config['assets'].map { |asset_path| File.join asset_source_dir, "#{asset_path}.#{@type}" }
17
- @asset_destination_path = config['destination_path']
23
+ @destination_path = config['destination_path']
18
24
  @attributes = config['attributes']
19
25
  end
20
26
 
27
+ def markup
28
+ # we must rebundle here, if at all, in order to make sure the
29
+ # markup and generated file have the same fingerprint
30
+ rebundle_assets if modified?
31
+ AssetTagMarkup.make_markup @type, asset_destination_path, @attributes
32
+ end
33
+
21
34
  def path
22
35
  asset_bundle.path
23
36
  end
24
37
 
25
- def asset_path
26
- "#{@asset_destination_path}-#{asset_stamp}.#{@type}"
38
+ def asset_destination_path
39
+ "#{@destination_path}-#{asset_stamp}.#{@type}"
27
40
  end
28
41
 
29
42
  def destination(site_destination_dir)
30
- File.join site_destination_dir, asset_path
43
+ File.join site_destination_dir, asset_destination_path
31
44
  end
32
45
 
33
46
  def mtime
34
- @assets.max { |f| File.stat(f).mtime.to_i }
47
+ @assets.map { |f| File.stat(f).mtime.to_i }.max
35
48
  end
36
49
 
37
50
  def modified?
38
- @@mtimes[path] != mtime
51
+ @@mtimes[asset_destination_canonical_path] != mtime
39
52
  end
40
53
 
41
- def write(site_destination_dir)
42
- is_modified = modified?
43
-
44
- rebundle_assets if is_modified
54
+ def destination_written_after_mtime_update?
55
+ @@writes_after_mtime_updates[asset_destination_canonical_path]
56
+ end
45
57
 
46
- if File.exists?(destination(site_destination_dir)) && !is_modified
58
+ def write(site_destination_dir)
59
+ if File.exists?(destination(site_destination_dir)) && destination_written_after_mtime_update?
47
60
  false
48
61
  else
49
- update_mtime
50
62
  write_destination site_destination_dir
63
+ @@writes_after_mtime_updates[asset_destination_canonical_path] = true
51
64
  true
52
65
  end
53
66
  end
54
67
 
55
- def markup
56
- AssetTagMarkup.make_markup @type, asset_path, @attributes
57
- end
58
-
59
68
  private
60
69
 
70
+ def asset_destination_canonical_path
71
+ "#{@destination_path}.#{@type}"
72
+ end
73
+
61
74
  def asset_stamp
62
- @asset_stamp ||= AssetStamp.from_file(path)
75
+ @asset_stamp ||= AssetStamp.from_file path
63
76
  end
64
77
 
65
78
  def asset_bundle
66
- @asset_bundle ||= AssetBundle.new(@type, @assets, @site_source_dir).make_bundle
79
+ @@asset_bundles[asset_destination_canonical_path] ||= AssetBundle.new(@type, @assets, @site_source_dir)
67
80
  end
68
81
 
69
82
  def rebundle_assets
70
83
  @asset_stamp = nil
71
84
  asset_bundle.make_bundle
85
+ update_mtime
72
86
  end
73
87
 
74
88
  def update_mtime
75
- @@mtimes[path] = mtime
89
+ p = asset_destination_canonical_path
90
+ @@mtimes[p] = mtime
91
+ @@writes_after_mtime_updates[p] = false
76
92
  end
77
93
  end
78
94
  end
@@ -24,16 +24,10 @@ module Jekyll::Minibundle
24
24
  if destination_exists?(site_destination_dir) && !modified?
25
25
  false
26
26
  else
27
- update_mtime
27
+ @@mtimes[path] = mtime
28
28
  write_destination site_destination_dir
29
29
  true
30
30
  end
31
31
  end
32
-
33
- private
34
-
35
- def update_mtime
36
- @@mtimes[path] = mtime
37
- end
38
32
  end
39
33
  end