jsus 0.3.1 → 0.3.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/.document CHANGED
@@ -1,5 +1,5 @@
1
1
  lib/**/*.rb
2
2
  bin/*
3
- -
3
+ -
4
4
  features/**/*.feature
5
5
  LICENSE.txt
data/.travis.yml CHANGED
@@ -1,4 +1,4 @@
1
- script: "rake"
1
+ script: "bundle exec rake"
2
2
  rvm:
3
3
  - 1.8.7
4
4
  - 1.9.2
data/.yardopts ADDED
@@ -0,0 +1,9 @@
1
+ --markup="markdown" lib/**/*.rb
2
+ --no-private
3
+ --no-protected
4
+ --main README.md
5
+ --hide-tag todo
6
+ -
7
+ LICENSE
8
+ CHANGELOG
9
+ docs/*.textile
data/CHANGELOG CHANGED
@@ -1,4 +1,25 @@
1
1
  = Jsus Changelog
2
+ == Version 0.3.2
3
+ Middleware changes:
4
+ * Fixed minor problem with middleware when package name and source file tag
5
+ are the same
6
+ * Settings are now shared between Jsus::Middleware and subclasses
7
+ * Middleware now also supports /include/ directive (generates includes file),
8
+ like -g option of CLI utility
9
+ * Hack for cache output paths to be recognizable by nginx
10
+
11
+ CLI changes:
12
+ * --very-verbose mode, outputs tree of your packages, very useful when debugging
13
+ missing dependencies.
14
+ * If you have circular dependencies in your code, jsus will detect them and issue
15
+ a huge warning message (WIP)
16
+
17
+ Shared changes:
18
+ * Pool instantiation will now follow symlinks one level deep
19
+ * Somewhat easier on eyes murdoc template
20
+ * Pool instantiation now also accepts array of directories as its argument
21
+ * YARD docs are now the default docs choice
22
+
2
23
  == Version 0.3.1
3
24
  * Added wildcard support for Jsus::Middleware
4
25
 
data/Gemfile CHANGED
@@ -6,7 +6,7 @@ gem "json_pure"
6
6
  gem "rgl"
7
7
 
8
8
  group :development do
9
- gem "bundler"
9
+ gem "rake"
10
10
  gem "rspec"
11
11
  gem "cucumber"
12
12
  gem "jeweler"
@@ -17,4 +17,5 @@ group :development do
17
17
  gem 'yui-compressor'
18
18
  gem 'sinatra'
19
19
  gem 'rack-test'
20
- end
20
+ gem 'yard'
21
+ end
@@ -9,7 +9,7 @@ Why?
9
9
  As a javascript programmer, you often need to split your code into
10
10
  multiple files. When you have 50+ different modules / libraries, you
11
11
  need some way to resolve complex dependencies and package all you need
12
- and nil you don't. Jsus is an utility that allows you to do just that:
12
+ and nil you don't. Jsus is an utility that allows you to do just that:
13
13
  package your libraries into one piece with all dependencies included.
14
14
 
15
15
  Features
@@ -21,17 +21,17 @@ Features
21
21
  headers denoting their requirements and what they provide.
22
22
  * Jsus automatically resolves dependencies, so you don't have to worry about
23
23
  order issues or anything else.
24
- * Jsus allows you to make "extensions". Extension is a monkey-patch you can
24
+ * Jsus allows you to make "extensions". Extension is a monkey-patch you can
25
25
  apply to any other library. Because sometimes you want to make project-specific
26
26
  change to a library you don't have control over and you want to be able to
27
27
  update this library without applying manual patches from their source.
28
- * Jsus uses [murdoc](https://github.com/markiz/murdoc) for doccu style docs
28
+ * Jsus uses [murdoc](https://github.com/markiz/murdoc) for doccu style docs
29
29
  generation.
30
30
  * Jsus generates special json files denoting source and resulting project
31
31
  structure which can be useful for later introspection.
32
32
  * Jsus can also generate a special js file with loader for your dependencies,
33
33
  so that you don't need to repackage everything during development cycle.
34
-
34
+
35
35
  Examples
36
36
  ========
37
37
 
@@ -42,6 +42,12 @@ Examples
42
42
  * `jsus . Output`
43
43
  * Look at what Output directory contains
44
44
 
45
+ Using with Rails / Sinatra / Whatever
46
+ =====================================
47
+
48
+ Jsus comes with a middleware in its backpack. See [rails example](https://github.com/jsus/jsus-rails-app)
49
+ and [sinatra example](https://github.com/jsus/jsus-sinatra-app).
50
+
45
51
  Plans
46
52
  =====
47
53
 
data/TODO CHANGED
@@ -1,3 +1 @@
1
- * Disallow circular dependencies
2
- * Rails integration
3
- * Cleanup jsus utility
1
+ * Disallow circular dependencies (mostly done)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.3.2
data/bin/jsus CHANGED
@@ -77,6 +77,11 @@ module Jsus
77
77
  Jsus.verbose = true
78
78
  end
79
79
 
80
+ opts.on_tail('--very-verbose', 'very verbose mode, shows pool stats beside usual verbose stuff') do
81
+ Jsus.verbose = true
82
+ options[:display_pool_stats] = true
83
+ end
84
+
80
85
  opts.on_tail('-b', '--benchmark', 'shows time spent on various stages') do
81
86
  options[:benchmark] = true
82
87
  end
@@ -192,6 +197,7 @@ module Jsus
192
197
  setup_output_directory
193
198
  preload_pool
194
199
  load_package
200
+ display_pool_stats if options[:display_pool_stats]
195
201
  compile_package
196
202
  post_process if options[:postproc]
197
203
  compress_package if options[:compress]
@@ -224,6 +230,30 @@ module Jsus
224
230
  checkpoint(:dependencies)
225
231
  end
226
232
 
233
+ def display_pool_stats
234
+ checkpoint(:pool_stats)
235
+ puts ""
236
+ puts "Pool stats:"
237
+ puts ""
238
+ puts "Main package:"
239
+ display_package @package
240
+ puts "Supplementary packages:"
241
+ @pool.packages.each do |package|
242
+ display_package package
243
+ end
244
+ puts ""
245
+ end
246
+
247
+ def display_package(package)
248
+ puts "Package: #{package.name}"
249
+ package.source_files.to_a.sort_by {|sf| sf.filename}.each do |sf|
250
+ puts " [#{sf.relative_filename}]"
251
+ puts " Provides: [#{sf.provides_names.join(", ")}]"
252
+ puts " Requires: [#{sf.requires_names.join(", ")}]"
253
+ end
254
+ puts ""
255
+ end
256
+
227
257
  def compile_package
228
258
  @package_content = @package.compile(nil)
229
259
  checkpoint(:compilation)
@@ -273,15 +303,8 @@ module Jsus
273
303
  includes_root = options[:includes_root] || @output_dir
274
304
  File.open(File.join(@output_dir, "includes.js"), "w") do |f|
275
305
  c = Jsus::Container.new(*(@package.source_files.to_a + @package.linked_external_dependencies.to_a))
276
- script = %{
277
- (function(prefix, loader) {
278
- var sources = %sources%;
279
- if (!loader) loader = function(path) {
280
- document.write('<scr' + 'ipt src="' + (prefix || '') + path + '"></script>');
281
- }
282
- for (var i = 0, j = sources.length; i < j; i++) loader(sources[i]);
283
- })(window.prefix, window.loader);}.sub("%sources%", JSON.pretty_generate(c.required_files(includes_root)))
284
- f.puts script
306
+ paths = c.required_files(includes_root)
307
+ f.puts Jsus::Util::CodeGenerator.generate_includes(paths)
285
308
  end
286
309
  checkpoint(:includes)
287
310
  end
@@ -354,4 +377,4 @@ module Jsus
354
377
  end
355
378
  end
356
379
 
357
- Jsus::CLI.run!
380
+ Jsus::CLI.run!
data/jsus.gemspec CHANGED
@@ -5,27 +5,28 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{jsus}
8
- s.version = "0.3.1"
8
+ s.version = "0.3.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Mark Abramov"]
12
- s.date = %q{2011-05-19}
12
+ s.date = %q{2011-06-19}
13
13
  s.default_executable = %q{jsus}
14
14
  s.description = %q{Javascript packager and dependency resolver}
15
15
  s.email = %q{markizko@gmail.com}
16
16
  s.executables = ["jsus"]
17
17
  s.extra_rdoc_files = [
18
- "README",
18
+ "README.md",
19
19
  "TODO"
20
20
  ]
21
21
  s.files = [
22
22
  ".document",
23
23
  ".rspec",
24
24
  ".travis.yml",
25
+ ".yardopts",
25
26
  "CHANGELOG",
26
27
  "Gemfile",
27
28
  "Manifest",
28
- "README",
29
+ "README.md",
29
30
  "Rakefile",
30
31
  "TODO",
31
32
  "UNLICENSE",
@@ -102,6 +103,7 @@ Gem::Specification.new do |s|
102
103
  "lib/jsus/source_file.rb",
103
104
  "lib/jsus/tag.rb",
104
105
  "lib/jsus/util.rb",
106
+ "lib/jsus/util/code_generator.rb",
105
107
  "lib/jsus/util/documenter.rb",
106
108
  "lib/jsus/util/file_cache.rb",
107
109
  "lib/jsus/util/inflection.rb",
@@ -217,7 +219,7 @@ Gem::Specification.new do |s|
217
219
  s.add_runtime_dependency(%q<activesupport>, [">= 0"])
218
220
  s.add_runtime_dependency(%q<json_pure>, [">= 0"])
219
221
  s.add_runtime_dependency(%q<rgl>, [">= 0"])
220
- s.add_development_dependency(%q<bundler>, [">= 0"])
222
+ s.add_development_dependency(%q<rake>, [">= 0"])
221
223
  s.add_development_dependency(%q<rspec>, [">= 0"])
222
224
  s.add_development_dependency(%q<cucumber>, [">= 0"])
223
225
  s.add_development_dependency(%q<jeweler>, [">= 0"])
@@ -228,11 +230,12 @@ Gem::Specification.new do |s|
228
230
  s.add_development_dependency(%q<yui-compressor>, [">= 0"])
229
231
  s.add_development_dependency(%q<sinatra>, [">= 0"])
230
232
  s.add_development_dependency(%q<rack-test>, [">= 0"])
233
+ s.add_development_dependency(%q<yard>, [">= 0"])
231
234
  else
232
235
  s.add_dependency(%q<activesupport>, [">= 0"])
233
236
  s.add_dependency(%q<json_pure>, [">= 0"])
234
237
  s.add_dependency(%q<rgl>, [">= 0"])
235
- s.add_dependency(%q<bundler>, [">= 0"])
238
+ s.add_dependency(%q<rake>, [">= 0"])
236
239
  s.add_dependency(%q<rspec>, [">= 0"])
237
240
  s.add_dependency(%q<cucumber>, [">= 0"])
238
241
  s.add_dependency(%q<jeweler>, [">= 0"])
@@ -243,12 +246,13 @@ Gem::Specification.new do |s|
243
246
  s.add_dependency(%q<yui-compressor>, [">= 0"])
244
247
  s.add_dependency(%q<sinatra>, [">= 0"])
245
248
  s.add_dependency(%q<rack-test>, [">= 0"])
249
+ s.add_dependency(%q<yard>, [">= 0"])
246
250
  end
247
251
  else
248
252
  s.add_dependency(%q<activesupport>, [">= 0"])
249
253
  s.add_dependency(%q<json_pure>, [">= 0"])
250
254
  s.add_dependency(%q<rgl>, [">= 0"])
251
- s.add_dependency(%q<bundler>, [">= 0"])
255
+ s.add_dependency(%q<rake>, [">= 0"])
252
256
  s.add_dependency(%q<rspec>, [">= 0"])
253
257
  s.add_dependency(%q<cucumber>, [">= 0"])
254
258
  s.add_dependency(%q<jeweler>, [">= 0"])
@@ -259,6 +263,7 @@ Gem::Specification.new do |s|
259
263
  s.add_dependency(%q<yui-compressor>, [">= 0"])
260
264
  s.add_dependency(%q<sinatra>, [">= 0"])
261
265
  s.add_dependency(%q<rack-test>, [">= 0"])
266
+ s.add_dependency(%q<yard>, [">= 0"])
262
267
  end
263
268
  end
264
269
 
data/lib/jsus.rb CHANGED
@@ -11,10 +11,7 @@ require 'fileutils'
11
11
  require 'pathname'
12
12
 
13
13
  #
14
- # Jsus -- a library for packaging up your source files.
15
- #
16
- # For better understanding of jsus ideas start with http://github.com/Markiz/jsus-examples
17
- #
14
+ # Jsus -- your better javascript packager.
18
15
  #
19
16
  module Jsus
20
17
  autoload :SourceFile, 'jsus/source_file'
@@ -26,19 +23,44 @@ module Jsus
26
23
  autoload :Util, 'jsus/util'
27
24
  autoload :Middleware, 'jsus/middleware'
28
25
 
29
- # Returns whether or not jsus is in verbose mode
26
+ # In verbose mode jsus shows a lot of warnings like missing dependencies.
27
+ # Default: false
28
+ #
29
+ # @return [Boolean] jsus verbosity mode
30
+ # @api public
30
31
  def self.verbose?
31
32
  !!@verbose
32
33
  end
33
34
 
34
- # Sets verbose mode to on. In verbose mode jsus shows a lot of warnings
35
- # like missing dependencies.
35
+ # @see .verbose?
36
+ # @param [Boolean] verbose verbose verbosity mode
37
+ # @api public
36
38
  def self.verbose=(verbose)
37
39
  @verbose = verbose
38
40
  end
39
41
 
40
- # Returns current version
42
+ # @return [String] Jsus version
43
+ # @api public
41
44
  def self.version
42
45
  @version ||= File.read(File.dirname(__FILE__) + "/../VERSION")
43
46
  end
44
- end
47
+
48
+
49
+ # Circular dependencies cannot be resolved and lead to "impossible"
50
+ # situations and problems, like missing source files or incorrect ordering.
51
+ #
52
+ # However, checking for cycles is quite computationally expensive, which
53
+ # is why you may want to disable it in production mode.
54
+ #
55
+ # @return [Boolean]
56
+ # @api public
57
+ def self.look_for_cycles?
58
+ @look_for_cycles == nil ? true : @look_for_cycles
59
+ end
60
+
61
+ # @see .look_for_cycles?
62
+ # @param [Boolean]
63
+ def self.look_for_cycles=(value)
64
+ @look_for_cycles = value
65
+ end
66
+ end
@@ -4,10 +4,12 @@ module Jsus
4
4
  # from an array is the fact that container maintains topological
5
5
  # sort for the source files.
6
6
  #
7
+ # This class is mostly used internally.
8
+ #
7
9
  class Container
10
+ # Instantiates a container from given sources.
8
11
  #
9
- # Every argument for initializer is pushed into the container.
10
- #
12
+ # @param [SourceFile]
11
13
  def initialize(*sources)
12
14
  sources.each do |source|
13
15
  push(source)
@@ -16,7 +18,9 @@ module Jsus
16
18
 
17
19
  # Public API
18
20
 
19
- # Pushes an item to container
21
+ # Pushes an item to the container
22
+ #
23
+ # @param [SourceFile] source pushed file
20
24
  def push(source)
21
25
  if source
22
26
  if source.kind_of?(Array) || source.kind_of?(Container)
@@ -30,7 +34,9 @@ module Jsus
30
34
  end
31
35
  alias_method :<<, :push
32
36
 
33
- # Flattens the container items.
37
+ # Flattens the container items
38
+ #
39
+ # @return [Array]
34
40
  def flatten
35
41
  map {|item| item.respond_to?(:flatten) ? item.flatten : item }.flatten
36
42
  end
@@ -38,16 +44,25 @@ module Jsus
38
44
  # Contains the source files. Please, don't use sources directly, if you
39
45
  # depend on them to be topologically sorted. Use collection methods like
40
46
  # inject/reject/map directly on the container instead.
47
+ #
48
+ # @return [Array]
49
+ # @api semipublic
41
50
  def sources
42
51
  @sources ||= []
43
52
  end
44
53
  alias_method :to_a, :sources
45
54
 
55
+ # Sets sources to new value.
56
+ #
57
+ # @api semipublic
46
58
  def sources=(new_value) # :nodoc:
47
59
  @sources = new_value
48
60
  end
49
61
 
50
- # Performs a sort and returns self.
62
+ # Topologically sorts items in container if required.
63
+ #
64
+ # @return [self]
65
+ # @api semipublic
51
66
  def sort!
52
67
  unless sorted?
53
68
  remove_replaced_files!
@@ -57,13 +72,24 @@ module Jsus
57
72
  self
58
73
  end
59
74
 
60
- # Returns whether collection is sorted already
75
+ # Returns whether container requires sorting.
76
+ #
77
+ # @return [Boolean]
78
+ # @api semipublic
61
79
  def sorted?
62
80
  !!@sorted
63
81
  end
64
82
 
65
83
  # Lists all the required files (dependencies and extensions) for
66
- # the sources in the container.
84
+ # the sources in the container. Consider it a projection from source files
85
+ # space onto filesystem space.
86
+ #
87
+ # Optionally accepts a filesystem point to calculate relative paths from.
88
+ #
89
+ # @param [String] root point from which the relative paths are calculated.
90
+ # When omitted, full paths are returned.
91
+ # @return [Array] ordered list of required files
92
+ # @api public
67
93
  def required_files(root = nil)
68
94
  sort!
69
95
  files = sources.map {|s| s.required_files }.flatten
@@ -74,13 +100,18 @@ module Jsus
74
100
  files
75
101
  end
76
102
 
77
- def inspect # :nodoc:
103
+ # Shows inspection of the container.
104
+ # @api public
105
+ def inspect
78
106
  "#<#{self.class.name}:#{self.object_id} #{self.sources.inspect}>"
79
107
  end
80
108
 
81
109
  # Private API
82
110
 
83
- def topsort # :nodoc:
111
+ # Performs topological sort inside current container.
112
+ #
113
+ # @api private
114
+ def topsort
84
115
  graph = RGL::DirectedAdjacencyGraph.new
85
116
  # init vertices
86
117
  items = sources
@@ -98,20 +129,46 @@ module Jsus
98
129
  end
99
130
  end
100
131
  result = []
132
+ if Jsus.look_for_cycles?
133
+ cycles = graph.cycles
134
+ unless cycles.empty?
135
+ puts "*" * 30
136
+ puts "ACHTUNG! WARNING! ATTENTION!"
137
+ puts "*" * 30
138
+ puts "Jsus has discovered you have circular dependencies in your code."
139
+ puts "Please resolve them immediately!"
140
+ puts "List of circular dependencies:"
141
+ cycles.each do |cycle|
142
+ puts "-" * 30
143
+ puts (cycle + [cycle.first]).map {|sf| sf.filename}.join(" => ")
144
+ end
145
+ puts "*" * 30
146
+ end
147
+ end
101
148
  graph.topsort_iterator.each { |item| result << item }
102
149
  result
103
150
  end
104
151
 
105
- def dependency_cache # :nodoc:
152
+ # Cached map of dependencies pointing to source files.
153
+ # @return [Hash]
154
+ # @api private
155
+ def dependency_cache
106
156
  @dependency_cache ||= {}
107
157
  end
108
158
 
109
- def provides_tree # :nodoc:
159
+ # Cached tree of what source files provide.
160
+ #
161
+ # @api private
162
+ # @return [Jsus::Util::Tree]
163
+ def provides_tree
110
164
  @provides_tree ||= provides_tree!
111
165
  end
112
166
 
113
- # Provides tree contains
114
- def provides_tree! # :nodoc:
167
+ # Returns tree of what source files provide.
168
+ #
169
+ # @api private
170
+ # @return [Jsus::Util::Tree]
171
+ def provides_tree!
115
172
  tree = Util::Tree.new
116
173
  # Provisions
117
174
  sources.each do |file|
@@ -128,17 +185,28 @@ module Jsus
128
185
  tree
129
186
  end
130
187
 
131
- def remove_replaced_files! # :nodoc:
188
+ # Removes files which are marked as replaced by other sources.
189
+ #
190
+ # @api private
191
+ def remove_replaced_files!
132
192
  sources.reject! do |sf|
133
193
  !sf.provides.empty? && sf.provides.any? { |tag| replacements_tree[tag] && replacements_tree[tag] != sf }
134
194
  end
135
195
  end
136
196
 
137
- def replacements_tree # :nodoc:
197
+ # Cached tree of what source files replace.
198
+ #
199
+ # @api private
200
+ # @return [Jsus::Util::Tree]
201
+ def replacements_tree
138
202
  @replacements_tree ||= replacements_tree!
139
203
  end
140
204
 
141
- def replacements_tree! # :nodoc:
205
+ # Returns tree of what source files replace.
206
+ #
207
+ # @api private
208
+ # @return [Jsus::Util::Tree]
209
+ def replacements_tree!
142
210
  tree = Util::Tree.new
143
211
  sources.each do |file|
144
212
  if file.replaces
@@ -148,25 +216,29 @@ module Jsus
148
216
  tree
149
217
  end
150
218
 
151
- def clear_cache! # :nodoc:
219
+ # Clears all caches for given container.
220
+ #
221
+ # @api private
222
+ def clear_cache!
152
223
  @provides_tree = nil
153
224
  @replacements_tree = nil
154
225
  @dependency_cache = nil
155
226
  @sorted = false
156
227
  end
157
228
 
158
-
229
+ # List of methods that clear cached state of container when called.
159
230
  CACHE_CLEAR_METHODS = [
160
231
  "map!", "reject!", "inject!", "collect!", "delete", "delete_at"
161
- ] # :nodoc:
232
+ ]
162
233
 
234
+ # List of methods that are delegated to underlying array of sources.
163
235
  DELEGATED_METHODS = [
164
236
  "==", "to_a", "map", "map!", "each", "inject", "inject!",
165
- "collect", "collect!", "reject", "reject!", "detect", "size",
166
- "length", "[]", "empty?", "index", "include?", "select",
237
+ "collect", "collect!", "reject", "reject!", "detect", "size",
238
+ "length", "[]", "empty?", "index", "include?", "select",
167
239
  "delete_if", "delete", "-", "+", "|", "&"
168
- ] # :nodoc:
169
- # delegates most Enumerable methods to #sources
240
+ ]
241
+
170
242
  (DELEGATED_METHODS).each do |m|
171
243
  class_eval <<-EVAL
172
244
  def #{m}(*args, &block)
@@ -177,4 +249,4 @@ module Jsus
177
249
  EVAL
178
250
  end
179
251
  end
180
- end
252
+ end