jsus 0.1.0 → 0.1.2

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.
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