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