slinky 0.7.3 → 0.8.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.
- 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
|