jsus 0.3.6 → 0.4.0
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/.travis.yml +2 -0
- data/CHANGELOG +5 -0
- data/Gemfile +7 -4
- data/VERSION +1 -1
- data/bin/jsus +1 -5
- data/cucumber.yml +1 -1
- data/features/command-line/external_dependency_resolution.feature +4 -4
- data/features/command-line/generate_includes.feature +34 -0
- data/features/command-line/mooforge_compatibility_layer.feature +1 -1
- data/features/command-line/postproc.feature +12 -3
- data/features/command-line/structure_json.feature +5 -40
- data/features/data/ExternalDependencyWithExternalDependency/Leonardo/Source/Core.js +2 -2
- data/features/step_definitions/cli_steps.rb +15 -9
- data/features/support/env.rb +1 -1
- data/jsus.gemspec +25 -7
- data/lib/extensions/rgl.rb +2 -1
- data/lib/jsus/cli.rb +43 -27
- data/lib/jsus/container.rb +71 -51
- data/lib/jsus/middleware.rb +2 -3
- data/lib/jsus/package.rb +27 -129
- data/lib/jsus/packager.rb +10 -6
- data/lib/jsus/pool.rb +48 -20
- data/lib/jsus/source_file.rb +119 -198
- data/lib/jsus/tag.rb +72 -106
- data/lib/jsus/util.rb +14 -4
- data/lib/jsus/util/compressor.rb +1 -1
- data/lib/jsus/util/documenter.rb +1 -1
- data/lib/jsus/util/mixins.rb +7 -0
- data/lib/jsus/util/mixins/operates_on_sources.rb +29 -0
- data/lib/jsus/util/post_processor.rb +35 -0
- data/lib/jsus/util/post_processor/base.rb +32 -0
- data/lib/jsus/util/post_processor/moocompat12.rb +19 -0
- data/lib/jsus/util/post_processor/mooltie8.rb +19 -0
- data/lib/jsus/util/post_processor/semicolon.rb +18 -0
- data/lib/jsus/util/validator/base.rb +3 -23
- data/lib/jsus/util/watcher.rb +8 -6
- data/spec/data/Extensions/app/javascripts/Core/Source/Hash.js +13 -0
- data/spec/data/Extensions/app/javascripts/Core/Source/Mash.js +13 -0
- data/spec/data/Extensions/app/javascripts/Core/package.yml +3 -1
- data/spec/data/Extensions/app/javascripts/Orwik/Extensions/Mash.js +16 -0
- data/spec/data/Extensions/app/javascripts/Orwik/package.yml +2 -1
- data/spec/data/OutsideDependencies/app/javascripts/Orwik/package.yml +3 -3
- data/spec/data/SimpleSources/dependent_source_one.js +15 -0
- data/spec/data/SimpleSources/replacement_source_one.js +13 -0
- data/spec/data/SimpleSources/simple_source_one.js +13 -0
- data/spec/data/SimpleSources/simple_source_two.js +13 -0
- data/spec/data/extension_1.js +15 -0
- data/spec/data/extension_2.js +15 -0
- data/spec/data/replacement.js +15 -0
- data/spec/jsus/container_spec.rb +72 -14
- data/spec/jsus/package_spec.rb +10 -128
- data/spec/jsus/packager_spec.rb +11 -11
- data/spec/jsus/pool_spec.rb +13 -22
- data/spec/jsus/source_file_spec.rb +66 -215
- data/spec/jsus/tag_spec.rb +24 -69
- data/spec/jsus/util/documenter_spec.rb +1 -1
- data/spec/jsus/util/post_processor/moocompat12_spec.rb +23 -0
- data/spec/jsus/util/post_processor/mooltie8_spec.rb +23 -0
- data/spec/jsus/util/post_processor/semicolon_spec.rb +21 -0
- data/spec/jsus/util/post_processors/base_spec.rb +6 -0
- data/spec/jsus/util/tree_spec.rb +3 -3
- data/spec/jsus/util/validator/base_spec.rb +4 -2
- data/spec/jsus/util/watcher_spec.rb +12 -2
- data/spec/shared/mixins_segs.rb +38 -0
- data/spec/spec_helper.rb +6 -0
- metadata +28 -10
- data/features/data/tmp2/package.js +0 -35
- data/features/data/tmp2/scripts.json +0 -13
- data/features/data/tmp2/tree.json +0 -26
- data/lib/jsus/compiler.rb +0 -28
- data/spec/shared/class_stubs.rb +0 -31
data/lib/jsus/container.rb
CHANGED
@@ -11,6 +11,10 @@ module Jsus
|
|
11
11
|
#
|
12
12
|
# @param [*SourceFile] sources
|
13
13
|
def initialize(*sources)
|
14
|
+
@sources = []
|
15
|
+
@normal_sources = []
|
16
|
+
@extensions = []
|
17
|
+
@replacements = []
|
14
18
|
sources.each do |source|
|
15
19
|
push(source)
|
16
20
|
end
|
@@ -23,10 +27,18 @@ module Jsus
|
|
23
27
|
# @param [SourceFile] source source pushed file
|
24
28
|
def push(source)
|
25
29
|
if source
|
26
|
-
if source.kind_of?(Array)
|
30
|
+
if source.kind_of?(Array)
|
27
31
|
source.each {|s| self.push(s) }
|
32
|
+
elsif source.kind_of?(Container)
|
33
|
+
source.all_sources.each {|s| self.push(s) }
|
28
34
|
else
|
29
|
-
|
35
|
+
if source.extension?
|
36
|
+
@extensions << source unless @extensions.include?(source)
|
37
|
+
elsif source.replacement?
|
38
|
+
@replacements << source unless @replacements.include?(source)
|
39
|
+
else
|
40
|
+
@normal_sources << source unless @normal_sources.include?(source)
|
41
|
+
end
|
30
42
|
end
|
31
43
|
end
|
32
44
|
clear_cache!
|
@@ -41,23 +53,24 @@ module Jsus
|
|
41
53
|
map {|item| item.respond_to?(:flatten) ? item.flatten : item }.flatten
|
42
54
|
end
|
43
55
|
|
44
|
-
# Contains the source files.
|
45
|
-
# depend on them to be topologically sorted. Use collection methods like
|
46
|
-
# inject/reject/map directly on the container instead.
|
56
|
+
# Contains the source files.
|
47
57
|
#
|
48
58
|
# @return [Array]
|
49
|
-
# @api
|
59
|
+
# @api public
|
50
60
|
def sources
|
51
|
-
|
61
|
+
sort!
|
62
|
+
@sources
|
52
63
|
end
|
53
64
|
alias_method :to_a, :sources
|
54
65
|
|
55
|
-
#
|
66
|
+
# Includes all sources, even those that would normally be replaced.
|
67
|
+
# Without any order.
|
56
68
|
#
|
69
|
+
# @return [Array]
|
57
70
|
# @api semipublic
|
58
|
-
def
|
59
|
-
@
|
60
|
-
end
|
71
|
+
def all_sources
|
72
|
+
@normal_sources + @extensions + @replacements
|
73
|
+
end # all_sources
|
61
74
|
|
62
75
|
# Topologically sorts items in container if required.
|
63
76
|
#
|
@@ -65,8 +78,10 @@ module Jsus
|
|
65
78
|
# @api semipublic
|
66
79
|
def sort!
|
67
80
|
unless sorted?
|
68
|
-
|
69
|
-
|
81
|
+
@sources = topsort
|
82
|
+
insert_extensions!
|
83
|
+
insert_replacements!
|
84
|
+
@sources.uniq!
|
70
85
|
@sorted = true
|
71
86
|
end
|
72
87
|
self
|
@@ -106,6 +121,23 @@ module Jsus
|
|
106
121
|
"#<#{self.class.name}:#{self.object_id} #{self.sources.inspect}>"
|
107
122
|
end
|
108
123
|
|
124
|
+
# Returns all the tags provided by source files.
|
125
|
+
# @return [Array]
|
126
|
+
# @api public
|
127
|
+
def provides
|
128
|
+
sort!
|
129
|
+
sources.map {|s| s.provides }.flatten
|
130
|
+
end # provides
|
131
|
+
|
132
|
+
# Returns all the tags required by source files, except for those which are
|
133
|
+
# provided by other files in the container (i.e. unresolved dependencies)
|
134
|
+
# @return [Array]
|
135
|
+
# @api public
|
136
|
+
def requires
|
137
|
+
sort!
|
138
|
+
sources.map {|s| s.requires }.flatten - provides
|
139
|
+
end # requires
|
140
|
+
|
109
141
|
# Private API
|
110
142
|
|
111
143
|
# Performs topological sort inside current container.
|
@@ -114,7 +146,7 @@ module Jsus
|
|
114
146
|
def topsort
|
115
147
|
graph = RGL::DirectedAdjacencyGraph.new
|
116
148
|
# init vertices
|
117
|
-
items =
|
149
|
+
items = @normal_sources
|
118
150
|
items.each {|item| graph.add_vertex(item) }
|
119
151
|
# init edges
|
120
152
|
items.each do |item|
|
@@ -177,58 +209,47 @@ module Jsus
|
|
177
209
|
def provides_tree!
|
178
210
|
tree = Util::Tree.new
|
179
211
|
# Provisions
|
180
|
-
|
181
|
-
file.provides
|
182
|
-
|
212
|
+
@normal_sources.each do |file|
|
213
|
+
provisions = file.provides
|
214
|
+
if replacement = @replacements.detect {|r| provisions.any? {|tag| tag == r.replaces } }
|
215
|
+
file = replacement
|
183
216
|
end
|
184
|
-
|
185
|
-
|
186
|
-
sources.each do |file|
|
187
|
-
if file.replaces
|
188
|
-
tree[file.replaces] = file
|
217
|
+
provisions.each do |tag|
|
218
|
+
tree[tag] = file
|
189
219
|
end
|
190
220
|
end
|
191
221
|
tree
|
192
222
|
end
|
193
223
|
|
194
|
-
# Removes files which are marked as replaced by other sources.
|
195
|
-
#
|
196
224
|
# @api private
|
197
|
-
def
|
198
|
-
|
199
|
-
|
225
|
+
def insert_extensions!
|
226
|
+
@extensions.each do |ext|
|
227
|
+
ext_tag = ext.extends
|
228
|
+
@sources.dup.each_with_index do |src, i|
|
229
|
+
if src.provides.any? {|tag| tag == ext_tag }
|
230
|
+
@sources.insert(i+1, ext)
|
231
|
+
break
|
232
|
+
end
|
233
|
+
end
|
200
234
|
end
|
201
|
-
end
|
202
|
-
|
203
|
-
# Cached tree of what source files replace.
|
204
|
-
#
|
205
|
-
# @api private
|
206
|
-
# @return [Jsus::Util::Tree]
|
207
|
-
def replacements_tree
|
208
|
-
@replacements_tree ||= replacements_tree!
|
209
|
-
end
|
235
|
+
end # insert_extensions!
|
210
236
|
|
211
|
-
# Returns tree of what source files replace.
|
212
|
-
#
|
213
237
|
# @api private
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
238
|
+
def insert_replacements!
|
239
|
+
@replacements.each do |repl|
|
240
|
+
@sources.each_with_index do |src, i|
|
241
|
+
if src.provides.any? {|tag| tag == repl.replaces }
|
242
|
+
@sources[i] = repl
|
243
|
+
break
|
244
|
+
end
|
220
245
|
end
|
221
246
|
end
|
222
|
-
|
223
|
-
end
|
247
|
+
end # insert_replacements!
|
224
248
|
|
225
249
|
# Clears all caches for given container.
|
226
250
|
#
|
227
251
|
# @api private
|
228
252
|
def clear_cache!
|
229
|
-
@provides_tree = nil
|
230
|
-
@replacements_tree = nil
|
231
|
-
@dependency_cache = nil
|
232
253
|
@sorted = false
|
233
254
|
end
|
234
255
|
|
@@ -246,9 +267,8 @@ module Jsus
|
|
246
267
|
]
|
247
268
|
|
248
269
|
(DELEGATED_METHODS).each do |m|
|
249
|
-
class_eval
|
270
|
+
class_eval(<<-EVAL, __FILE__, __LINE__ + 1)
|
250
271
|
def #{m}(*args, &block)
|
251
|
-
sort!
|
252
272
|
#{"clear_cache!" if CACHE_CLEAR_METHODS.include?(m)}
|
253
273
|
self.sources.send(:#{m}, *args, &block)
|
254
274
|
end
|
data/lib/jsus/middleware.rb
CHANGED
@@ -175,7 +175,7 @@ module Jsus
|
|
175
175
|
def generate_requires(path_string)
|
176
176
|
files = path_string_to_files(path_string)
|
177
177
|
if !files.empty?
|
178
|
-
response = Container.new(*files).map {|f| f.
|
178
|
+
response = Container.new(*files).map {|f| f.source }.join("\n")
|
179
179
|
response = Jsus::Util::Compressor.compress(response, :method => self.class.settings[:compression_method]) if request_options[:compress]
|
180
180
|
respond_with(response)
|
181
181
|
else
|
@@ -262,8 +262,7 @@ module Jsus
|
|
262
262
|
# @api semipublic
|
263
263
|
def get_associated_files(source_file_or_package)
|
264
264
|
if package = pool.packages.detect {|pkg| pkg.name == source_file_or_package}
|
265
|
-
package.
|
266
|
-
package.linked_external_dependencies.to_a + package.source_files.to_a
|
265
|
+
pool.compile_package(package).to_a
|
267
266
|
elsif source_file = pool.lookup(source_file_or_package)
|
268
267
|
pool.lookup_dependencies(source_file).to_a << source_file
|
269
268
|
else
|
data/lib/jsus/package.rb
CHANGED
@@ -3,6 +3,7 @@ module Jsus
|
|
3
3
|
# Package is a (self-contained) unit with all the info required to build
|
4
4
|
# a javascript package.
|
5
5
|
#
|
6
|
+
|
6
7
|
class Package
|
7
8
|
# directory which this package resides in (full path)
|
8
9
|
attr_accessor :directory
|
@@ -10,29 +11,27 @@ module Jsus
|
|
10
11
|
attr_accessor :pool
|
11
12
|
|
12
13
|
# Constructors
|
13
|
-
|
14
14
|
#
|
15
15
|
# Creates a package from given directory.
|
16
16
|
#
|
17
17
|
# @param [String] directory path to directory containing a package
|
18
|
-
# @
|
19
|
-
#
|
20
|
-
# @raise an error when the given directory doesn't contain a package.yml or package.json
|
21
|
-
# file with meta info.
|
18
|
+
# @raise [RuntimeError] when the given directory doesn't contain a
|
19
|
+
# package.yml or package.json file with meta info.
|
22
20
|
# @api public
|
23
|
-
def initialize(directory
|
21
|
+
def initialize(directory)
|
24
22
|
self.directory = File.expand_path(directory)
|
25
|
-
if File.exists?(File.join(directory, 'package.yml'))
|
26
|
-
|
23
|
+
@header = if File.exists?(File.join(directory, 'package.yml'))
|
24
|
+
YAML.load_file(File.join(directory, 'package.yml'))
|
27
25
|
elsif File.exists?(File.join(directory, 'package.json'))
|
28
|
-
|
26
|
+
JSON.load(Jsus::Util.read_file(File.join(directory, 'package.json')))
|
29
27
|
else
|
30
28
|
Jsus.logger.fatal "Directory #{directory} does not contain a valid package.yml / package.json file!"
|
31
29
|
raise "Directory #{directory} does not contain a valid package.yml / package.json file!"
|
32
30
|
end
|
33
31
|
Dir.chdir(directory) do
|
34
|
-
files.each do |
|
35
|
-
source_file = SourceFile.from_file(
|
32
|
+
files.each do |filename|
|
33
|
+
source_file = SourceFile.from_file(filename, :namespace => name)
|
34
|
+
source_file.package = self
|
36
35
|
if source_file
|
37
36
|
if source_file.extension?
|
38
37
|
extensions << source_file
|
@@ -40,14 +39,10 @@ module Jsus
|
|
40
39
|
source_files << source_file
|
41
40
|
end
|
42
41
|
else
|
43
|
-
Jsus.logger.warn "#{
|
42
|
+
Jsus.logger.warn "#{filename} is not found for #{name}"
|
44
43
|
end
|
45
44
|
end
|
46
45
|
end
|
47
|
-
if options[:pool]
|
48
|
-
self.pool = options[:pool]
|
49
|
-
self.pool << self
|
50
|
-
end
|
51
46
|
end
|
52
47
|
|
53
48
|
|
@@ -82,115 +77,23 @@ module Jsus
|
|
82
77
|
def files
|
83
78
|
header["files"] = header["files"] || header["sources"] || []
|
84
79
|
end
|
85
|
-
alias_method :sources, :files
|
86
80
|
|
87
|
-
# @return [Array] an array of provided tags
|
81
|
+
# @return [Array] an array of provided tags
|
88
82
|
# @api public
|
89
83
|
def provides
|
90
|
-
source_files.map {|s| s.provides }.flatten
|
91
|
-
end
|
92
|
-
|
93
|
-
# @return [Array] an array of provided tags names including those provided by linked external dependencies.
|
94
|
-
# @api public
|
95
|
-
def provides_names
|
96
|
-
source_files.map {|s| s.provides_names(:short => true) }.flatten |
|
97
|
-
linked_external_dependencies.map {|d| d.provides_names }.flatten
|
84
|
+
source_files.map {|s| s.provides }.flatten
|
98
85
|
end
|
86
|
+
alias_method :provisions, :provides
|
99
87
|
|
100
|
-
# @return [Array]
|
88
|
+
# @return [Array] array dependencies tags for all source files in the package
|
101
89
|
# @api public
|
102
90
|
def dependencies
|
103
91
|
result = source_files.map {|source| source.dependencies }.flatten
|
104
|
-
result |= linked_external_dependencies.map {|d| d.dependencies}.flatten
|
105
92
|
result -= provides
|
106
93
|
result
|
107
94
|
end
|
108
|
-
|
109
|
-
|
110
|
-
# @api public
|
111
|
-
def dependencies_names
|
112
|
-
dependencies.map {|d| d.name(:short => true) }
|
113
|
-
end
|
114
|
-
|
115
|
-
# @return [Array] an array of external dependencies' tags (including resolved ones).
|
116
|
-
# @api public
|
117
|
-
def external_dependencies
|
118
|
-
source_files.map {|s| s.external_dependencies }.flatten
|
119
|
-
end
|
120
|
-
|
121
|
-
# @return [Array] an array of external dependencies' names (including resolved ones).
|
122
|
-
# @api public
|
123
|
-
def external_dependencies_names
|
124
|
-
external_dependencies.map {|d| d.name }
|
125
|
-
end
|
126
|
-
|
127
|
-
# @return [Jsus::Container] source files with external dependencies in correct order.
|
128
|
-
# @api public
|
129
|
-
def linked_external_dependencies
|
130
|
-
@linked_external_dependencies ||= Container.new
|
131
|
-
end
|
132
|
-
|
133
|
-
# Compiles source files and linked external source files into a given category.
|
134
|
-
# @param [String, nil] directory directory to output the result into
|
135
|
-
# @return [String] content of merged source files
|
136
|
-
# @api public
|
137
|
-
def compile(directory = ".")
|
138
|
-
fn = directory ? File.join(directory, filename) : nil
|
139
|
-
Packager.new(*(source_files.to_a + linked_external_dependencies.to_a)).pack(fn)
|
140
|
-
end
|
141
|
-
|
142
|
-
# Generates tree structure for files in package into a json file.
|
143
|
-
# @param [String] directory directory to output the result
|
144
|
-
# @param [String] filename resulting filename
|
145
|
-
# @return [Hash] hash with tree structure
|
146
|
-
# @api public
|
147
|
-
def generate_tree(directory = ".", filename = "tree.json")
|
148
|
-
FileUtils.mkdir_p(directory)
|
149
|
-
result = ActiveSupport::OrderedHash.new
|
150
|
-
source_files.each do |source|
|
151
|
-
components = File.dirname(source.relative_filename).split(File::SEPARATOR)
|
152
|
-
# deleting source dir by convention
|
153
|
-
components.delete("Source")
|
154
|
-
node = result
|
155
|
-
components.each do |component|
|
156
|
-
node[component] ||= ActiveSupport::OrderedHash.new
|
157
|
-
node = node[component]
|
158
|
-
end
|
159
|
-
node[File.basename(source.filename, ".js")] = source.to_hash
|
160
|
-
end
|
161
|
-
File.open(File.join(directory, filename), "w") { |resulting_file| resulting_file << JSON.pretty_generate(result) }
|
162
|
-
result
|
163
|
-
end
|
164
|
-
|
165
|
-
# Generates info about resulting compiled package into a json file.
|
166
|
-
# @param [String] directory directory to output the result
|
167
|
-
# @param [String] filename resulting filename
|
168
|
-
# @return [Hash] hash with scripts info
|
169
|
-
# @api public
|
170
|
-
def generate_scripts_info(directory = ".", filename = "scripts.json")
|
171
|
-
FileUtils.mkdir_p directory
|
172
|
-
File.open(File.join(directory, filename), "w") { |resulting_file| resulting_file << JSON.pretty_generate(self.to_hash) }
|
173
|
-
self.to_hash
|
174
|
-
end
|
175
|
-
|
176
|
-
# Looks up all the external dependencies in the pool.
|
177
|
-
# @api semipublic
|
178
|
-
def include_dependencies!
|
179
|
-
source_files.each do |source|
|
180
|
-
if pool
|
181
|
-
deps = pool.lookup_dependencies(source).to_a - @source_files.to_a
|
182
|
-
linked_external_dependencies << deps
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
# Executes #include_extensions for all the source files.
|
188
|
-
# @api semipublic
|
189
|
-
def include_extensions!
|
190
|
-
source_files.each do |source|
|
191
|
-
source.include_extensions!
|
192
|
-
end
|
193
|
-
end
|
95
|
+
alias_method :requires, :dependencies
|
96
|
+
alias_method :requirements, :dependencies
|
194
97
|
|
195
98
|
# Lists the required files for the package.
|
196
99
|
# @return [Array] ordered list of full paths to required files.
|
@@ -200,30 +103,31 @@ module Jsus
|
|
200
103
|
end
|
201
104
|
|
202
105
|
# Hash representation of the package.
|
106
|
+
# @return [Hash]
|
203
107
|
# @api public
|
204
108
|
def to_hash
|
205
109
|
{
|
206
110
|
name => {
|
207
|
-
:
|
208
|
-
:provides
|
209
|
-
:requires
|
111
|
+
:description => description,
|
112
|
+
:provides => provides.map {|tag| tag.name },
|
113
|
+
:requires => requires.map {|tag| tag.namespace == name ? tag.name : tag.full_name }
|
210
114
|
}
|
211
115
|
}
|
212
116
|
end
|
213
117
|
|
214
118
|
|
215
|
-
#
|
216
|
-
# @return [
|
119
|
+
# Array with source files
|
120
|
+
# @return [Array]
|
217
121
|
# @api semipublic
|
218
122
|
def source_files
|
219
|
-
@source_files ||=
|
123
|
+
@source_files ||= []
|
220
124
|
end
|
221
125
|
|
222
|
-
#
|
223
|
-
# @return [
|
126
|
+
# Array with extensions
|
127
|
+
# @return [Array]
|
224
128
|
# @api semipublic
|
225
129
|
def extensions
|
226
|
-
@extensions ||=
|
130
|
+
@extensions ||= []
|
227
131
|
end
|
228
132
|
|
229
133
|
# Private API
|
@@ -234,11 +138,5 @@ module Jsus
|
|
234
138
|
def header=(new_header)
|
235
139
|
@header = new_header
|
236
140
|
end
|
237
|
-
|
238
|
-
# @param [Enumerable] new_value external dependencies
|
239
|
-
# @api private
|
240
|
-
def linked_external_dependencies=(new_value)
|
241
|
-
@linked_external_dependencies = new_value
|
242
|
-
end
|
243
141
|
end
|
244
142
|
end
|