slinky 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +4 -0
- data/Gemfile +8 -7
- data/README.md +36 -4
- data/Rakefile +4 -4
- data/VERSION +1 -1
- data/lib/slinky.rb +2 -0
- data/lib/slinky/builder.rb +5 -1
- data/lib/slinky/compiled_file.rb +5 -5
- data/lib/slinky/listener.rb +35 -0
- data/lib/slinky/manifest.rb +197 -49
- data/lib/slinky/proxy_server.rb +0 -1
- data/lib/slinky/runner.rb +7 -1
- data/lib/slinky/server.rb +15 -5
- data/slinky.gemspec +38 -37
- data/spec/slinky_spec.rb +128 -27
- data/spec/spec_helper.rb +16 -1
- metadata +64 -53
data/.travis.yml
ADDED
data/Gemfile
CHANGED
@@ -2,21 +2,22 @@ source "http://rubygems.org"
|
|
2
2
|
|
3
3
|
gem "eventmachine", ">= 0.12.0"
|
4
4
|
gem "eventmachine_httpserver", ">= 0.2.0"
|
5
|
-
gem "em-proxy", ">= 0.1.
|
6
|
-
gem "rainbow", ">= 1.1.
|
5
|
+
gem "em-proxy", ">= 0.1.6"
|
6
|
+
gem "rainbow", ">= 1.1.3"
|
7
7
|
gem "haml", ">= 3.0.0"
|
8
8
|
gem "sass", ">= 3.1.1"
|
9
9
|
gem "coffee-script", ">= 2.2.0"
|
10
10
|
gem "mime-types", ">= 1.16"
|
11
11
|
gem "yui-compressor", ">= 0.9.6"
|
12
|
+
gem "listen", ">= 0.4.5"
|
12
13
|
|
13
14
|
group :development do
|
14
|
-
gem "rspec", "~> 2.
|
15
|
+
gem "rspec", "~> 2.10.0"
|
15
16
|
gem "yard", "~> 0.6.0"
|
16
|
-
gem "bundler", "~> 1.
|
17
|
-
gem "jeweler", "~> 1.
|
17
|
+
gem "bundler", "~> 1.1.0"
|
18
|
+
gem "jeweler", "~> 1.8.0"
|
18
19
|
gem 'cover_me', '>= 1.0.0.rc6'
|
19
|
-
gem "fakefs"
|
20
|
-
gem "em-http-request"
|
20
|
+
gem "fakefs", '~> 0.4.0'
|
21
|
+
gem "em-http-request", '~> 1.0.0'
|
21
22
|
# gem "em-synchrony", ">= 0"
|
22
23
|
end
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#Slinky
|
1
|
+
#Slinky
|
2
2
|
|
3
3
|
Slinky helps you write rich web applications using compiled web
|
4
4
|
languages like SASS, HAML and CoffeeScript. The slinky server
|
@@ -11,6 +11,8 @@ Once you're ready for production the slinky builder will compile all of
|
|
11
11
|
your sources and concatenate and minify your javascript and css,
|
12
12
|
leaving you a directory that's ready to be pushed to your servers.
|
13
13
|
|
14
|
+
[](http://travis-ci.org/mwylde/slinky)
|
15
|
+
|
14
16
|
## Quickstart
|
15
17
|
|
16
18
|
```
|
@@ -82,7 +84,37 @@ a
|
|
82
84
|
color: red
|
83
85
|
```
|
84
86
|
|
85
|
-
###
|
87
|
+
### Specifing dependencies
|
88
|
+
|
89
|
+
As HAML and SASS scripts can include external content as part of their
|
90
|
+
build process, it may be that you would like to specify that files are
|
91
|
+
to be recompiled whenever other files change. For example, you may use
|
92
|
+
mustache templates defined each in their own file, but have set up
|
93
|
+
your HAML file to include them all into the HTML. Thus when one of the
|
94
|
+
mustache files changes, you would like the HAML file to be recompiled
|
95
|
+
so that the templates can be updated also.
|
96
|
+
|
97
|
+
These relationships are specified as "dependencies," and like requirements
|
98
|
+
they are incdicated through a special `slinky_depends("file")` directive in
|
99
|
+
your source files. For our template example, the index.haml files might look
|
100
|
+
like this:
|
101
|
+
|
102
|
+
```haml
|
103
|
+
slinky_depends("scripts/templates/*.mustache")
|
104
|
+
!!!5
|
105
|
+
|
106
|
+
%html
|
107
|
+
%head
|
108
|
+
%title My App
|
109
|
+
slinky_styles
|
110
|
+
slinky_scripts
|
111
|
+
- Dir.glob("./scripts/templates/*.mustache") do |f|
|
112
|
+
- name = File.basename(f).split(".")[0..-2].join(".")
|
113
|
+
%script{:id => name, :type => "text/x-handlebars-template"}= File.read(f)
|
114
|
+
%body
|
115
|
+
```
|
116
|
+
|
117
|
+
## Configuration
|
86
118
|
|
87
119
|
Slinky can optionally be configured using a yaml file. By default, it
|
88
120
|
looks for a file called `slinky.yaml` in the source directory, but you
|
@@ -90,7 +122,7 @@ can also supply a file name on the command line using `-c`.
|
|
90
122
|
|
91
123
|
There are currently two directives supported:
|
92
124
|
|
93
|
-
|
125
|
+
### Proxies
|
94
126
|
|
95
127
|
Slinky has a built-in proxy server which lets you test ajax requests
|
96
128
|
with your actual backend servers. To set it up, your slinky.yaml file
|
@@ -128,7 +160,7 @@ an AJAX request is outstanding. However, when run locally the request
|
|
128
160
|
returns so quickly that you can't even see the loading indicator. By
|
129
161
|
adding in a lag this problem is remedied.
|
130
162
|
|
131
|
-
|
163
|
+
### Ignores
|
132
164
|
|
133
165
|
By default slinky will include every javascript and css file it finds
|
134
166
|
into the combined scripts.js and styles.css files. However, it may be
|
data/Rakefile
CHANGED
@@ -13,12 +13,12 @@ require 'jeweler'
|
|
13
13
|
Jeweler::Tasks.new do |gem|
|
14
14
|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
15
|
gem.name = "slinky"
|
16
|
-
gem.homepage = "http://github.com/
|
16
|
+
gem.homepage = "http://mwylde.github.com/slinky/"
|
17
17
|
gem.license = "MIT"
|
18
18
|
gem.summary = %Q{Static file server for javascript apps}
|
19
|
-
gem.description = %Q{A static file server for rich
|
20
|
-
gem.email = "
|
21
|
-
gem.authors = ["
|
19
|
+
gem.description = %Q{A static file server for rich web apps that automatically compiles SASS, HAML, CoffeeScript and more}
|
20
|
+
gem.email = "micah@micahw.com"
|
21
|
+
gem.authors = ["Micah Wylde"]
|
22
22
|
end
|
23
23
|
Jeweler::RubygemsDotOrgTasks.new
|
24
24
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/lib/slinky.rb
CHANGED
@@ -10,6 +10,7 @@ require 'rainbow'
|
|
10
10
|
require 'optparse'
|
11
11
|
require 'mime/types'
|
12
12
|
require 'yui/compressor'
|
13
|
+
require 'listen'
|
13
14
|
|
14
15
|
require "#{ROOT}/slinky/em-popen3"
|
15
16
|
require "#{ROOT}/slinky/compilers"
|
@@ -20,6 +21,7 @@ require "#{ROOT}/slinky/proxy_server"
|
|
20
21
|
require "#{ROOT}/slinky/server"
|
21
22
|
require "#{ROOT}/slinky/runner"
|
22
23
|
require "#{ROOT}/slinky/builder"
|
24
|
+
require "#{ROOT}/slinky/listener"
|
23
25
|
|
24
26
|
# load compilers
|
25
27
|
Dir.glob("#{ROOT}/slinky/compilers/*.rb").each{|compiler|
|
data/lib/slinky/builder.rb
CHANGED
@@ -2,7 +2,11 @@ module Slinky
|
|
2
2
|
class Builder
|
3
3
|
def self.build dir, build_dir, config
|
4
4
|
manifest = Manifest.new(dir, config, :build_to => build_dir, :devel => false)
|
5
|
-
|
5
|
+
begin
|
6
|
+
manifest.build
|
7
|
+
rescue BuildFailedError
|
8
|
+
$stderr.puts "Build failed"
|
9
|
+
end
|
6
10
|
end
|
7
11
|
end
|
8
12
|
end
|
data/lib/slinky/compiled_file.rb
CHANGED
@@ -80,11 +80,11 @@ module Slinky
|
|
80
80
|
# Calls the supplied callback with the path of the compiled file,
|
81
81
|
# compiling the source file first if necessary.
|
82
82
|
def file &cb
|
83
|
-
if needs_update?
|
84
|
-
|
85
|
-
else
|
86
|
-
|
87
|
-
end
|
83
|
+
#if needs_update?
|
84
|
+
compile &cb
|
85
|
+
#else
|
86
|
+
# cb.call @output_path, nil, nil, nil
|
87
|
+
#end
|
88
88
|
end
|
89
89
|
|
90
90
|
# Returns whether the source file has changed since it was last
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Thread.abort_on_exception = true
|
2
|
+
|
3
|
+
module Slinky
|
4
|
+
class Listener
|
5
|
+
def initialize manifest
|
6
|
+
@manifest = manifest
|
7
|
+
end
|
8
|
+
|
9
|
+
def run
|
10
|
+
|
11
|
+
listener = Listen.to(@manifest.dir)
|
12
|
+
listener.change do |mod, add, rem|
|
13
|
+
handle_mod(mod) if mod.size > 0
|
14
|
+
handle_add(add) if add.size > 0
|
15
|
+
handle_rem(rem) if rem.size > 0
|
16
|
+
end
|
17
|
+
listener.start(false)
|
18
|
+
end
|
19
|
+
|
20
|
+
def handle_mod files
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle_add files
|
24
|
+
EM.next_tick {
|
25
|
+
@manifest.add_all_by_path files
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def handle_rem files
|
30
|
+
EM.next_tick {
|
31
|
+
@manifest.remove_all_by_path files
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/slinky/manifest.rb
CHANGED
@@ -1,13 +1,18 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require 'pathname'
|
3
|
+
require 'digest/md5'
|
3
4
|
|
4
5
|
module Slinky
|
5
6
|
# extensions of files that can contain build directives
|
6
7
|
DIRECTIVE_FILES = %w{js css html haml sass scss coffee}
|
8
|
+
DEPENDS_DIRECTIVE = /^[^\n\w]*(slinky_depends)\((".*"|'.+'|)\)[^\n\w]*$/
|
7
9
|
REQUIRE_DIRECTIVE = /^[^\n\w]*(slinky_require)\((".*"|'.+'|)\)[^\n\w]*$/
|
8
10
|
SCRIPTS_DIRECTIVE = /^[^\n\w]*(slinky_scripts)[^\n\w]*$/
|
9
11
|
STYLES_DIRECTIVE = /^[^\n\w]*(slinky_styles)[^\n\w]*$/
|
10
|
-
BUILD_DIRECTIVES = Regexp.union(
|
12
|
+
BUILD_DIRECTIVES = Regexp.union(DEPENDS_DIRECTIVE,
|
13
|
+
REQUIRE_DIRECTIVE,
|
14
|
+
SCRIPTS_DIRECTIVE,
|
15
|
+
STYLES_DIRECTIVE)
|
11
16
|
CSS_URL_MATCHER = /url\(['"]?([^'"\/][^\s)]+\.[a-z]+)(\?\d+)?['"]?\)/
|
12
17
|
|
13
18
|
# Raised when a compilation fails for any reason
|
@@ -46,7 +51,23 @@ module Slinky
|
|
46
51
|
else
|
47
52
|
@files.reject{|f| @config.ignores.any?{|p| f.in_tree? p}}
|
48
53
|
end
|
49
|
-
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Adds a file to the manifest, updating the dependency graph
|
57
|
+
def add_all_by_path paths
|
58
|
+
manifest_update paths do |path|
|
59
|
+
md = find_by_path(File.dirname(path)).first
|
60
|
+
mf = md.add_file(File.basename(path))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Removes a file from the manifest
|
65
|
+
def remove_all_by_path paths
|
66
|
+
manifest_update paths do |path|
|
67
|
+
mf = find_by_path(path).first()
|
68
|
+
mf.parent.remove_file(mf)
|
69
|
+
end
|
70
|
+
end
|
50
71
|
|
51
72
|
# Finds the file at the given path in the manifest if one exists,
|
52
73
|
# otherwise nil.
|
@@ -54,8 +75,8 @@ module Slinky
|
|
54
75
|
# @param String path the path of the file relative to the manifest
|
55
76
|
#
|
56
77
|
# @return ManifestFile the manifest file at that path if one exists
|
57
|
-
def find_by_path path
|
58
|
-
@manifest_dir.find_by_path path
|
78
|
+
def find_by_path path, allow_multiple = false
|
79
|
+
@manifest_dir.find_by_path path, allow_multiple
|
59
80
|
end
|
60
81
|
|
61
82
|
def scripts_string
|
@@ -71,19 +92,21 @@ module Slinky
|
|
71
92
|
def compress ext, output, compressor
|
72
93
|
scripts = dependency_list.reject{|x| x.output_path.extname != ext}
|
73
94
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
95
|
+
if scripts.size > 0
|
96
|
+
s = scripts.collect{|s|
|
97
|
+
f = File.open(s.build_to.to_s, 'rb'){|f| f.read}
|
98
|
+
(block_given?) ? (yield s, f) : f
|
99
|
+
}.join("\n")
|
78
100
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
101
|
+
File.open(output, "w+"){|f|
|
102
|
+
f.write(compressor.compress(s))
|
103
|
+
}
|
104
|
+
scripts.collect{|s| FileUtils.rm(s.build_to)}
|
105
|
+
end
|
83
106
|
end
|
84
107
|
|
85
108
|
def compress_scripts
|
86
|
-
compressor = YUI::JavaScriptCompressor.new(:munge =>
|
109
|
+
compressor = YUI::JavaScriptCompressor.new(:munge => false)
|
87
110
|
compress(".js", "#{@build_to}/scripts.js", compressor)
|
88
111
|
end
|
89
112
|
|
@@ -118,9 +141,11 @@ module Slinky
|
|
118
141
|
graph = []
|
119
142
|
files(false).each{|mf|
|
120
143
|
mf.directives[:slinky_require].each{|rf|
|
121
|
-
required = mf.parent.find_by_path(rf)
|
122
|
-
if required
|
123
|
-
|
144
|
+
required = mf.parent.find_by_path(rf, true)
|
145
|
+
if required.size > 0
|
146
|
+
required.each{|x|
|
147
|
+
graph << [x, mf]
|
148
|
+
}
|
124
149
|
else
|
125
150
|
error = "Could not find file #{rf} required by #{mf.source}"
|
126
151
|
$stderr.puts error.foreground(:red)
|
@@ -175,6 +200,27 @@ module Slinky
|
|
175
200
|
files_rec c
|
176
201
|
end
|
177
202
|
end
|
203
|
+
|
204
|
+
def invalidate_cache
|
205
|
+
@files = nil
|
206
|
+
@dependency_graph = nil
|
207
|
+
end
|
208
|
+
|
209
|
+
def manifest_update paths
|
210
|
+
paths.each{|path|
|
211
|
+
if path[0] == '/'
|
212
|
+
path = Pathname.new(path).relative_path_from(Pathname.new(@dir).expand_path).to_s
|
213
|
+
end
|
214
|
+
yield path
|
215
|
+
}
|
216
|
+
invalidate_cache
|
217
|
+
files.each{|f|
|
218
|
+
if f.directives.include?(:slinky_scripts) || f.directives.include?(:slinky_styles)
|
219
|
+
f.invalidate
|
220
|
+
f.process
|
221
|
+
end
|
222
|
+
}
|
223
|
+
end
|
178
224
|
end
|
179
225
|
|
180
226
|
class ManifestDir
|
@@ -191,10 +237,9 @@ module Slinky
|
|
191
237
|
# skip the build dir
|
192
238
|
next if Pathname.new(File.absolute_path(path)) == Pathname.new(build_dir)
|
193
239
|
if File.directory? path
|
194
|
-
|
195
|
-
@children << ManifestDir.new(path, self, build_dir, manifest)
|
240
|
+
add_child(path)
|
196
241
|
else
|
197
|
-
|
242
|
+
add_file(path)
|
198
243
|
end
|
199
244
|
end
|
200
245
|
end
|
@@ -203,15 +248,28 @@ module Slinky
|
|
203
248
|
# otherwise nil.
|
204
249
|
#
|
205
250
|
# @param String path the path of the file relative to the directory
|
251
|
+
# @param Boolean allow_multiple if enabled, can return multiple paths
|
252
|
+
# according to glob rules
|
206
253
|
#
|
207
|
-
# @return ManifestFile the manifest file at that path if one exists
|
208
|
-
def find_by_path path
|
254
|
+
# @return [ManifestFile] the manifest file at that path if one exists
|
255
|
+
def find_by_path path, allow_multiple = false
|
209
256
|
components = path.to_s.split(File::SEPARATOR).reject{|x| x == ""}
|
210
257
|
case components.size
|
211
258
|
when 0
|
212
|
-
self
|
259
|
+
[self]
|
213
260
|
when 1
|
214
|
-
@
|
261
|
+
path = [@dir, components[0]].join(File::SEPARATOR)
|
262
|
+
if (Dir.exists?(path) rescue false)
|
263
|
+
c = @children.find{|d|
|
264
|
+
Pathname.new(d.dir).cleanpath == Pathname.new(path).cleanpath
|
265
|
+
}
|
266
|
+
unless c
|
267
|
+
c = add_child(path)
|
268
|
+
end
|
269
|
+
[c]
|
270
|
+
else
|
271
|
+
@files.find_all{|f| f.matches? components[0], allow_multiple}
|
272
|
+
end
|
215
273
|
else
|
216
274
|
if components[0] == ".."
|
217
275
|
@parent.find_by_path components[1..-1].join(File::SEPARATOR)
|
@@ -219,24 +277,63 @@ module Slinky
|
|
219
277
|
child = @children.find{|d|
|
220
278
|
Pathname.new(d.dir).basename.to_s == components[0]
|
221
279
|
}
|
222
|
-
|
280
|
+
if child
|
281
|
+
child.find_by_path(components[1..-1].join(File::SEPARATOR),
|
282
|
+
allow_multiple)
|
283
|
+
else
|
284
|
+
[]
|
285
|
+
end
|
223
286
|
end
|
224
287
|
end
|
225
288
|
end
|
226
289
|
|
290
|
+
# Adds a child directory
|
291
|
+
def add_child path
|
292
|
+
if Dir.exists? path
|
293
|
+
build_dir = (@build_dir + File.basename(path)).cleanpath
|
294
|
+
md = ManifestDir.new(path, self, build_dir, @manifest)
|
295
|
+
@children << md
|
296
|
+
md
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# Adds a file on the filesystem to the manifest
|
301
|
+
#
|
302
|
+
# @param String path The path of the file
|
303
|
+
def add_file path
|
304
|
+
file = File.basename(path)
|
305
|
+
full_path = [@dir, file].join(File::SEPARATOR)
|
306
|
+
if File.exists? full_path
|
307
|
+
mf = ManifestFile.new(full_path, @build_dir, @manifest, self)
|
308
|
+
@files << mf
|
309
|
+
mf
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
# Removes a file from the manifest
|
314
|
+
#
|
315
|
+
# @param ManifestFile mf The file to be deleted
|
316
|
+
def remove_file mf
|
317
|
+
@files.delete(mf)
|
318
|
+
end
|
319
|
+
|
227
320
|
def build
|
228
|
-
|
229
|
-
@build_dir.
|
321
|
+
unless Dir.exists?(@build_dir.to_s)
|
322
|
+
FileUtils.mkdir(@build_dir.to_s)
|
230
323
|
end
|
231
324
|
(@files + @children).each{|m|
|
232
325
|
m.build
|
233
326
|
}
|
234
327
|
end
|
328
|
+
|
329
|
+
def to_s
|
330
|
+
"<ManifestDir:'#{@dir}'>"
|
331
|
+
end
|
235
332
|
end
|
236
333
|
|
237
334
|
class ManifestFile
|
238
335
|
attr_accessor :source, :build_path
|
239
|
-
attr_reader :last_built, :directives, :parent, :manifest
|
336
|
+
attr_reader :last_built, :directives, :parent, :manifest, :updated
|
240
337
|
|
241
338
|
def initialize source, build_path, manifest, parent = nil, options = {:devel => false}
|
242
339
|
@parent = parent
|
@@ -251,17 +348,32 @@ module Slinky
|
|
251
348
|
@devel = true if options[:devel]
|
252
349
|
end
|
253
350
|
|
351
|
+
def invalidate
|
352
|
+
@last_built = Time.new(0)
|
353
|
+
@last_md5 = nil
|
354
|
+
end
|
355
|
+
|
254
356
|
# Predicate which determines whether the supplied name is the same
|
255
357
|
# as the file's name, taking into account compiled file
|
256
358
|
# extensions. For example, if mf refers to "/tmp/test/hello.sass",
|
257
359
|
# `mf.matches? "hello.sass"` and `mf.matches? "hello.css"` should
|
258
360
|
# both return true.
|
259
361
|
#
|
260
|
-
# @param
|
261
|
-
# @
|
262
|
-
|
362
|
+
# @param String a filename
|
363
|
+
# @param Bool match_glob if true, matches according to glob rules
|
364
|
+
# @return Bool True if the filename matches, false otherwise
|
365
|
+
def matches? s, match_glob = false
|
263
366
|
name = Pathname.new(@source).basename.to_s
|
264
|
-
|
367
|
+
output = output_path.basename.to_s
|
368
|
+
# check for stars that are not escaped
|
369
|
+
r = /(?<!\\)\*/
|
370
|
+
if match_glob && s.match(r)
|
371
|
+
a = s.split(r)
|
372
|
+
r2 = a.reduce{|a, x| /#{a}.*#{x}/}
|
373
|
+
name.match(r2) || output.match(r2)
|
374
|
+
else
|
375
|
+
name == s || output == s
|
376
|
+
end
|
265
377
|
end
|
266
378
|
|
267
379
|
# Predicate which determines whether the file is the supplied path
|
@@ -313,7 +425,7 @@ module Slinky
|
|
313
425
|
end
|
314
426
|
end
|
315
427
|
|
316
|
-
directives
|
428
|
+
@directives = directives
|
317
429
|
end
|
318
430
|
|
319
431
|
# If there are any build directives for this file, the file is
|
@@ -323,19 +435,16 @@ module Slinky
|
|
323
435
|
# @return String the path of the de-directivefied file
|
324
436
|
def handle_directives path, to = nil
|
325
437
|
if @directives.size > 0
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
rescue
|
337
|
-
nil
|
338
|
-
end
|
438
|
+
out = File.read(path)
|
439
|
+
out.gsub!(DEPENDS_DIRECTIVE, "")
|
440
|
+
out.gsub!(REQUIRE_DIRECTIVE, "")
|
441
|
+
out.gsub!(SCRIPTS_DIRECTIVE, @manifest.scripts_string)
|
442
|
+
out.gsub!(STYLES_DIRECTIVE, @manifest.styles_string)
|
443
|
+
to = to || Tempfile.new("slinky").path + ".cache"
|
444
|
+
File.open(to, "w+"){|f|
|
445
|
+
f.write(out)
|
446
|
+
}
|
447
|
+
to
|
339
448
|
else
|
340
449
|
path
|
341
450
|
end
|
@@ -357,14 +466,45 @@ module Slinky
|
|
357
466
|
path ? Pathname.new(path) : nil
|
358
467
|
end
|
359
468
|
|
469
|
+
# Gets the md5 hash of the source file
|
470
|
+
def md5
|
471
|
+
Digest::MD5.hexdigest(File.read(@source)) rescue nil
|
472
|
+
end
|
473
|
+
|
360
474
|
# Gets manifest file ready for serving or building by handling the
|
361
475
|
# directives and compiling the file if neccesary.
|
362
476
|
# @param String path to which the file should be compiled
|
363
477
|
#
|
364
478
|
# @return String the path of the processed file, ready for serving
|
365
479
|
def process to = nil
|
366
|
-
#
|
367
|
-
|
480
|
+
return if @processing # prevent infinite recursion
|
481
|
+
start_time = Time.now
|
482
|
+
hash = md5
|
483
|
+
if hash != @last_md5
|
484
|
+
find_directives
|
485
|
+
end
|
486
|
+
|
487
|
+
depends = @directives[:slinky_depends].map{|f|
|
488
|
+
p = parent.find_by_path(f, true)
|
489
|
+
$stderr.puts "File #{f} depended on by #{@source} not found".foreground(:red) unless p.size > 0
|
490
|
+
p
|
491
|
+
}.flatten.compact if @directives[:slinky_depends]
|
492
|
+
depends ||= []
|
493
|
+
@processing = true
|
494
|
+
# process each file on which we're dependent, watching out for
|
495
|
+
# infinite loops
|
496
|
+
depends.each{|f| f.process }
|
497
|
+
@processing = false
|
498
|
+
|
499
|
+
# get hash of source file
|
500
|
+
if @last_path && hash == @last_md5 && depends.all?{|f| f.updated < start_time}
|
501
|
+
@last_path
|
502
|
+
else
|
503
|
+
@last_md5 = hash
|
504
|
+
@updated = Time.now
|
505
|
+
# mangle file appropriately
|
506
|
+
@last_path = handle_directives (compile @source), to
|
507
|
+
end
|
368
508
|
end
|
369
509
|
|
370
510
|
# Path to which the file will be built
|
@@ -379,8 +519,12 @@ module Slinky
|
|
379
519
|
FileUtils.mkdir_p(@build_path)
|
380
520
|
end
|
381
521
|
to = build_to
|
382
|
-
|
383
|
-
|
522
|
+
begin
|
523
|
+
path = process to
|
524
|
+
rescue
|
525
|
+
raise BuildFailedError
|
526
|
+
end
|
527
|
+
|
384
528
|
if !path
|
385
529
|
raise BuildFailedError
|
386
530
|
elsif path != to
|
@@ -389,5 +533,9 @@ module Slinky
|
|
389
533
|
end
|
390
534
|
to
|
391
535
|
end
|
536
|
+
|
537
|
+
def to_s
|
538
|
+
"<Slinky::ManifestFile '#{@source}'>"
|
539
|
+
end
|
392
540
|
end
|
393
541
|
end
|