jsus 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +1 -1
- data/.travis.yml +1 -1
- data/.yardopts +9 -0
- data/CHANGELOG +21 -0
- data/Gemfile +3 -2
- data/{README → README.md} +10 -4
- data/TODO +1 -3
- data/VERSION +1 -1
- data/bin/jsus +33 -10
- data/jsus.gemspec +12 -7
- data/lib/jsus.rb +31 -9
- data/lib/jsus/container.rb +96 -24
- data/lib/jsus/middleware.rb +160 -43
- data/lib/jsus/package.rb +65 -25
- data/lib/jsus/packager.rb +15 -10
- data/lib/jsus/pool.rb +54 -40
- data/lib/jsus/source_file.rb +105 -80
- data/lib/jsus/tag.rb +65 -39
- data/lib/jsus/util.rb +8 -6
- data/lib/jsus/util/code_generator.rb +21 -0
- data/lib/jsus/util/documenter.rb +34 -6
- data/lib/jsus/util/file_cache.rb +16 -5
- data/lib/jsus/util/inflection.rb +9 -2
- data/lib/jsus/util/tree.rb +54 -18
- data/lib/jsus/util/validator/base.rb +13 -5
- data/lib/jsus/util/validator/mooforge.rb +8 -2
- data/markup/stylesheet.css +84 -16
- data/spec/data/ChainDependencies/app/javascripts/Class/package.yml +2 -2
- data/spec/jsus/middleware_spec.rb +25 -0
- data/spec/jsus/pool_spec.rb +9 -4
- metadata +23 -7
data/lib/jsus/packager.rb
CHANGED
@@ -1,30 +1,35 @@
|
|
1
1
|
module Jsus
|
2
2
|
#
|
3
|
-
# Packager is a plain simple class accepting several source files
|
3
|
+
# Packager is a plain simple class accepting several source files
|
4
4
|
# and joining their contents.
|
5
5
|
#
|
6
6
|
# It uses Container for storage which means it automatically sorts sources.
|
7
7
|
#
|
8
8
|
class Packager
|
9
|
-
|
9
|
+
# Container with source files
|
10
|
+
attr_accessor :container
|
10
11
|
|
11
|
-
#
|
12
|
+
#
|
12
13
|
# Inits packager with the given sources.
|
13
14
|
#
|
15
|
+
# @param [SourceFile] source files
|
16
|
+
# @api public
|
14
17
|
def initialize(*sources)
|
15
18
|
self.container = Container.new(*sources)
|
16
19
|
end
|
17
20
|
|
18
|
-
|
21
|
+
# @return [Jsus::Container] container with source files
|
22
|
+
# @api public
|
23
|
+
def sources
|
19
24
|
container
|
20
25
|
end
|
21
26
|
|
22
|
-
#
|
23
27
|
# Concatenates all the sources' contents into a single string.
|
24
28
|
# If given a filename, outputs into a file.
|
25
29
|
#
|
26
|
-
#
|
27
|
-
#
|
30
|
+
# @param [String, nil] output file name
|
31
|
+
# @return [String] concatenated source files
|
32
|
+
# @api public
|
28
33
|
def pack(output_file = nil)
|
29
34
|
result = sources.map {|s| s.content }.join("\n")
|
30
35
|
|
@@ -32,10 +37,10 @@ module Jsus
|
|
32
37
|
FileUtils.mkdir_p(File.dirname(output_file))
|
33
38
|
File.open(output_file, "w") {|f| f << result }
|
34
39
|
end
|
35
|
-
|
40
|
+
|
36
41
|
result
|
37
42
|
end
|
38
43
|
|
39
|
-
|
44
|
+
|
40
45
|
end
|
41
|
-
end
|
46
|
+
end
|
data/lib/jsus/pool.rb
CHANGED
@@ -12,32 +12,33 @@ module Jsus
|
|
12
12
|
#
|
13
13
|
# Basic constructor.
|
14
14
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
15
|
+
# @param [Array, String, nil] directory or list of directories to load source
|
16
|
+
# packages from.
|
17
|
+
# @api public
|
18
|
+
def initialize(dir_or_dirs = nil)
|
19
|
+
if dir_or_dirs
|
20
|
+
directories = Array(dir_or_dirs)
|
21
|
+
directories.each do |dir|
|
22
|
+
# '**{,/*/**}' thingie is to resolve problem with not following symlinks
|
23
|
+
# one level of symlinks
|
24
|
+
# See also: http://stackoverflow.com/questions/357754/can-i-traverse-symlinked-directories-in-ruby-with-a-glob
|
25
|
+
Dir[File.join(dir, '**{,/*/**}', 'package.{yml,json}')].uniq.each do |package_path|
|
26
|
+
Package.new(File.dirname(package_path), :pool => self)
|
27
|
+
end
|
24
28
|
end
|
25
29
|
end
|
26
30
|
flush_cache!
|
27
31
|
end
|
28
32
|
|
29
33
|
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
34
|
+
# @return [Array] array containing all the packages in the pool. Unordered.
|
35
|
+
# @api public
|
33
36
|
def packages
|
34
37
|
@packages ||= []
|
35
38
|
end
|
36
39
|
|
37
|
-
#
|
38
|
-
#
|
39
|
-
# Attention: the sources are no more ordered.
|
40
|
-
#
|
40
|
+
# @return [Array] array with all the sources in the pool. Unordered
|
41
|
+
# @api public
|
41
42
|
def sources
|
42
43
|
@sources ||= []
|
43
44
|
end
|
@@ -48,6 +49,9 @@ module Jsus
|
|
48
49
|
#
|
49
50
|
# If given a source file, returns the input.
|
50
51
|
#
|
52
|
+
# @param [String, Jsus::Tag, Jsus::SourceFile]
|
53
|
+
# @return [Jsus::SourceFile]
|
54
|
+
# @api public
|
51
55
|
def lookup(source_or_key)
|
52
56
|
case source_or_key
|
53
57
|
when String
|
@@ -66,8 +70,9 @@ module Jsus
|
|
66
70
|
#
|
67
71
|
# Looks up for dependencies for given file recursively.
|
68
72
|
#
|
69
|
-
#
|
70
|
-
#
|
73
|
+
# @param [String, Jsus::Tag, Jsus::SourceFile]
|
74
|
+
# @return [Jsus::Container] container with all the dependencies
|
75
|
+
# @api public
|
71
76
|
def lookup_dependencies(source_or_source_key)
|
72
77
|
source = lookup(source_or_source_key)
|
73
78
|
result = Container.new
|
@@ -82,9 +87,9 @@ module Jsus
|
|
82
87
|
result.sort!
|
83
88
|
end
|
84
89
|
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
90
|
+
# @param [String, Jsus::Tag]
|
91
|
+
# @return [Array] array with source files with extensions for given tag.
|
92
|
+
# @api public
|
88
93
|
def lookup_extensions(tag_or_tag_key)
|
89
94
|
tag = Tag[tag_or_tag_key]
|
90
95
|
extensions_map[tag]
|
@@ -93,12 +98,9 @@ module Jsus
|
|
93
98
|
#
|
94
99
|
# Pushes an item into a pool.
|
95
100
|
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
# * Array or Container (pushing all the contained source files into the pool)
|
100
|
-
#
|
101
|
-
# returns self.
|
101
|
+
# @param [Jsus::SourceFile, Jsus::Package, Array] items to push
|
102
|
+
# @return [self]
|
103
|
+
# @api public
|
102
104
|
def <<(source_or_sources_or_package)
|
103
105
|
case
|
104
106
|
when source_or_sources_or_package.kind_of?(SourceFile)
|
@@ -132,7 +134,7 @@ module Jsus
|
|
132
134
|
|
133
135
|
#
|
134
136
|
# Drops any cached info
|
135
|
-
#
|
137
|
+
# @api public
|
136
138
|
def flush_cache!
|
137
139
|
@cached_dependencies = {}
|
138
140
|
end
|
@@ -145,6 +147,9 @@ module Jsus
|
|
145
147
|
# You probably will find yourself using #include_dependencies instead.
|
146
148
|
# This method caches results locally, use flush_cache! to drop.
|
147
149
|
#
|
150
|
+
# @param [String, Jsus::Tag, Jsus::SourceFile]
|
151
|
+
# @return [Array] array of direct dependencies for given entity
|
152
|
+
# @api private
|
148
153
|
def lookup_direct_dependencies(source_or_source_key)
|
149
154
|
source = lookup(source_or_source_key)
|
150
155
|
@cached_dependencies[source] ||= lookup_direct_dependencies!(source)
|
@@ -153,6 +158,9 @@ module Jsus
|
|
153
158
|
#
|
154
159
|
# Performs the actual lookup for #lookup_direct_dependencies
|
155
160
|
#
|
161
|
+
# @param [String, Jsus::Tag, Jsus::SourceFile]
|
162
|
+
# @return [Array] array of direct dependencies for given entity
|
163
|
+
# @api private
|
156
164
|
def lookup_direct_dependencies!(source)
|
157
165
|
return [] unless source
|
158
166
|
|
@@ -165,24 +173,22 @@ module Jsus
|
|
165
173
|
end.flatten.map {|tag| lookup(tag) }
|
166
174
|
end
|
167
175
|
|
168
|
-
#
|
169
|
-
#
|
170
|
-
#
|
176
|
+
# @return [Jsus::Util::Tree] tree containing all the sources
|
177
|
+
# @api private
|
171
178
|
def source_tree
|
172
179
|
@source_tree ||= Util::Tree.new
|
173
180
|
end
|
174
181
|
|
175
|
-
#
|
176
|
-
#
|
177
|
-
#
|
182
|
+
# @return [Jsus::Util::Tree] tree containing all the provides tags
|
183
|
+
# @api private
|
178
184
|
def provides_tree
|
179
185
|
@provides_tree ||= Util::Tree.new
|
180
186
|
end
|
181
187
|
|
182
188
|
|
183
|
-
#
|
184
189
|
# Registers the source in both trees
|
185
|
-
#
|
190
|
+
# @param [Jsus::SourceFile]
|
191
|
+
# @api private
|
186
192
|
def add_source_to_trees(source)
|
187
193
|
if source.package
|
188
194
|
source_tree.insert("/" + source.package.name + "/" + File.basename(source.filename), source)
|
@@ -196,16 +202,24 @@ module Jsus
|
|
196
202
|
|
197
203
|
protected
|
198
204
|
|
199
|
-
|
205
|
+
# @return [Hash] map of provided tags onto source files. Used to check
|
206
|
+
# redeclaration.
|
207
|
+
# @api private
|
208
|
+
def provides_map
|
200
209
|
@provides_map ||= {}
|
201
210
|
end
|
202
211
|
|
203
|
-
|
212
|
+
# @return [Hash] map of extension tags onto source files. Used to check
|
213
|
+
# redeclaration.
|
214
|
+
# @api private
|
215
|
+
def extensions_map
|
204
216
|
@extensions_map ||= Hash.new{|hash, key| hash[key] = [] }
|
205
217
|
end
|
206
218
|
|
207
|
-
|
219
|
+
# @return [Hash] map of replacement tags onto source files.
|
220
|
+
# @api private
|
221
|
+
def replacement_map
|
208
222
|
@replacement_map ||= {}
|
209
223
|
end
|
210
224
|
end
|
211
|
-
end
|
225
|
+
end
|
data/lib/jsus/source_file.rb
CHANGED
@@ -5,22 +5,31 @@ module Jsus
|
|
5
5
|
#
|
6
6
|
# SourceFile is a base for any Jsus operation.
|
7
7
|
#
|
8
|
-
# It contains
|
8
|
+
# It contains general info about source as well as file content.
|
9
9
|
#
|
10
10
|
class SourceFile
|
11
|
-
|
11
|
+
# Filename relative to package root
|
12
|
+
attr_accessor :relative_filename
|
13
|
+
# Full filename
|
14
|
+
attr_accessor :filename
|
15
|
+
# Package owning the sourcefile
|
16
|
+
attr_accessor :package
|
17
|
+
|
12
18
|
# Constructors
|
13
19
|
|
14
20
|
# Basic constructor.
|
15
21
|
#
|
16
|
-
# You probably should use SourceFile.from_file instead.
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
22
|
+
# You probably should use SourceFile.from_file instead of this one.
|
23
|
+
#
|
24
|
+
# @param [Hash] options
|
25
|
+
# @option options [Jsus::Package] :package package to assign source file to.
|
26
|
+
# @option options [String] :relative_filename used in Package to generate
|
27
|
+
# tree structure of the source files
|
28
|
+
# @option options [String] :filename full filename for the given source file
|
29
|
+
# @option options [String] :content file content of the source file
|
30
|
+
# @option options [Jsus::Pool] :pool owner pool for that file
|
31
|
+
# @option options [String] :header header of the file
|
32
|
+
# @api semipublic
|
24
33
|
def initialize(options = {})
|
25
34
|
[:package, :header, :relative_filename, :filename, :content, :pool].each do |field|
|
26
35
|
send("#{field}=", options[field]) if options[field]
|
@@ -30,12 +39,13 @@ module Jsus
|
|
30
39
|
#
|
31
40
|
# Initializes a SourceFile given the filename and options
|
32
41
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
42
|
+
# @param [String]
|
43
|
+
# @param [Hash] options
|
44
|
+
# @option options [Jsus::Pool] :pool owning pool
|
45
|
+
# @option options [Jsus::Package] :package owning package
|
46
|
+
# @return [Jsus::SourceFile]
|
47
|
+
# @raise [Jsus::BadSourceFileException] when file cannot be parsed
|
48
|
+
# @api public
|
39
49
|
def self.from_file(filename, options = {})
|
40
50
|
if File.exists?(filename)
|
41
51
|
source = File.open(filename, 'r:utf-8') {|f| f.read }
|
@@ -64,121 +74,116 @@ module Jsus
|
|
64
74
|
|
65
75
|
# Public API
|
66
76
|
|
67
|
-
#
|
68
|
-
#
|
69
|
-
# Contains information about authorship, naming, source files, etc.
|
70
|
-
#
|
77
|
+
# @return [Hash] a header parsed from YAML-formatted source file first comment.
|
78
|
+
# @api public
|
71
79
|
def header
|
72
80
|
self.header = {} unless @header
|
73
81
|
@header
|
74
82
|
end
|
75
83
|
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
84
|
+
# @return [String] description of the source file.
|
85
|
+
# @api public
|
79
86
|
def description
|
80
87
|
header["description"]
|
81
88
|
end
|
82
89
|
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
90
|
+
# @return [Array] list of dependencies for given file
|
91
|
+
# @api public
|
86
92
|
def dependencies
|
87
93
|
@dependencies
|
88
94
|
end
|
89
95
|
alias_method :requires, :dependencies
|
90
96
|
|
91
97
|
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
# Doesn't change anything for external dependencies
|
98
|
+
# @param [Hash] options
|
99
|
+
# @option options [Boolean] :short whether inner dependencies should not
|
100
|
+
# prepend package name, e.g. 'Class' instead of 'Core/Class' when in
|
101
|
+
# package 'Core'.
|
97
102
|
#
|
103
|
+
# Note Doesn't change anything for external dependencies
|
104
|
+
#
|
105
|
+
# @return [Array] array with names of dependencies. Unordered.
|
106
|
+
# @api public
|
98
107
|
def dependencies_names(options = {})
|
99
108
|
dependencies.map {|d| d.name(options) }
|
100
109
|
end
|
101
110
|
alias_method :requires_names, :dependencies_names
|
102
111
|
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
112
|
+
# @return [Array] array of external dependencies tags. Unordered.
|
113
|
+
# @api public
|
106
114
|
def external_dependencies
|
107
115
|
dependencies.select {|d| d.external? }
|
108
116
|
end
|
109
117
|
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
118
|
+
# @returns [Array] array with names for external dependencies. Unordered.
|
119
|
+
# @api public
|
113
120
|
def external_dependencies_names
|
114
121
|
external_dependencies.map {|d| d.name }
|
115
122
|
end
|
116
123
|
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
124
|
+
# @return [Array] array with provides tags.
|
125
|
+
# @api public
|
120
126
|
def provides
|
121
127
|
@provides
|
122
128
|
end
|
123
129
|
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
130
|
+
# @param [Hash] options
|
131
|
+
# @option options [Boolean] :short whether provides should not prepend package
|
132
|
+
# name, e.g. 'Class' instead of 'Core/Class' when in package 'Core'.
|
133
|
+
# @return [Array] array with provides names.
|
134
|
+
# @api public
|
129
135
|
def provides_names(options = {})
|
130
136
|
provides.map {|p| p.name(options)}
|
131
137
|
end
|
132
138
|
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
139
|
+
# @return [Jsus::Tag] tag for replaced file, if any
|
140
|
+
# @api public
|
136
141
|
def replaces
|
137
142
|
@replaces
|
138
143
|
end
|
139
144
|
|
140
145
|
|
141
|
-
#
|
142
|
-
#
|
143
|
-
#
|
144
|
-
#
|
145
|
-
#
|
146
|
-
# the result.
|
147
|
-
#
|
146
|
+
# @returns [Jsus::Tag] tag for source file, for which this one is an extension.
|
147
|
+
# @example file Foo.js in package Core provides ['Class', 'Hash']. File
|
148
|
+
# Bar.js in package Bar extends 'Core/Class'. That means its contents would be
|
149
|
+
# appended to the Foo.js when compiling the result.
|
150
|
+
# @api public
|
148
151
|
def extends
|
149
152
|
@extends
|
150
153
|
end
|
151
154
|
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
155
|
+
# @return [Boolean] whether the source file is an extension.
|
156
|
+
# @api public
|
155
157
|
def extension?
|
156
158
|
extends && !extends.empty?
|
157
159
|
end
|
158
160
|
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
161
|
+
# @return [Array] array of included extensions for given source.
|
162
|
+
# @api public
|
162
163
|
def extensions
|
163
164
|
@extensions ||= []
|
164
165
|
@extensions = @extensions.flatten.compact.uniq
|
165
166
|
@extensions
|
166
167
|
end
|
167
168
|
|
168
|
-
|
169
|
+
# @param [Array] list of extensions for given file
|
170
|
+
# @api semipublic
|
171
|
+
def extensions=(new_value)
|
169
172
|
@extensions = new_value
|
170
173
|
end
|
171
174
|
|
172
|
-
#
|
173
|
-
# Looks up for extensions in the #pool and then includes
|
175
|
+
# Looks up for extensions in the pool and then includes
|
174
176
|
# extensions for all the provides tag this source file has.
|
175
177
|
# Caches the result.
|
176
178
|
#
|
179
|
+
# @api semipublic
|
177
180
|
def include_extensions
|
178
181
|
@included_extensions ||= include_extensions!
|
179
182
|
end
|
180
183
|
|
181
|
-
|
184
|
+
# @see #include_extensions
|
185
|
+
# @api semipublic
|
186
|
+
def include_extensions!
|
182
187
|
if pool
|
183
188
|
provides.each do |p|
|
184
189
|
extensions << pool.lookup_extensions(p)
|
@@ -186,19 +191,18 @@ module Jsus
|
|
186
191
|
end
|
187
192
|
end
|
188
193
|
|
189
|
-
#
|
190
|
-
#
|
191
|
-
#
|
192
|
-
#
|
194
|
+
# @return [Array] array of files required by this files including all the filenames for extensions.
|
195
|
+
# SourceFile filename always goes first, all the extensions are unordered.
|
196
|
+
# @api public
|
193
197
|
def required_files
|
194
198
|
include_extensions
|
195
199
|
[filename, extensions.map {|e| e.filename}].flatten
|
196
200
|
end
|
197
201
|
|
202
|
+
# @return [Hash] hash containing basic info with dependencies/provides tags' names
|
203
|
+
# and description for source file.
|
198
204
|
#
|
199
|
-
#
|
200
|
-
# and description for source file.
|
201
|
-
#
|
205
|
+
# @api public
|
202
206
|
def to_hash
|
203
207
|
{
|
204
208
|
"desc" => description,
|
@@ -207,12 +211,17 @@ module Jsus
|
|
207
211
|
}
|
208
212
|
end
|
209
213
|
|
210
|
-
|
214
|
+
# Human readable description of source file.
|
215
|
+
# @return [String]
|
216
|
+
# @api public
|
217
|
+
def inspect
|
211
218
|
self.to_hash.inspect
|
212
219
|
end
|
213
|
-
# Private API
|
214
220
|
|
215
|
-
|
221
|
+
# Parses header and gets info from it.
|
222
|
+
# @param [String] header content
|
223
|
+
# @api private
|
224
|
+
def header=(new_header)
|
216
225
|
@header = new_header
|
217
226
|
# prepare defaults
|
218
227
|
@header["description"] ||= ""
|
@@ -233,19 +242,28 @@ module Jsus
|
|
233
242
|
end
|
234
243
|
end
|
235
244
|
|
236
|
-
|
245
|
+
# @param [String] file content
|
246
|
+
# @api private
|
247
|
+
def content=(new_value)
|
237
248
|
@content = new_value
|
238
249
|
end
|
239
250
|
|
240
|
-
|
251
|
+
# @return [String] file contents, *including* extensions
|
252
|
+
# @api semipublic
|
253
|
+
def content
|
241
254
|
include_extensions
|
242
255
|
[@content, extensions.map {|e| e.content}].flatten.compact.join("\n")
|
243
256
|
end
|
244
257
|
|
245
|
-
|
258
|
+
# @return [String] Original file contents
|
259
|
+
# @api semipublic
|
260
|
+
def original_content
|
246
261
|
@content
|
247
262
|
end
|
248
263
|
|
264
|
+
# @param [Enumerable] list of tags
|
265
|
+
# @return [Array] normalized tags list
|
266
|
+
# @api private
|
249
267
|
def parse_tag_list(tag_list)
|
250
268
|
tag_list.map do |tag_name|
|
251
269
|
case tag_name
|
@@ -266,24 +284,31 @@ module Jsus
|
|
266
284
|
|
267
285
|
# Assigns an instance of Jsus::Pool to the source file.
|
268
286
|
# Also performs push to that pool.
|
287
|
+
# @param [Jsus::Pool]
|
288
|
+
# @api private
|
269
289
|
def pool=(new_value)
|
270
290
|
@pool = new_value
|
271
291
|
@pool << self if @pool
|
272
292
|
end
|
273
293
|
|
274
294
|
# A pool which the source file is assigned to. Used in #include_extensions!
|
295
|
+
# @return [Jsus::Pool]
|
296
|
+
# @api semipublic
|
275
297
|
def pool
|
276
298
|
@pool
|
277
299
|
end
|
278
300
|
|
279
|
-
|
301
|
+
# @api public
|
302
|
+
def ==(other)
|
280
303
|
eql?(other)
|
281
304
|
end
|
282
305
|
|
283
|
-
|
306
|
+
# @api public
|
307
|
+
def eql?(other)
|
284
308
|
other.kind_of?(SourceFile) && filename == other.filename
|
285
309
|
end
|
286
310
|
|
311
|
+
# @api public
|
287
312
|
def hash
|
288
313
|
[self.class, filename].hash
|
289
314
|
end
|