slinky 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/Gemfile +4 -3
- data/README.md +6 -1
- data/Rakefile +4 -0
- data/VERSION +1 -1
- data/ext/transitive_closure/extconf.rb +4 -0
- data/ext/transitive_closure/transitive_closure.c +40 -0
- data/lib/slinky/builder.rb +1 -0
- data/lib/slinky/compilers/sass-compiler.rb +7 -2
- data/lib/slinky/graph.rb +35 -41
- data/lib/slinky/listener.rb +3 -3
- data/lib/slinky/manifest.rb +40 -12
- data/lib/slinky/proxy_server.rb +26 -16
- data/lib/slinky/pure_transitive_clsoure.rb +14 -0
- data/lib/slinky/runner.rb +13 -14
- data/lib/slinky/templates/error.css +3 -1
- data/lib/slinky/templates/inject.css +3 -1
- data/lib/slinky.rb +17 -17
- data/slinky.gemspec +20 -12
- data/spec/compilers_spec.rb +7 -0
- data/spec/manifest_spec.rb +64 -5
- data/spec/slinky_spec.rb +22 -5
- data/spec/spec_helper.rb +12 -10
- metadata +77 -59
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
YjdjMDMwZGIzZWU4YjE2MmIwOGU0ZTIyMzc2ZDYyZDg2M2I2NWRmMg==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e7454d54e24a3dd4658b574d91b72f23352b481f
|
4
|
+
data.tar.gz: 05f244c1d61cd33874fd3255a7272abed81c8353
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
Nzk1ZjNlMzcxMDVjYjFiNWFhODNhZGUyMzcyYzM1YzBkMjI3MzljNGFhYzEw
|
11
|
-
ODFiNGFjZmM5MDYyNzAyMzc4ZjExNjQ3NDkyOWNmNzAxZTYyYzU=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
YzQ1ZmIzMDY5NjdlYjMyYzg4MzZkMjczMzk5MGRlNjBiZGEyNWM1YmNhMzFj
|
14
|
-
Nzc1ZTQ1Yzc3OTdmZTk2YTc1NmE4ZDI3YjM3YTRkYWE0YzA2MmU1OThiODMy
|
15
|
-
Y2NjZDExZDY1ZGQ0YTg0NDBmMTg0MGFmNTM3ZjMwMzgzN2M5NzI=
|
6
|
+
metadata.gz: 51eb2cc2384abeb57f85948650bbd5f959f4c4fa9cf8af5e91369b6e2b605991b239bee5f2038e2c1996999f0d90000878d328cc1d3188324c7059bd17fa43b7
|
7
|
+
data.tar.gz: f518c418deecba493794d84f9d80ef860b3d8402eb1ff97e9380ea29f8c1d4253fa8ba485f73df1d7f0dbbbd5fab7ee6610e27a57dd2ff4a5f9aee7eabe5d782
|
data/Gemfile
CHANGED
@@ -8,12 +8,12 @@ gem "em-websocket", "~> 0.3"
|
|
8
8
|
gem "em-proxy", "~> 0.1"
|
9
9
|
gem "rainbow", "~> 1.1"
|
10
10
|
gem "mime-types", "~> 1.16"
|
11
|
-
gem "
|
11
|
+
gem "uglifier", "~> 2.5"
|
12
12
|
gem "listen", "~> 2.4"
|
13
13
|
|
14
14
|
# compilation support gems
|
15
15
|
gem "haml", "~> 3.1"
|
16
|
-
gem "sass", "~> 3.
|
16
|
+
gem "sass", "~> 3.3"
|
17
17
|
gem "coffee-script", "~> 2.2"
|
18
18
|
|
19
19
|
group :development do
|
@@ -21,11 +21,12 @@ group :development do
|
|
21
21
|
gem "yard", "~> 0.8"
|
22
22
|
gem "bundler", "~> 1.5"
|
23
23
|
gem "jeweler", "~> 1.8"
|
24
|
-
gem "fakefs", '
|
24
|
+
gem "fakefs", '0.5.3', :require => "fakefs/safe"
|
25
25
|
gem "em-http-request", '~> 1.0'
|
26
26
|
gem 'simplecov'
|
27
27
|
# optional compilation gems
|
28
28
|
gem "less", ">= 2.2.0"
|
29
29
|
gem "therubyracer" # for less
|
30
30
|
gem "react-jsx", '~> 0.8.0'
|
31
|
+
gem "rake-compiler", '~> 0.9.3'
|
31
32
|
end
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@ proxying and automatic browser reloads. And once you're ready to
|
|
8
8
|
deploy, Slinky will compile, concatenate, and minify your sources,
|
9
9
|
leaving you ready to push to production.
|
10
10
|
|
11
|
-
[![Build Status](https://
|
11
|
+
[![Build Status](https://travis-ci.org/mwylde/slinky.svg?branch=master)](https://travis-ci.org/mwylde/slinky)
|
12
12
|
|
13
13
|
#### What can slinky do for you?
|
14
14
|
|
@@ -176,6 +176,11 @@ slinky_depends("scripts/templates/*.mustache")
|
|
176
176
|
%body
|
177
177
|
```
|
178
178
|
|
179
|
+
The paths in `slinky_depends` can be either relative or absolute. If
|
180
|
+
relative, they support simple globbing (as in the example above). If
|
181
|
+
absolute, they support
|
182
|
+
[the full path matching syntax](#path-matching).
|
183
|
+
|
179
184
|
## Configuration
|
180
185
|
|
181
186
|
Slinky can optionally be configured using a yaml file. By default, it
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.1
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
static VALUE all_paths_costs(VALUE module, VALUE rsize, VALUE distArray)
|
4
|
+
{
|
5
|
+
int size = FIX2INT(rsize);
|
6
|
+
int distArrayLen = size*size;
|
7
|
+
|
8
|
+
// Create copy of distArray
|
9
|
+
int cDistArray[distArrayLen];
|
10
|
+
int i, k, j;
|
11
|
+
for (i = 0; i < distArrayLen; i++) {
|
12
|
+
cDistArray[i] = FIX2INT(rb_ary_entry(distArray, i));
|
13
|
+
}
|
14
|
+
|
15
|
+
for (k = 0; k < size; k++) {
|
16
|
+
for (i = 0; i < size; i++) {
|
17
|
+
for (j = 0; j < size; j++) {
|
18
|
+
if (cDistArray[size*i+j] > cDistArray[size*i+k] + cDistArray[size*k+j]) {
|
19
|
+
cDistArray[size*i+j] = cDistArray[size*i+k] + cDistArray[size*k+j];
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
// Copy cDistArray back into distArray
|
26
|
+
for (i = 0; i < distArrayLen; i++) {
|
27
|
+
rb_ary_store(distArray, i, INT2FIX(cDistArray[i]));
|
28
|
+
}
|
29
|
+
|
30
|
+
return distArray;
|
31
|
+
}
|
32
|
+
|
33
|
+
void Init_transitive_closure(void)
|
34
|
+
{
|
35
|
+
VALUE cSlinky;
|
36
|
+
|
37
|
+
cSlinky = rb_define_module("Slinky");
|
38
|
+
|
39
|
+
rb_define_module_function(cSlinky, "all_paths_costs", all_paths_costs, 2);
|
40
|
+
}
|
data/lib/slinky/builder.rb
CHANGED
@@ -8,10 +8,15 @@ module Slinky
|
|
8
8
|
|
9
9
|
def SassCompiler::compile s, file
|
10
10
|
syntax = file.end_with?(".sass") ? :sass : :scss
|
11
|
-
|
11
|
+
if Pathname.new(file).basename.to_s.start_with?("_")
|
12
|
+
# This is a partial, don't render it
|
13
|
+
""
|
14
|
+
else
|
15
|
+
sass_engine = Sass::Engine.new(s,
|
12
16
|
:syntax => syntax,
|
13
17
|
:load_paths => [File.dirname(file)])
|
14
|
-
|
18
|
+
sass_engine.render
|
19
|
+
end
|
15
20
|
end
|
16
21
|
end
|
17
22
|
end
|
data/lib/slinky/graph.rb
CHANGED
@@ -4,6 +4,7 @@ module Slinky
|
|
4
4
|
# graph algorithms.
|
5
5
|
class Graph
|
6
6
|
include Enumerable
|
7
|
+
include TSort
|
7
8
|
|
8
9
|
attr_reader :nodes, :edges
|
9
10
|
|
@@ -32,37 +33,32 @@ module Slinky
|
|
32
33
|
return @transitive_closure if @transitive_closure
|
33
34
|
|
34
35
|
g = adjacency_matrix
|
35
|
-
|
36
|
+
|
36
37
|
index_map = {}
|
37
38
|
nodes.each_with_index{|f, i| index_map[f] = i}
|
38
39
|
|
39
40
|
size = nodes.size
|
40
41
|
|
42
|
+
# The max int supported by the transitive closure C extension (2^30 - 1)
|
43
|
+
maxint = 1073741823
|
44
|
+
|
41
45
|
# Set up the distance matrix
|
42
|
-
dist = Array.new(size
|
46
|
+
dist = Array.new(size * size, maxint)
|
43
47
|
nodes.each_with_index{|fi, i|
|
44
|
-
dist[i
|
48
|
+
dist[size * i + i] = 0
|
45
49
|
g[fi].each{|fj|
|
46
|
-
dist[i
|
50
|
+
dist[size * i + index_map[fj]] = 1
|
47
51
|
}
|
48
52
|
}
|
49
53
|
|
50
54
|
# Compute the all-paths costs
|
51
|
-
size
|
52
|
-
size.times{|i|
|
53
|
-
size.times{|j|
|
54
|
-
if dist[i][j] > dist[i][k] + dist[k][j]
|
55
|
-
dist[i][j] = dist[i][k] + dist[k][j]
|
56
|
-
end
|
57
|
-
}
|
58
|
-
}
|
59
|
-
}
|
55
|
+
Slinky::all_paths_costs(size, dist)
|
60
56
|
|
61
57
|
# Compute the transitive closure in map form
|
62
58
|
@transitive_closure = Hash.new{|h,k| h[k] = []}
|
63
59
|
size.times{|i|
|
64
60
|
size.times{|j|
|
65
|
-
if dist[i
|
61
|
+
if dist[size * i + j] < maxint
|
66
62
|
@transitive_closure[nodes[i]] << nodes[j]
|
67
63
|
end
|
68
64
|
}
|
@@ -71,43 +67,41 @@ module Slinky
|
|
71
67
|
@transitive_closure
|
72
68
|
end
|
73
69
|
|
74
|
-
#
|
75
|
-
|
76
|
-
|
77
|
-
|
70
|
+
# Methods needed for TSort mixin
|
71
|
+
def tsort_each_node &block
|
72
|
+
nodes.each(&block)
|
73
|
+
end
|
74
|
+
|
75
|
+
def tsort_each_child node, &block
|
76
|
+
adjacency_matrix.fetch(node, []).each(&block)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Uses the tsort library to build a list of files in topological
|
80
|
+
# order, so that when required in this order all dependencies are
|
81
|
+
# met.
|
78
82
|
def dependency_list
|
79
83
|
return @dependency_list if @dependency_list
|
80
84
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
next unless e
|
92
|
-
graph.delete e
|
93
|
-
s << m unless graph.any?{|e| e[1] == m}
|
94
|
-
}
|
95
|
-
end
|
96
|
-
if graph != []
|
97
|
-
problems = graph.collect{|e| e.collect{|x| x.source}.join(" -> ")}
|
98
|
-
raise DependencyError.new("Dependencies #{problems.join(", ")} could not be satisfied")
|
99
|
-
end
|
100
|
-
@dependency_list = l
|
85
|
+
results = []
|
86
|
+
each_strongly_connected_component{|component|
|
87
|
+
if component.size == 1
|
88
|
+
results << component.first
|
89
|
+
else
|
90
|
+
cycle = component.map{|x| x.source}.join(" -> ")
|
91
|
+
raise DependencyError.new("Dependencies #{cycle} could not be satisfied")
|
92
|
+
end
|
93
|
+
}
|
94
|
+
@dependency_list = results
|
101
95
|
end
|
102
96
|
|
103
|
-
def each &block
|
97
|
+
def each &block
|
104
98
|
edges.each do |e|
|
105
99
|
if block_given?
|
106
100
|
block.call e
|
107
|
-
else
|
101
|
+
else
|
108
102
|
yield e
|
109
103
|
end
|
110
|
-
end
|
104
|
+
end
|
111
105
|
end
|
112
106
|
end
|
113
107
|
end
|
data/lib/slinky/listener.rb
CHANGED
@@ -23,12 +23,12 @@ module Slinky
|
|
23
23
|
if mf
|
24
24
|
mf.output_path
|
25
25
|
else
|
26
|
-
|
26
|
+
nil
|
27
27
|
end
|
28
|
-
}
|
28
|
+
}.compact
|
29
29
|
|
30
30
|
# only reload if something's actually changed
|
31
|
-
if manifest_md5 != @manifest.md5
|
31
|
+
if manifest_md5 != @manifest.md5 && files.size > 0
|
32
32
|
manifest_md5 = @manifest.md5
|
33
33
|
@livereload.reload_browser(files)
|
34
34
|
end
|
data/lib/slinky/manifest.rb
CHANGED
@@ -8,11 +8,13 @@ module Slinky
|
|
8
8
|
# extensions of non-compiled files that can contain build directives
|
9
9
|
DIRECTIVE_FILES = %w{js css html}
|
10
10
|
DEPENDS_DIRECTIVE = /^[^\n\w]*(slinky_depends)\((".*"|'.+'|)\)[^\n\w]*$/
|
11
|
+
EXTERNAL_DEPENDS_DIRECTIVE = /^[^\n\w]*(slinky_depends_external)\((".*"|'.+'|)\)[^\n\w]*$/
|
11
12
|
REQUIRE_DIRECTIVE = /^[^\n\w]*(slinky_require)\((".*"|'.+'|)\)[^\n\w]*$/
|
12
13
|
SCRIPTS_DIRECTIVE = /^[^\n\w]*(slinky_scripts)[^\n\w]*$/
|
13
14
|
STYLES_DIRECTIVE = /^[^\n\w]*(slinky_styles)[^\n\w]*$/
|
14
15
|
PRODUCT_DIRECTIVE = /^[^\n\w]*(slinky_product)\((".*"|'.+'|)\)[^\n\w]*$/
|
15
16
|
BUILD_DIRECTIVES = Regexp.union(DEPENDS_DIRECTIVE,
|
17
|
+
EXTERNAL_DEPENDS_DIRECTIVE,
|
16
18
|
REQUIRE_DIRECTIVE,
|
17
19
|
SCRIPTS_DIRECTIVE,
|
18
20
|
STYLES_DIRECTIVE,
|
@@ -213,7 +215,7 @@ module Slinky
|
|
213
215
|
FileUtils.mkdir_p("#{@build_to}/#{Pathname.new(product).dirname}")
|
214
216
|
File.open("#{@build_to}/#{product}", "w+"){|f|
|
215
217
|
unless @no_minify
|
216
|
-
f.write(compressor
|
218
|
+
f.write(compressor[s])
|
217
219
|
else
|
218
220
|
f.write(s)
|
219
221
|
end
|
@@ -308,9 +310,12 @@ module Slinky
|
|
308
310
|
def compressor_for_product product
|
309
311
|
case type_for_product(product)
|
310
312
|
when ".js"
|
311
|
-
|
313
|
+
# Use UglifyJS
|
314
|
+
lambda{|s| Uglifier.compile(s.force_encoding("UTF-8"),
|
315
|
+
mangle: false, output: {ascii_only: false})}
|
312
316
|
when ".css"
|
313
|
-
|
317
|
+
# Use SASS's compressed output
|
318
|
+
lambda{|s| Sass::Engine.new(s, :syntax => :scss, :style => :compressed).render}
|
314
319
|
end
|
315
320
|
end
|
316
321
|
|
@@ -356,9 +361,11 @@ module Slinky
|
|
356
361
|
}
|
357
362
|
invalidate_cache
|
358
363
|
files.each{|f|
|
359
|
-
if f.directives.include?(:slinky_scripts) ||
|
364
|
+
if f.directives.include?(:slinky_scripts) ||
|
365
|
+
f.directives.include?(:slinky_styles) ||
|
366
|
+
f.directives.include?(:slinky_product)
|
360
367
|
f.invalidate
|
361
|
-
f.
|
368
|
+
f.find_directives
|
362
369
|
end
|
363
370
|
}
|
364
371
|
end
|
@@ -492,7 +499,7 @@ module Slinky
|
|
492
499
|
|
493
500
|
def initialize source, build_path, manifest, parent = nil, options = {:devel => false}
|
494
501
|
@parent = parent
|
495
|
-
@source = source
|
502
|
+
@source = Pathname.new(source).cleanpath.to_s
|
496
503
|
@last_built = Time.at(0)
|
497
504
|
|
498
505
|
@cfile = Compilers.cfile_for_file(@source)
|
@@ -636,6 +643,7 @@ module Slinky
|
|
636
643
|
if path && @directives.size > 0
|
637
644
|
out = File.read(path)
|
638
645
|
out.gsub!(DEPENDS_DIRECTIVE, "")
|
646
|
+
out.gsub!(EXTERNAL_DEPENDS_DIRECTIVE, "")
|
639
647
|
out.gsub!(REQUIRE_DIRECTIVE, "")
|
640
648
|
out.gsub!(SCRIPTS_DIRECTIVE){ @manifest.scripts_string }
|
641
649
|
out.gsub!(STYLES_DIRECTIVE){ @manifest.styles_string }
|
@@ -673,6 +681,20 @@ module Slinky
|
|
673
681
|
Digest::MD5.hexdigest(File.read(@source)) rescue nil
|
674
682
|
end
|
675
683
|
|
684
|
+
# The list of paths to files external to the manifest that this file
|
685
|
+
# depends on
|
686
|
+
def external_dependencies
|
687
|
+
(@directives[:slinky_depends_external] || []).map{|ed|
|
688
|
+
Dir.glob(File.join(@manifest.dir, ed))
|
689
|
+
}.flatten
|
690
|
+
end
|
691
|
+
|
692
|
+
def external_dependencies_updated?
|
693
|
+
return false if external_dependencies.empty?
|
694
|
+
|
695
|
+
external_dependencies.map{|x| File.mtime(x)}.max > (@updated || Time.at(0))
|
696
|
+
end
|
697
|
+
|
676
698
|
# Gets manifest file ready for serving or building by handling the
|
677
699
|
# directives and compiling the file if neccesary.
|
678
700
|
# @param String path to which the file should be compiled
|
@@ -688,22 +710,28 @@ module Slinky
|
|
688
710
|
|
689
711
|
SlinkyError.batch_errors do
|
690
712
|
depends = @directives[:slinky_depends].map{|f|
|
691
|
-
|
692
|
-
|
713
|
+
ps = if f.start_with?("/")
|
714
|
+
@manifest.find_by_pattern(f)
|
715
|
+
else
|
716
|
+
parent.find_by_path(f, true)
|
717
|
+
end
|
718
|
+
unless ps.size > 0
|
693
719
|
SlinkyError.raise DependencyError,
|
694
|
-
"File #{f}
|
720
|
+
"File #{f} depended on by #{@source} not found"
|
695
721
|
end
|
696
|
-
|
722
|
+
ps
|
697
723
|
}.flatten.compact if @directives[:slinky_depends]
|
698
724
|
depends ||= []
|
699
725
|
@processing = true
|
700
|
-
# process each file on which we're dependent, watching out for
|
726
|
+
# process each file on which we're dependent, watching out for
|
701
727
|
# infinite loops
|
702
728
|
depends.each{|f| f.process }
|
703
729
|
@processing = false
|
704
730
|
|
705
731
|
# get hash of source file
|
706
|
-
if @last_path && hash == @last_md5 &&
|
732
|
+
if @last_path && hash == @last_md5 &&
|
733
|
+
depends.all?{|f| f.updated < start_time} &&
|
734
|
+
!external_dependencies_updated?
|
707
735
|
@last_path
|
708
736
|
else
|
709
737
|
@last_md5 = hash
|
data/lib/slinky/proxy_server.rb
CHANGED
@@ -23,7 +23,14 @@ module Slinky
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.rewrite_path path, proxy
|
26
|
-
|
26
|
+
if proxy[0] == "/"
|
27
|
+
# If we're proxying everything, we just want to pass the path
|
28
|
+
# through unmodified. Otherwise we end up stripping the
|
29
|
+
# initial slash, which is the wrong behavior.
|
30
|
+
path
|
31
|
+
else
|
32
|
+
path.gsub(/^#{proxy[0]}/, "")
|
33
|
+
end
|
27
34
|
end
|
28
35
|
|
29
36
|
def self.replace_path http, old_path, new_path, addition
|
@@ -44,25 +51,28 @@ module Slinky
|
|
44
51
|
proxy = nil
|
45
52
|
start_time = nil
|
46
53
|
conn.server :slinky, :host => "127.0.0.1", :port => slinky_port
|
47
|
-
|
54
|
+
server = nil
|
55
|
+
|
48
56
|
conn.on_data do |data|
|
49
57
|
begin
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
58
|
+
matches = data.match(ProxyServer::HTTP_MATCHER)
|
59
|
+
if matches
|
60
|
+
path = matches[2]
|
61
|
+
proxy = ProxyServer.find_matcher(proxies, path)
|
62
|
+
start_time = Time.now
|
63
|
+
server = if proxy
|
64
|
+
new_path = ProxyServer.rewrite_path path, proxy
|
65
|
+
data = ProxyServer.replace_path(data, path, new_path, proxy[1].path)
|
66
|
+
new_host = proxy[1].select(:host, :port).join(":")
|
67
|
+
data = ProxyServer.replace_host(data, new_host)
|
68
|
+
conn.server [proxy[1].host, proxy[1].port],
|
69
|
+
:host => proxy[1].host, :port => proxy[1].port
|
70
|
+
[proxy[1].host, proxy[1].port]
|
71
|
+
else :slinky
|
72
|
+
end
|
73
|
+
end
|
63
74
|
[data, [server]]
|
64
75
|
rescue
|
65
|
-
$stderr.puts "Got error: #{$!}".foreground(:red)
|
66
76
|
conn.send_data "HTTP/1.1 500 Ooops...something went wrong\r\n"
|
67
77
|
end
|
68
78
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Slinky
|
2
|
+
# Pure ruby implementation of all paths cost for a graph
|
3
|
+
def self.all_paths_costs size, dist
|
4
|
+
size.times{|k|
|
5
|
+
size.times{|i|
|
6
|
+
size.times{|j|
|
7
|
+
if dist[size * i + j] > dist[size * i + k] + dist[size * k + j]
|
8
|
+
dist[size * i + j] = dist[size * i + k] + dist[size * k + j]
|
9
|
+
end
|
10
|
+
}
|
11
|
+
}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
data/lib/slinky/runner.rb
CHANGED
@@ -1,16 +1,24 @@
|
|
1
1
|
module Slinky
|
2
2
|
class Runner
|
3
3
|
COMMANDS = %w{start build}
|
4
|
-
|
4
|
+
|
5
|
+
def version
|
6
|
+
root = File.expand_path(File.dirname(__FILE__))
|
7
|
+
File.open("#{root}/../../VERSION"){|f|
|
8
|
+
f.read.strip
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
5
12
|
def initialize argv
|
6
13
|
# While slinky largely works in Ruby 1.8, the tests don't run
|
7
14
|
# properly and using 1.9 is highly recommended.
|
8
15
|
if RUBY_VERSION.start_with?("1.8")
|
9
16
|
$stderr.puts(("Slinky is unsupported on Ruby 1.8." + \
|
10
17
|
" Using 1.9 is highly recommended.").foreground(:red))
|
11
|
-
|
12
18
|
end
|
13
|
-
|
19
|
+
|
20
|
+
puts "slinky #{version}"
|
21
|
+
|
14
22
|
@argv = argv
|
15
23
|
@options = {}
|
16
24
|
|
@@ -30,26 +38,17 @@ module Slinky
|
|
30
38
|
$stderr.puts(e.message.foreground(:red))
|
31
39
|
exit(1)
|
32
40
|
end
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
def version
|
37
|
-
root = File.expand_path(File.dirname(__FILE__))
|
38
|
-
File.open("#{root}/../../VERSION"){|f|
|
39
|
-
puts "slinky #{f.read.strip}"
|
40
|
-
}
|
41
|
-
exit
|
42
41
|
end
|
43
42
|
|
44
43
|
def parser
|
45
44
|
@parser ||= OptionParser.new do |opts|
|
46
45
|
opts.banner = "Usage: slinky [options] #{COMMANDS.join('|')}"
|
47
|
-
opts.on("-v", "--version", "Outputs current version number and exits"){
|
46
|
+
opts.on("-v", "--version", "Outputs current version number and exits"){ exit }
|
48
47
|
opts.on("-o DIR", "--build-dir DIR", "Directory to which the site will be built.", "Use in conjunction with the 'build' command."){|dir| @options[:build_dir] = File.expand_path(dir)}
|
49
48
|
opts.on("-p PORT", "--port PORT", "Port to run on (default: #{@options[:port]})"){|p| @options[:port] = p.to_i}
|
50
49
|
opts.on("-s DIR", "--src-dir DIR", "Directory containing project source"){|p| @options[:src_dir] = p}
|
51
50
|
opts.on("-n", "--no-proxy", "Don't set up proxy server"){ @options[:no_proxy] = true }
|
52
|
-
opts.on("-r", "--no-livereload", "Don't start a livereload server"){ @options[:no_livereload] = true }
|
51
|
+
opts.on("-r", "--no-livereload", "Don't start a livereload server"){ @options[:no_livereload] = true }
|
53
52
|
opts.on("-c FILE", "--config FILE", "Path to configuration file"){|f| @options[:config] = f}
|
54
53
|
opts.on("-m", "--dont-minify", "Don't minify js/css"){ @options[:no_minify] = true }
|
55
54
|
end
|
@@ -13,7 +13,8 @@
|
|
13
13
|
font-size: 1.5em;
|
14
14
|
line-height: 1.5em;
|
15
15
|
color: whitesmoke;
|
16
|
-
text-shadow: -1px -1px rgba(0, 0, 0, 0.2)
|
16
|
+
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
|
17
|
+
z-index: 100000;
|
17
18
|
}
|
18
19
|
|
19
20
|
#slinky-error .slinky-body {
|
@@ -25,6 +26,7 @@
|
|
25
26
|
color: black;
|
26
27
|
background-color: whitesmoke;
|
27
28
|
border-bottom: 1px solid #aaa;
|
29
|
+
z-index: 100000;
|
28
30
|
}
|
29
31
|
|
30
32
|
#slinky-error .slinky-body li {
|
@@ -11,7 +11,8 @@ body:before {
|
|
11
11
|
font-size: 2.5em;
|
12
12
|
line-height: 2.5em;
|
13
13
|
color: whitesmoke;
|
14
|
-
text-shadow: -1px -1px rgba(0, 0, 0, 0.2)
|
14
|
+
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
|
15
|
+
z-index: 100000;
|
15
16
|
}
|
16
17
|
|
17
18
|
body:after {
|
@@ -24,4 +25,5 @@ body:after {
|
|
24
25
|
color: black;
|
25
26
|
background-color: whitesmoke;
|
26
27
|
border-bottom: 1px solid #aaa;
|
28
|
+
z-index: 100000;
|
27
29
|
}
|
data/lib/slinky.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
|
-
require 'uri'
|
2
|
-
require 'yaml'
|
3
|
-
require 'eventmachine'
|
4
1
|
require 'em-proxy'
|
5
2
|
require 'em-websocket'
|
3
|
+
require 'eventmachine'
|
6
4
|
require 'evma_httpserver'
|
7
|
-
require 'uri'
|
8
|
-
require 'tempfile'
|
9
|
-
require 'rainbow'
|
10
|
-
require 'optparse'
|
11
|
-
require 'mime/types'
|
12
|
-
require 'yui/compressor'
|
13
5
|
require 'listen'
|
6
|
+
require 'mime/types'
|
14
7
|
require 'multi_json'
|
8
|
+
require 'optparse'
|
9
|
+
require 'rainbow'
|
10
|
+
require 'tempfile'
|
11
|
+
require 'tsort'
|
12
|
+
require 'uglifier'
|
13
|
+
require 'uri'
|
14
|
+
require 'uri'
|
15
|
+
require 'yaml'
|
15
16
|
|
16
17
|
require "slinky/em-popen3"
|
17
18
|
require "slinky/errors"
|
@@ -27,6 +28,13 @@ require "slinky/builder"
|
|
27
28
|
require "slinky/listener"
|
28
29
|
require "slinky/live_reload"
|
29
30
|
|
31
|
+
begin
|
32
|
+
require "transitive_closure"
|
33
|
+
rescue LoadError
|
34
|
+
puts "Using pure Ruby implementation of Slinky::all_paths_costs"
|
35
|
+
require 'slinky/pure_transitive_closure'
|
36
|
+
end
|
37
|
+
|
30
38
|
# load compilers
|
31
39
|
root = File.expand_path(File.dirname(__FILE__))
|
32
40
|
Dir.glob("#{root}/slinky/compilers/*.rb").each{|compiler|
|
@@ -38,11 +46,3 @@ Dir.glob("#{root}/slinky/compilers/*.rb").each{|compiler|
|
|
38
46
|
puts "Failed to load #{compiler}: syntax error"
|
39
47
|
end
|
40
48
|
}
|
41
|
-
|
42
|
-
# Without this monkeypatch data uris in CSS cause compression to fail
|
43
|
-
class YUI::Compressor
|
44
|
-
def command
|
45
|
-
@command.insert 1, "-Xss8m"
|
46
|
-
@command.map { |word| Shellwords.escape(word) }.join(" ")
|
47
|
-
end
|
48
|
-
end
|