slinky 0.7.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/.travis.yml +1 -1
- data/Gemfile +2 -0
- data/README.md +119 -8
- data/VERSION +1 -1
- data/lib/slinky.rb +2 -0
- data/lib/slinky/builder.rb +4 -2
- data/lib/slinky/compiled_file.rb +1 -1
- data/lib/slinky/compilers.rb +5 -2
- data/lib/slinky/compilers/clojurescript-compiler.rb +4 -4
- data/lib/slinky/compilers/coffee-compiler.rb +4 -3
- data/lib/slinky/compilers/haml-compiler.rb +4 -3
- data/lib/slinky/compilers/jsx-compiler.rb +13 -0
- data/lib/slinky/compilers/less-compiler.rb +4 -3
- data/lib/slinky/compilers/sass-compiler.rb +4 -3
- data/lib/slinky/config_reader.rb +18 -2
- data/lib/slinky/errors.rb +91 -0
- data/lib/slinky/graph.rb +113 -0
- data/lib/slinky/manifest.rb +290 -123
- data/lib/slinky/proxy_server.rb +1 -1
- data/lib/slinky/runner.rb +1 -1
- data/lib/slinky/server.rb +41 -5
- data/lib/slinky/templates/error.css +32 -0
- data/lib/slinky/templates/error.haml +13 -0
- data/lib/slinky/templates/error.js +26 -0
- data/lib/slinky/templates/inject.css +27 -0
- data/slinky.gemspec +17 -3
- data/spec/compilers_spec.rb +15 -0
- data/spec/manifest_spec.rb +750 -0
- data/spec/slinky_spec.rb +9 -421
- data/spec/spec_helper.rb +22 -7
- metadata +83 -47
data/lib/slinky/proxy_server.rb
CHANGED
data/lib/slinky/runner.rb
CHANGED
@@ -70,7 +70,7 @@ module Slinky
|
|
70
70
|
EM::run {
|
71
71
|
@config ||= Config.empty
|
72
72
|
|
73
|
-
Slinky::Server.dir = @options[:src_dir]
|
73
|
+
Slinky::Server.dir = @options[:src_dir] || @config.src_dir
|
74
74
|
Slinky::Server.config = @config
|
75
75
|
manifest = Manifest.new(Slinky::Server.dir,
|
76
76
|
Slinky::Server.config)
|
data/lib/slinky/server.rb
CHANGED
@@ -2,6 +2,11 @@ module Slinky
|
|
2
2
|
module Server
|
3
3
|
include EM::HttpServer
|
4
4
|
|
5
|
+
INJECT_CSS = File.read("#{File.dirname(__FILE__)}/templates/inject.css")
|
6
|
+
ERROR_CSS = File.read("#{File.dirname(__FILE__)}/templates/error.css")
|
7
|
+
ERROR_HAML = File.read("#{File.dirname(__FILE__)}/templates/error.haml")
|
8
|
+
ERROR_JS = File.read("#{File.dirname(__FILE__)}/templates/error.js")
|
9
|
+
|
5
10
|
# Sets the root directory from which files should be served
|
6
11
|
def self.dir= _dir; @dir = _dir; end
|
7
12
|
# Gets the root directory from which files should be served
|
@@ -59,17 +64,48 @@ module Slinky
|
|
59
64
|
resp
|
60
65
|
end
|
61
66
|
|
67
|
+
# Produces nice error output for various kinds of formats
|
68
|
+
def self.format_error_output resp, mf, error
|
69
|
+
resp.content =
|
70
|
+
case Pathname.new(mf.output_path).extname
|
71
|
+
when ".html"
|
72
|
+
Haml::Engine.new(ERROR_HAML).
|
73
|
+
render(Object.new, errors: error.messages, css: ERROR_CSS)
|
74
|
+
when ".css"
|
75
|
+
resp.status = 200 # browsers ignore 500'd css
|
76
|
+
INJECT_CSS.gsub("{REPLACE_ERRORS}",
|
77
|
+
error.messages.join("\n").gsub("'", "\""))
|
78
|
+
when ".js"
|
79
|
+
resp.status = 200 # browsers ignore 500'd js
|
80
|
+
ERROR_JS
|
81
|
+
.gsub("{REPLACE_CSS}",
|
82
|
+
JSON.dump({css: ERROR_CSS.gsub("\n", "")}))
|
83
|
+
.gsub("{REPLACE_ERRORS}", JSON.dump(error.messages))
|
84
|
+
else
|
85
|
+
error.message
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
62
89
|
# Takes a manifest file and produces a response for it
|
63
90
|
def self.handle_file resp, mf, compile = true
|
64
91
|
begin
|
65
|
-
|
66
|
-
|
92
|
+
path = mf.process(nil, compile)
|
93
|
+
serve_file resp, path.to_s
|
94
|
+
rescue SlinkyError => e
|
95
|
+
resp.status = 500
|
96
|
+
if self.config.enable_browser_errors
|
97
|
+
format_error_output(resp, mf, e)
|
67
98
|
else
|
68
|
-
|
99
|
+
resp.content = e.message
|
69
100
|
end
|
70
|
-
|
101
|
+
e.messages.each{|m|
|
102
|
+
$stderr.puts(m.foreground(:red))
|
103
|
+
}
|
104
|
+
rescue => e
|
71
105
|
resp.status = 500
|
72
|
-
resp
|
106
|
+
format_error_output(resp, mf, SlinkyError.new(
|
107
|
+
"Unknown error handling #{mf.source}: #{$!}\n"))
|
108
|
+
$stderr.puts("Unknown error handling #{mf.source}: #{$!}".foreground(:red))
|
73
109
|
end
|
74
110
|
resp
|
75
111
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#slinky-error {
|
2
|
+
font-family: Helvetica, Arial, Sans-Serif;
|
3
|
+
}
|
4
|
+
|
5
|
+
#slinky-error .slinky-header {
|
6
|
+
position: absolute;
|
7
|
+
top: 0;
|
8
|
+
left: 0;
|
9
|
+
right: 0;
|
10
|
+
height: 100px;
|
11
|
+
background-color: rgb(141, 55, 55);
|
12
|
+
text-align: center;
|
13
|
+
font-size: 1.5em;
|
14
|
+
line-height: 1.5em;
|
15
|
+
color: whitesmoke;
|
16
|
+
text-shadow: -1px -1px rgba(0, 0, 0, 0.2)
|
17
|
+
}
|
18
|
+
|
19
|
+
#slinky-error .slinky-body {
|
20
|
+
position: absolute;
|
21
|
+
top: 100px; left: 0; right: 0;
|
22
|
+
padding: 0 50px;
|
23
|
+
padding-bottom: 20px;
|
24
|
+
font-size: 1.25em;
|
25
|
+
color: black;
|
26
|
+
background-color: whitesmoke;
|
27
|
+
border-bottom: 1px solid #aaa;
|
28
|
+
}
|
29
|
+
|
30
|
+
#slinky-error .slinky-body li {
|
31
|
+
padding-top: 20px;
|
32
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
(function(errors) {
|
2
|
+
var domLoaded = function() {
|
3
|
+
var css = {REPLACE_CSS};
|
4
|
+
var cssEl = document.createElement("style");
|
5
|
+
cssEl.type = "text/css";
|
6
|
+
cssEl.innerText = css.css;
|
7
|
+
document.head.appendChild(cssEl);
|
8
|
+
|
9
|
+
var el = document.getElementById("slinky-error");
|
10
|
+
if(el == null) {
|
11
|
+
el = document.createElement("div");
|
12
|
+
el.id = "slinky-error";
|
13
|
+
el.innerHTML = '<div class="slinky-header"><h1>Oh no! Build'
|
14
|
+
+ ' error!</h1></div><div class="slinky-body"><ul></ul></div>';
|
15
|
+
document.body.appendChild(el);
|
16
|
+
}
|
17
|
+
|
18
|
+
var ul = el.getElementsByTagName("ul")[0];
|
19
|
+
errors.forEach(function(error) {
|
20
|
+
var li = document.createElement("li");
|
21
|
+
li.innerText = error;
|
22
|
+
ul.appendChild(li);
|
23
|
+
});
|
24
|
+
};
|
25
|
+
document.addEventListener("DOMContentLoaded", domLoaded, false);
|
26
|
+
})({REPLACE_ERRORS});
|
@@ -0,0 +1,27 @@
|
|
1
|
+
body:before {
|
2
|
+
font-family: Helvetica, Arial, Sans-Serif;
|
3
|
+
content: "oh no! build error!";
|
4
|
+
position: absolute;
|
5
|
+
top: 0;
|
6
|
+
left: 0;
|
7
|
+
right: 0;
|
8
|
+
height: 100px;
|
9
|
+
background-color: rgb(141, 55, 55);
|
10
|
+
text-align: center;
|
11
|
+
font-size: 2.5em;
|
12
|
+
line-height: 2.5em;
|
13
|
+
color: whitesmoke;
|
14
|
+
text-shadow: -1px -1px rgba(0, 0, 0, 0.2)
|
15
|
+
}
|
16
|
+
|
17
|
+
body:after {
|
18
|
+
font-family: Helvetica, Arial, Sans-Serif;
|
19
|
+
content: '{REPLACE_ERRORS}';
|
20
|
+
position: absolute;
|
21
|
+
top: 100px; left: 0; right: 0;
|
22
|
+
padding: 20px 50px;
|
23
|
+
font-size: 1.25em;
|
24
|
+
color: black;
|
25
|
+
background-color: whitesmoke;
|
26
|
+
border-bottom: 1px solid #aaa;
|
27
|
+
}
|
data/slinky.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: slinky 0.
|
5
|
+
# stub: slinky 0.8.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "slinky"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.8.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Micah Wylde"]
|
14
|
-
s.date = "2014-
|
14
|
+
s.date = "2014-07-19"
|
15
15
|
s.description = "A static file server for rich web apps that automatically compiles SASS, HAML, CoffeeScript and more"
|
16
16
|
s.email = "micah@micahw.com"
|
17
17
|
s.executables = ["slinky"]
|
@@ -36,18 +36,26 @@ Gem::Specification.new do |s|
|
|
36
36
|
"lib/slinky/compilers/clojurescript-compiler.rb",
|
37
37
|
"lib/slinky/compilers/coffee-compiler.rb",
|
38
38
|
"lib/slinky/compilers/haml-compiler.rb",
|
39
|
+
"lib/slinky/compilers/jsx-compiler.rb",
|
39
40
|
"lib/slinky/compilers/less-compiler.rb",
|
40
41
|
"lib/slinky/compilers/sass-compiler.rb",
|
41
42
|
"lib/slinky/config_reader.rb",
|
42
43
|
"lib/slinky/em-popen3.rb",
|
44
|
+
"lib/slinky/errors.rb",
|
45
|
+
"lib/slinky/graph.rb",
|
43
46
|
"lib/slinky/listener.rb",
|
44
47
|
"lib/slinky/live_reload.rb",
|
45
48
|
"lib/slinky/manifest.rb",
|
46
49
|
"lib/slinky/proxy_server.rb",
|
47
50
|
"lib/slinky/runner.rb",
|
48
51
|
"lib/slinky/server.rb",
|
52
|
+
"lib/slinky/templates/error.css",
|
53
|
+
"lib/slinky/templates/error.haml",
|
54
|
+
"lib/slinky/templates/error.js",
|
55
|
+
"lib/slinky/templates/inject.css",
|
49
56
|
"slinky.gemspec",
|
50
57
|
"spec/compilers_spec.rb",
|
58
|
+
"spec/manifest_spec.rb",
|
51
59
|
"spec/slinky_spec.rb",
|
52
60
|
"spec/spec_helper.rb"
|
53
61
|
]
|
@@ -60,6 +68,7 @@ Gem::Specification.new do |s|
|
|
60
68
|
s.specification_version = 4
|
61
69
|
|
62
70
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
71
|
+
s.add_runtime_dependency(%q<multi_json>, ["~> 1.9.2"])
|
63
72
|
s.add_runtime_dependency(%q<eventmachine>, ["~> 1.0"])
|
64
73
|
s.add_runtime_dependency(%q<eventmachine_httpserver>, ["~> 0.2"])
|
65
74
|
s.add_runtime_dependency(%q<em-websocket>, ["~> 0.3"])
|
@@ -80,7 +89,9 @@ Gem::Specification.new do |s|
|
|
80
89
|
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
81
90
|
s.add_development_dependency(%q<less>, [">= 2.2.0"])
|
82
91
|
s.add_development_dependency(%q<therubyracer>, [">= 0"])
|
92
|
+
s.add_development_dependency(%q<react-jsx>, ["~> 0.8.0"])
|
83
93
|
else
|
94
|
+
s.add_dependency(%q<multi_json>, ["~> 1.9.2"])
|
84
95
|
s.add_dependency(%q<eventmachine>, ["~> 1.0"])
|
85
96
|
s.add_dependency(%q<eventmachine_httpserver>, ["~> 0.2"])
|
86
97
|
s.add_dependency(%q<em-websocket>, ["~> 0.3"])
|
@@ -101,8 +112,10 @@ Gem::Specification.new do |s|
|
|
101
112
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
102
113
|
s.add_dependency(%q<less>, [">= 2.2.0"])
|
103
114
|
s.add_dependency(%q<therubyracer>, [">= 0"])
|
115
|
+
s.add_dependency(%q<react-jsx>, ["~> 0.8.0"])
|
104
116
|
end
|
105
117
|
else
|
118
|
+
s.add_dependency(%q<multi_json>, ["~> 1.9.2"])
|
106
119
|
s.add_dependency(%q<eventmachine>, ["~> 1.0"])
|
107
120
|
s.add_dependency(%q<eventmachine_httpserver>, ["~> 0.2"])
|
108
121
|
s.add_dependency(%q<em-websocket>, ["~> 0.3"])
|
@@ -123,6 +136,7 @@ Gem::Specification.new do |s|
|
|
123
136
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
124
137
|
s.add_dependency(%q<less>, [">= 2.2.0"])
|
125
138
|
s.add_dependency(%q<therubyracer>, [">= 0"])
|
139
|
+
s.add_dependency(%q<react-jsx>, ["~> 0.8.0"])
|
126
140
|
end
|
127
141
|
end
|
128
142
|
|
data/spec/compilers_spec.rb
CHANGED
@@ -90,4 +90,19 @@ eos
|
|
90
90
|
}
|
91
91
|
end
|
92
92
|
end
|
93
|
+
|
94
|
+
context "JSXCompiler" do
|
95
|
+
it "should be able to compile .jsx files" do
|
96
|
+
src = <<-EOF
|
97
|
+
/** @jsx React.DOM */
|
98
|
+
React.renderComponent(
|
99
|
+
<h1>Hello, world!</h1>,
|
100
|
+
document.getElementById('example')
|
101
|
+
);
|
102
|
+
EOF
|
103
|
+
compiler_test("/compilers/test.jsx", ".js", src){|s|
|
104
|
+
s.include?("Hello, world!")
|
105
|
+
}
|
106
|
+
end
|
107
|
+
end
|
93
108
|
end
|
@@ -0,0 +1,750 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "Manifest" do
|
4
|
+
before :each do
|
5
|
+
@mprod = Slinky::Manifest.new("/src", @config, :devel => false, :build_to => "/build")
|
6
|
+
@mdevel = Slinky::Manifest.new("/src", @config)
|
7
|
+
@md_prod = @mprod.manifest_dir
|
8
|
+
@md_devel = @mdevel.manifest_dir
|
9
|
+
end
|
10
|
+
|
11
|
+
context "General" do
|
12
|
+
it "should build manifest dir with all files in current dir" do
|
13
|
+
@md_prod.files.collect{|f| f.source}.should == ["/src/test.haml"]
|
14
|
+
@md_devel.files.collect{|f| f.source}.should == ["/src/test.haml"]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should build manifest with all files in fs" do
|
18
|
+
@mprod.files.collect{|f|
|
19
|
+
f.source
|
20
|
+
}.sort.should == @files.collect{|x| "/src/" + x}.sort
|
21
|
+
@mdevel.files.collect{|f|
|
22
|
+
f.source
|
23
|
+
}.sort.should == @files.collect{|x| "/src/" + x}.sort
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should not include dot files" do
|
27
|
+
File.open("/src/.index.haml.swp", "w+"){|f| f.write("x")}
|
28
|
+
manifest = Slinky::Manifest.new("/src", @config)
|
29
|
+
manifest.files.map{|x| x.source}.include?("/src/.index.haml.swp").should == false
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should be able to compute a hash for the entire manifest" do
|
33
|
+
m = @mdevel
|
34
|
+
hash1 = m.md5
|
35
|
+
File.open("/src/hello.html", "w+") {|f| f.write("Hell!") }
|
36
|
+
$stdout.should_receive(:puts).with("Compiled /src/test.haml".foreground(:green)).exactly(2).times
|
37
|
+
m.add_all_by_path(["/src/hello.html"])
|
38
|
+
m.md5.should_not == hash1
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should find files in the manifest by path" do
|
42
|
+
@mdevel.find_by_path("test.haml").first.source.should == "/src/test.haml"
|
43
|
+
@mdevel.find_by_path("asdf.haml").first.should == nil
|
44
|
+
@mdevel.find_by_path("l1/l2/test.txt").first.source.should == "/src/l1/l2/test.txt"
|
45
|
+
@mdevel.find_by_path("l1/test.css").first.source.should == "/src/l1/test.sass"
|
46
|
+
l1 = @mdevel.manifest_dir.children.find{|c| c.dir == "/src/l1"}
|
47
|
+
l1.find_by_path("../test.haml").first.source.should == "/src/test.haml"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should produce the correct scripts string for production" do
|
51
|
+
@mprod.scripts_string.should match \
|
52
|
+
%r!<script type="text/javascript" src="/scripts.js\?\d+"></script>!
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should produce the correct scripts string for devel" do
|
56
|
+
@mdevel.scripts_string.should == [
|
57
|
+
'<script type="text/javascript" src="/l1/test5.js"></script>',
|
58
|
+
'<script type="text/javascript" src="/l1/l2/test6.js"></script>',
|
59
|
+
'<script type="text/javascript" src="/l1/test2.js"></script>',
|
60
|
+
'<script type="text/javascript" src="/l1/l2/test3.js"></script>',
|
61
|
+
'<script type="text/javascript" src="/l1/test.js"></script>'].join("\n")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should produce the correct styles string for production" do
|
65
|
+
@mprod.styles_string.should match \
|
66
|
+
%r!<link rel="stylesheet" href="/styles.css\?\d+" />!
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should produce the correct styles string for development" do
|
70
|
+
File.open("/src/l1/l2/bad.sass", "w+"){|f|
|
71
|
+
f.write "require('../test.sass')\ncolor: red;"
|
72
|
+
}
|
73
|
+
manifest = Slinky::Manifest.new("/src", @config)
|
74
|
+
@mdevel.styles_string.should == [
|
75
|
+
'<link rel="stylesheet" href="/l1/test.css" />',
|
76
|
+
'<link rel="stylesheet" href="/l1/l2/test2.css" />'].join("\n")
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should allow the creation of ManifestFiles" do
|
80
|
+
mf = Slinky::ManifestFile.new("/src/test.haml", "", @mprod)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should correctly determine output_path" do
|
84
|
+
mf = Slinky::ManifestFile.new("/src/test.haml", "/src/build", @mprod)
|
85
|
+
mf.output_path.to_s.should == "/src/test.html"
|
86
|
+
mf = Slinky::ManifestFile.new("/src/l1/test.js", "/src/build", @mprod)
|
87
|
+
mf.output_path.to_s.should == "/src/l1/test.js"
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should correctly determine relative_output_path" do
|
91
|
+
mf = Slinky::ManifestFile.new("/src/test.haml", "/src/build", @mprod)
|
92
|
+
mf.relative_output_path.to_s.should == "test.html"
|
93
|
+
mf = Slinky::ManifestFile.new("/src/l1/test.js", "/src/build", @mprod)
|
94
|
+
mf.relative_output_path.to_s.should == "l1/test.js"
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should build tmp file without directives" do
|
98
|
+
original = "/src/test.haml"
|
99
|
+
mf = Slinky::ManifestFile.new("/src/test.haml", "/src/build", @mprod)
|
100
|
+
path = mf.handle_directives mf.source
|
101
|
+
File.read(original).match(/slinky_scripts|slinky_styles/).should_not == nil
|
102
|
+
File.read(path).match(/slinky_scripts|slinky_styles/).should == nil
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should build tmp file without directives for .js" do
|
106
|
+
original = "/src/l1/test.js"
|
107
|
+
mf = Slinky::ManifestFile.new("/src/l1/test.js", "/src/build", @mprod)
|
108
|
+
path = mf.handle_directives mf.source
|
109
|
+
File.read(original).match(/slinky_require/).should_not == nil
|
110
|
+
File.read(path).match(/slinky_require/).should == nil
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should compile files that need it" do
|
114
|
+
$stdout.should_receive(:puts).with("Compiled /src/test.haml".foreground(:green))
|
115
|
+
mf = Slinky::ManifestFile.new("/src/test.haml", "/src/build", @mprod)
|
116
|
+
FileUtils.mkdir("/src/build")
|
117
|
+
build_path = mf.process mf.build_to
|
118
|
+
build_path.to_s.split(".")[-1].should == "html"
|
119
|
+
File.read("/src/test.haml").match("<head>").should == nil
|
120
|
+
File.read(build_path).match("<head>").should_not == nil
|
121
|
+
|
122
|
+
$stdout.should_receive(:puts).with("Compiled /src/test.haml".foreground(:green))
|
123
|
+
mf = Slinky::ManifestFile.new("/src/test.haml", "/src/build", @mprod)
|
124
|
+
build_path = mf.process "/src/build/test.html"
|
125
|
+
File.read("/src/build/test.html").match("<head>").should_not == nil
|
126
|
+
FileUtils.rm_rf("/src/build") rescue nil
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should give the proper error message for compilers with unmet dependencies" do
|
130
|
+
File.open("/src/test.fake", "w+"){|f| f.write("hello, fake data")}
|
131
|
+
$stderr.should_receive(:puts).with(/Missing dependency/)
|
132
|
+
mf = Slinky::ManifestFile.new("/src/test.fake", "/src/build", @mprod)
|
133
|
+
build_path = mf.process
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should report errors for bad files" do
|
137
|
+
File.open("/src/l1/l2/bad.sass", "w+"){|f|
|
138
|
+
f.write "color: red;"
|
139
|
+
}
|
140
|
+
mf = Slinky::ManifestFile.new("/src/l1/l2/bad.sass", "/src/build", @mprod)
|
141
|
+
expect { mf.process }.to raise_error Slinky::BuildFailedError
|
142
|
+
end
|
143
|
+
|
144
|
+
it "shouldn't crash on syntax errors" do
|
145
|
+
File.open("/src/l1/asdf.haml", "w+"){|f|
|
146
|
+
f.write("%h1{:width => 50px}")
|
147
|
+
}
|
148
|
+
mf = Slinky::ManifestFile.new("/src/l1/asdf.haml", "/src/build", @mprod)
|
149
|
+
expect { mf.process }.to raise_error Slinky::BuildFailedError
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should properly determine build directives" do
|
153
|
+
mf = Slinky::ManifestFile.new("/src/test.haml", "/src/build", @mprod)
|
154
|
+
mf.find_directives.should == {:slinky_scripts => [], :slinky_styles => []}
|
155
|
+
mf = Slinky::ManifestFile.new("/src/l1/test.js", "/src/build", @mprod)
|
156
|
+
mf.find_directives.should == {:slinky_require => ["test2.js", "l2/test3.js"]}
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should properly determine build_to path" do
|
160
|
+
mf = Slinky::ManifestFile.new("/src/test.haml", "/src/build", @mprod)
|
161
|
+
mf.build_to.should == Pathname.new("/src/build/test.html")
|
162
|
+
mf = Slinky::ManifestFile.new("/src/l1/test.js", "/src/build", @mprod)
|
163
|
+
mf.build_to.should == Pathname.new("/src/build/test.js")
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should build both compiled files and non-compiled files" do
|
167
|
+
$stdout.should_receive(:puts).with("Compiled /src/test.haml".foreground(:green))
|
168
|
+
mf = Slinky::ManifestFile.new("/src/test.haml", "/src/build", @mprod)
|
169
|
+
path = mf.build
|
170
|
+
path.to_s.should == "/src/build/test.html"
|
171
|
+
File.read("/src/test.haml").match("<head>").should == nil
|
172
|
+
File.read(path).match("<head>").should_not == nil
|
173
|
+
|
174
|
+
$stdout.should_not_receive(:puts)
|
175
|
+
mf = Slinky::ManifestFile.new("/src/l1/l2/test.txt", "/src/build/l1/l2", @mprod)
|
176
|
+
path = mf.build
|
177
|
+
path.to_s.should == "/src/build/l1/l2/test.txt"
|
178
|
+
File.read("/src/build/l1/l2/test.txt").should == "hello\n"
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should match files" do
|
182
|
+
mf = Slinky::ManifestFile.new("/src/l1/l2/test.txt", "/src/build/l1/l2", @mprod)
|
183
|
+
mf.matches?("test.txt").should == true
|
184
|
+
mf = Slinky::ManifestFile.new("/src/l1/test.sass", "", @mprod)
|
185
|
+
mf.matches?("test.css").should == true
|
186
|
+
mf.matches?("test.sass").should == true
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should match file paths" do
|
190
|
+
mf = Slinky::ManifestFile.new("/src/l1/l2/test.txt", "/src/build/l1/l2", @mprod)
|
191
|
+
mf.matches_path?("test.txt").should == false
|
192
|
+
mf.matches_path?("/l1/l2/test.txt").should == true
|
193
|
+
mf.matches_path?("/l1/l2/*.txt").should == false
|
194
|
+
mf.matches_path?("/l1/l2/*.txt", true).should == true
|
195
|
+
mf = Slinky::ManifestFile.new("/src/l1/test.sass", "", @mprod)
|
196
|
+
mf.matches_path?("/l1/test.css").should == true
|
197
|
+
mf.matches_path?("/l1/test.sass").should == true
|
198
|
+
mf.matches_path?("/l1/*.css", true).should == true
|
199
|
+
mf.matches_path?("/l1/*.sass", true).should == true
|
200
|
+
mf.matches_path?("l1/test.sass").should == false
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should should properly determine if in tree" do
|
204
|
+
mf = Slinky::ManifestFile.new("/src/l1/l2/test.txt", "/src/build/l1/l2", @mprod)
|
205
|
+
mf.in_tree?("/l1").should == true
|
206
|
+
mf.in_tree?("/l1/l2").should == true
|
207
|
+
mf.in_tree?("/l1/l2/test.txt").should == true
|
208
|
+
mf.in_tree?("/l1/l3").should == false
|
209
|
+
mf.in_tree?("test.txt").should == false
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should correctly build the dependency graph" do
|
213
|
+
@mprod.dependency_graph.collect{|x| x.collect{|y| y.source}}.sort.should ==
|
214
|
+
[["/src/l1/test2.js", "/src/l1/test.js"],
|
215
|
+
["/src/l1/l2/test3.coffee", "/src/l1/test.js"],
|
216
|
+
["/src/l1/test5.js", "/src/l1/test2.js"],
|
217
|
+
["/src/l1/l2/test6.js", "/src/l1/l2/test3.coffee"]].sort
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should fail if a required file isn't in the manifest" do
|
221
|
+
FileUtils.rm("/src/l1/test2.js")
|
222
|
+
manifest = Slinky::Manifest.new("/src", @config, :devel => false, :build_to => "/build")
|
223
|
+
proc {
|
224
|
+
manifest.dependency_graph
|
225
|
+
}.should raise_error Slinky::FileNotFoundError
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should build a correct dependency list" do
|
229
|
+
@mprod.dependency_list.collect{|x| x.source}.should == ["/src/test.haml", "/src/l1/test.sass", "/src/l1/test5.js", "/src/l1/l2/test.txt", "/src/l1/l2/test2.css", "/src/l1/l2/test6.js", "/src/l1/l2/l3/test2.txt", "/src/l1/test2.js", "/src/l1/l2/test3.coffee", "/src/l1/test.js"]
|
230
|
+
end
|
231
|
+
|
232
|
+
it "should fail if there is a cycle in the dependency graph" do
|
233
|
+
File.open("/src/l1/test5.js", "w+"){|f| f.write("slinky_require('test.js')")}
|
234
|
+
manifest = Slinky::Manifest.new("/src", @config, :devel => false, :build_to => "/build")
|
235
|
+
proc { manifest.dependency_list }.should raise_error Slinky::DependencyError
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should handle depends directives" do
|
239
|
+
File.open("/src/l1/test5.coffee", "w+"){|f| f.write("slinky_depends('test.sass')")}
|
240
|
+
manifest = Slinky::Manifest.new("/src", @config, :devel => true)
|
241
|
+
f = manifest.find_by_path("l1/test5.js").first
|
242
|
+
f.should_not == nil
|
243
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/l1\/test.sass/)
|
244
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/l1\/test5.coffee/)
|
245
|
+
f.process
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should handle depends directives with glob patterns" do
|
249
|
+
File.open("/src/l1/test5.coffee", "w+"){|f| f.write("slinky_depends('*.sass')")}
|
250
|
+
File.open("/src/l1/test2.sass", "w+"){|f| f.write("body\n\tcolor: red")}
|
251
|
+
manifest = Slinky::Manifest.new("/src", @config, :devel => true)
|
252
|
+
f = manifest.find_by_path("l1/test5.js").first
|
253
|
+
f.should_not == nil
|
254
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/l1\/test.sass/)
|
255
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/l1\/test2.sass/)
|
256
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/l1\/test5.coffee/)
|
257
|
+
f.process
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should handle depends directives with infinite loops" do
|
261
|
+
File.open("/src/l1/test5.coffee", "w+"){|f| f.write("slinky_depends('*.sass')")}
|
262
|
+
File.open("/src/l1/test2.sass", "w+"){|f| f.write("/* slinky_depends('*.coffee')")}
|
263
|
+
manifest = Slinky::Manifest.new("/src", @config, :devel => true)
|
264
|
+
f = manifest.find_by_path("l1/test5.js").first
|
265
|
+
f.should_not == nil
|
266
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/l1\/test.sass/)
|
267
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/l1\/test2.sass/)
|
268
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/l1\/test5.coffee/)
|
269
|
+
f.process
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should handle depends directives in config" do
|
273
|
+
cf "/depend/script/vendor/backbone.js"
|
274
|
+
cf "/depend/script/vendor/jquery.js"
|
275
|
+
cf "/depend/script/vendor/underscore.js"
|
276
|
+
|
277
|
+
config = <<eos
|
278
|
+
dependencies:
|
279
|
+
"/script/vendor/backbone.js":
|
280
|
+
- "/script/vendor/jquery.js"
|
281
|
+
- "/script/vendor/underscore.js"
|
282
|
+
eos
|
283
|
+
config = Slinky::ConfigReader.new(config)
|
284
|
+
|
285
|
+
mdevel = Slinky::Manifest.new("/depend", config, :devel => true)
|
286
|
+
|
287
|
+
files = mdevel.files_for_product("/scripts.js").map{|x| x.source}
|
288
|
+
files[2].should == "/depend/script/vendor/backbone.js"
|
289
|
+
end
|
290
|
+
|
291
|
+
it "should cache files" do
|
292
|
+
File.open("/src/l1/cache.coffee", "w+"){|f| f.write("() -> 'hello, world!'\n")}
|
293
|
+
manifest = Slinky::Manifest.new("/src", @config, :devel => true)
|
294
|
+
f = manifest.find_by_path("l1/cache.js").first
|
295
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/l1\/cache.coffee/)
|
296
|
+
f.process
|
297
|
+
f.process
|
298
|
+
File.open("/src/l1/cache.coffee", "a"){|f| f.write("() -> 'goodbye, world!'\n")}
|
299
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/l1\/cache.coffee/)
|
300
|
+
f.process
|
301
|
+
end
|
302
|
+
|
303
|
+
it "should handle new directives" do
|
304
|
+
manifest = Slinky::Manifest.new("/src", @config, :devel => true)
|
305
|
+
f = manifest.find_by_path("l1/test.js").first
|
306
|
+
f.process
|
307
|
+
f.directives.should == {:slinky_require=>["test2.js", "l2/test3.js"]}
|
308
|
+
File.open("/src/l1/test.js", "a"){|f| f.write("slinky_require('test5.js')\n")}
|
309
|
+
f.process
|
310
|
+
f.directives.should == {:slinky_require=>["test2.js", "l2/test3.js", "test5.js"]}
|
311
|
+
end
|
312
|
+
|
313
|
+
it "should detect new files" do
|
314
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/test.haml/)
|
315
|
+
manifest = Slinky::Manifest.new("/src", @config, :devel => true)
|
316
|
+
File.open("/src/l1/cache.coffee", "w+"){|f| f.write("console.log 'hello'")}
|
317
|
+
manifest.add_all_by_path(["/src/l1/cache.coffee"])
|
318
|
+
f = manifest.find_by_path("l1/cache.js").first
|
319
|
+
f.should_not == nil
|
320
|
+
manifest.scripts_string.match("cache.js").should_not == nil
|
321
|
+
FileUtils.mkdir("/src/l1/hello")
|
322
|
+
File.open("/src/l1/hello/asdf.sass", "w+"){|f| f.write("hello")}
|
323
|
+
f = manifest.find_by_path("l1/hello/asdf.sass")
|
324
|
+
f.should_not == nil
|
325
|
+
end
|
326
|
+
|
327
|
+
it "should handle deletion of files" do
|
328
|
+
File.open("/src/l1/cache.coffee", "w+"){|f| f.write("console.log 'hello'")}
|
329
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/test.haml/)
|
330
|
+
manifest = Slinky::Manifest.new("/src", @config, :devel => true)
|
331
|
+
f = manifest.find_by_path("l1/cache.coffee").first
|
332
|
+
f.should_not == nil
|
333
|
+
manifest.scripts_string.match("l1/cache.js").should_not == nil
|
334
|
+
|
335
|
+
FileUtils.rm("/src/l1/cache.coffee")
|
336
|
+
File.exists?("/src/l1/cache.coffee").should == false
|
337
|
+
manifest.remove_all_by_path(["/src/l1/cache.coffee"])
|
338
|
+
f = manifest.find_by_path("l1/cache.coffee").first
|
339
|
+
f.should == nil
|
340
|
+
manifest.scripts_string.match("l1/cache.js").should == nil
|
341
|
+
end
|
342
|
+
|
343
|
+
it "should ignore the build directory" do
|
344
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/.+/).exactly(6).times
|
345
|
+
options = {:src_dir => "/src", :build_dir => "/src/build"}
|
346
|
+
Slinky::Builder.build(options, @config)
|
347
|
+
File.exists?("/src/build/build").should_not == true
|
348
|
+
File.exists?("/src/build/test.html").should == true
|
349
|
+
Slinky::Builder.build(options, @config)
|
350
|
+
File.exists?("/src/build/build").should == false
|
351
|
+
end
|
352
|
+
|
353
|
+
it "should combine and compress javascript" do
|
354
|
+
FileUtils.rm_rf("/build") rescue nil
|
355
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/.+/).exactly(3).times
|
356
|
+
@mprod.build
|
357
|
+
File.exists?("/build/scripts.js").should == true
|
358
|
+
File.size("/build/scripts.js").should > 90
|
359
|
+
File.read("/build/scripts.js").match('"Hello, world"').should_not == nil
|
360
|
+
File.exists?("/build/l1/test.js").should == false
|
361
|
+
end
|
362
|
+
|
363
|
+
it "should combine and compress css" do
|
364
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/.+/).exactly(3).times
|
365
|
+
@mprod.build
|
366
|
+
File.exists?("/build/styles.css").should == true
|
367
|
+
File.size("/build/styles.css").should > 25
|
368
|
+
File.read("/build/styles.css").match(/color:\s*red/).should_not == nil
|
369
|
+
File.exists?("/build/l1/test.css").should == false
|
370
|
+
end
|
371
|
+
|
372
|
+
it "should modify css urls to point to correct paths when compiled" do
|
373
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/.+/).exactly(3).times
|
374
|
+
@mprod.build
|
375
|
+
css = File.read("/build/styles.css")
|
376
|
+
css.include?("url('/l1/asdf.png')").should == true
|
377
|
+
css.include?("url('/l1/bg.png')").should == true
|
378
|
+
css.include?("url('/l1/l2/l3/hello.png')").should == true
|
379
|
+
end
|
380
|
+
|
381
|
+
it "should properly filter out ignores in files list" do
|
382
|
+
config = Slinky::ConfigReader.new("ignore:\n - /l1/test2.js")
|
383
|
+
config.ignore.should == ["/l1/test2.js"]
|
384
|
+
mdevel = Slinky::Manifest.new("/src", config)
|
385
|
+
mfiles = mdevel.files(false).map{|x| x.source}.sort
|
386
|
+
files = (@files - ["l1/test2.js"]).map{|x| "/src/" + x}.sort
|
387
|
+
mfiles.should == files
|
388
|
+
# double check
|
389
|
+
mfiles.include?("/src/l1/test2.js").should == false
|
390
|
+
end
|
391
|
+
|
392
|
+
it "should properly filter out relative ignores in files list" do
|
393
|
+
config = Slinky::ConfigReader.new("ignore:\n - l1/test2.js")
|
394
|
+
config.ignore.should == ["l1/test2.js"]
|
395
|
+
mdevel = Slinky::Manifest.new("/src", config)
|
396
|
+
mfiles = mdevel.files(false).map{|x| x.source}.sort
|
397
|
+
files = (@files - ["l1/test2.js"]).map{|x| "/src/" + x}.sort
|
398
|
+
mfiles.should == files
|
399
|
+
# double check
|
400
|
+
mfiles.include?("/src/l1/test2.js").should == false
|
401
|
+
end
|
402
|
+
|
403
|
+
it "should properly filter out directory ignores in files list" do
|
404
|
+
config = Slinky::ConfigReader.new("ignore:\n - /l1/l2")
|
405
|
+
config.ignore.should == ["/l1/l2"]
|
406
|
+
mdevel = Slinky::Manifest.new("/src", config)
|
407
|
+
mfiles = mdevel.files(false).map{|x| x.source}.sort
|
408
|
+
files = (@files.reject{|x| x.start_with?("l1/l2")}).map{|x| "/src/" + x}.sort
|
409
|
+
mfiles.should == files
|
410
|
+
end
|
411
|
+
|
412
|
+
it "should properly handle ignores for scripts" do
|
413
|
+
File.open("/src/l1/l2/ignore.js", "w+"){|f| f.write("IGNORE!!!")}
|
414
|
+
config = Slinky::ConfigReader.new("ignore:\n - /l1/l2/ignore.js")
|
415
|
+
config.ignore.should == ["/l1/l2/ignore.js"]
|
416
|
+
|
417
|
+
mdevel = Slinky::Manifest.new("/src", config)
|
418
|
+
mdevel.scripts_string.scan(/src=\"(.+?)\"/).flatten.
|
419
|
+
include?("/l1/l2/ignore.js").should == false
|
420
|
+
|
421
|
+
mprod = Slinky::Manifest.new("/src", config, :devel => false,
|
422
|
+
:build_to => "/build")
|
423
|
+
|
424
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/.+/).exactly(3).times
|
425
|
+
mprod.build
|
426
|
+
|
427
|
+
File.read("/build/scripts.js").include?("IGNORE!!!").should == false
|
428
|
+
end
|
429
|
+
|
430
|
+
it "should properly handle ignores for styles" do
|
431
|
+
File.open("/src/l1/l2/ignore.css", "w+"){|f| f.write("IGNORE!!!")}
|
432
|
+
config = Slinky::ConfigReader.new("ignore:\n - /l1/l2/ignore.css")
|
433
|
+
config.ignore.should == ["/l1/l2/ignore.css"]
|
434
|
+
|
435
|
+
mdevel = Slinky::Manifest.new("/src", config)
|
436
|
+
mdevel.styles_string.scan(/href=\"(.+?)\"/).flatten.
|
437
|
+
include?("/l1/l2/ignore.css").should == false
|
438
|
+
|
439
|
+
mprod = Slinky::Manifest.new("/src", config, :devel => false,
|
440
|
+
:build_to => "/build")
|
441
|
+
|
442
|
+
$stdout.should_receive(:puts).with(/Compiled \/src\/.+/).exactly(3).times
|
443
|
+
mprod.build
|
444
|
+
|
445
|
+
File.read("/build/styles.css").include?("IGNORE!!!").should == false
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
context "FindByPattern" do
|
450
|
+
def test(md, pattern, files)
|
451
|
+
md.find_by_pattern(pattern).map{|mf| mf.relative_source_path.to_s}
|
452
|
+
.sort.should == files.sort
|
453
|
+
end
|
454
|
+
|
455
|
+
before :all do
|
456
|
+
FileUtils.mkdir("/find")
|
457
|
+
|
458
|
+
cf("/find/main.js")
|
459
|
+
cf("/find/main/main.js")
|
460
|
+
cf("/find/main/test.js")
|
461
|
+
cf("/find/src/main.coffee")
|
462
|
+
cf("/find/src/main_test.js")
|
463
|
+
cf("/find/src/main/main.js")
|
464
|
+
cf("/find/src/component/main.js")
|
465
|
+
cf("/find/src/component/test.js")
|
466
|
+
cf("/find/src/component/test/test.js")
|
467
|
+
|
468
|
+
@md = Slinky::Manifest.new("/find", @config, :devel => false)
|
469
|
+
end
|
470
|
+
|
471
|
+
it "find_by_pattern should follow rule #1" do
|
472
|
+
test(@md, "/src/", [
|
473
|
+
"src/main.coffee",
|
474
|
+
"src/main_test.js",
|
475
|
+
"src/main/main.js",
|
476
|
+
"src/component/main.js",
|
477
|
+
"src/component/test.js",
|
478
|
+
"src/component/test/test.js"
|
479
|
+
])
|
480
|
+
end
|
481
|
+
|
482
|
+
it "find_by_pattern should follow rule #2" do
|
483
|
+
test(@md, "test.js", ["main/test.js",
|
484
|
+
"src/component/test.js",
|
485
|
+
"src/component/test/test.js"])
|
486
|
+
end
|
487
|
+
|
488
|
+
it "find_by_pattern should follow rule #3" do
|
489
|
+
test(@md, "/main/*.js", [
|
490
|
+
"main/main.js",
|
491
|
+
"main/test.js"
|
492
|
+
])
|
493
|
+
end
|
494
|
+
|
495
|
+
it "find_by_pattern should follow rule #4" do
|
496
|
+
test(@md, "main/", [
|
497
|
+
"main/main.js",
|
498
|
+
"main/test.js",
|
499
|
+
"src/main/main.js"
|
500
|
+
])
|
501
|
+
|
502
|
+
test(@md, "main/main*", [
|
503
|
+
"main/main.js",
|
504
|
+
"src/main/main.js"
|
505
|
+
])
|
506
|
+
end
|
507
|
+
|
508
|
+
it "find_by_pattern should follow rule #5" do
|
509
|
+
test(@md, "/*/*.js", [
|
510
|
+
"main/main.js",
|
511
|
+
"main/test.js",
|
512
|
+
"src/main.coffee",
|
513
|
+
"src/main_test.js"
|
514
|
+
])
|
515
|
+
|
516
|
+
test(@md, "/*/*test.js", [
|
517
|
+
"main/test.js",
|
518
|
+
"src/main_test.js"
|
519
|
+
])
|
520
|
+
end
|
521
|
+
|
522
|
+
it "find_by_pattern should follow rule #6" do
|
523
|
+
test(@md, "/**/*.js", [
|
524
|
+
"main.js",
|
525
|
+
"main/main.js",
|
526
|
+
"main/test.js",
|
527
|
+
"src/main.coffee",
|
528
|
+
"src/main_test.js",
|
529
|
+
"src/main/main.js",
|
530
|
+
"src/component/main.js",
|
531
|
+
"src/component/test.js",
|
532
|
+
"src/component/test/test.js"
|
533
|
+
])
|
534
|
+
|
535
|
+
test(@md, "src/**/*.js", [
|
536
|
+
"src/main.coffee",
|
537
|
+
"src/main_test.js",
|
538
|
+
"src/main/main.js",
|
539
|
+
"src/component/main.js",
|
540
|
+
"src/component/test.js",
|
541
|
+
"src/component/test/test.js"
|
542
|
+
])
|
543
|
+
end
|
544
|
+
end
|
545
|
+
|
546
|
+
context "Products" do
|
547
|
+
it "should fail if non-configured product is requested" do
|
548
|
+
proc { @mdevel.files_for_product("/something.js") }
|
549
|
+
.should raise_error Slinky::NoSuchProductError
|
550
|
+
end
|
551
|
+
|
552
|
+
it "should allow specification of products" do
|
553
|
+
config = <<eos
|
554
|
+
produce:
|
555
|
+
"/special.js":
|
556
|
+
include:
|
557
|
+
- "/l1/*.js"
|
558
|
+
exclude:
|
559
|
+
- "/l1/exclude.js"
|
560
|
+
eos
|
561
|
+
config = Slinky::ConfigReader.new(config)
|
562
|
+
config.produce.should == {"/special.js" => {
|
563
|
+
"include" => ["/l1/*.js"],
|
564
|
+
"exclude" => ["/l1/exclude.js"]
|
565
|
+
}}
|
566
|
+
|
567
|
+
File.open("/src/l1/exclude.js", "w+").close
|
568
|
+
|
569
|
+
mdevel = Slinky::Manifest.new("/src", config, :devel => true)
|
570
|
+
|
571
|
+
mdevel.files_for_product("/special.js")
|
572
|
+
.map{|x| x.source}.sort.should == [
|
573
|
+
"/src/l1/test2.js", "/src/l1/test.js", "/src/l1/test5.js",
|
574
|
+
"/src/l1/l2/test3.coffee", "/src/l1/l2/test6.js"].sort
|
575
|
+
end
|
576
|
+
|
577
|
+
it "should not require an exclude for products" do
|
578
|
+
config = {"produce" => {"/special.js" => {"include" => ["/l1/*.js"]}}}
|
579
|
+
|
580
|
+
config = Slinky::ConfigReader.new(config)
|
581
|
+
|
582
|
+
File.open("/src/l1/exclude.js", "w+").close
|
583
|
+
|
584
|
+
mdevel = Slinky::Manifest.new("/src", config, :devel => true)
|
585
|
+
|
586
|
+
mdevel.files_for_product("/special.js")
|
587
|
+
.map{|x| x.source}.sort.should == ["/src/l1/exclude.js",
|
588
|
+
"/src/l1/l2/test3.coffee",
|
589
|
+
"/src/l1/l2/test6.js",
|
590
|
+
"/src/l1/test.js",
|
591
|
+
"/src/l1/test2.js",
|
592
|
+
"/src/l1/test5.js"].sort
|
593
|
+
end
|
594
|
+
|
595
|
+
it "should support full match syntax for excludes" do
|
596
|
+
config = <<eos
|
597
|
+
produce:
|
598
|
+
"/special.js":
|
599
|
+
include:
|
600
|
+
- "/l1/*.js"
|
601
|
+
exclude:
|
602
|
+
- "exclude.js"
|
603
|
+
eos
|
604
|
+
config = Slinky::ConfigReader.new(config)
|
605
|
+
config.produce.should == {"/special.js" => {
|
606
|
+
"include" => ["/l1/*.js"],
|
607
|
+
"exclude" => ["exclude.js"]
|
608
|
+
}}
|
609
|
+
|
610
|
+
File.open("/src/l1/exclude.js", "w+").close
|
611
|
+
|
612
|
+
mdevel = Slinky::Manifest.new("/src", config, :devel => true)
|
613
|
+
|
614
|
+
mdevel.files_for_product("/special.js")
|
615
|
+
.map{|x| x.source}.sort.should == [
|
616
|
+
"/src/l1/test2.js", "/src/l1/test.js", "/src/l1/test5.js",
|
617
|
+
"/src/l1/l2/test3.coffee", "/src/l1/l2/test6.js"].sort
|
618
|
+
end
|
619
|
+
|
620
|
+
it "should fail if a product rule does not match anything" do
|
621
|
+
config = <<eos
|
622
|
+
produce:
|
623
|
+
"/special.js":
|
624
|
+
include:
|
625
|
+
- "/l1/doesntexist.js"
|
626
|
+
eos
|
627
|
+
config = Slinky::ConfigReader.new(config)
|
628
|
+
|
629
|
+
mdevel = Slinky::Manifest.new("/src", config, :devel => true)
|
630
|
+
|
631
|
+
proc { mdevel.files_for_product("/special.js") }
|
632
|
+
.should raise_error Slinky::FileNotFoundError
|
633
|
+
end
|
634
|
+
|
635
|
+
it "should allow product directives" do
|
636
|
+
config = <<eos
|
637
|
+
produce:
|
638
|
+
"/special.js":
|
639
|
+
include:
|
640
|
+
- "/l1/*.js"
|
641
|
+
eos
|
642
|
+
config = Slinky::ConfigReader.new(config)
|
643
|
+
|
644
|
+
File.open("/src/product.html", "w+"){|f|
|
645
|
+
f.write("<html><head>\nslinky_product('/special.js')\n</head></html")
|
646
|
+
}
|
647
|
+
|
648
|
+
mdevel = Slinky::Manifest.new("/src", config, :devel => true)
|
649
|
+
path = mdevel.find_by_path("/product.html").first.process(nil, true)
|
650
|
+
|
651
|
+
contents = File.read(path)
|
652
|
+
contents.include?("slinky_product").should == false
|
653
|
+
contents.include?('<script type="text/javascript" src="/l1/test.js">').
|
654
|
+
should == true
|
655
|
+
end
|
656
|
+
|
657
|
+
it "should full match syntax" do
|
658
|
+
config = {"produce" => {"/special.js" => {"include" => ["/l1/**/*.js"]}}}
|
659
|
+
|
660
|
+
config = Slinky::ConfigReader.new(config)
|
661
|
+
|
662
|
+
mdevel = Slinky::Manifest.new("/src", config, :devel => true)
|
663
|
+
|
664
|
+
mdevel.files_for_product("/special.js")
|
665
|
+
.map{|x| x.source}.sort.should == ["/src/l1/l2/test3.coffee",
|
666
|
+
"/src/l1/l2/test6.js",
|
667
|
+
"/src/l1/test.js",
|
668
|
+
"/src/l1/test2.js",
|
669
|
+
"/src/l1/test5.js"].sort
|
670
|
+
end
|
671
|
+
|
672
|
+
it "should build products in production mode" do
|
673
|
+
config = <<eos
|
674
|
+
produce:
|
675
|
+
"/special.js":
|
676
|
+
include:
|
677
|
+
- "/l1/*.js"
|
678
|
+
eos
|
679
|
+
config = Slinky::ConfigReader.new(config)
|
680
|
+
|
681
|
+
File.open("/src/product.html", "w+"){|f|
|
682
|
+
f.write("<html><head>\nslinky_product('/special.js')\n</head></html")
|
683
|
+
}
|
684
|
+
|
685
|
+
mprod = Slinky::Manifest.new("/src",
|
686
|
+
config,
|
687
|
+
:devel => false,
|
688
|
+
:build_to => "/build_special")
|
689
|
+
|
690
|
+
$stdout.should_receive(:puts).with(/Compiled/).exactly(2).times
|
691
|
+
path = mprod.find_by_path("/product.html").first.process(nil, true)
|
692
|
+
mprod.build
|
693
|
+
|
694
|
+
File.exists?("/build_special/special.js").should == true
|
695
|
+
File.read("/build_special/special.js").
|
696
|
+
include?('console.log("Hello!");').should == true
|
697
|
+
File.exists?("/build_special/scripts.js").should == false
|
698
|
+
File.exists?("/build_special/styles.css").should == false
|
699
|
+
end
|
700
|
+
|
701
|
+
it "should build products inside directories" do
|
702
|
+
config = <<eos
|
703
|
+
produce:
|
704
|
+
"/d1/d2/d3/special.js":
|
705
|
+
include:
|
706
|
+
- "/l1/*.js"
|
707
|
+
eos
|
708
|
+
config = Slinky::ConfigReader.new(config)
|
709
|
+
|
710
|
+
mprod = Slinky::Manifest.new("/src",
|
711
|
+
config,
|
712
|
+
:devel => false,
|
713
|
+
:build_to => "/build_nested")
|
714
|
+
|
715
|
+
$stdout.should_receive(:puts).with(/Compiled/).exactly(2).times
|
716
|
+
mprod.build
|
717
|
+
|
718
|
+
File.exists?("/build_nested/d1/d2/d3/special.js").should == true
|
719
|
+
end
|
720
|
+
|
721
|
+
it "should not build scripts if they are not included in products" do
|
722
|
+
config = <<eos
|
723
|
+
produce:
|
724
|
+
"/special.js":
|
725
|
+
include:
|
726
|
+
- "/l1/l2/test6.js"
|
727
|
+
eos
|
728
|
+
config = Slinky::ConfigReader.new(config)
|
729
|
+
|
730
|
+
File.open("/src/product.html", "w+"){|f|
|
731
|
+
f.write("<html><head>\nslinky_product('/special.js')\n</head></html")
|
732
|
+
}
|
733
|
+
|
734
|
+
mprod = Slinky::Manifest.new("/src",
|
735
|
+
config,
|
736
|
+
:devel => false,
|
737
|
+
:build_to => "/build_special")
|
738
|
+
|
739
|
+
$stdout.should_receive(:puts).with(/Compiled/).exactly(1).times
|
740
|
+
path = mprod.find_by_path("/product.html").first.process(nil, true)
|
741
|
+
mprod.build
|
742
|
+
|
743
|
+
File.exists?("/build_special/special.js").should == true
|
744
|
+
File.read("/build_special/special.js").
|
745
|
+
include?('console.log("Hello!");').should == false
|
746
|
+
File.exists?("/build_special/scripts.js").should == false
|
747
|
+
File.exists?("/build_special/styles.css").should == false
|
748
|
+
end
|
749
|
+
end
|
750
|
+
end
|