ninjs 0.16.3 → 0.16.4

Sign up to get free protection for your applications and to get access to all the features.
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