jsus 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,4 +1,14 @@
1
- = JsBundler Changelog
1
+ = Jsus Changelog
2
+
3
+ == Version 0.1.2
4
+ * Removed Bundler class which seemed like totally unneccessary
5
+ * jsus command-line utility now works in single-project mode
6
+ * Some major refactoring, introduced new concepts: Pool, Packager and Container
7
+ * Inserted license text to LICENSE, updated TODO
8
+
9
+ == Version 0.1.1 (not released)
10
+ * Massive refactoring
11
+ * Moved out packing logic to brand new Packager and Container classes
2
12
 
3
13
  == Version 0.1.0
4
14
  * Initial release
data/LICENSE CHANGED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010, Mark Abramov (Markiz)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/Manifest CHANGED
@@ -7,9 +7,12 @@ TODO
7
7
  bin/jsus
8
8
  jsus.gemspec
9
9
  lib/jsus.rb
10
- lib/jsus/bundler.rb
10
+ lib/jsus/container.rb
11
11
  lib/jsus/package.rb
12
+ lib/jsus/packager.rb
13
+ lib/jsus/pool.rb
12
14
  lib/jsus/source_file.rb
15
+ lib/jsus/topsortable.rb
13
16
  spec/data/Basic/README
14
17
  spec/data/Basic/app/javascripts/Orwik/Source/Library/Color.js
15
18
  spec/data/Basic/app/javascripts/Orwik/Source/Widget/Input/Input.Color.js
@@ -29,8 +32,12 @@ spec/data/OutsideDependencies/app/javascripts/Orwik/package.yml
29
32
  spec/data/bad_test_source_one.js
30
33
  spec/data/bad_test_source_two.js
31
34
  spec/data/test_source_one.js
32
- spec/lib/jsus/bundler_spec.rb
35
+ spec/lib/jsus/container_spec.rb
33
36
  spec/lib/jsus/package_spec.rb
37
+ spec/lib/jsus/packager_spec.rb
38
+ spec/lib/jsus/pool_spec.rb
34
39
  spec/lib/jsus/source_file_spec.rb
40
+ spec/lib/jsus/topsortable_spec.rb
41
+ spec/shared/class_stubs.rb
35
42
  spec/spec.opts
36
43
  spec/spec_helper.rb
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
3
  require 'echoe'
4
- Echoe.new('jsus', '0.1.0') do |g|
4
+ Echoe.new('jsus', '0.1.2') do |g|
5
5
  g.description = "Packager/compiler for js-files that resolves dependencies and can compile everything into one file, providing all the neccessary meta-info."
6
6
  g.url = "http://github.com/markiz/jsus"
7
7
  g.author = "Markiz, idea by Inviz (http://github.com/Inviz)"
data/TODO CHANGED
@@ -0,0 +1,5 @@
1
+ * External dependencies mechanism
2
+ * Disallow circular dependencies
3
+ * Package extensions (e.g. package Core.ext that would be able to extend package Core)
4
+ * Rails integration
5
+ * Documentation, RDocs
data/bin/jsus CHANGED
@@ -3,8 +3,11 @@ require 'rubygems'
3
3
  require 'jsus'
4
4
 
5
5
  unless ARGV.length == 2
6
- puts "SYNOPSYS: jsus <input_directory_with_packages> <output_directory_for_packages>"
6
+ puts "SYNOPSYS: jsus <input_directory_with_package> <output_directory_for_package>"
7
7
  exit
8
8
  else
9
- Jsus::Bundler.new(ARGV[0]).compile(ARGV[1])
9
+ package = Jsus::Package.new(ARGV[0])
10
+ package.compile(ARGV[1])
11
+ package.generate_scripts_info(ARGV[1])
12
+ package.generate_tree(ARGV[1])
10
13
  end
@@ -2,17 +2,17 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{jsus}
5
- s.version = "0.1.0"
5
+ s.version = "0.1.2"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Markiz, idea by Inviz (http://github.com/Inviz)"]
9
- s.date = %q{2010-06-03}
9
+ s.date = %q{2010-06-04}
10
10
  s.default_executable = %q{jsus}
11
11
  s.description = %q{Packager/compiler for js-files that resolves dependencies and can compile everything into one file, providing all the neccessary meta-info.}
12
12
  s.email = %q{markizko@gmail.com}
13
13
  s.executables = ["jsus"]
14
- s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "TODO", "bin/jsus", "lib/jsus.rb", "lib/jsus/bundler.rb", "lib/jsus/package.rb", "lib/jsus/source_file.rb"]
15
- s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "TODO", "bin/jsus", "lib/jsus.rb", "lib/jsus/bundler.rb", "lib/jsus/package.rb", "lib/jsus/source_file.rb", "spec/data/Basic/README", "spec/data/Basic/app/javascripts/Orwik/Source/Library/Color.js", "spec/data/Basic/app/javascripts/Orwik/Source/Widget/Input/Input.Color.js", "spec/data/Basic/app/javascripts/Orwik/Source/Widget/Input/Input.js", "spec/data/Basic/app/javascripts/Orwik/Source/Widget/Widget.js", "spec/data/Basic/app/javascripts/Orwik/package.yml", "spec/data/OutsideDependencies/README", "spec/data/OutsideDependencies/app/javascripts/Core/Source/Class/Class.Extras.js", "spec/data/OutsideDependencies/app/javascripts/Core/Source/Class/Class.js", "spec/data/OutsideDependencies/app/javascripts/Core/Source/Native/Hash.js", "spec/data/OutsideDependencies/app/javascripts/Core/package.yml", "spec/data/OutsideDependencies/app/javascripts/Orwik/Source/Library/Color.js", "spec/data/OutsideDependencies/app/javascripts/Orwik/Source/Widget/Input/Input.Color.js", "spec/data/OutsideDependencies/app/javascripts/Orwik/Source/Widget/Input/Input.js", "spec/data/OutsideDependencies/app/javascripts/Orwik/Source/Widget/Widget.js", "spec/data/OutsideDependencies/app/javascripts/Orwik/package.yml", "spec/data/bad_test_source_one.js", "spec/data/bad_test_source_two.js", "spec/data/test_source_one.js", "spec/lib/jsus/bundler_spec.rb", "spec/lib/jsus/package_spec.rb", "spec/lib/jsus/source_file_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "jsus.gemspec"]
14
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "TODO", "bin/jsus", "lib/jsus.rb", "lib/jsus/container.rb", "lib/jsus/package.rb", "lib/jsus/packager.rb", "lib/jsus/pool.rb", "lib/jsus/source_file.rb", "lib/jsus/topsortable.rb"]
15
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "TODO", "bin/jsus", "jsus.gemspec", "lib/jsus.rb", "lib/jsus/container.rb", "lib/jsus/package.rb", "lib/jsus/packager.rb", "lib/jsus/pool.rb", "lib/jsus/source_file.rb", "lib/jsus/topsortable.rb", "spec/data/Basic/README", "spec/data/Basic/app/javascripts/Orwik/Source/Library/Color.js", "spec/data/Basic/app/javascripts/Orwik/Source/Widget/Input/Input.Color.js", "spec/data/Basic/app/javascripts/Orwik/Source/Widget/Input/Input.js", "spec/data/Basic/app/javascripts/Orwik/Source/Widget/Widget.js", "spec/data/Basic/app/javascripts/Orwik/package.yml", "spec/data/OutsideDependencies/README", "spec/data/OutsideDependencies/app/javascripts/Core/Source/Class/Class.Extras.js", "spec/data/OutsideDependencies/app/javascripts/Core/Source/Class/Class.js", "spec/data/OutsideDependencies/app/javascripts/Core/Source/Native/Hash.js", "spec/data/OutsideDependencies/app/javascripts/Core/package.yml", "spec/data/OutsideDependencies/app/javascripts/Orwik/Source/Library/Color.js", "spec/data/OutsideDependencies/app/javascripts/Orwik/Source/Widget/Input/Input.Color.js", "spec/data/OutsideDependencies/app/javascripts/Orwik/Source/Widget/Input/Input.js", "spec/data/OutsideDependencies/app/javascripts/Orwik/Source/Widget/Widget.js", "spec/data/OutsideDependencies/app/javascripts/Orwik/package.yml", "spec/data/bad_test_source_one.js", "spec/data/bad_test_source_two.js", "spec/data/test_source_one.js", "spec/lib/jsus/container_spec.rb", "spec/lib/jsus/package_spec.rb", "spec/lib/jsus/packager_spec.rb", "spec/lib/jsus/pool_spec.rb", "spec/lib/jsus/source_file_spec.rb", "spec/lib/jsus/topsortable_spec.rb", "spec/shared/class_stubs.rb", "spec/spec.opts", "spec/spec_helper.rb"]
16
16
  s.homepage = %q{http://github.com/markiz/jsus}
17
17
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Jsus", "--main", "README"]
18
18
  s.require_paths = ["lib"]
@@ -3,12 +3,16 @@ require 'pathname'
3
3
  require 'rubygems'
4
4
  require 'json'
5
5
  require 'active_support/ordered_hash'
6
+ require 'active_support/core_ext/module/delegation'
6
7
  require 'rgl/adjacency'
7
8
  require 'rgl/topsort'
8
9
 
10
+ require 'jsus/topsortable'
9
11
  require 'jsus/source_file'
12
+ require 'jsus/container'
13
+ require 'jsus/packager'
14
+ require 'jsus/pool'
10
15
  require 'jsus/package'
11
- require 'jsus/bundler'
12
16
 
13
17
  module Jsus
14
18
  # Shortcut for Bundler.new
@@ -16,28 +20,4 @@ module Jsus
16
20
  Bundler.new(*args, &block)
17
21
  end
18
22
 
19
- # Topological sort for packages and source files
20
- def self.topsort(items)
21
- graph = RGL::DirectedAdjacencyGraph.new
22
- provides_hash = {}
23
- # init vertices
24
- items.each do |item|
25
- graph.add_vertex(item)
26
- item.provides.each do |provides|
27
- provides_hash[provides] = item
28
- end
29
- end
30
- # init edges
31
- items.each do |item|
32
- item.dependencies.each do |dependency|
33
- if required_item = provides_hash[dependency]
34
- graph.add_edge(required_item, item)
35
- end
36
- end
37
- end
38
- result = []
39
- graph.topsort_iterator.each { |item| result << item }
40
- result
41
- end
42
-
43
23
  end
@@ -0,0 +1,42 @@
1
+ module Jsus
2
+ class Container
3
+ include Topsortable
4
+
5
+ def initialize(*sources)
6
+ sources.each do |source|
7
+ self << source
8
+ end
9
+ end
10
+
11
+ def <<(source)
12
+ if source
13
+ if source.kind_of?(Array) || source.kind_of?(Container)
14
+ source.each {|s| self << s }
15
+ else
16
+ sources << source
17
+ sort!
18
+ end
19
+ end
20
+ self
21
+ end
22
+
23
+ def sources
24
+ @sources ||= []
25
+ end
26
+
27
+ def sources=(new_value)
28
+ @sources = new_value
29
+ end
30
+
31
+ def sort!
32
+ self.sources = topsort(:sources)
33
+ end
34
+
35
+ def inspect
36
+ "#<#{self.class.name}:#{self.object_id} #{self.sources.inspect}>"
37
+ end
38
+
39
+ # delegate undefined methods to #sources
40
+ (Array.instance_methods - self.instance_methods).each {|m| delegate m, :to => :sources }
41
+ end
42
+ end
@@ -1,28 +1,31 @@
1
1
  module Jsus
2
2
  class Package
3
+ attr_accessor :relative_directory
4
+ attr_accessor :directory
5
+ attr_accessor :pool
3
6
  # Constructors
4
- def initialize(directory)
5
- self.relative_directory = Pathname.new(directory).relative_path_from(Pathname.new(".")).to_s
7
+ def initialize(directory, options = {})
8
+ self.relative_directory = directory #Pathname.new(directory).relative_path_from(Pathname.new(".")).to_s
6
9
  self.directory = File.expand_path(directory)
7
10
  self.header = YAML.load_file(File.join(directory, 'package.yml'))
11
+ self.pool = options[:pool]
8
12
  Dir.chdir(directory) do
9
13
  files.each do |source|
10
- source_files << SourceFile.from_file(source)
14
+ source_files << SourceFile.from_file(source, :package => self)
11
15
  end
12
16
  end
13
- calculate_requirement_order
14
17
  end
15
18
 
16
19
 
17
20
  # Public API
18
- attr_accessor :relative_directory
19
- attr_accessor :directory
20
-
21
- attr_writer :header
22
21
  def header
23
22
  @header ||= {}
24
23
  end
25
24
 
25
+ def header=(new_header)
26
+ @header = new_header
27
+ end
28
+
26
29
  def name
27
30
  header["name"] ||= ""
28
31
  end
@@ -40,7 +43,7 @@ module Jsus
40
43
  end
41
44
 
42
45
  def files
43
- header["files"] = header["sources"] || header["files"] || []
46
+ header["files"] = header["files"] || header["sources"] || []
44
47
  end
45
48
 
46
49
  alias_method :sources, :files
@@ -55,20 +58,10 @@ module Jsus
55
58
 
56
59
  def description
57
60
  header["description"] ||= ""
58
- end
59
-
60
- attr_accessor :required_files
61
+ end
61
62
 
62
63
  def compile(directory = ".")
63
- FileUtils.mkdir_p directory
64
- Dir.chdir(directory) do
65
- File.open(filename, "w") do |resulting_file|
66
- required_files.each do |required_file|
67
- resulting_file.puts(IO.read(required_file))
68
- end
69
- end
70
- generate_scripts_info(".")
71
- end
64
+ Packager.new(*source_files).pack(File.join(directory, filename))
72
65
  end
73
66
 
74
67
  def generate_tree(directory = ".", filename = "tree.json")
@@ -76,47 +69,45 @@ module Jsus
76
69
  result = ActiveSupport::OrderedHash.new
77
70
  source_files.each do |source|
78
71
  components = File.dirname(source.relative_filename).split(File::SEPARATOR)
72
+ # deleting source dir by convention
79
73
  components.delete("Source")
80
- components << File.basename(source.filename, ".js")
81
74
  node = result
82
75
  components.each do |component|
83
76
  node[component] ||= ActiveSupport::OrderedHash.new
84
77
  node = node[component]
85
78
  end
86
- node["desc"] = source.description
87
- node["requires"] = source.dependencies
88
- node["provides"] = source.provides
89
- end
90
- Dir.chdir(directory) do
91
- File.open(filename, "w") { |resulting_file| resulting_file << JSON.pretty_generate(result) }
79
+ node[File.basename(source.filename, ".js")] = source.to_hash
92
80
  end
81
+ File.open(File.join(directory, filename), "w") { |resulting_file| resulting_file << JSON.pretty_generate(result) }
82
+ result
93
83
  end
94
84
 
95
85
  def generate_scripts_info(directory = ".", filename = "scripts.json")
96
- Dir.chdir(directory) do
97
- result = {}
98
- result[name] = {}
99
- result[name]["desc"] = description
100
- result[name]["requires"] = dependencies
101
- result[name]["provides"] = provides
102
- File.open(filename, "w") { |resulting_file| resulting_file << JSON.pretty_generate(result) }
103
- end
86
+ FileUtils.mkdir_p directory
87
+ File.open(File.join(directory, filename), "w") { |resulting_file| resulting_file << JSON.pretty_generate(self.to_hash) }
88
+ self.to_hash
104
89
  end
105
90
 
106
- protected
107
91
 
108
- attr_writer :source_files
109
- def source_files
110
- @source_files ||= []
111
- @source_files.compact!
112
- @source_files
92
+ def required_files
93
+ source_files.map {|s| s.filename }
113
94
  end
114
95
 
115
- def calculate_requirement_order
116
- self.source_files = Jsus.topsort(source_files)
117
- self.required_files = source_files.map {|f| f.filename}
96
+ def to_hash
97
+ {
98
+ name => {
99
+ :desc => description,
100
+ :provides => provides,
101
+ :requires => dependencies
102
+ }
103
+ }
118
104
  end
119
105
 
120
106
 
107
+ def source_files
108
+ @source_files ||= Container.new
109
+ end
110
+
111
+ protected
121
112
  end
122
113
  end
@@ -0,0 +1,26 @@
1
+ module Jsus
2
+ class Packager
3
+ attr_accessor :container
4
+
5
+ def initialize(*sources)
6
+ self.container = Container.new(*sources)
7
+ end
8
+
9
+ def sources
10
+ container.sources
11
+ end
12
+
13
+ def pack(output_file = nil)
14
+ result = sources.map {|s| s.content }.join("\n")
15
+
16
+ if output_file
17
+ FileUtils.mkdir_p(File.dirname(output_file))
18
+ File.open(output_file, "w") {|f| f << result }
19
+ end
20
+
21
+ result
22
+ end
23
+
24
+
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ module Jsus
2
+ class Pool
3
+ def sources
4
+ @sources ||= Container.new
5
+ end
6
+
7
+ def lookup(key)
8
+ @provides_map[key]
9
+ end
10
+
11
+ def <<(source)
12
+ sources << source
13
+ @provides_map = sources.inject({}) do |result, source|
14
+ source.provides(:full => true).each {|p| result[p] = source }
15
+ result
16
+ end
17
+ self
18
+ end
19
+
20
+ (Array.instance_methods - self.instance_methods).each {|m| delegate m, :to => :sources }
21
+ end
22
+ end
@@ -3,40 +3,73 @@ module Jsus
3
3
  attr_accessor :header
4
4
  attr_accessor :relative_filename
5
5
  attr_accessor :filename
6
+ attr_accessor :content
7
+ attr_accessor :package
6
8
  # constructors
7
9
 
8
- def self.from_file(filename)
10
+ def initialize(options = {})
11
+ [:header, :relative_filename, :filename, :content, :package].each do |field|
12
+ send("#{field}=", options[field]) if options[field]
13
+ end
14
+ options[:pool] << self if options[:pool]
15
+ end
16
+
17
+ def self.from_file(filename, options = {})
9
18
  if File.exists?(filename)
10
- source = File.read(filename) # TODO: read only first several lines of file
19
+ source = File.read(filename)
11
20
  yaml_data = source.match(%r(^/\*\s*(---.*?)\*/)m)
12
- if (yaml_data && yaml_data[1] && header = YAML.load(yaml_data[1]))
13
- result = new
14
- result.header = header
15
- result.relative_filename = filename
16
- result.filename = File.expand_path(filename)
17
- result
21
+ if (yaml_data && yaml_data[1] && header = YAML.load(yaml_data[1]))
22
+ options[:header] = header
23
+ options[:relative_filename] = filename
24
+ options[:filename] = File.expand_path(filename)
25
+ options[:content] = source
26
+ new(options)
18
27
  else
19
- # puts "WARNING: file #{filename} has invalid format (should be YAML)"
28
+ #puts "WARNING: file #{filename} has invalid format (should be YAML)"
20
29
  nil
21
30
  end
22
31
  else
23
- # puts "WARNING: file #{filename} does not exist"
32
+ #puts "WARNING: file #{filename} does not exist"
24
33
  nil
25
34
  end
26
35
  end
27
36
 
28
37
  # Public API
29
- def dependencies
30
- header["requires"] ||= []
38
+ def dependencies(options = {})
39
+ header["requires"] = [header["requires"] || []].flatten
40
+ header["requires"].map! {|r| r.gsub(/^\//, "") }
41
+ if options[:full] && package
42
+ header["requires"].map {|r| "#{package.name}/#{r}"}
43
+ else
44
+ header["requires"]
45
+ end
31
46
  end
47
+ alias_method :requires, :dependencies
32
48
 
33
- def provides
34
- header["provides"] ||= []
49
+ def provides(options = {})
50
+ header["provides"] = [header["provides"] || []].flatten
51
+ if options[:full] && package
52
+ header["provides"].map {|p| "#{package.name}/#{p}"}
53
+ else
54
+ header["provides"]
55
+ end
35
56
  end
36
57
 
37
58
  def description
38
59
  header["description"] ||= ""
39
60
  end
40
61
 
62
+ def to_hash
63
+ {
64
+ "desc" => description,
65
+ "requires" => dependencies,
66
+ "provides" => provides
67
+ }
68
+ end
69
+
70
+ def inspect
71
+ self.to_hash.inspect
72
+ end
73
+
41
74
  end
42
75
  end
@@ -0,0 +1,29 @@
1
+ module Jsus
2
+ module Topsortable
3
+ # Topological sort for packages and source files
4
+ def topsort(to_sort = :items)
5
+ graph = RGL::DirectedAdjacencyGraph.new
6
+ provides_hash = {}
7
+ # init vertices
8
+ items = self.send(to_sort)
9
+ items.each do |item|
10
+ graph.add_vertex(item)
11
+ item.provides.each do |provides|
12
+ provides_hash[provides] = item
13
+ end
14
+ end
15
+ # init edges
16
+ items.each do |item|
17
+ item.dependencies.each do |dependency|
18
+ if required_item = provides_hash[dependency]
19
+ graph.add_edge(required_item, item)
20
+ end
21
+ end
22
+ end
23
+ result = []
24
+ graph.topsort_iterator.each { |item| result << item }
25
+ result
26
+ end
27
+
28
+ end
29
+ end
@@ -1,4 +1,4 @@
1
- name: "core"
1
+ name: "Core"
2
2
  exports: "mootools-core.js"
3
3
  web: "[mootools.net](http://mootools.net)"
4
4
  description: "MooTools, The JavaScript framework"
@@ -7,6 +7,6 @@ copyright: "&copy; [MooTools](http://mootools.net)"
7
7
  authors: "[The MooTools development team](http://mootools.net/developers)"
8
8
  version: "1.2.4"
9
9
  files:
10
- - "Source/Source/Class/Class.js"
11
- - "Source/Source/Class/Class.Extras.js"
12
- - "Source/Source/Native/Hash.js"
10
+ - "Source/Class/Class.js"
11
+ - "Source/Class/Class.Extras.js"
12
+ - "Source/Native/Hash.js"
@@ -0,0 +1,56 @@
1
+ require 'spec/spec_helper'
2
+
3
+
4
+ describe Jsus::Container do
5
+ let(:simple_source) { Source.new(:provides => [0], :dependencies => [], :content => "// simple") }
6
+ let(:another_simple_source) { Source.new(:provides => [1], :dependencies => [], :content => "// simple 2") }
7
+ let(:dependant_source) { Source.new(:provides => [3], :dependencies => [0], :content => "// simple 3") }
8
+
9
+ let(:simple_container) { Jsus::Container.new(simple_source, another_simple_source) }
10
+ let(:container_with_dependency) { Jsus::Container.new(dependant_source, simple_source) }
11
+
12
+ describe "initialization" do
13
+ it "should accept sources as arguments" do
14
+ simple_container.should have_exactly(2).sources
15
+ simple_container.sources.should include(simple_source, another_simple_source)
16
+ end
17
+ end
18
+
19
+ describe "#<<" do
20
+ it "should allow multiple items via arrays" do
21
+ container = Jsus::Container.new
22
+ container << [simple_source, another_simple_source]
23
+ container.should have_exactly(2).sources
24
+ end
25
+
26
+ it "should allow multiple items via containers" do
27
+ container = Jsus::Container.new
28
+ container << Jsus::Container.new(simple_source, another_simple_source)
29
+ container.should have_exactly(2).sources
30
+ end
31
+
32
+ end
33
+
34
+ describe "#sources" do
35
+ subject { container_with_dependency }
36
+ it "should always be sorted" do
37
+ subject.sources.index(simple_source).should < subject.sources.index(dependant_source)
38
+ subject << another_simple_source
39
+ subject.sources.index(simple_source).should < subject.sources.index(dependant_source)
40
+ end
41
+
42
+ it "should not allow duplicates" do
43
+ subject.should have_exactly(2).sources
44
+ subject << simple_source
45
+ subject.should have_exactly(2).sources
46
+ subject << another_simple_source
47
+ subject.should have_exactly(3).sources
48
+ end
49
+
50
+ it "should not allow nils" do
51
+ lambda {
52
+ subject << nil
53
+ }.should_not raise_error
54
+ end
55
+ end
56
+ end
@@ -16,6 +16,11 @@ describe Jsus::Package do
16
16
  subject.filename.should == "orwik.js"
17
17
  end
18
18
 
19
+ it "should pass pool in options" do
20
+ pool = Object.new
21
+ Jsus::Package.new(input_dir, :pool => pool).pool.should == pool
22
+ end
23
+
19
24
  it "should set provided modules from source files" do
20
25
  subject.provides.should have_exactly(4).items
21
26
  subject.provides.should include("Color", "Input", "Input.Color", "Widget")
@@ -29,15 +34,6 @@ describe Jsus::Package do
29
34
  subject.directory.should == File.expand_path(input_dir)
30
35
  subject.relative_directory.should == input_dir
31
36
  end
32
-
33
- it "should set up required files in correct order" do
34
- required_files = subject.required_files
35
- input_index = required_files.index {|s| s=~ /\/Input.js$/}
36
- color_index = required_files.index {|s| s=~ /\/Color.js$/}
37
- input_color_index = required_files.index {|s| s=~ /\/Input.Color.js$/}
38
- input_index.should < input_color_index
39
- color_index.should < input_color_index
40
- end
41
37
  end
42
38
  end
43
39
 
@@ -49,9 +45,11 @@ describe Jsus::Package do
49
45
  required_files = Dir["#{input_dir}/**/*.js"].map {|f| IO.read(f) }
50
46
  required_files.each {|f| compiled_content.should include(f)}
51
47
  end
48
+ end
52
49
 
50
+ describe "#generate_scripts_info" do
53
51
  it "should create scripts.json file containing all the info about the package" do
54
- subject.compile(output_dir)
52
+ subject.generate_scripts_info(output_dir)
55
53
  File.exists?("#{output_dir}/scripts.json").should be_true
56
54
  info = JSON.parse(IO.read("#{output_dir}/scripts.json"))
57
55
  info = info["orwik"]
@@ -81,4 +79,15 @@ describe Jsus::Package do
81
79
  tree["Library"]["Color"]["provides"].should == ["Color"]
82
80
  end
83
81
  end
82
+
83
+ describe "#required_files" do
84
+ it "should list required files in correct order" do
85
+ required_files = subject.required_files
86
+ input_index = required_files.index {|s| s=~ /\/Input.js$/}
87
+ color_index = required_files.index {|s| s=~ /\/Color.js$/}
88
+ input_color_index = required_files.index {|s| s=~ /\/Input.Color.js$/}
89
+ input_index.should < input_color_index
90
+ color_index.should < input_color_index
91
+ end
92
+ end
84
93
  end
@@ -0,0 +1,37 @@
1
+ require 'spec/spec_helper'
2
+
3
+
4
+ describe Jsus::Packager do
5
+ let(:simple_source) { Source.new(:provides => [0], :dependencies => [], :content => "// simple") }
6
+ let(:another_simple_source) { Source.new(:provides => [1], :dependencies => [], :content => "// simple 2") }
7
+ let(:dependant_source) { Source.new(:provides => [3], :dependencies => [0], :content => "// simple 3") }
8
+
9
+ let(:simple_package) { Jsus::Packager.new(simple_source, another_simple_source) }
10
+ let(:package_with_dependency) { Jsus::Packager.new(dependant_source, simple_source) }
11
+
12
+ before(:each) { cleanup }
13
+ after(:each) { cleanup }
14
+
15
+ describe "initialization" do
16
+ it "should accept sources as arguments" do
17
+ simple_package.should have_exactly(2).sources
18
+ simple_package.sources.should include(simple_source, another_simple_source)
19
+ end
20
+ end
21
+
22
+ describe "#pack" do
23
+ subject { Jsus::Packager.new(simple_source) }
24
+ it "should concatenate source files" do
25
+ simple_package.pack.should include(simple_source.content, another_simple_source.content)
26
+ end
27
+
28
+ it "should output to file if given a filename" do
29
+ simple_package.pack("spec/tmp/test.js")
30
+ IO.read("spec/tmp/test.js").should include(simple_source.content, another_simple_source.content)
31
+ end
32
+
33
+ it "should resolve dependencies" do
34
+ package_with_dependency.pack.should == "#{simple_source.content}\n#{dependant_source.content}"
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec/spec_helper'
2
+ describe Jsus::Pool do
3
+ let(:package) { Jsus::Package.new("spec/data/OutsideDependencies/app/javascripts/Core") }
4
+ subject { Jsus::Pool.new }
5
+
6
+ before(:each) do
7
+ subject << package.source_files
8
+ end
9
+
10
+ describe "#lookup" do
11
+ it "should find a source file providing given full name" do
12
+ subject.lookup("Core/Hash").should be_kind_of(Jsus::SourceFile)
13
+ end
14
+
15
+ it "should return nil if nothing could be found" do
16
+ subject.lookup("Core/WTF").should be_nil
17
+ end
18
+ end
19
+ end
@@ -3,6 +3,8 @@ require 'spec/spec_helper'
3
3
  describe Jsus::SourceFile do
4
4
  before(:each) { cleanup }
5
5
  after(:all) { cleanup }
6
+ let(:package) { Package.new(:name => "Core") }
7
+ subject { Jsus::SourceFile.from_file("spec/data/OutsideDependencies/app/javascripts/Core/Source/Class/Class.Extras.js", :package => package) }
6
8
  context "initialization" do
7
9
  context "from file" do
8
10
  subject { Jsus::SourceFile.from_file('spec/data/test_source_one.js') }
@@ -23,11 +25,59 @@ describe Jsus::SourceFile do
23
25
  end
24
26
  end
25
27
 
28
+
26
29
  context "when file does not exist" do
27
30
  it "should return nil" do
28
31
  Jsus::SourceFile.from_file('spec/data/non-existant-file.js').should == nil
29
32
  end
30
33
  end
31
34
  end
35
+
36
+ it "should set all available fields from constructor" do
37
+ source = Jsus::SourceFile.new(:package => 1, :content => 2, :filename => 3,
38
+ :relative_filename => 4, :header => 5)
39
+ source.package.should == 1
40
+ source.content.should == 2
41
+ source.filename.should == 3
42
+ source.relative_filename.should == 4
43
+ source.header.should == 5
44
+ end
45
+
46
+ it "should register package in pool from constructor" do
47
+ pool = mock("Pool")
48
+ pool.should_receive("<<").with(instance_of(Jsus::SourceFile))
49
+ Jsus::SourceFile.new(:pool => pool)
50
+ end
51
+
52
+ end
53
+
54
+ describe "#provides" do
55
+ it "should return the stuff it provides" do
56
+ subject.provides.should == ["Chain", "Events", "Options"]
57
+ end
58
+
59
+ it "should prepend package prefix if asked for fully formed provides" do
60
+ subject.provides(:full => true).should == ["Core/Chain", "Core/Events", "Core/Options"]
61
+ end
62
+
63
+ it "should work well when given single string instead of array" do
64
+ subject.header["provides"] = "Mash"
65
+ subject.provides.should == ["Mash"]
66
+ end
67
+ end
68
+
69
+ describe "#dependencies" do
70
+ it "should truncate leading slash" do
71
+ subject.dependencies.should == ["Class"]
72
+ end
73
+
74
+ it "should prepend package prefix if asked for fully formed dependencies" do
75
+ subject.dependencies(:full => true).should == ["Core/Class"]
76
+ end
77
+
78
+ it "should work well when given single string instead of array" do
79
+ subject.header["requires"] = "Class"
80
+ subject.dependencies.should == ["Class"]
81
+ end
32
82
  end
33
83
  end
@@ -0,0 +1,51 @@
1
+ require 'spec/spec_helper'
2
+
3
+ class SortableItem
4
+ attr_accessor :value
5
+ attr_accessor :dependencies
6
+ attr_accessor :provides
7
+ def initialize(value)
8
+ @value = value
9
+ @provides = [value]
10
+ end
11
+ end
12
+
13
+ class SortableClass
14
+ include Jsus::Topsortable
15
+ attr_accessor :items
16
+ end
17
+
18
+ describe Jsus::Topsortable do
19
+ subject { SortableClass.new }
20
+ let(:items) { (0..5).map {|i| SortableItem.new(i) } }
21
+ let(:topsorted_values) { subject.topsort(:items).map {|item| item.value } }
22
+ before(:each) do
23
+ subject.items = items
24
+ end
25
+
26
+ it "should topologically sort items correctly" do
27
+ items[0].dependencies = [1, 2, 3]
28
+ items[1].dependencies = [3, 4, 5]
29
+ items[2].dependencies = [1, 3, 4, 5]
30
+ items[3].dependencies = []
31
+ items[4].dependencies = [3, 5]
32
+ items[5].dependencies = [3]
33
+ topsorted_values.should == [3, 5, 4, 1, 2, 0]
34
+ end
35
+
36
+ it "should play well with multiple provides case" do
37
+ items[0].dependencies = [2, 3]
38
+ items[0].provides = [0, 10 ,20, 30]
39
+ items[1].dependencies = [10, 30]
40
+ items[1].provides = [1, 21]
41
+ items[2].dependencies = []
42
+ items[2].provides = [2, 32, 42]
43
+ items[3].dependencies = [42]
44
+ items[3].provides = [3, 43, 53]
45
+ items[4].dependencies = [21]
46
+ items[4].provides = [4, 44]
47
+ items[5].dependencies = [43, 32, 44]
48
+ items[5].provides = [5, 55]
49
+ topsorted_values.should == [2, 3, 0, 1, 4, 5]
50
+ end
51
+ end
@@ -0,0 +1,26 @@
1
+ # Stubs for classes that mimic jsus classes without being actually them
2
+
3
+
4
+ class Source
5
+ attr_accessor :provides
6
+ attr_accessor :dependencies
7
+ attr_accessor :content
8
+
9
+ def initialize(options = {})
10
+ options.each do |attr, value|
11
+ send("#{attr}=", value)
12
+ end
13
+ end
14
+ end
15
+
16
+
17
+ class Package
18
+ attr_accessor :name
19
+
20
+ def initialize(options = {})
21
+ options.each do |attr, value|
22
+ send("#{attr}=", value)
23
+ end
24
+ end
25
+ end
26
+
@@ -1,7 +1,9 @@
1
1
  require 'lib/jsus'
2
+ Dir["spec/shared/*.rb"].each {|f| require f}
2
3
 
3
4
  # cleanup compiled stuff
4
5
  def cleanup
5
6
  `rm -rf spec/data/Basic/public`
6
7
  `rm -rf spec/data/OutsideDependencies/public`
8
+ `rm -rf spec/tmp/`
7
9
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 0
9
- version: 0.1.0
8
+ - 2
9
+ version: 0.1.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Markiz, idea by Inviz (http://github.com/Inviz)
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-03 00:00:00 +04:00
17
+ date: 2010-06-04 00:00:00 +04:00
18
18
  default_executable: jsus
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -78,9 +78,12 @@ extra_rdoc_files:
78
78
  - TODO
79
79
  - bin/jsus
80
80
  - lib/jsus.rb
81
- - lib/jsus/bundler.rb
81
+ - lib/jsus/container.rb
82
82
  - lib/jsus/package.rb
83
+ - lib/jsus/packager.rb
84
+ - lib/jsus/pool.rb
83
85
  - lib/jsus/source_file.rb
86
+ - lib/jsus/topsortable.rb
84
87
  files:
85
88
  - CHANGELOG
86
89
  - LICENSE
@@ -89,10 +92,14 @@ files:
89
92
  - Rakefile
90
93
  - TODO
91
94
  - bin/jsus
95
+ - jsus.gemspec
92
96
  - lib/jsus.rb
93
- - lib/jsus/bundler.rb
97
+ - lib/jsus/container.rb
94
98
  - lib/jsus/package.rb
99
+ - lib/jsus/packager.rb
100
+ - lib/jsus/pool.rb
95
101
  - lib/jsus/source_file.rb
102
+ - lib/jsus/topsortable.rb
96
103
  - spec/data/Basic/README
97
104
  - spec/data/Basic/app/javascripts/Orwik/Source/Library/Color.js
98
105
  - spec/data/Basic/app/javascripts/Orwik/Source/Widget/Input/Input.Color.js
@@ -112,12 +119,15 @@ files:
112
119
  - spec/data/bad_test_source_one.js
113
120
  - spec/data/bad_test_source_two.js
114
121
  - spec/data/test_source_one.js
115
- - spec/lib/jsus/bundler_spec.rb
122
+ - spec/lib/jsus/container_spec.rb
116
123
  - spec/lib/jsus/package_spec.rb
124
+ - spec/lib/jsus/packager_spec.rb
125
+ - spec/lib/jsus/pool_spec.rb
117
126
  - spec/lib/jsus/source_file_spec.rb
127
+ - spec/lib/jsus/topsortable_spec.rb
128
+ - spec/shared/class_stubs.rb
118
129
  - spec/spec.opts
119
130
  - spec/spec_helper.rb
120
- - jsus.gemspec
121
131
  has_rdoc: true
122
132
  homepage: http://github.com/markiz/jsus
123
133
  licenses: []
@@ -1,39 +0,0 @@
1
- module Jsus
2
- class Bundler
3
- def initialize(directory)
4
- Dir[File.join(directory, "**", "package.yml")].each do |package_name|
5
- path = Pathname.new(package_name)
6
- Dir.chdir path.parent.parent.to_s do
7
- package = Package.new(path.parent.relative_path_from(path.parent.parent).to_s)
8
- self.packages << package
9
- end
10
- end
11
- calculate_requirement_order
12
- end
13
-
14
-
15
- attr_writer :packages
16
- def packages
17
- @packages ||= []
18
- end
19
-
20
- attr_accessor :required_files
21
-
22
- def compile(directory)
23
- FileUtils.mkdir_p(directory)
24
- Dir.chdir directory do
25
- packages.each do |package|
26
- package.compile(package.relative_directory)
27
- package.generate_tree(package.relative_directory)
28
- end
29
- end
30
- end
31
-
32
-
33
- protected
34
- def calculate_requirement_order
35
- @packages = Jsus.topsort(packages)
36
- @required_files = @packages.map {|p| p.required_files }.flatten
37
- end
38
- end
39
- end
@@ -1,46 +0,0 @@
1
- require 'spec/spec_helper'
2
-
3
- describe Jsus::Bundler do
4
- subject { Jsus::Bundler.new(input_dir) }
5
- let(:input_dir) { "spec/data/Basic/app/javascripts" }
6
- let(:output_dir) { "spec/data/Basic/public/javascripts" }
7
- before(:each) { cleanup }
8
- after(:all) { cleanup }
9
- context "initialization" do
10
- context "from a directory" do
11
- subject { Jsus::Bundler.new("spec/data/Basic/") }
12
- it "should load packages" do
13
- subject.packages.map {|p| p.name}.should == ["orwik"]
14
- subject.packages.map {|p| p.relative_directory }.should == ["Orwik"]
15
- end
16
- end
17
- end
18
-
19
- describe "#required_files" do
20
- it "should return an array with correctly sorted required files" do
21
- files = subject.required_files
22
- color_index = files.find_index {|f| f =~ /\/Color.js/}
23
- input_index = files.find_index {|f| f =~ /\/Input.js/}
24
- input_color_index = files.find_index {|f| f =~ /\/Input.Color.js/}
25
- color_index.should < input_color_index
26
- input_index.should < input_color_index
27
- end
28
- end
29
-
30
- describe "#compile" do
31
- it "should generate scripts.json file with all the dependencies and provides for each package" do
32
- subject.compile(output_dir)
33
- File.exists?("#{output_dir}/Orwik/scripts.json").should be_true
34
- end
35
-
36
- it "should generate js file for each package" do
37
- subject.compile(output_dir)
38
- File.exists?("#{output_dir}/Orwik/orwik.js").should be_true
39
- end
40
-
41
- it "should generate tree.json file for each package" do
42
- subject.compile(output_dir)
43
- File.exists?("#{output_dir}/Orwik/tree.json").should be_true
44
- end
45
- end
46
- end