sstephenson-sprockets 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/sprocketize CHANGED
@@ -5,6 +5,7 @@ require "optparse"
5
5
 
6
6
  load_path = (ENV["SPROCKETS_PATH"] || "").split(":")
7
7
  filenames = []
8
+ options = { :load_path => load_path, :source_files => filenames, :expand_paths => false }
8
9
 
9
10
  OptionParser.new do |opts|
10
11
  opts.summary_width = 28
@@ -23,6 +24,10 @@ OptionParser.new do |opts|
23
24
  load_path << directory
24
25
  end
25
26
 
27
+ opts.on("-a DIRECTORY", "--asset-root=DIRECTORY", "Copy provided assets into DIRECTORY") do |directory|
28
+ options[:asset_root] = directory
29
+ end
30
+
26
31
  opts.on_tail("-h", "--help", "Shows this help message") do
27
32
  opts.show_usage
28
33
  end
@@ -44,5 +49,6 @@ OptionParser.new do |opts|
44
49
  end
45
50
  end
46
51
 
47
- secretary = Sprockets::Secretary.new(:load_path => load_path, :source_files => filenames, :expand_paths => false)
52
+ secretary = Sprockets::Secretary.new(options)
53
+ secretary.install_assets if options[:asset_root]
48
54
  print secretary.output_file
@@ -8,9 +8,9 @@ module Sprockets
8
8
  end
9
9
 
10
10
  # Returns a Pathname for the location relative to this pathname's absolute location.
11
- def find(location)
11
+ def find(location, kind = :file)
12
12
  location = File.join(absolute_location, location)
13
- File.file?(location) ? Pathname.new(environment, location) : nil
13
+ File.send("#{kind}?", location) ? Pathname.new(environment, location) : nil
14
14
  end
15
15
 
16
16
  def parent_pathname
@@ -1,11 +1,12 @@
1
1
  module Sprockets
2
2
  class Preprocessor
3
- attr_reader :environment, :output_file, :source_files
3
+ attr_reader :environment, :output_file, :source_files, :asset_paths
4
4
 
5
5
  def initialize(environment, options = {})
6
6
  @environment = environment
7
7
  @output_file = OutputFile.new
8
8
  @source_files = []
9
+ @asset_paths = []
9
10
  @options = options
10
11
  end
11
12
 
@@ -16,12 +17,19 @@ module Sprockets
16
17
  source_file.each_source_line do |source_line|
17
18
  if source_line.require?
18
19
  require_from_source_line(source_line)
20
+ elsif source_line.provide?
21
+ provide_from_source_line(source_line)
19
22
  else
20
23
  record_source_line(source_line)
21
24
  end
22
25
  end
23
26
  end
24
27
 
28
+ def provide(asset_path)
29
+ return if !asset_path || asset_paths.include?(asset_path)
30
+ asset_paths << asset_path
31
+ end
32
+
25
33
  protected
26
34
  attr_reader :options
27
35
 
@@ -29,6 +37,10 @@ module Sprockets
29
37
  require pathname_from(source_line).source_file
30
38
  end
31
39
 
40
+ def provide_from_source_line(source_line)
41
+ provide asset_path_from(source_line)
42
+ end
43
+
32
44
  def record_source_line(source_line)
33
45
  skip_pdoc_comments(source_line) do
34
46
  unless source_line.comment? && strip_comments?
@@ -84,6 +96,10 @@ module Sprockets
84
96
  File.join(File.dirname(location), File.basename(location, ".js") + ".js")
85
97
  end
86
98
 
99
+ def asset_path_from(source_line)
100
+ source_line.source_file.find(source_line.provide, :directory)
101
+ end
102
+
87
103
  def raise_load_error_for(source_line)
88
104
  kind = kind_of_require_from(source_line).to_s.tr("_", " ")
89
105
  file = File.split(location_from(source_line)).last
@@ -46,6 +46,14 @@ module Sprockets
46
46
  preprocessor.output_file
47
47
  end
48
48
 
49
+ def install_assets
50
+ if @options[:asset_root]
51
+ preprocessor.asset_paths.each do |asset_path|
52
+ copy_assets_from(asset_path.absolute_location)
53
+ end
54
+ end
55
+ end
56
+
49
57
  protected
50
58
  def expand_paths(paths, options = {})
51
59
  if options.has_key?(:expand_paths) ? options[:expand_paths] : @options[:expand_paths]
@@ -62,5 +70,29 @@ module Sprockets
62
70
  File.join(@options[:root], path)
63
71
  end
64
72
  end
73
+
74
+ def copy_assets_from(asset_path)
75
+ relative_file_paths_beneath(asset_path).each do |filename|
76
+ source, destination = File.join(asset_path, filename), File.join(asset_root, File.dirname(filename))
77
+ if !File.directory?(source)
78
+ FileUtils.mkdir_p(destination)
79
+ FileUtils.cp(source, destination)
80
+ end
81
+ end
82
+ end
83
+
84
+ def relative_file_paths_beneath(path)
85
+ Dir[File.join(path, "**", "*")].map do |filename|
86
+ File.join(*path_pieces(filename)[path_pieces(path).length..-1])
87
+ end
88
+ end
89
+
90
+ def asset_root
91
+ from_root(@options[:asset_root])
92
+ end
93
+
94
+ def path_pieces(path)
95
+ path.split(File::SEPARATOR)
96
+ end
65
97
  end
66
98
  end
@@ -15,8 +15,8 @@ module Sprockets
15
15
  end
16
16
  end
17
17
 
18
- def find(location)
19
- pathname.parent_pathname.find(location)
18
+ def find(location, kind = :file)
19
+ pathname.parent_pathname.find(location, kind)
20
20
  end
21
21
 
22
22
  def ==(source_file)
@@ -32,6 +32,14 @@ module Sprockets
32
32
  !!require
33
33
  end
34
34
 
35
+ def provide
36
+ @provide ||= (comment || "")[/^=\s+provide\s+\"(.*?)\"\s*$/, 1]
37
+ end
38
+
39
+ def provide?
40
+ !!provide
41
+ end
42
+
35
43
  def inspect
36
44
  "line #@number of #{@source_file.pathname}"
37
45
  end
@@ -1,7 +1,7 @@
1
1
  module Sprockets
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 4
4
+ MINOR = 5
5
5
  TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join(".")
data/lib/sprockets.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
3
  require "yaml"
4
+ require "fileutils"
4
5
 
5
6
  require "sprockets/version"
6
7
  require "sprockets/error"
@@ -0,0 +1 @@
1
+ /* nothing */
@@ -0,0 +1,3 @@
1
+ //= provide "../assets"
2
+
3
+ var ScriptWithAssets = { };
data/test/test_helper.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require File.join(File.dirname(__FILE__), *%w".. lib sprockets")
2
2
  require "test/unit"
3
+ require "fileutils"
4
+ require "tmpdir"
3
5
 
4
6
  class Test::Unit::TestCase
5
7
  FIXTURES_PATH = File.expand_path(File.join(File.dirname(__FILE__), "fixtures")) unless defined?(FIXTURES_PATH)
@@ -40,4 +42,14 @@ class Test::Unit::TestCase
40
42
  def source_line(line, source_file = nil, line_number = 1)
41
43
  Sprockets::SourceLine.new(source_file || source_file("dummy"), line, line_number)
42
44
  end
45
+
46
+ def with_temporary_directory
47
+ path = File.join(Dir.tmpdir, [caller[0][/`(.*)'/, 1], Time.now.to_f].join("_"))
48
+ begin
49
+ FileUtils.mkdir(path)
50
+ yield path
51
+ ensure
52
+ FileUtils.rm_rf(path)
53
+ end
54
+ end
43
55
  end
@@ -31,4 +31,53 @@ class SecretaryTest < Test::Unit::TestCase
31
31
  assert_equal [File.join(FIXTURES_PATH, "src", "foo.js")],
32
32
  secretary.preprocessor.source_files.map { |source_file| source_file.pathname.absolute_location }
33
33
  end
34
+
35
+ def test_install_assets_into_empty_directory
36
+ with_temporary_directory do |temp|
37
+ secretary = Sprockets::Secretary.new(:root => FIXTURES_PATH, :asset_root => temp)
38
+ secretary.add_source_files("src/script_with_assets.js")
39
+
40
+ assert_equal [], Dir[File.join(temp, "**", "*")]
41
+ secretary.install_assets
42
+ assert_equal paths_relative_to(temp,
43
+ "images", "images/script_with_assets", "images/script_with_assets/one.png",
44
+ "images/script_with_assets/two.png", "stylesheets", "stylesheets/script_with_assets.css"),
45
+ Dir[File.join(temp, "**", "*")]
46
+ end
47
+ end
48
+
49
+ def test_install_assets_into_nonexistent_directory
50
+ with_temporary_directory do |temp|
51
+ temp = File.join(temp, "assets")
52
+ secretary = Sprockets::Secretary.new(:root => FIXTURES_PATH, :asset_root => temp)
53
+ secretary.add_source_files("src/script_with_assets.js")
54
+
55
+ assert_equal [], Dir[File.join(temp, "**", "*")]
56
+ secretary.install_assets
57
+ assert_equal paths_relative_to(temp,
58
+ "images", "images/script_with_assets", "images/script_with_assets/one.png",
59
+ "images/script_with_assets/two.png", "stylesheets", "stylesheets/script_with_assets.css"),
60
+ Dir[File.join(temp, "**", "*")]
61
+ end
62
+ end
63
+
64
+ def test_install_assets_into_subdirectories_that_already_exist
65
+ with_temporary_directory do |temp|
66
+ secretary = Sprockets::Secretary.new(:root => FIXTURES_PATH, :asset_root => temp)
67
+ secretary.add_source_files("src/script_with_assets.js")
68
+
69
+ FileUtils.mkdir_p(File.join(temp, "images", "script_with_assets"))
70
+ assert_equal paths_relative_to(temp, "images", "images/script_with_assets"), Dir[File.join(temp, "**", "*")]
71
+ secretary.install_assets
72
+ assert_equal paths_relative_to(temp,
73
+ "images", "images/script_with_assets", "images/script_with_assets/one.png",
74
+ "images/script_with_assets/two.png", "stylesheets", "stylesheets/script_with_assets.css"),
75
+ Dir[File.join(temp, "**", "*")]
76
+ end
77
+ end
78
+
79
+ protected
80
+ def paths_relative_to(root, *paths)
81
+ paths.map { |path| File.join(root, path) }
82
+ end
34
83
  end
@@ -45,6 +45,17 @@ class SourceLineTest < Test::Unit::TestCase
45
45
  assert_equal "\"foo\"", source_line("//= require \"foo\"").require
46
46
  end
47
47
 
48
+ def test_line_that_contains_a_provide_comment_should_be_a_provide
49
+ assert source_line("//= provide \"../assets\"").provide?
50
+ assert !source_line("//= provide").provide?
51
+ assert !source_line("//= provide <../assets>").provide?
52
+ end
53
+
54
+ def test_provide_should_be_extracted_from_provide_lines
55
+ assert_nil source_line("//= provide").provide
56
+ assert_equal "../assets", source_line("//= provide \"../assets\"").provide
57
+ end
58
+
48
59
  def test_inspect_should_include_source_file_location_and_line_number
49
60
  environment = environment_for_fixtures
50
61
  pathname = Sprockets::Pathname.new(environment, "/a/b/c.js")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sstephenson-sprockets
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Stephenson
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-29 00:00:00 -08:00
12
+ date: 2009-01-30 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -47,8 +47,16 @@ files:
47
47
  - test/fixtures/src/foo/foo.js
48
48
  - test/fixtures/src/foo.js
49
49
  - test/fixtures/src/constants.yml
50
+ - test/fixtures/src/script_with_assets.js
50
51
  - test/fixtures/multiline_comments_should_be_removed_by_default.js
51
52
  - test/fixtures/requiring_a_single_file_should_replace_the_require_comment_with_the_file_contents.js
53
+ - test/fixtures/assets
54
+ - test/fixtures/assets/stylesheets
55
+ - test/fixtures/assets/stylesheets/script_with_assets.css
56
+ - test/fixtures/assets/images
57
+ - test/fixtures/assets/images/script_with_assets
58
+ - test/fixtures/assets/images/script_with_assets/two.png
59
+ - test/fixtures/assets/images/script_with_assets/one.png
52
60
  - test/fixtures/double_slash_comments_that_are_not_requires_should_be_removed_by_default.js
53
61
  - test/fixtures/constants.yml
54
62
  - test/fixtures/requiring_a_file_that_does_not_exist_should_raise_an_error.js