jekyll-minibundle 0.1.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.
- data/History.md +4 -0
- data/Rakefile +45 -0
- data/Readme.md +138 -0
- data/lib/jekyll/minibundle.rb +3 -0
- data/lib/jekyll/minibundle/asset_bundle.rb +48 -0
- data/lib/jekyll/minibundle/asset_file_support.rb +16 -0
- data/lib/jekyll/minibundle/asset_stamp.rb +9 -0
- data/lib/jekyll/minibundle/bundle_file.rb +76 -0
- data/lib/jekyll/minibundle/bundle_markup.rb +18 -0
- data/lib/jekyll/minibundle/mini_bundle_block.rb +33 -0
- data/lib/jekyll/minibundle/mini_stamp_tag.rb +19 -0
- data/lib/jekyll/minibundle/stamp_file.rb +69 -0
- data/lib/jekyll/minibundle/version.rb +5 -0
- data/test/fixture/site/_assets/scripts/app.js +5 -0
- data/test/fixture/site/_assets/scripts/dependency.js +4 -0
- data/test/fixture/site/_assets/styles/common.css +2 -0
- data/test/fixture/site/_assets/styles/reset.css +2 -0
- data/test/fixture/site/_bin/remove_comments +3 -0
- data/test/fixture/site/_plugins/minibundle.rb +1 -0
- data/test/fixture/site/_tmp/site.css +2 -0
- data/test/fixture/site/index.html +31 -0
- data/test/integration/minibundle_test.rb +72 -0
- data/test/integration/ministamp_test.rb +22 -0
- data/test/support/test_case.rb +51 -0
- metadata +141 -0
data/History.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
require 'shellwords'
|
3
|
+
|
4
|
+
require_relative 'lib/jekyll/minibundle/version'
|
5
|
+
gem_name = 'jekyll-minibundle'
|
6
|
+
|
7
|
+
namespace :gem do
|
8
|
+
CLEAN.include "#{gem_name}-*.gem"
|
9
|
+
|
10
|
+
desc 'Package the software as a gem'
|
11
|
+
task :build => :test do
|
12
|
+
sh %{gem build #{gem_name}.gemspec}
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Install the software as a gem'
|
16
|
+
task :install => :build do
|
17
|
+
sh %{gem install #{gem_name}-#{Jekyll::Minibundle::VERSION}}
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Uninstall the gem'
|
21
|
+
task :uninstall => :clean do
|
22
|
+
sh %{gem uninstall #{gem_name}}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'Run tests'
|
27
|
+
task :test do
|
28
|
+
test_dir = 'test'
|
29
|
+
test_glob = 'integration/**/*_test.rb'
|
30
|
+
includes = ['lib', test_dir].join(':')
|
31
|
+
tests = Dir["#{test_dir}/#{test_glob}"].
|
32
|
+
map { |file| %r{^test/(.+)\.rb$}.match(file)[1] }.
|
33
|
+
shelljoin
|
34
|
+
test_cmd = %{bundle exec ruby -I#{includes} -e 'ARGV.each { |f| require f }' #{tests}}
|
35
|
+
bundle_cmd = File.expand_path(File.join(File.dirname(__FILE__), test_dir, 'fixture/site/_bin/remove_comments'))
|
36
|
+
env = {
|
37
|
+
'JEKYLL_MINIBUNDLE_CMD_JS' => bundle_cmd,
|
38
|
+
'JEKYLL_MINIBUNDLE_CMD_CSS' => bundle_cmd
|
39
|
+
}
|
40
|
+
sh(env, test_cmd)
|
41
|
+
end
|
42
|
+
|
43
|
+
CLEAN.include 'test/fixture/site/_site'
|
44
|
+
|
45
|
+
task :default => :test
|
data/Readme.md
ADDED
@@ -0,0 +1,138 @@
|
|
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, you need your asset bundling tool of choice
|
8
|
+
only. The plugin needs no other configuration than setting an
|
9
|
+
environment variable.
|
10
|
+
|
11
|
+
Tested with Ruby MRI 1.9.3. Ruby 1.8 is *not* supported.
|
12
|
+
|
13
|
+
# Features
|
14
|
+
|
15
|
+
There are two features: asset stamping with MD5 digest over the
|
16
|
+
contents of the asset, and asset bundling combined with the first
|
17
|
+
feature.
|
18
|
+
|
19
|
+
You still need a separate bundling tool, such as
|
20
|
+
[UglifyJS2](https://github.com/mishoo/UglifyJS2) to do the actual work
|
21
|
+
of bundling (concatenation, minification). There are no other
|
22
|
+
dependencies.
|
23
|
+
|
24
|
+
Why is this good? Well, a unique content specific identifier in asset
|
25
|
+
filename is the best way to handle web caching, because you can allow
|
26
|
+
caching the asset for forever. Calculating MD5 digest over the
|
27
|
+
contents of the asset is fast and the resulting digest is reasonably
|
28
|
+
unique to be generated automatically.
|
29
|
+
|
30
|
+
Asset bundling is good for reducing the number of requests to server
|
31
|
+
upon page load. It also allows minification for stylesheets and
|
32
|
+
JavaScript sources, which makes asset sizes smaller and thus faster to
|
33
|
+
load over network.
|
34
|
+
|
35
|
+
# Usage
|
36
|
+
|
37
|
+
The plugin is shipped as a
|
38
|
+
[RubyGem](https://rubygems.org/gems/jekyll-minibundle):
|
39
|
+
|
40
|
+
gem install jekyll-minibundle
|
41
|
+
|
42
|
+
Add file `_plugins/minibundle.rb` to your Jekyll site project with
|
43
|
+
this line:
|
44
|
+
|
45
|
+
require 'jekyll/minibundle'
|
46
|
+
|
47
|
+
## Asset stamping
|
48
|
+
|
49
|
+
Asset stamping is intended to be used together with
|
50
|
+
[Compass](http://compass-style.org/) and other similar asset
|
51
|
+
generation tools where you do not want to include unprocessed input
|
52
|
+
assets in the generated site.
|
53
|
+
|
54
|
+
Configure Compass to take inputs from `_assets/styles/*.scss` and to
|
55
|
+
put output to `_tmp/site.css`. Use `ministamp` tag to copy the
|
56
|
+
processed style asset to the generated site:
|
57
|
+
|
58
|
+
<link href="{% ministamp _tmp/site.css assets/site.css %}" rel="stylesheet" media="screen, projection">
|
59
|
+
|
60
|
+
Output, containing the MD5 digest in the filename:
|
61
|
+
|
62
|
+
<link href="assets/site-390be921ee0eff063817bb5ef2954300.css" rel="stylesheet" media="screen, projection">
|
63
|
+
|
64
|
+
This feature does not require any external tools.
|
65
|
+
|
66
|
+
## Asset bundling
|
67
|
+
|
68
|
+
A straightforward way to bundle assets with any tool that supports
|
69
|
+
reading input files from STDIN and writing the output to STDOUT. The
|
70
|
+
bundled file has MD5 digest in the filename.
|
71
|
+
|
72
|
+
Place `minibundle` block with configuration to your content file where
|
73
|
+
you want the generated markup to appear. For example, for bundling
|
74
|
+
JavaScript sources:
|
75
|
+
|
76
|
+
{% minibundle js %}
|
77
|
+
source_dir: _assets/scripts
|
78
|
+
destination_path: assets/site
|
79
|
+
assets:
|
80
|
+
- dependency
|
81
|
+
- app
|
82
|
+
attributes:
|
83
|
+
id: my-scripts
|
84
|
+
{% endminibundle %}
|
85
|
+
|
86
|
+
Then, specify the command for launching your favorite bundling tool in
|
87
|
+
`$JEKYLL_MINIBUNDLE_CMD_JS` environment variable. For example, when
|
88
|
+
launching Jekyll:
|
89
|
+
|
90
|
+
$ JEKYLL_MINIBUNDLE_CMD_JS="./node_modules/.bin/uglifyjs --" jekyll
|
91
|
+
|
92
|
+
You can pass custom attributes to the generated markup with
|
93
|
+
`attributes` map in the configuration.
|
94
|
+
|
95
|
+
Output:
|
96
|
+
|
97
|
+
<script type="text/javascript" src="assets/site-8e764372a0dbd296033cb2a416f064b5.js" id="my-scripts"></script>
|
98
|
+
|
99
|
+
For bundling CSS assets, you use `css` as the argument to `minibundle` block:
|
100
|
+
|
101
|
+
{% minibundle css %}
|
102
|
+
source_dir: _assets/styles
|
103
|
+
destination_path: assets/site
|
104
|
+
assets:
|
105
|
+
- reset
|
106
|
+
- common
|
107
|
+
attributes:
|
108
|
+
media: screen
|
109
|
+
{% endminibundle %}
|
110
|
+
|
111
|
+
And then specify the command for launching bundling in
|
112
|
+
`$JEKYLL_MINIBUNDLE_CMD_CSS` environment variable.
|
113
|
+
|
114
|
+
# Example site
|
115
|
+
|
116
|
+
See the contents of `test/fixture/site` directory.
|
117
|
+
|
118
|
+
# License
|
119
|
+
|
120
|
+
Copyright (c) 2012 Tuomas Kareinen
|
121
|
+
|
122
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
123
|
+
of this software and associated documentation files (the "Software"), to deal
|
124
|
+
in the Software without restriction, including without limitation the rights
|
125
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
126
|
+
copies of the Software, and to permit persons to whom the Software is
|
127
|
+
furnished to do so, subject to the following conditions:
|
128
|
+
|
129
|
+
The above copyright notice and this permission notice shall be included in
|
130
|
+
all copies or substantial portions of the Software.
|
131
|
+
|
132
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
133
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
134
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
135
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
136
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
137
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
138
|
+
THE SOFTWARE.
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module Jekyll::Minibundle
|
4
|
+
class AssetBundle
|
5
|
+
def initialize(type, assets, site_dir)
|
6
|
+
@type, @assets, @site_dir = type, assets, site_dir
|
7
|
+
@temp_file = Tempfile.new "jekyll-minibundle-#{@type}-"
|
8
|
+
at_exit { @temp_file.close! }
|
9
|
+
end
|
10
|
+
|
11
|
+
def path
|
12
|
+
@temp_file.path
|
13
|
+
end
|
14
|
+
|
15
|
+
def make_bundle
|
16
|
+
pipe_bundling_to_temp_file bundling_cmd do |wr|
|
17
|
+
puts "Bundling #{@type} assets:"
|
18
|
+
@assets.each do |asset|
|
19
|
+
puts " #{asset}"
|
20
|
+
IO.foreach(asset) { |line| wr.write line }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def bundling_cmd
|
29
|
+
key = "JEKYLL_MINIBUNDLE_CMD_#{@type.upcase}"
|
30
|
+
cmd = ENV[key]
|
31
|
+
raise "You need to set bundling command in $#{key}" if !cmd
|
32
|
+
cmd
|
33
|
+
end
|
34
|
+
|
35
|
+
def pipe_bundling_to_temp_file(cmd)
|
36
|
+
pid = nil
|
37
|
+
rd, wr = IO.pipe
|
38
|
+
Dir.chdir @site_dir do
|
39
|
+
pid = spawn cmd, out: [@temp_file.path, 'w'], in: rd
|
40
|
+
end
|
41
|
+
yield wr
|
42
|
+
wr.close
|
43
|
+
Process.waitpid2 pid
|
44
|
+
ensure
|
45
|
+
wr.close unless wr.closed?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Jekyll::Minibundle
|
4
|
+
module AssetFileSupport
|
5
|
+
def static_file!(site)
|
6
|
+
static_file_exists = site.static_files.find { |f| f.path == path }
|
7
|
+
site.static_files << self unless static_file_exists
|
8
|
+
end
|
9
|
+
|
10
|
+
def write_destination(gensite_dir)
|
11
|
+
destination_path = destination gensite_dir
|
12
|
+
FileUtils.mkdir_p File.dirname(destination_path)
|
13
|
+
FileUtils.cp path, destination_path
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'jekyll/minibundle/asset_bundle'
|
2
|
+
require 'jekyll/minibundle/asset_file_support'
|
3
|
+
require 'jekyll/minibundle/bundle_markup'
|
4
|
+
|
5
|
+
module Jekyll::Minibundle
|
6
|
+
class BundleFile
|
7
|
+
include AssetFileSupport
|
8
|
+
|
9
|
+
@@mtimes = Hash.new
|
10
|
+
|
11
|
+
def initialize(config)
|
12
|
+
@type = config['type']
|
13
|
+
@site_dir = config['site_dir']
|
14
|
+
source_dir = File.join @site_dir, config['source_dir']
|
15
|
+
@destination_path = config['destination_path']
|
16
|
+
@assets = config['assets'].map { |asset_path| File.join source_dir, "#{asset_path}.#{@type}" }
|
17
|
+
@attributes = config['attributes']
|
18
|
+
update_mtime
|
19
|
+
end
|
20
|
+
|
21
|
+
def path
|
22
|
+
asset_bundle.path
|
23
|
+
end
|
24
|
+
|
25
|
+
def asset_path
|
26
|
+
"#{@destination_path}-#{asset_stamp}.#{@type}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def destination(destination_base_dir)
|
30
|
+
File.join destination_base_dir, asset_path
|
31
|
+
end
|
32
|
+
|
33
|
+
def mtime
|
34
|
+
@assets.max { |f| File.stat(f).mtime.to_i }
|
35
|
+
end
|
36
|
+
|
37
|
+
def modified?
|
38
|
+
@@mtimes[path] != mtime
|
39
|
+
end
|
40
|
+
|
41
|
+
def write(gensite_dir)
|
42
|
+
rebundle_assets if modified?
|
43
|
+
destination_path = destination gensite_dir
|
44
|
+
|
45
|
+
return false if File.exist?(destination_path) and !modified?
|
46
|
+
|
47
|
+
update_mtime
|
48
|
+
write_destination gensite_dir
|
49
|
+
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def markup
|
54
|
+
BundleMarkup.make_markup @type, asset_path, @attributes
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def asset_stamp
|
60
|
+
@asset_stamp ||= AssetStamp.from_file(path)
|
61
|
+
end
|
62
|
+
|
63
|
+
def asset_bundle
|
64
|
+
@asset_bundle ||= AssetBundle.new(@type, @assets, @site_dir).make_bundle
|
65
|
+
end
|
66
|
+
|
67
|
+
def rebundle_assets
|
68
|
+
@asset_stamp = nil
|
69
|
+
asset_bundle.make_bundle
|
70
|
+
end
|
71
|
+
|
72
|
+
def update_mtime
|
73
|
+
@@mtimes[path] = mtime
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Jekyll::Minibundle
|
2
|
+
module BundleMarkup
|
3
|
+
def self.make_markup(type, path, attributes)
|
4
|
+
case type
|
5
|
+
when :js
|
6
|
+
%{<script type="text/javascript" src="#{path}"#{make_attributes(attributes)}></script>}
|
7
|
+
when :css
|
8
|
+
%{<link rel="stylesheet" href="#{path}"#{make_attributes(attributes)}>}
|
9
|
+
else
|
10
|
+
raise "Unknown type for generating bundle markup: #{type}, #{path}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.make_attributes(attributes)
|
15
|
+
attributes.map { |name, value| %{ #{name}="#{value}"} }.join('')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'jekyll/minibundle/bundle_file'
|
3
|
+
|
4
|
+
module Jekyll::Minibundle
|
5
|
+
class MiniBundleBlock < Liquid::Block
|
6
|
+
def initialize(tag_name, type, _tokens)
|
7
|
+
super
|
8
|
+
@type = type.strip.to_sym
|
9
|
+
end
|
10
|
+
|
11
|
+
def render(context)
|
12
|
+
current_config = YAML.load super
|
13
|
+
site = context.registers[:site]
|
14
|
+
config = default_config.
|
15
|
+
merge(current_config).
|
16
|
+
merge({ 'type' => @type, 'site_dir' => site.source})
|
17
|
+
file = BundleFile.new config
|
18
|
+
file.static_file! site
|
19
|
+
file.markup
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_config
|
23
|
+
{
|
24
|
+
'source_dir' => '_assets',
|
25
|
+
'destination_path' => 'assets/site',
|
26
|
+
'assets' => [],
|
27
|
+
'attributes' => {}
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Liquid::Template.register_tag('minibundle', Jekyll::Minibundle::MiniBundleBlock)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'jekyll/minibundle/stamp_file'
|
2
|
+
|
3
|
+
module Jekyll::Minibundle
|
4
|
+
class MiniStampTag < Liquid::Tag
|
5
|
+
def initialize(tag_name, text, _tokens)
|
6
|
+
super
|
7
|
+
@source, @destination = text.split(/\s+/, 3)[0, 2]
|
8
|
+
end
|
9
|
+
|
10
|
+
def render(context)
|
11
|
+
site = context.registers[:site]
|
12
|
+
file = StampFile.new File.join(site.source, @source), @destination
|
13
|
+
file.static_file! site
|
14
|
+
file.asset_path
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Liquid::Template.register_tag('ministamp', Jekyll::Minibundle::MiniStampTag)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'jekyll/minibundle/asset_file_support'
|
2
|
+
require 'jekyll/minibundle/asset_stamp'
|
3
|
+
|
4
|
+
module Jekyll::Minibundle
|
5
|
+
class StampFile
|
6
|
+
include AssetFileSupport
|
7
|
+
|
8
|
+
@@mtimes = Hash.new
|
9
|
+
|
10
|
+
def initialize(source_path, destination_path)
|
11
|
+
@source_path = source_path
|
12
|
+
@destination_dir = File.dirname destination_path
|
13
|
+
@destination_extension = File.extname destination_path
|
14
|
+
base = File.basename destination_path
|
15
|
+
@destination_base_prefix = base[0 .. -(@destination_extension.size + 1)]
|
16
|
+
update_mtime
|
17
|
+
end
|
18
|
+
|
19
|
+
def path
|
20
|
+
@source_path
|
21
|
+
end
|
22
|
+
|
23
|
+
def asset_path
|
24
|
+
File.join @destination_dir, destination_basename
|
25
|
+
end
|
26
|
+
|
27
|
+
def destination(gensite_dir)
|
28
|
+
File.join gensite_dir, @destination_dir, destination_basename
|
29
|
+
end
|
30
|
+
|
31
|
+
def mtime
|
32
|
+
File.stat(path).mtime.to_i
|
33
|
+
end
|
34
|
+
|
35
|
+
def modified?
|
36
|
+
@@mtimes[path] != mtime
|
37
|
+
end
|
38
|
+
|
39
|
+
def write(gensite_dir)
|
40
|
+
clear_asset_stamp if modified?
|
41
|
+
destination_path = destination gensite_dir
|
42
|
+
|
43
|
+
return false if File.exist?(destination_path) and !modified?
|
44
|
+
|
45
|
+
update_mtime
|
46
|
+
write_destination gensite_dir
|
47
|
+
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def destination_basename
|
54
|
+
"#{@destination_base_prefix}-#{asset_stamp}#{@destination_extension}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def asset_stamp
|
58
|
+
@asset_stamp ||= AssetStamp.from_file(path)
|
59
|
+
end
|
60
|
+
|
61
|
+
def clear_asset_stamp
|
62
|
+
@asset_stamp = nil
|
63
|
+
end
|
64
|
+
|
65
|
+
def update_mtime
|
66
|
+
@@mtimes[path] = mtime
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'jekyll/minibundle'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
---
|
2
|
+
layout: nil
|
3
|
+
---
|
4
|
+
|
5
|
+
<!DOCTYPE html>
|
6
|
+
<html>
|
7
|
+
<head>
|
8
|
+
<link rel="stylesheet" href="{% ministamp _tmp/site.css assets/screen.css %}" media="screen">
|
9
|
+
{% minibundle css %}
|
10
|
+
source_dir: _assets/styles
|
11
|
+
destination_path: assets/site
|
12
|
+
assets:
|
13
|
+
- reset
|
14
|
+
- common
|
15
|
+
attributes:
|
16
|
+
id: my-styles
|
17
|
+
media: projection
|
18
|
+
{% endminibundle %}
|
19
|
+
</head>
|
20
|
+
<body>
|
21
|
+
{% minibundle js %}
|
22
|
+
source_dir: _assets/scripts
|
23
|
+
destination_path: assets/site
|
24
|
+
assets:
|
25
|
+
- dependency
|
26
|
+
- app
|
27
|
+
attributes:
|
28
|
+
id: my-scripts
|
29
|
+
{% endminibundle %}
|
30
|
+
</body>
|
31
|
+
</html>
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'support/test_case'
|
2
|
+
|
3
|
+
module Jekyll::Minibundle::Test
|
4
|
+
class MiniBundleTest < TestCase
|
5
|
+
EXPECTED_CSS_ASSET_PATH = 'assets/site-b2e0ecc1c100effc2c7353caad20c327.css'
|
6
|
+
EXPECTED_JS_ASSET_PATH = 'assets/site-f78e0c4497343c33e9282df5d684540e.js'
|
7
|
+
|
8
|
+
def test_css_asset_bundle_has_configured_attributes
|
9
|
+
element = find_html_element_from_index(%{head link[href="#{EXPECTED_CSS_ASSET_PATH}"]}).first
|
10
|
+
assert_equal 'my-styles', element['id']
|
11
|
+
assert_equal 'projection', element['media']
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_js_asset_bundle_has_configured_attributes
|
15
|
+
element = find_html_element_from_index(%{body script[src="#{EXPECTED_JS_ASSET_PATH}"]}).first
|
16
|
+
assert_equal 'my-scripts', element['id']
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_css_asset_bundle_has_stamp
|
20
|
+
actual = find_html_element_from_index('head link[media="projection"]').first['href']
|
21
|
+
assert_equal EXPECTED_CSS_ASSET_PATH, actual
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_js_asset_bundle_has_stamp
|
25
|
+
actual = find_html_element_from_index('body script').first['src']
|
26
|
+
assert_equal EXPECTED_JS_ASSET_PATH, actual
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_css_asset_bundle_is_copied_to_destination_dir
|
30
|
+
assert File.exists?(gensite_path(EXPECTED_CSS_ASSET_PATH))
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_js_asset_bundle_is_copied_to_destination_dir
|
34
|
+
assert File.exists?(gensite_path(EXPECTED_JS_ASSET_PATH))
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_css_asset_bundle_is_concatenated_in_configured_order
|
38
|
+
bundle = File.read(gensite_path(EXPECTED_CSS_ASSET_PATH))
|
39
|
+
assert bundle.index('html { margin: 0; }') < bundle.index('p { margin: 0; }')
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_js_asset_bundle_is_concatenated_in_configured_order
|
43
|
+
bundle = File.read(gensite_path(EXPECTED_JS_ASSET_PATH))
|
44
|
+
assert bundle.index('root.dependency = {};') < bundle.index('root.app = {};')
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_css_asset_bundle_is_minified
|
48
|
+
source_contents_size = source_assets_size('_assets/styles', %w{reset common}, 'css')
|
49
|
+
destination_contents_size = File.read(gensite_path(EXPECTED_CSS_ASSET_PATH)).size
|
50
|
+
assert destination_contents_size < source_contents_size
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_js_asset_bundle_is_minified
|
54
|
+
source_contents_size = source_assets_size('_assets/scripts', %w{dependency app}, 'js')
|
55
|
+
destination_contents_size = File.read(gensite_path(EXPECTED_JS_ASSET_PATH)).size
|
56
|
+
assert destination_contents_size < source_contents_size
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def find_html_element_from_index(css)
|
62
|
+
find_html_element(read_from_gensite('index.html'), css)
|
63
|
+
end
|
64
|
+
|
65
|
+
def source_assets_size(fixture_subdir, assets, type)
|
66
|
+
assets.
|
67
|
+
map { |f| File.read fixture_path(fixture_subdir, "#{f}.#{type}") }.
|
68
|
+
join('').
|
69
|
+
size
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'support/test_case'
|
2
|
+
|
3
|
+
module Jekyll::Minibundle::Test
|
4
|
+
class MiniStampTest < TestCase
|
5
|
+
EXPECTED_ASSET_PATH = 'assets/screen-390be921ee0eff063817bb5ef2954300.css'
|
6
|
+
|
7
|
+
def test_asset_path_has_stamp
|
8
|
+
actual = find_html_element(read_from_gensite('index.html'), 'head link').first['href']
|
9
|
+
assert_equal EXPECTED_ASSET_PATH, actual
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_asset_file_is_copied_to_destination_dir
|
13
|
+
assert File.exists?(gensite_path(EXPECTED_ASSET_PATH))
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_asset_file_is_equal_to_source_file
|
17
|
+
source_contents = File.read fixture_path('_tmp/site.css')
|
18
|
+
destination_contents = File.read gensite_path(EXPECTED_ASSET_PATH)
|
19
|
+
assert_equal source_contents, destination_contents
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'nokogiri'
|
5
|
+
require 'jekyll'
|
6
|
+
require 'jekyll/minibundle'
|
7
|
+
|
8
|
+
module Jekyll::Minibundle::Test
|
9
|
+
class TestCase < ::MiniTest::Unit::TestCase
|
10
|
+
FIXTURE_DIR = File.expand_path(File.join(File.dirname(__FILE__), '../fixture/site'))
|
11
|
+
|
12
|
+
def fixture_path(*args)
|
13
|
+
File.join(FIXTURE_DIR, *args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def gensite_path(*args)
|
17
|
+
File.join(_gensite_dir, *args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def read_from_gensite(*args)
|
21
|
+
File.read gensite_path(*args)
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_html_element(file, css)
|
25
|
+
Nokogiri::HTML(file).css(css)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def _gensite_dir(&block)
|
31
|
+
@@_gensite_dir ||= begin
|
32
|
+
dir = Dir.mktmpdir('jekyll-minibundle-test-')
|
33
|
+
at_exit do
|
34
|
+
FileUtils.rm_rf dir
|
35
|
+
puts "Cleaned generated site for tests: #{dir}"
|
36
|
+
end
|
37
|
+
Dir.chdir(dir) { _generate_site dir }
|
38
|
+
puts "Generated site for tests: #{dir}"
|
39
|
+
dir
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def _generate_site(destination)
|
44
|
+
options = {
|
45
|
+
'source' => fixture_path,
|
46
|
+
'destination' => destination
|
47
|
+
}
|
48
|
+
Jekyll::Site.new(Jekyll.configuration(options)).process
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jekyll-minibundle
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tuomas Kareinen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: jekyll
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.11.2
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.11.2
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: minitest
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 4.3.3
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 4.3.3
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: nokogiri
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.5.5
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.5.5
|
62
|
+
description: ! 'Provides ''minibundle'' block for bundling multiple assets, ''ministamp''
|
63
|
+
|
64
|
+
tag for stamping a single asset.
|
65
|
+
|
66
|
+
|
67
|
+
No other dependencies than the asset bundler of your choice.
|
68
|
+
|
69
|
+
'
|
70
|
+
email: tkareine@gmail.com
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- History.md
|
76
|
+
- Rakefile
|
77
|
+
- Readme.md
|
78
|
+
- lib/jekyll/minibundle.rb
|
79
|
+
- lib/jekyll/minibundle/asset_bundle.rb
|
80
|
+
- lib/jekyll/minibundle/asset_file_support.rb
|
81
|
+
- lib/jekyll/minibundle/asset_stamp.rb
|
82
|
+
- lib/jekyll/minibundle/bundle_file.rb
|
83
|
+
- lib/jekyll/minibundle/bundle_markup.rb
|
84
|
+
- lib/jekyll/minibundle/mini_bundle_block.rb
|
85
|
+
- lib/jekyll/minibundle/mini_stamp_tag.rb
|
86
|
+
- lib/jekyll/minibundle/stamp_file.rb
|
87
|
+
- lib/jekyll/minibundle/version.rb
|
88
|
+
- test/fixture/site/_assets/scripts/app.js
|
89
|
+
- test/fixture/site/_assets/scripts/dependency.js
|
90
|
+
- test/fixture/site/_assets/styles/common.css
|
91
|
+
- test/fixture/site/_assets/styles/reset.css
|
92
|
+
- test/fixture/site/_bin/remove_comments
|
93
|
+
- test/fixture/site/_plugins/minibundle.rb
|
94
|
+
- test/fixture/site/_tmp/site.css
|
95
|
+
- test/fixture/site/index.html
|
96
|
+
- test/integration/minibundle_test.rb
|
97
|
+
- test/integration/ministamp_test.rb
|
98
|
+
- test/support/test_case.rb
|
99
|
+
homepage: https://github.com/tkareine/jekyll-minibundle
|
100
|
+
licenses:
|
101
|
+
- MIT
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options:
|
104
|
+
- --line-numbers
|
105
|
+
- --title
|
106
|
+
- jekyll-minibundle
|
107
|
+
- --exclude
|
108
|
+
- test
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
none: false
|
113
|
+
requirements:
|
114
|
+
- - ! '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ! '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubyforge_project:
|
125
|
+
rubygems_version: 1.8.24
|
126
|
+
signing_key:
|
127
|
+
specification_version: 3
|
128
|
+
summary: Straightforward asset bundling plugin for Jekyll
|
129
|
+
test_files:
|
130
|
+
- test/fixture/site/_assets/scripts/app.js
|
131
|
+
- test/fixture/site/_assets/scripts/dependency.js
|
132
|
+
- test/fixture/site/_assets/styles/common.css
|
133
|
+
- test/fixture/site/_assets/styles/reset.css
|
134
|
+
- test/fixture/site/_bin/remove_comments
|
135
|
+
- test/fixture/site/_plugins/minibundle.rb
|
136
|
+
- test/fixture/site/_tmp/site.css
|
137
|
+
- test/fixture/site/index.html
|
138
|
+
- test/integration/minibundle_test.rb
|
139
|
+
- test/integration/ministamp_test.rb
|
140
|
+
- test/support/test_case.rb
|
141
|
+
has_rdoc:
|