distil 0.13.6 → 0.14.0.b

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.
Files changed (59) hide show
  1. data/Rakefile +1 -0
  2. data/VERSION +1 -1
  3. data/assets/distil.js +9 -7
  4. data/bin/distil +36 -60
  5. data/distil.gemspec +17 -32
  6. data/distil.tmproj +46 -15
  7. data/lib/distil/browser.rb +30 -26
  8. data/lib/distil/configurable.rb +64 -153
  9. data/lib/distil/error-reporter.rb +22 -20
  10. data/lib/distil/file-vendor.rb +29 -0
  11. data/lib/distil/hash-additions.rb +45 -0
  12. data/lib/distil/javascript-code.rb +12 -0
  13. data/lib/distil/{task/validate-js-task.rb → javascript-file-validator.rb} +19 -23
  14. data/lib/distil/library.rb +243 -0
  15. data/lib/distil/product/cache-manifest-product.rb +21 -0
  16. data/lib/distil/product/css-product.rb +41 -23
  17. data/lib/distil/product/html-product.rb +20 -0
  18. data/lib/distil/product/javascript-product.rb +122 -111
  19. data/lib/distil/product.rb +90 -76
  20. data/lib/distil/project.rb +370 -104
  21. data/lib/distil/recursive-http-fetcher.rb +72 -0
  22. data/lib/distil/server.rb +43 -0
  23. data/lib/distil/source-file/css-file.rb +56 -3
  24. data/lib/distil/source-file/html-file.rb +5 -6
  25. data/lib/distil/source-file/javascript-file.rb +96 -8
  26. data/lib/distil/source-file/json-file.rb +2 -4
  27. data/lib/distil/source-file/yui-minifiable-file.rb +19 -0
  28. data/lib/distil/source-file.rb +50 -92
  29. data/lib/distil/subclass-tracker.rb +13 -0
  30. data/lib/distil.rb +21 -37
  31. metadata +40 -39
  32. data/assets/mime.types +0 -1240
  33. data/lib/distil/configurable/file-set.rb +0 -85
  34. data/lib/distil/configurable/interpolated.rb +0 -36
  35. data/lib/distil/configurable/output-path.rb +0 -25
  36. data/lib/distil/configurable/project-path.rb +0 -25
  37. data/lib/distil/product/concatenated.rb +0 -83
  38. data/lib/distil/product/debug.rb +0 -32
  39. data/lib/distil/product/javascript-base-product.rb +0 -35
  40. data/lib/distil/product/javascript-doc-product.rb +0 -61
  41. data/lib/distil/product/minified.rb +0 -41
  42. data/lib/distil/product/page-product.rb +0 -27
  43. data/lib/distil/product/pdoc-product.rb +0 -42
  44. data/lib/distil/project/distil-project.rb +0 -157
  45. data/lib/distil/project/external-project.rb +0 -58
  46. data/lib/distil/project/remote-project.rb +0 -43
  47. data/lib/distil/target.rb +0 -251
  48. data/lib/distil/task/css-dependency-task.rb +0 -64
  49. data/lib/distil/task/jsl-dependency-task.rb +0 -50
  50. data/lib/distil/task/nib-task.rb +0 -72
  51. data/lib/distil/task.rb +0 -50
  52. data/lib/jsdoc.conf +0 -18
  53. data/lib/test/HtmlTestReporter.js +0 -127
  54. data/lib/test/Test.js +0 -248
  55. data/lib/test/TestReporter.js +0 -79
  56. data/lib/test/TestRunner.js +0 -132
  57. data/lib/test/browser.rb +0 -97
  58. data/lib/test/scriptwrapper.html +0 -10
  59. data/lib/test/unittest.html +0 -127
@@ -1,144 +1,410 @@
1
1
  module Distil
2
2
 
3
- class Project < Configurable
3
+ BUILD_FILE= 'Buildfile'
4
+ DEFAULT_OUTPUT_FOLDER= 'build'
5
+ DEFAULT_LANGUAGE= 'en'
4
6
 
7
+ APPLICATION_TYPE= 'application'
8
+ FRAMEWORK_TYPE= 'framework'
9
+
10
+ class Project < Configurable
5
11
  include ErrorReporter
12
+ include FileVendor
13
+ include JavascriptFileValidator
14
+
15
+ attr_reader :name, :path, :folder, :source_folder, :output_folder, :include_paths
16
+ attr_reader :assets, :asset_aliases
17
+ attr_reader :libraries_by_name, :libraries
18
+ attr_reader :languages, :project_type
19
+ attr_reader :source_files
20
+ attr_reader :global_export
21
+ attr_reader :additional_globals
22
+ attr_reader :subprojects
23
+ attr_reader :dependency_aliases
24
+
25
+ alias_config_key :project_type, :type
26
+
27
+ def self.find(dir=nil)
28
+ cwd= Dir.pwd
29
+ dir ||= Dir.pwd
30
+ while dir.length > 1
31
+ return from_file(File.join(dir, BUILD_FILE)) if File.exists?(File.join(dir, BUILD_FILE))
32
+
33
+ projects= Dir.glob(File.join(dir, "*.jsproj"))
34
+ return from_file(projects.first) if 1==projects.size
35
+
36
+ unless 0==projects.size
37
+ puts "More than one candidate for Project:"
38
+ projects.each { |e|
39
+ puts " #{path_relative_to_folder(e, cwd)}"
40
+ }
41
+ exit 1
42
+ end
43
+
44
+ dir= File.dirname(dir)
45
+ end
46
+
47
+ nil
48
+ end
49
+
50
+ def self.from_file(file)
51
+ yaml= YAML::load_file(file)
52
+ if File.exists?("#{file}.local")
53
+ local_yaml= YAML::load_file("#{file}.local")
54
+ yaml.deep_merge!(local_yaml)
55
+ end
56
+ new(file, yaml)
57
+ end
58
+
59
+ def initialize(path, config={}, parent=nil)
60
+ @path= path
61
+ @folder= File.dirname(@path)
62
+ @source_folder= @folder
63
+ @output_folder= DEFAULT_OUTPUT_FOLDER
64
+ @include_paths= [@folder]
65
+ @include_files= []
66
+ @asset_aliases= {}
67
+ @dependency_aliases= {}
68
+ @assets= Set.new
69
+ @source_files= Set.new
70
+ @subprojects= []
71
+ @libraries= parent ? parent.libraries : []
72
+ @libraries_by_name= parent ? parent.libraries_by_name : {}
73
+ @languages= []
74
+ @additional_globals= []
75
+ @name= File.basename(@folder, ".*")
76
+
77
+ ignore_warnings= false
78
+
79
+ child_config= config.dup
80
+ child_config.delete("targets")
81
+ child_config.delete("require")
82
+
83
+ Dir.chdir(@folder) do
84
+ configure_with config do |c|
85
+
86
+ c.with :name do |name|
87
+ @name= name
88
+ end
89
+
90
+ c.with :output_folder do |output_folder|
91
+ @output_folder= output_folder
92
+ end
93
+ FileUtils.mkdir_p output_folder
94
+
95
+ c.with :source_folder do |source_folder|
96
+ @source_folder= source_folder
97
+ end
98
+
99
+ c.with :export do |export|
100
+ export=@name.as_identifier if true==export
101
+ @global_export= export
102
+ end
103
+
104
+ c.with_each :globals do |global|
105
+ @additional_globals << global
106
+ end
107
+
108
+ c.with_each :languages do |language|
109
+ @languages << language
110
+ end
111
+
112
+ c.with_each :require do |asset|
113
+ asset= Library.new(asset, self)
114
+ @libraries << asset
115
+ @libraries_by_name[asset.name]= asset
116
+ end
117
+
118
+ c.with_each :source do |file|
119
+ include_file(file)
120
+ end
121
+
122
+ c.with_each :targets do |target|
123
+ target_config= child_config.dup
124
+ target_config.deep_merge!(target)
125
+ @subprojects << Project.new(path, target_config, self)
126
+ end
127
+
128
+ end # configure_with
129
+ end
130
+
131
+ end
132
+
133
+ def validate_files
134
+ validate_javascript_files
135
+ end
6
136
 
7
- option :output_folder, ProjectPath, "build/$(mode)", :aliases=>['output']
8
- option :source_folder, ProjectPath, ""
137
+ def compute_source_files
138
+ return if @source_files_computed
139
+ @source_files_computed= true
140
+
141
+ inspected= Set.new
142
+ ordered_files= []
9
143
 
10
- option :path, String
11
- option :mode, DEBUG_MODE, :valid_values=>[DEBUG_MODE, RELEASE_MODE]
12
- option :force
144
+ add_file= lambda { |f|
145
+ return unless include_files.include?(f)
146
+ return if inspected.include?(f)
147
+ inspected << f
148
+
149
+ if f.respond_to? :dependencies
150
+ f.dependencies.each { |d|
151
+ add_file.call d
152
+ }
153
+ end
154
+
155
+ ordered_files << f
156
+ }
157
+
158
+ include_files.each { |f| add_file.call(f) }
159
+ ordered_files.each { |f|
160
+ next if f.is_a?(SourceFile) && f.is_asset
161
+
162
+ used= false
163
+ products.each { |p|
164
+ used= true if p.include_file(f)
165
+ }
166
+
167
+ next if !used
168
+
169
+ if !f.is_a?(Library)
170
+ @source_files << f
171
+ @assets.merge(f.assets) if f.assets
172
+ end
173
+ }
174
+ end
13
175
 
14
- def up_to_date
15
- true
176
+ def up_to_date?
177
+ products.each { |product|
178
+ return false if !product.up_to_date?
179
+ }
180
+ return true
16
181
  end
17
182
 
18
183
  def build
19
- end
184
+ subprojects.each { |subproject|
185
+ subproject.build
186
+ }
20
187
 
188
+ compute_source_files
189
+ return if up_to_date?
190
+
191
+ validate_files
192
+ build_assets
193
+
194
+ products.each { |product|
195
+ product.build
196
+ }
197
+ end
198
+
21
199
  def clean
200
+ compute_source_files
201
+ products.each { |product|
202
+ product.clean
203
+ }
22
204
  end
23
205
 
24
- def self.fetch_project_using_git(options = {})
25
- uri= options["repository"]
26
- path= options["path"]
27
-
206
+ def inspect
207
+ "<#{self.class}:0x#{object_id.to_s(16)} name=#{name}>"
208
+ end
209
+
210
+ def output_path
211
+ @output_path ||= File.join(folder, output_folder)
212
+ end
213
+
214
+ def relative_path_for(thing)
215
+ Project.path_relative_to_folder(thing.is_a?(String) ? thing : thing.full_path, path)
216
+ end
217
+
218
+ def relative_output_path_for(thing)
219
+ return nil if !thing
220
+ # puts "relative_output_path_for: #{thing} #{output_path}"
221
+ Project.path_relative_to_folder(thing.is_a?(String) ? thing : thing.output_path, output_path)
222
+ end
223
+
224
+ def notice_text
28
225
  begin
29
- `git --version 2>/dev/null`
226
+ @notice_text ||= File.read(File.join(@folder, @notice)).strip
30
227
  rescue
31
- nil
32
- end
33
- if $?.nil? || !$?.success?
34
- raise ValidationError.new("The git version control tool is required to pull this repository: #{uri}")
228
+ @notice_text ||= ""
35
229
  end
230
+ end
231
+
232
+ def products
233
+ return @products unless @products.nil?
36
234
 
37
- FileUtils.mkdir_p(path)
38
- Dir.chdir path do
39
- clone_cmd = "git clone #{uri} ."
40
- clone_cmd += " -q"
41
- clone_cmd += " -b #{options["version"]}" if options["version"]
42
- if !system(clone_cmd)
43
- raise ValidationError.new("Failed to clone external project: #{uri}")
44
- end
45
- end
235
+ @products= []
236
+ langs= languages.empty? ? [nil] : languages
237
+
238
+ Product.subclasses.each { |klass|
239
+ langs.each { |lang|
240
+ klass.variants.each { |v|
241
+ @products << klass.new(self, lang, v)
242
+ }
243
+ }
244
+ }
245
+
246
+ @products
46
247
  end
47
248
 
48
- def self.from_config(config, parent=nil)
249
+ def symlink_assets
250
+ Dir.chdir(output_path) do
251
+ folders= []
49
252
 
50
- if config.is_a?(String)
51
- string= config
52
- uri= URI.parse(string)
53
-
54
- config= { "name" => File.basename(config, ".*") }
55
-
56
- case
57
- when ['.js', '.css'].include?(File.extname(uri.path))
58
- config["href"]= uri.to_s
59
- when uri.scheme
60
- config["repository"]= uri.to_s
61
- else
62
- config["path"]= uri.to_s
63
-
64
- full_path= File.expand_path(config["path"])
65
-
66
- if File.exist?(full_path) && File.file?(full_path)
67
- config["path"]= File.dirname(full_path)
68
- else
69
- config["path"]= full_path
253
+ files= assets+source_files
254
+ files.each { |a|
255
+ next if (a.full_path).starts_with?(output_path)
256
+
257
+ path= relative_output_path_for(a)
258
+
259
+ parts= File.dirname(path).split(File::SEPARATOR)
260
+ if ('.'==parts[0])
261
+ product_path= File.join(output_folder, path)
262
+ FileUtils.rm product_path if File.exists? product_path
263
+ File.symlink path, product_path
264
+ next
70
265
  end
71
- end
72
- end
73
266
 
74
- if !config["name"]
75
- case when config["repository"]
76
- uri= URI.parse(config["repository"])
77
- config["name"]= File.basename(uri.path, ".*")
78
- when config["path"]
79
- config["name"]= File.basename(config["path"], ".*")
80
- else
81
- raise ValidationError.new("External project has neither name, path nor repository")
82
- end
83
- end
267
+ folders << parts[0] if !folders.include?(parts[0])
268
+ }
269
+
270
+ folders.each { |f|
271
+ target= f
272
+ source= relative_output_path_for(File.join(source_folder, f))
84
273
 
85
- if config["href"]
86
- return RemoteProject.new(config, parent)
274
+ FileUtils.rm target if File.symlink?(target)
275
+ next if File.directory?(target)
276
+ File.symlink source, target
277
+ }
87
278
  end
88
-
89
- config["path"]||= "ext/#{config["name"]}"
90
-
91
- if config["repository"] && !File.directory?(config["path"])
92
- fetch_project_using_git(config)
279
+ end
280
+
281
+ def copy_assets
282
+ assets.each { |a|
283
+ a.copy_to(output_folder, source_folder)
284
+ }
285
+ end
286
+
287
+ def build_assets
288
+ symlink_assets
289
+ # if (RELEASE_MODE==mode)
290
+ # copy_assets
291
+ # else
292
+ # symlink_assets
293
+ # end
294
+ end
295
+
296
+ def add_alias_for_asset(alias_name, asset)
297
+ if asset_aliases.include?(alias_name)
298
+ error "Attempt to register asset with the same alias as another asset: #{alias_name}"
299
+ return
93
300
  end
301
+ asset_aliases[asset]= alias_name
302
+ end
303
+
304
+ def include_files
305
+ @include_files
306
+ end
307
+
308
+ def include_file(file)
309
+ return if file.nil?
94
310
 
95
- config["mode"]||= parent.mode if parent
96
-
97
- path= config["path"]
98
- if !path
99
- ErrorReporter.error "No path for project: #{config["name"]}"
100
- return nil
311
+ asset= @libraries_by_name[file]
312
+ if (asset)
313
+ @include_files << asset unless @include_files.include?(asset)
314
+ return
101
315
  end
102
316
 
103
- if !File.directory?(path)
104
- ErrorReporter.error "Path is not valid for project: #{config["name"]}"
105
- return nil
317
+ matches= glob(file)
318
+ matches= glob(File.join(source_folder, file)) if matches.empty?
319
+
320
+ if (matches.empty?)
321
+ error("No matching files found for: #{file}")
322
+ return
106
323
  end
107
324
 
108
- basename= File.basename(path)
109
-
110
- case
111
- when exist?(path, "#{basename}.jsproj")
112
- project_file= File.join(path, "#{basename}.jsproj")
113
- project_info= YAML.load_file(project_file)
114
- project_info.merge!(config)
115
- project_info["path"]= path
116
- project= ExternalProject.new(project_info, parent)
117
- if parent
118
- project.build_command ||= "distil --mode=#{parent.mode} --force=#{parent.force}"
325
+ matches.each { |m|
326
+ if File.directory?(m)
327
+ include_file(File.join(m, "**/*"))
119
328
  else
120
- project.build_command ||= "distil"
329
+ f= file_from_path(m)
330
+ unless @include_files.include?(f)
331
+ @include_files << f
332
+ # determine language
333
+ f.language= languages.find { |l| File.fnmatch?("**/#{l}/**", f.full_path) }
334
+ end
121
335
  end
122
- when exist?(path, "Makefile") || exist?(path, "makefile")
123
- project= ExternalProject.new(config, parent)
124
- project.build_command ||= "make"
125
- when exist?(path, "Rakefile") || exist?(path, "rakefile")
126
- project= ExternalProject.new(config, parent)
127
- project.build_command ||= "rake"
128
- when exist?(path, "Jakefile") || exist?(path, "jakefile")
129
- project= ExternalProject.new(config, parent)
130
- project.build_command ||= "jake"
131
- else
132
- ErrorReporter.error "Could not determine type for project: #{config["name"]}"
336
+ }
337
+ end
338
+
339
+ def glob(path)
340
+ return path if File.exists?(path)
341
+
342
+ files= []
343
+
344
+ parts= path.split(File::SEPARATOR)
345
+ asset_name= parts[0]
346
+ file_path= File.join(parts.slice(1..-1))
347
+
348
+ if (@libraries_by_name.include?(asset_name))
349
+ asset= @libraries_by_name[asset_name]
350
+ return Dir.glob(File.join(asset.output_path, file_path))
133
351
  end
134
- return project
135
352
 
353
+ files.concat(Dir.glob(path));
354
+
355
+ include_paths.each { |i|
356
+ files.concat(Dir.glob(File.join(i, path)))
357
+ }
358
+ return files
359
+ end
360
+
361
+ def add_alias_for_file(alias_name, file)
362
+ @dependency_aliases[alias_name]= file
363
+ end
364
+
365
+ def find_file(path, content_type=nil, mode=nil)
366
+ return path if File.exists?(path)
367
+
368
+ include_paths.each { |i|
369
+ f= File.join(i, path)
370
+ return f if File.exists?(f)
371
+ }
372
+
373
+ # Check remote assets
374
+ parts= path.split(File::SEPARATOR)
375
+ asset_name= parts[0]
376
+ file_path= File.join(parts.slice(1..-1))
377
+
378
+ return nil unless @libraries_by_name.include?(asset_name)
379
+ asset= @libraries_by_name[asset_name]
380
+
381
+ return asset.file_for(content_type, nil, mode) if 1==parts.length
382
+
383
+ f= File.join(asset.output_path, file_path)
384
+ return f if File.exists?(f)
385
+
386
+ nil
387
+ end
388
+
389
+ def self.path_relative_to_folder(path, folder)
390
+ path= File.expand_path(path)
391
+ outputFolder= File.expand_path(folder).to_s
392
+
393
+ # Remove leading slash and split into parts
394
+ file_parts= path.slice(1..-1).split('/');
395
+ output_parts= outputFolder.slice(1..-1).split('/');
396
+
397
+ common_prefix_length= 0
398
+
399
+ file_parts.each_index { |i|
400
+ common_prefix_length= i
401
+ break if file_parts[i]!=output_parts[i]
402
+ }
403
+
404
+ return '../'*(output_parts.length-common_prefix_length) + file_parts[common_prefix_length..-1].join('/')
136
405
  end
137
406
 
138
407
  end
139
408
 
409
+
140
410
  end
141
-
142
- require 'distil/project/remote-project'
143
- require 'distil/project/external-project'
144
- require 'distil/project/distil-project'
@@ -0,0 +1,72 @@
1
+ module Distil
2
+
3
+ class RecursiveHTTPFetcher
4
+ attr_accessor :quiet
5
+
6
+ def initialize(urls_to_fetch, level = 1, cwd = ".")
7
+ @level = level
8
+ @cwd = cwd
9
+ @urls_to_fetch = RUBY_VERSION >= '1.9' ? urls_to_fetch.to_s.lines : urls_to_fetch.to_s.to_a
10
+ @quiet = true
11
+ end
12
+
13
+ def ls
14
+ @urls_to_fetch.collect do |url|
15
+ if url =~ /^svn(\+ssh)?:\/\/.*/ || url =~ /\/svn\//
16
+ `svn ls #{url}`.split("\n").map {|entry| "/#{entry}"} rescue nil
17
+ else
18
+ open(url) do |stream|
19
+ links("", stream.read)
20
+ end rescue nil
21
+ end
22
+ end.flatten
23
+ end
24
+
25
+ def push_d(dir)
26
+ @cwd = File.join(@cwd, dir)
27
+ FileUtils.mkdir_p(@cwd)
28
+ end
29
+
30
+ def pop_d
31
+ @cwd = File.dirname(@cwd)
32
+ end
33
+
34
+ def links(base_url, contents)
35
+ links = []
36
+ contents.scan(/href\s*=\s*\"*[^\">]*/i) do |link|
37
+ link = link.sub(/href="/i, "")
38
+ next if link =~ /svnindex.xsl$/
39
+ next if link =~ /^(\w*:|)\/\// || link =~ /^\./
40
+ links << File.join(base_url, link)
41
+ end
42
+ links
43
+ end
44
+
45
+ def download(link)
46
+ puts "+ #{File.join(@cwd, File.basename(link))}" unless @quiet
47
+ open(link) do |stream|
48
+ File.open(File.join(@cwd, File.basename(link)), "wb") do |file|
49
+ file.write(stream.read)
50
+ end
51
+ end
52
+ end
53
+
54
+ def fetch(links = @urls_to_fetch)
55
+ links.each do |l|
56
+ (l =~ /\/$/ || links == @urls_to_fetch) ? fetch_dir(l) : download(l)
57
+ end
58
+ end
59
+
60
+ def fetch_dir(url)
61
+ @level += 1
62
+ push_d(File.basename(url)) if @level > 0
63
+ open(url) do |stream|
64
+ contents = stream.read
65
+ fetch(links(url, contents))
66
+ end
67
+ pop_d if @level > 0
68
+ @level -= 1
69
+ end
70
+ end
71
+
72
+ end
@@ -0,0 +1,43 @@
1
+ module Distil
2
+
3
+ def self.start_server(project, options)
4
+ require 'webrick'
5
+ require 'directory_watcher'
6
+
7
+ port= options['server_port'] || 8888;
8
+ path= options['url']
9
+ config= {
10
+ :Port => port
11
+ }
12
+
13
+ server= WEBrick::HTTPServer.new(config)
14
+ server.mount(path || '/', WEBrick::HTTPServlet::FileHandler, project.output_folder)
15
+
16
+ ['INT', 'TERM'].each { |signal|
17
+ trap(signal){ server.shutdown }
18
+ }
19
+
20
+ puts "watching #{project.folder}"
21
+ dw = DirectoryWatcher.new(project.folder, {
22
+ :glob=>"**/*",
23
+ :pre_load => true,
24
+ :interval => 1
25
+ })
26
+ dw.add_observer { |*args|
27
+ args.each { |event|
28
+ puts event
29
+ if :modified==event.type
30
+ puts event.path
31
+ end
32
+ }
33
+ }
34
+
35
+ dw.start
36
+ gets
37
+ # b= Browser.new
38
+ # b.open("http://localhost:#{port}/#{path}")
39
+ # server.start
40
+ dw.stop
41
+ end
42
+
43
+ end
@@ -1,14 +1,67 @@
1
1
  module Distil
2
2
 
3
+ CSS_IMPORT_REGEX = /@import\s+url\("?(.*\.css)"?\)/
4
+ CSS_IMAGE_URL_REGEX= /url\("?(.*\.(jpg|png|gif))"?\)/
5
+
3
6
  class CssFile < SourceFile
4
-
7
+ include YuiMinifiableFile
8
+
5
9
  extension "css"
6
10
  content_type "css"
7
11
 
8
- def minified_content(source)
9
- super(source).gsub(/\}/,"}\n").gsub(/.*@import url\(\".*\"\);/,'')
12
+ def content
13
+ return @content unless @content.nil?
14
+ @content= File.read(full_path)
15
+ # Replace all ' (single quotes) with " (double quotes)
16
+ @content.gsub!(/\'/,'"')
17
+ # Force a newline after a rule terminating ; (semi-colon)
18
+ @content.gsub!(/;(\n|\r)*/, ";\n")
19
+ @content
10
20
  end
11
21
 
22
+ def rewrite_content_relative_to_path(path)
23
+ content.gsub(CSS_IMAGE_URL_REGEX) { |match|
24
+ image_file= File.join(dirname, $1)
25
+
26
+ if (!File.exists?(image_file))
27
+ match
28
+ else
29
+ asset= project.file_from_path(image_file)
30
+ "url(\"#{asset.relative_path}\")"
31
+ end
32
+ }
33
+ end
34
+
35
+ def dependencies
36
+ @dependencies unless @dependencies.nil?
37
+
38
+ line_num=0
39
+ content.each_line { |line|
40
+ line_num+=1
41
+
42
+ line.scan(CSS_IMPORT_REGEX) { |match|
43
+ css_file= File.join(dirname, $1)
44
+
45
+ if (!File.exists?(css_file))
46
+ error "Imported CSS file not found: #{$1}", line_num
47
+ else
48
+ add_dependency(project.file_from_path(css_file))
49
+ end
50
+ }
51
+
52
+ line.scan(CSS_IMAGE_URL_REGEX) { |match|
53
+ image_file= File.join(dirname, $1)
54
+
55
+ if (!File.exists?(image_file))
56
+ warning "Resource not found: #{$1}", line_num
57
+ else
58
+ asset= project.file_from_path(image_file)
59
+ add_asset(asset)
60
+ end
61
+ }
62
+ }
63
+ end
64
+
12
65
  end
13
66
 
14
67
  end