ninjs 0.16.3 → 0.16.4

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 (45) hide show
  1. data/VERSION +1 -1
  2. data/lib/sprockets/.gitignore +4 -0
  3. data/lib/sprockets/CHANGELOG +22 -0
  4. data/lib/sprockets/LICENSE +20 -0
  5. data/lib/sprockets/README.markdown +230 -0
  6. data/lib/sprockets/bin/sprocketize +54 -0
  7. data/lib/sprockets/ext/nph-sprockets.cgi +127 -0
  8. data/lib/sprockets/lib/sprockets.rb +42 -0
  9. data/lib/sprockets/lib/sprockets/concatenation.rb +36 -0
  10. data/lib/sprockets/lib/sprockets/environment.rb +52 -0
  11. data/lib/sprockets/lib/sprockets/error.rb +5 -0
  12. data/lib/sprockets/lib/sprockets/pathname.rb +37 -0
  13. data/lib/sprockets/lib/sprockets/preprocessor.rb +96 -0
  14. data/lib/sprockets/lib/sprockets/secretary.rb +110 -0
  15. data/lib/sprockets/lib/sprockets/source_file.rb +56 -0
  16. data/lib/sprockets/lib/sprockets/source_line.rb +85 -0
  17. data/lib/sprockets/lib/sprockets/version.rb +9 -0
  18. data/lib/sprockets/sprockets.gemspec +15 -0
  19. data/lib/sprockets/test/fixtures/assets/images/script_with_assets/one.png +1 -0
  20. data/lib/sprockets/test/fixtures/assets/images/script_with_assets/two.png +1 -0
  21. data/lib/sprockets/test/fixtures/assets/stylesheets/script_with_assets.css +1 -0
  22. data/lib/sprockets/test/fixtures/constants.yml +1 -0
  23. data/lib/sprockets/test/fixtures/double_slash_comments_that_are_not_requires_should_be_ignored_when_strip_comments_is_false.js +8 -0
  24. data/lib/sprockets/test/fixtures/double_slash_comments_that_are_not_requires_should_be_removed_by_default.js +2 -0
  25. data/lib/sprockets/test/fixtures/multiline_comments_should_be_removed_by_default.js +4 -0
  26. data/lib/sprockets/test/fixtures/requiring_a_file_after_it_has_already_been_required_should_do_nothing.js +5 -0
  27. data/lib/sprockets/test/fixtures/requiring_a_file_that_does_not_exist_should_raise_an_error.js +1 -0
  28. data/lib/sprockets/test/fixtures/requiring_a_single_file_should_replace_the_require_comment_with_the_file_contents.js +3 -0
  29. data/lib/sprockets/test/fixtures/requiring_the_current_file_should_do_nothing.js +1 -0
  30. data/lib/sprockets/test/fixtures/src/constants.yml +3 -0
  31. data/lib/sprockets/test/fixtures/src/foo.js +1 -0
  32. data/lib/sprockets/test/fixtures/src/foo/bar.js +4 -0
  33. data/lib/sprockets/test/fixtures/src/foo/foo.js +1 -0
  34. data/lib/sprockets/test/fixtures/src/script_with_assets.js +3 -0
  35. data/lib/sprockets/test/fixtures/src/script_with_comments.js +13 -0
  36. data/lib/sprockets/test/test_concatenation.rb +28 -0
  37. data/lib/sprockets/test/test_environment.rb +64 -0
  38. data/lib/sprockets/test/test_helper.rb +55 -0
  39. data/lib/sprockets/test/test_pathname.rb +43 -0
  40. data/lib/sprockets/test/test_preprocessor.rb +107 -0
  41. data/lib/sprockets/test/test_secretary.rb +89 -0
  42. data/lib/sprockets/test/test_source_file.rb +34 -0
  43. data/lib/sprockets/test/test_source_line.rb +89 -0
  44. data/ninjs.gemspec +55 -13
  45. metadata +46 -4
@@ -0,0 +1,42 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require "yaml"
4
+ require "fileutils"
5
+
6
+ module Sprockets
7
+ class << self
8
+ def running_on_windows?
9
+ RUBY_PLATFORM =~ /(win|w)32$/
10
+ end
11
+
12
+ def absolute?(location)
13
+ same_when_expanded?(location) || platform_absolute_path?(location)
14
+ end
15
+
16
+ protected
17
+ def same_when_expanded?(location)
18
+ location[0, 1] == File.expand_path(location)[0, 1]
19
+ end
20
+
21
+ def platform_absolute_path?(location)
22
+ false
23
+ end
24
+
25
+ if Sprockets.running_on_windows?
26
+ def platform_absolute_path?(location)
27
+ location[0, 1] == File::SEPARATOR && File.expand_path(location) =~ /[A-Za-z]:[\/\\]/
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ require "sprockets/version"
34
+ require "sprockets/error"
35
+ require "sprockets/environment"
36
+ require "sprockets/pathname"
37
+ require "sprockets/source_line"
38
+ require "sprockets/source_file"
39
+ require "sprockets/concatenation"
40
+ require "sprockets/preprocessor"
41
+ require "sprockets/secretary"
42
+
@@ -0,0 +1,36 @@
1
+ module Sprockets
2
+ class Concatenation
3
+ attr_reader :source_lines
4
+
5
+ def initialize
6
+ @source_lines = []
7
+ @source_file_mtimes = {}
8
+ end
9
+
10
+ def record(source_line)
11
+ source_lines << source_line
12
+ record_mtime_for(source_line.source_file)
13
+ source_line
14
+ end
15
+
16
+ def to_s
17
+ source_lines.join
18
+ end
19
+
20
+ def mtime
21
+ @source_file_mtimes.values.max
22
+ end
23
+
24
+ def save_to(filename)
25
+ timestamp = mtime
26
+ File.open(filename, "w") { |file| file.write(to_s) }
27
+ File.utime(timestamp, timestamp, filename)
28
+ true
29
+ end
30
+
31
+ protected
32
+ def record_mtime_for(source_file)
33
+ @source_file_mtimes[source_file] ||= source_file.mtime
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,52 @@
1
+ module Sprockets
2
+ class Environment
3
+ attr_reader :root, :load_path
4
+
5
+ def initialize(root, load_path = [])
6
+ @load_path = [@root = Pathname.new(self, root)]
7
+
8
+ load_path.reverse_each do |location|
9
+ register_load_location(location)
10
+ end
11
+ end
12
+
13
+ def pathname_from(location)
14
+ Pathname.new(self, absolute_location_from(location))
15
+ end
16
+
17
+ def register_load_location(location)
18
+ pathname = pathname_from(location)
19
+ load_path.delete(pathname)
20
+ load_path.unshift(pathname)
21
+ location
22
+ end
23
+
24
+ def find(location)
25
+ if Sprockets.absolute?(location) && File.exists?(location)
26
+ pathname_from(location)
27
+ else
28
+ find_all(location).first
29
+ end
30
+ end
31
+
32
+ def constants(reload = false)
33
+ @constants = nil if reload
34
+ @constants ||= find_all("constants.yml").inject({}) do |constants, pathname|
35
+ contents = YAML.load(pathname.contents) rescue nil
36
+ contents = {} unless contents.is_a?(Hash)
37
+ constants.merge(contents)
38
+ end
39
+ end
40
+
41
+ protected
42
+ def absolute_location_from(location)
43
+ location = location.to_s
44
+ location = File.join(root.absolute_location, location) unless Sprockets.absolute?(location)
45
+ File.expand_path(location)
46
+ end
47
+
48
+ def find_all(location)
49
+ load_path.map { |pathname| pathname.find(location) }.compact
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,5 @@
1
+ module Sprockets
2
+ class Error < ::StandardError; end
3
+ class LoadError < Error; end
4
+ class UndefinedConstantError < Error; end
5
+ end
@@ -0,0 +1,37 @@
1
+ module Sprockets
2
+ class Pathname
3
+ attr_reader :environment, :absolute_location
4
+
5
+ def initialize(environment, absolute_location)
6
+ @environment = environment
7
+ @absolute_location = File.expand_path(absolute_location)
8
+ end
9
+
10
+ # Returns a Pathname for the location relative to this pathname's absolute location.
11
+ def find(location, kind = :file)
12
+ location = File.join(absolute_location, location)
13
+ File.send("#{kind}?", location) ? Pathname.new(environment, location) : nil
14
+ end
15
+
16
+ def parent_pathname
17
+ Pathname.new(environment, File.dirname(absolute_location))
18
+ end
19
+
20
+ def source_file
21
+ SourceFile.new(environment, self)
22
+ end
23
+
24
+ def contents
25
+ IO.read(absolute_location)
26
+ end
27
+
28
+ def ==(pathname)
29
+ environment == pathname.environment &&
30
+ absolute_location == pathname.absolute_location
31
+ end
32
+
33
+ def to_s
34
+ absolute_location
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,96 @@
1
+ module Sprockets
2
+ class Preprocessor
3
+ attr_reader :environment, :concatenation, :source_files, :asset_paths
4
+
5
+ def initialize(environment, options = {})
6
+ @environment = environment
7
+ @concatenation = Concatenation.new
8
+ @source_files = []
9
+ @asset_paths = []
10
+ @options = options
11
+ end
12
+
13
+ def require(source_file)
14
+ return if source_files.include?(source_file)
15
+ source_files << source_file
16
+ source_file.interpolate_constants = interpolate_constants?
17
+
18
+ source_file.each_source_line do |source_line|
19
+ if source_line.require?
20
+ require_from_source_line(source_line)
21
+ elsif source_line.provide?
22
+ provide_from_source_line(source_line)
23
+ else
24
+ record_source_line(source_line)
25
+ end
26
+ end
27
+ end
28
+
29
+ def provide(asset_path)
30
+ return if !asset_path || asset_paths.include?(asset_path)
31
+ asset_paths << asset_path
32
+ end
33
+
34
+ protected
35
+ attr_reader :options
36
+
37
+ def require_from_source_line(source_line)
38
+ require pathname_from(source_line).source_file
39
+ end
40
+
41
+ def provide_from_source_line(source_line)
42
+ provide asset_path_from(source_line)
43
+ end
44
+
45
+ def record_source_line(source_line)
46
+ unless source_line.comment? && strip_comments?
47
+ concatenation.record(source_line)
48
+ end
49
+ end
50
+
51
+ def strip_comments?
52
+ options[:strip_comments] != false
53
+ end
54
+
55
+ def interpolate_constants?
56
+ options[:interpolate_constants] != false
57
+ end
58
+
59
+ def pathname_from(source_line)
60
+ pathname = send(pathname_finder_from(source_line), source_line)
61
+ raise_load_error_for(source_line) unless pathname
62
+ pathname
63
+ end
64
+
65
+ def pathname_for_require_from(source_line)
66
+ environment.find(location_from(source_line))
67
+ end
68
+
69
+ def pathname_for_relative_require_from(source_line)
70
+ source_line.source_file.find(location_from(source_line))
71
+ end
72
+
73
+ def pathname_finder_from(source_line)
74
+ "pathname_for_#{kind_of_require_from(source_line)}_from"
75
+ end
76
+
77
+ def kind_of_require_from(source_line)
78
+ source_line.require[/^(.)/, 1] == '"' ? :relative_require : :require
79
+ end
80
+
81
+ def location_from(source_line)
82
+ location = source_line.require[/^.(.*).$/, 1]
83
+ File.join(File.dirname(location), File.basename(location, ".js") + ".js")
84
+ end
85
+
86
+ def asset_path_from(source_line)
87
+ source_line.source_file.find(source_line.provide, :directory)
88
+ end
89
+
90
+ def raise_load_error_for(source_line)
91
+ kind = kind_of_require_from(source_line).to_s.tr("_", " ")
92
+ file = File.split(location_from(source_line)).last
93
+ raise LoadError, "can't find file for #{kind} `#{file}' (#{source_line.inspect})"
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,110 @@
1
+ module Sprockets
2
+ class Secretary
3
+ DEFAULT_OPTIONS = {
4
+ :root => ".",
5
+ :load_path => [],
6
+ :source_files => [],
7
+ :expand_paths => true,
8
+ :strip_comments => true,
9
+ :interpolate_constants => true
10
+ }
11
+
12
+ attr_reader :environment, :preprocessor
13
+
14
+ def initialize(options = {})
15
+ reset!(options)
16
+ end
17
+
18
+ def reset!(options = @options)
19
+ @options = DEFAULT_OPTIONS.merge(options)
20
+ @environment = Sprockets::Environment.new(@options[:root])
21
+ @preprocessor = Sprockets::Preprocessor.new(@environment,
22
+ :strip_comments => @options[:strip_comments],
23
+ :interpolate_constants => @options[:interpolate_constants])
24
+
25
+ add_load_locations(@options[:load_path])
26
+ add_source_files(@options[:source_files])
27
+ end
28
+
29
+ def add_load_location(load_location, options = {})
30
+ add_load_locations([load_location], options)
31
+ end
32
+
33
+ def add_load_locations(load_locations, options = {})
34
+ expand_paths(load_locations, options).each do |load_location|
35
+ environment.register_load_location(load_location)
36
+ end
37
+ end
38
+
39
+ def add_source_file(source_file, options = {})
40
+ add_source_files([source_file], options)
41
+ end
42
+
43
+ def add_source_files(source_files, options = {})
44
+ expand_paths(source_files, options).each do |source_file|
45
+ if pathname = environment.find(source_file)
46
+ preprocessor.require(pathname.source_file)
47
+ else
48
+ raise Sprockets::LoadError, "no such file `#{source_file}'"
49
+ end
50
+ end
51
+ end
52
+
53
+ def concatenation
54
+ preprocessor.concatenation
55
+ end
56
+
57
+ def install_assets
58
+ if @options[:asset_root]
59
+ preprocessor.asset_paths.each do |asset_path|
60
+ copy_assets_from(asset_path.absolute_location)
61
+ end
62
+ end
63
+ end
64
+
65
+ def source_last_modified
66
+ preprocessor.source_files.map { |s| s.mtime }.max
67
+ end
68
+
69
+ protected
70
+ def expand_paths(paths, options = {})
71
+ if options.has_key?(:expand_paths) ? options[:expand_paths] : @options[:expand_paths]
72
+ paths.map { |path| Dir[from_root(path)].sort }.flatten.compact
73
+ else
74
+ paths.map { |path| from_root(path) }
75
+ end
76
+ end
77
+
78
+ def from_root(path)
79
+ if Sprockets.absolute?(path)
80
+ path
81
+ else
82
+ File.join(@options[:root], path)
83
+ end
84
+ end
85
+
86
+ def copy_assets_from(asset_path)
87
+ relative_file_paths_beneath(asset_path).each do |filename|
88
+ source, destination = File.join(asset_path, filename), File.join(asset_root, File.dirname(filename))
89
+ if !File.directory?(source)
90
+ FileUtils.mkdir_p(destination)
91
+ FileUtils.cp(source, destination)
92
+ end
93
+ end
94
+ end
95
+
96
+ def relative_file_paths_beneath(path)
97
+ Dir[File.join(path, "**", "*")].map do |filename|
98
+ File.join(*path_pieces(filename)[path_pieces(path).length..-1])
99
+ end
100
+ end
101
+
102
+ def asset_root
103
+ from_root(@options[:asset_root])
104
+ end
105
+
106
+ def path_pieces(path)
107
+ path.split(File::SEPARATOR)
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,56 @@
1
+ module Sprockets
2
+ class SourceFile
3
+ attr_reader :environment, :pathname
4
+ attr_accessor :interpolate_constants
5
+
6
+ def initialize(environment, pathname)
7
+ @environment = environment
8
+ @pathname = pathname
9
+ @interpolate_constants = true
10
+ end
11
+
12
+ def source_lines
13
+ @lines ||= begin
14
+ lines = []
15
+
16
+ comments = []
17
+ File.open(pathname.absolute_location) do |file|
18
+ file.each do |line|
19
+ lines << line = SourceLine.new(self, line, file.lineno)
20
+
21
+ if line.begins_pdoc_comment? || comments.any?
22
+ comments << line
23
+ end
24
+
25
+ if line.ends_multiline_comment?
26
+ if line.ends_pdoc_comment?
27
+ comments.each { |l| l.comment! }
28
+ end
29
+ comments.clear
30
+ end
31
+ end
32
+ end
33
+
34
+ lines
35
+ end
36
+ end
37
+
38
+ def each_source_line(&block)
39
+ source_lines.each(&block)
40
+ end
41
+
42
+ def find(location, kind = :file)
43
+ pathname.parent_pathname.find(location, kind)
44
+ end
45
+
46
+ def ==(source_file)
47
+ pathname == source_file.pathname
48
+ end
49
+
50
+ def mtime
51
+ File.mtime(pathname.absolute_location)
52
+ rescue Errno::ENOENT
53
+ Time.now
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,85 @@
1
+ module Sprockets
2
+ class SourceLine
3
+ attr_reader :source_file, :line, :number
4
+
5
+ def initialize(source_file, line, number)
6
+ @source_file = source_file
7
+ @line = line
8
+ @number = number
9
+ end
10
+
11
+ def comment
12
+ @comment ||= line[/^\s*\/\/(.*)/, 1]
13
+ end
14
+
15
+ def comment?
16
+ !!comment
17
+ end
18
+
19
+ def comment!
20
+ @comment = line
21
+ end
22
+
23
+ def begins_multiline_comment?
24
+ line =~ /^\s*\/\*(.*)/
25
+ end
26
+
27
+ def begins_pdoc_comment?
28
+ line =~ /^\s*\/\*\*(.*)/
29
+ end
30
+
31
+ def ends_multiline_comment?
32
+ line =~ /^(.*)\*\/\s*/
33
+ end
34
+
35
+ def ends_pdoc_comment?
36
+ line =~ /^(.*)\*\*\/\s*/
37
+ end
38
+
39
+ def require
40
+ @require ||= (comment || "")[/^=\s+require\s+(\"(.*?)\"|<(.*?)>)\s*$/, 1]
41
+ end
42
+
43
+ def require?
44
+ !!require
45
+ end
46
+
47
+ def provide
48
+ @provide ||= (comment || "")[/^=\s+provide\s+\"(.*?)\"\s*$/, 1]
49
+ end
50
+
51
+ def provide?
52
+ !!provide
53
+ end
54
+
55
+ def inspect
56
+ "line #@number of #{@source_file.pathname}"
57
+ end
58
+
59
+ def to_s(constants = source_file.environment.constants)
60
+ result = line.chomp
61
+ interpolate_constants!(result, constants) if interpolate_constants?
62
+ strip_trailing_whitespace!(result)
63
+ result + $/
64
+ end
65
+
66
+ protected
67
+ def interpolate_constants?
68
+ source_file.interpolate_constants != false
69
+ end
70
+ def interpolate_constants!(result, constants)
71
+ result.gsub!(/<%=(.*?)%>/) do
72
+ constant = $1.strip
73
+ if value = constants[constant]
74
+ value
75
+ else
76
+ raise UndefinedConstantError, "couldn't find constant `#{constant}' in #{inspect}"
77
+ end
78
+ end
79
+ end
80
+
81
+ def strip_trailing_whitespace!(result)
82
+ result.gsub!(/\s+$/, "")
83
+ end
84
+ end
85
+ end