linner 0.4.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad0db2767b837ef41fc611523a7208c1ae2eb7dc
4
- data.tar.gz: 0b0171fa4c551709cd155859cc9723033a2ef3b6
3
+ metadata.gz: 163b9428e612081d56821206cf90610b4d5653c1
4
+ data.tar.gz: ef2a80cc220dc6ebfc834368b5f1a3726295300a
5
5
  SHA512:
6
- metadata.gz: 6a505783f236a3a1ea6a9390a5b40dc9d62de55798aa2cc2cf83a9d3e4b695ec5af96dcf267c70b2d72d64ed8bdd2b01a42c096d2a5cd4944b9e7aac0727908f
7
- data.tar.gz: 7b8751ebbbafd8ec0db858d793d80ab1e16513be93331bd14e363cdd77a294867807a140d9814abb057f05724a4368cc196d44867aad676d3ffde81637872d43
6
+ metadata.gz: ba2dd94fda915cd2d24b44ac1313193516140e094510676e1276b1cffb1726f3b40b5c324a7c82baa084c34ef77f5f5e3cb766f93c1bbb7b33e6da7db17b297e
7
+ data.tar.gz: 23321997a50676a923bc9517365f74559f0078d31342efd9f05953cff8f1eca05cd60168285e003dcf096515f6cb3c37ce6387d84a3906de217530080a372796
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ v 0.4.1
2
+ - `manifest.yml` support
3
+ - lots of badges support
4
+
1
5
  v 0.4.0
2
6
  - revision support
3
7
  - fix memory leak in `cache_miss?`
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Linner
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/linner.png)](http://badge.fury.io/rb/linner) [![Build Status](https://travis-ci.org/SaitoWu/linner.png)](https://travis-ci.org/SaitoWu/linner) [![Code Climate](https://codeclimate.com/repos/520fd56e56b10241f50f15a3/badges/e8beb45f55b5c1fa6142/gpa.png)](https://codeclimate.com/repos/520fd56e56b10241f50f15a3/feed) [![Dependency Status](https://gemnasium.com/SaitoWu/linner.png)](https://gemnasium.com/SaitoWu/linner)
4
+
3
5
  Linner is a full-featured HTML5 application assembler.
4
6
 
5
7
  ![Linner](http://d.pr/i/bWPA+)
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ desc "test"
4
+ task :test do
5
+ sh 'rspec'
6
+ end
7
+
8
+ task :default => [:test]
@@ -3,6 +3,7 @@ require "nokogiri"
3
3
  require "linner/version"
4
4
  require "linner/command"
5
5
  require "linner/asset"
6
+ require "linner/cache"
6
7
  require "linner/helper"
7
8
  require "linner/reactor"
8
9
  require "linner/wrapper"
@@ -23,12 +24,30 @@ module Linner
23
24
  @root ||= Pathname('.').expand_path
24
25
  end
25
26
 
27
+ def env
28
+ @env ||= Environment.new begin
29
+ linner_file = root.join("Linnerfile")
30
+ config_file = root.join("config.yml")
31
+ File.exist?(linner_file) ? linner_file : config_file
32
+ end
33
+ end
34
+
26
35
  def cache
27
- @cache ||= {}
36
+ @cache ||= Cache.new
28
37
  end
29
38
 
30
- def env
31
- @env ||= Environment.new root.join("config.yml")
39
+ def manifest
40
+ @manifest ||= begin
41
+ hash = {}
42
+ env.groups.each do |config|
43
+ config["concat"].to_h.each do |dest, pattern|
44
+ asset = Asset.new(File.join env.public_folder, dest)
45
+ hash[dest] = asset.relative_digest_path
46
+ asset.revision!
47
+ end
48
+ end
49
+ hash
50
+ end
32
51
  end
33
52
 
34
53
  def compile?
@@ -36,11 +55,13 @@ module Linner
36
55
  end
37
56
 
38
57
  def sass_engine_options
39
- @options ||= Compass.configuration.to_sass_engine_options
40
- env.paths.each do |load_path|
41
- @options[:load_paths] << Sass::Importers::Filesystem.new(load_path)
58
+ @options ||= begin
59
+ options = Compass.configuration.to_sass_engine_options
60
+ env.paths.each do |load_path|
61
+ options[:load_paths] << Sass::Importers::Filesystem.new(load_path)
62
+ end
63
+ options
42
64
  end
43
- @options
44
65
  end
45
66
 
46
67
  def perform(*asset)
@@ -56,19 +77,15 @@ private
56
77
  config["concat"].each_with_index do |pair, index|
57
78
  dest, pattern, order = pair.first, pair.last, config["order"]||[]
58
79
  matches = Dir.glob(pattern).order_by(order)
59
- next if matches.select {|p| cache_miss? p}.empty?
60
- dest = Asset.new(File.join env.public_folder, dest)
61
- definition = Wrapper.definition if dest.path == env.definition
62
- dest.content = matches.inject(definition || "") {|s, m| s << cache[m].content}
63
- dest.compress if compile?
64
- dest.write
80
+ next if matches.select {|p| cache.miss? p}.empty?
81
+ write_asset(dest, matches)
65
82
  end
66
83
  end
67
84
 
68
85
  def copy(config)
69
86
  config["copy"].each do |dest, pattern|
70
87
  Dir.glob(pattern).each do |path|
71
- next if not cache_miss?(path)
88
+ next if not cache.miss?(path)
72
89
  logical_path = Asset.new(path).logical_path
73
90
  dest_path = File.join(env.public_folder, dest, logical_path)
74
91
  FileUtils.mkdir_p File.dirname(dest_path)
@@ -78,29 +95,34 @@ private
78
95
  end
79
96
 
80
97
  def revision
81
- revision = File.join env.public_folder, env.revision
82
- doc = Nokogiri::HTML.parse(File.read revision)
83
- doc.search("script").each do |x|
84
- next unless src = x.attributes["src"]
85
- asset = Asset.new(File.join env.public_folder, src)
86
- x.set_attribute "src", asset.revision!
87
- end
88
- doc.search("link").each do |x|
89
- next unless href = x.attributes["href"]
90
- asset = Asset.new(File.join env.public_folder, href)
91
- x.set_attribute "href", asset.revision!
92
- end
93
- File.open(revision, "w") do |f|
94
- f.write doc.to_html
98
+ dump_manifest
99
+ return unless File.exist?(rev = File.join(env.public_folder, env.revision.to_s))
100
+ doc = Nokogiri::HTML.parse(File.read rev)
101
+ replace_tag_with_manifest_value doc, "script", "src"
102
+ replace_tag_with_manifest_value doc, "link", "href"
103
+ File.open(rev, "w") {|f| f.write doc.to_html}
104
+ end
105
+
106
+ private
107
+
108
+ def write_asset(dest, child_assets)
109
+ asset = Asset.new(File.join env.public_folder, dest)
110
+ definition = (asset.path == env.definition ? Wrapper.definition : "")
111
+ asset.content = child_assets.inject(definition) {|s, m| s << cache[m].content}
112
+ asset.compress if compile?
113
+ asset.write
114
+ end
115
+
116
+ def replace_tag_with_manifest_value doc, tag, attribute
117
+ doc.search(tag).each do |x|
118
+ next unless node = x.attributes[attribute]
119
+ x.set_attribute attribute, manifest[node.value]
95
120
  end
96
121
  end
97
122
 
98
- def cache_miss?(path)
99
- asset = Asset.new(path)
100
- if cache[path] and cache[path].mtime == asset.mtime
101
- false
102
- else
103
- cache[path] = asset
123
+ def dump_manifest
124
+ File.open(File.join(env.public_folder, env.manifest), "w") do |f|
125
+ YAML.dump(manifest, f)
104
126
  end
105
127
  end
106
128
  end
@@ -7,9 +7,7 @@ module Linner
7
7
 
8
8
  def initialize(path)
9
9
  @path = path
10
- if File.exist? @path
11
- @mtime ||= File.mtime(path).to_i
12
- end
10
+ @mtime = File.mtime(path).to_i if File.exist?(path)
13
11
  end
14
12
 
15
13
  def mtime
@@ -17,17 +15,20 @@ module Linner
17
15
  end
18
16
 
19
17
  def extname
20
- File.extname @path
18
+ @extname = File.extname path
19
+ end
20
+
21
+ def digest_path
22
+ digest = Digest::MD5.hexdigest content
23
+ path.chomp(extname) << "-#{digest}" << extname
21
24
  end
22
25
 
23
- def digest
24
- Digest::MD5.hexdigest content
26
+ def relative_digest_path
27
+ digest_path.gsub /#{Linner.env.public_folder}/, ""
25
28
  end
26
29
 
27
30
  def revision!
28
- revision = @path.chomp(extname) << "-#{digest}" << extname
29
- File.rename @path, revision
30
- revision.gsub /#{Linner.env.public_folder}/, ""
31
+ File.rename path, digest_path
31
32
  end
32
33
 
33
34
  def content
@@ -0,0 +1,19 @@
1
+ module Linner
2
+ class Cache < Hash
3
+ def miss? path
4
+ asset = Asset.new path
5
+ if self[path] and self[path].mtime == asset.mtime
6
+ false
7
+ else
8
+ self[path] = asset
9
+ end
10
+ end
11
+
12
+ def expire_by paths
13
+ is_include_partial_styles = paths.any? do |path|
14
+ Asset.new(path).stylesheet? and File.basename(path).start_with? "_"
15
+ end
16
+ self.reject! {|k, v| v.stylesheet?} if is_include_partial_styles
17
+ end
18
+ end
19
+ end
@@ -18,46 +18,18 @@ module Linner
18
18
  desc "build", "build assets"
19
19
  def build
20
20
  Linner.compile = true
21
-
22
21
  clean
23
-
24
- Notifier.profile do
25
- Linner.perform
26
- end
22
+ Notifier.profile { Linner.perform }
27
23
  end
28
24
 
29
25
  desc "watch", "watch assets"
30
26
  def watch
31
- trap :INT do
32
- Notifier.exit
33
- Process.kill("QUIT", 0)
34
- end
35
-
27
+ trap(:INT) { exit! }
36
28
  clean
37
-
38
- @proc = Proc.new do |modified, added, removed|
39
- begin
40
- Notifier.profile{ Linner.perform }
41
- rescue
42
- Notifier.error $!
43
- end
44
- end
45
- @proc.call
46
-
47
- Listen.to env.app_folder, env.vendor_folder, env.test_folder do |modified, added, removed|
48
- is_include_partial_styles = (modified + added + removed).any? do |path|
49
- Asset.new(path).stylesheet? and File.basename(path).start_with? "_"
50
- end
51
- Linner.cache.reject! {|k, v| v.stylesheet?} if is_include_partial_styles
52
- @proc.call
53
- end
54
-
55
- @reactor = Reactor.supervise_as(:reactor).actors.first
56
- Listen.to env.public_folder, relative_path: true do |modified, added, removed|
57
- @reactor.reload_browser(modified + added + removed)
58
- end
59
-
60
- sleep
29
+ perform_proc.call
30
+ watch_for_perform
31
+ watch_for_reload
32
+ Process.wait
61
33
  end
62
34
 
63
35
  desc "clean", "clean assets"
@@ -75,6 +47,35 @@ module Linner
75
47
  def env
76
48
  Linner.env
77
49
  end
50
+
51
+ def perform_proc
52
+ @proc ||= Proc.new do |modified, added, removed|
53
+ begin
54
+ Notifier.profile{ Linner.perform }
55
+ rescue
56
+ Notifier.error $!
57
+ end
58
+ end
59
+ end
60
+
61
+ def watch_for_perform
62
+ Listen.to env.watched_paths do |modified, added, removed|
63
+ Linner.cache.expire_by(modified + added + removed)
64
+ perform_proc.call
65
+ end
66
+ end
67
+
68
+ def watch_for_reload
69
+ reactor = Reactor.supervise_as(:reactor).actors.first
70
+ Listen.to env.public_folder, relative_path: true do |modified, added, removed|
71
+ reactor.reload_browser(modified + added + removed)
72
+ end
73
+ end
74
+
75
+ def exit!
76
+ Notifier.exit
77
+ Kernel::exit
78
+ end
78
79
  end
79
80
  end
80
81
 
@@ -9,22 +9,26 @@ module Linner
9
9
  @env = @convension.rmerge!(@env)
10
10
  end
11
11
 
12
- def paths
13
- groups.map { |group| group["paths"] }.flatten.uniq
14
- end
15
-
16
12
  %w(app test vendor public).each do |method|
17
13
  define_method("#{method}_folder") do
18
14
  @env["paths"][method]
19
15
  end
20
16
  end
21
17
 
22
- def revision
23
- @env["revision"]
18
+ def paths
19
+ groups.map { |group| group["paths"] }.flatten.uniq
20
+ end
21
+
22
+ def watched_paths
23
+ [app_folder, vendor_folder, test_folder].select do |path|
24
+ File.exists? path
25
+ end
24
26
  end
25
27
 
26
- def notification
27
- @env["notification"]
28
+ %w(revision notification manifest).each do |method|
29
+ define_method("#{method}") do
30
+ @env[method]
31
+ end
28
32
  end
29
33
 
30
34
  def modules_ignored
@@ -13,25 +13,18 @@ module Linner
13
13
  order_ary = ary.inject([[]]) do |a, x|
14
14
  x != "..." ? a.last << x : a<< []; a
15
15
  end
16
- order_by_before(self, order_ary.first)
17
- order_by_after(self, order_ary.last)
16
+ order_by_direction(order_ary.first, :before)
17
+ order_by_direction(order_ary.last, :after)
18
18
  self
19
19
  end
20
20
 
21
21
  private
22
- def order_by_before(list, before)
23
- before.reverse.each do |f|
24
- if i = list.index {|x| x =~ /#{f}/i}
25
- list.unshift list.delete_at i
26
- end
27
- end
28
- end
29
-
30
- def order_by_after(list, after)
31
- after.reverse.each do |f|
32
- if i = list.index {|x| x =~ /#{f}/i}
33
- list.push list.delete_at i
34
- end
22
+ def order_by_direction(ary, direction)
23
+ ary = ary.reverse if direction == :before
24
+ ary.each do |f|
25
+ next unless i = self.index {|x| x =~ /#{f}/i}
26
+ item = self.delete_at i
27
+ direction == :before ? self.unshift(item) : self.push(item)
35
28
  end
36
29
  end
37
30
  end
@@ -6,7 +6,7 @@
6
6
  <meta name="description" content="">
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1">
8
8
 
9
- <link rel="stylesheet" href="styles/app.css">
9
+ <link rel="stylesheet" href="/styles/app.css">
10
10
  </head>
11
11
  <body>
12
12
  <!--[if lt IE 7]>
@@ -15,8 +15,7 @@
15
15
 
16
16
  <p>Hello world! This is Linner Boilerplate.</p>
17
17
 
18
- <script src="scripts/vendor.js"></script>
19
- <script src="scripts/app.js"></script>
20
- <script>require("app")()</script>
18
+ <script src="/scripts/vendor.js"></script>
19
+ <script src="/scripts/app.js"></script>
21
20
  </body>
22
21
  </html>
@@ -3,21 +3,24 @@ paths:
3
3
  groups:
4
4
  scripts:
5
5
  concat:
6
- "scripts/app.js": "app/**/*.{js,coffee}"
7
- "scripts/vendor.js": "vendor/**/*.{js,coffee}"
6
+ "/scripts/app.js": "app/**/*.{js,coffee}"
7
+ "/scripts/vendor.js": "vendor/**/*.{js,coffee}"
8
8
  order:
9
9
  - "vendor/jquery-1.10.2.js"
10
10
  - "..."
11
+ - "app/scripts/app.coffee"
11
12
  styles:
12
13
  concat:
13
- "styles/app.css": "app/styles/**/[a-z]*.{css,scss,sass}"
14
+ "/styles/app.css": "app/styles/**/[a-z]*.{css,scss,sass}"
14
15
  images:
15
16
  copy:
16
- "images/": "app/images/**/*.{png,gif}"
17
+ "/images/": "app/images/**/*.{png,gif}"
17
18
  views:
18
19
  copy:
19
20
  "/": "app/views/**/*.{html,hbs}"
20
21
  modules:
21
22
  wrapper: "cmd"
23
+ ignored: "{vendor/**/*,app/scripts/app.{js,coffee}"
24
+ definition: "/scripts/app.js"
22
25
  revision: "index.html"
23
26
  notification: true
@@ -1,3 +1,3 @@
1
1
  module Linner
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -22,15 +22,16 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency "thor", "~> 0.18"
23
23
  spec.add_dependency "tilt", "~> 1.4"
24
24
  spec.add_dependency "sass", "~> 3.2"
25
- spec.add_dependency "listen", "~> 1.2"
25
+ spec.add_dependency "listen", "~> 1.3"
26
26
  spec.add_dependency "nio4r", "~> 0.5.0"
27
- spec.add_dependency "uglifier", "~> 2.1"
27
+ spec.add_dependency "uglifier", "~> 2.2"
28
28
  spec.add_dependency "nokogiri", "~> 1.6.0"
29
29
  spec.add_dependency "compass", "~> 0.12.2"
30
30
  spec.add_dependency "cssminify", "~> 1.0.2"
31
31
  spec.add_dependency "coffee-script", "~> 2.2"
32
- spec.add_dependency "terminal-notifier", "~> 1.4"
32
+ spec.add_dependency "terminal-notifier", "~> 1.5"
33
33
 
34
+ spec.add_development_dependency "pry"
34
35
  spec.add_development_dependency "rake"
35
36
  spec.add_development_dependency "rspec", "~> 2.14"
36
37
  spec.add_development_dependency "bundler", "~> 1.3"
@@ -5,13 +5,19 @@ describe Asset do
5
5
  before(:each) do
6
6
  @script_asset = Asset.new("app/scripts/app.js")
7
7
  @style_asset = Asset.new("app/styles/app.css")
8
+ @dest_asset = Asset.new("public/app.js")
8
9
  end
9
10
 
10
- it "should be return right logical_path" do
11
+ it "should return right logical_path" do
11
12
  @script_asset.logical_path.should == "app.js"
12
13
  @style_asset.logical_path.should == "app.css"
13
14
  end
14
15
 
16
+ it "should return right digest_path" do
17
+ @dest_asset.digest_path.should == "public/app-cdd1c27fabeede75d12b8adf46e987fd.js"
18
+ @dest_asset.relative_digest_path.should == "/app-cdd1c27fabeede75d12b8adf46e987fd.js"
19
+ end
20
+
15
21
  it "should be javascript" do
16
22
  @script_asset.javascript?.should be_true
17
23
  @style_asset.stylesheet?.should be_true
@@ -17,6 +17,7 @@ describe Environment do
17
17
  it "should equals default config" do
18
18
  @env.notification.should be_true
19
19
  @env.wrapper.should == "cmd"
20
+ @env.manifest.should == "manifest.yml"
20
21
  @env.revision.should == false
21
22
  @env.groups.should respond_to(:each)
22
23
  end
@@ -6,21 +6,21 @@ describe Array do
6
6
  end
7
7
 
8
8
  it "won't change when before and after are empty array" do
9
- @array.order_by([]).should =~ @array
9
+ @array.order_by([]).should == @array
10
10
  end
11
11
 
12
12
  it "will change by before items" do
13
13
  @array.order_by(["jquery.js", "vendor.js"])
14
- @array.should =~ %w[jquery.js vendor.js app.js bootstrap.css reset.css]
14
+ @array.should == %w[jquery.js vendor.js app.js bootstrap.css reset.css]
15
15
  end
16
16
 
17
17
  it "will change by after items" do
18
18
  @array.order_by(["...", "reset.css", "bootstrap.css"])
19
- @array.should =~ %w[app.js jquery.js vendor.js reset.css bootstrap.css]
19
+ @array.should == %w[app.js jquery.js vendor.js reset.css bootstrap.css]
20
20
  end
21
21
 
22
22
  it "will change by before and after items" do
23
23
  @array.order_by(["jquery.js", "vendor.js", "...", "reset.css", "bootstrap.css"])
24
- @array.should =~ %w[jquery.js vendor.js app.js reset.css bootstrap.css]
24
+ @array.should == %w[jquery.js vendor.js app.js reset.css bootstrap.css]
25
25
  end
26
26
  end
@@ -24,8 +24,8 @@ groups:
24
24
  modules:
25
25
  wrapper: "cmd"
26
26
  ignored: "vendor/**/*"
27
- definition: "scripts/app.js"
27
+ definition: "/scripts/app.js"
28
28
 
29
+ manifest: "manifest.yml"
29
30
  revision: false
30
-
31
31
  notification: true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: linner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Saito
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-16 00:00:00.000000000 Z
11
+ date: 2013-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: reel
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - ~>
74
74
  - !ruby/object:Gem::Version
75
- version: '1.2'
75
+ version: '1.3'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ~>
81
81
  - !ruby/object:Gem::Version
82
- version: '1.2'
82
+ version: '1.3'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: nio4r
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - ~>
102
102
  - !ruby/object:Gem::Version
103
- version: '2.1'
103
+ version: '2.2'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - ~>
109
109
  - !ruby/object:Gem::Version
110
- version: '2.1'
110
+ version: '2.2'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: nokogiri
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -170,14 +170,28 @@ dependencies:
170
170
  requirements:
171
171
  - - ~>
172
172
  - !ruby/object:Gem::Version
173
- version: '1.4'
173
+ version: '1.5'
174
174
  type: :runtime
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - ~>
179
179
  - !ruby/object:Gem::Version
180
- version: '1.4'
180
+ version: '1.5'
181
+ - !ruby/object:Gem::Dependency
182
+ name: pry
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - '>='
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - '>='
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: rake
183
197
  requirement: !ruby/object:Gem::Requirement
@@ -230,6 +244,7 @@ extra_rdoc_files: []
230
244
  files:
231
245
  - .gitignore
232
246
  - .rspec
247
+ - .travis.yml
233
248
  - CHANGELOG
234
249
  - Gemfile
235
250
  - Gemfile.lock
@@ -241,6 +256,7 @@ files:
241
256
  - docs/config.md
242
257
  - lib/linner.rb
243
258
  - lib/linner/asset.rb
259
+ - lib/linner/cache.rb
244
260
  - lib/linner/command.rb
245
261
  - lib/linner/compressor.rb
246
262
  - lib/linner/environment.rb