jsus 0.3.6 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/tag.rb
CHANGED
@@ -6,46 +6,51 @@ module Jsus
|
|
6
6
|
# @example
|
7
7
|
# "Core/Class" is a tag
|
8
8
|
class Tag
|
9
|
-
#
|
10
|
-
|
11
|
-
# Whether tag is external
|
12
|
-
attr_accessor :external
|
9
|
+
# Default separator of full name parts
|
10
|
+
SEPARATOR = "/".freeze
|
13
11
|
|
14
12
|
# Constructors
|
15
13
|
|
16
14
|
#
|
17
|
-
# Creates a tag from given
|
18
|
-
#
|
19
|
-
# The way it works may seem a bit tricky but actually it parses name/options
|
20
|
-
# combinations in different ways and may be best described by examples:
|
15
|
+
# Creates a tag from given string.
|
21
16
|
#
|
22
17
|
# @example
|
23
18
|
#
|
24
|
-
# a = Tag.new("Class")
|
25
|
-
# b = Tag.new("Core/Class")
|
26
|
-
#
|
27
|
-
# c = Tag.new("Class", :package => core) # :package_name => "Core", :name => "Class", :external => false
|
28
|
-
# d = Tag.new("Core/Class", :package => core) # :package_name => "Core", :name => "Class", :external => false
|
29
|
-
# mash = Package.new(...) # let's consider its name is 'Mash'
|
30
|
-
# e = Tag.new("Core/Class", :package => mash) # :package_name => "Core", :name => "Class", :external => true
|
31
|
-
#
|
32
|
-
# Between all those, tags b,c,d and e are equal, meaning they all use
|
33
|
-
# the same spot in Hash or wherever else.
|
19
|
+
# a = Tag.new("Class") # :namespace => nil, :name => "Class"
|
20
|
+
# b = Tag.new("Core/Class") # :namespace => "Core", :name => "Class"
|
21
|
+
# c = Tag.new("Mootools/Core") # :namespace => "Mootools/Core", :name => "Class"
|
34
22
|
#
|
35
|
-
# @param [String] name tag name
|
36
|
-
# @param [Hash] options
|
37
|
-
# @option options [String] :package_name owner package name
|
38
|
-
# @option options [Jsus::Package] :package :owner package
|
39
|
-
# @option options [Boolean] :external whether tag is considered external
|
23
|
+
# @param [String] name full tag name
|
40
24
|
# @api public
|
41
|
-
def initialize(
|
42
|
-
|
43
|
-
[:name, :package, :package_name, :external].each do |field|
|
44
|
-
self.send("#{field}=", normalized_options[field])
|
45
|
-
end
|
25
|
+
def initialize(full_name)
|
26
|
+
self.full_name = full_name
|
46
27
|
end
|
47
28
|
|
48
|
-
#
|
29
|
+
# Full name, including namespace
|
30
|
+
# @return [String]
|
31
|
+
# @api public
|
32
|
+
def full_name
|
33
|
+
if namespace
|
34
|
+
"#{namespace}#{SEPARATOR}#{name}"
|
35
|
+
else
|
36
|
+
"#{name}"
|
37
|
+
end
|
38
|
+
end # full_name
|
39
|
+
alias_method :to_s, :full_name
|
40
|
+
|
41
|
+
|
42
|
+
# Assigns full name
|
43
|
+
# @param [String] full_name full tag name, including namespace
|
44
|
+
# @api semipublic
|
45
|
+
def full_name=(full_name)
|
46
|
+
@full_name = full_name
|
47
|
+
name_parts = @full_name.split(SEPARATOR)
|
48
|
+
self.namespace = name_parts[0..-2].join(SEPARATOR) if name_parts.size > 1
|
49
|
+
self.name = name_parts[-1]
|
50
|
+
end # full_name=
|
51
|
+
|
52
|
+
# Instantiates a tag.
|
53
|
+
# @note When given a tag instead of tag name, returns the input
|
49
54
|
# @api public
|
50
55
|
def self.new(tag_or_name, *args, &block)
|
51
56
|
if tag_or_name.kind_of?(Tag)
|
@@ -63,46 +68,56 @@ module Jsus
|
|
63
68
|
|
64
69
|
# Public API
|
65
70
|
|
66
|
-
#
|
67
|
-
# @api public
|
68
|
-
def external?
|
69
|
-
!!external
|
70
|
-
end
|
71
|
-
|
72
|
-
# @param [Hash] options
|
73
|
-
# @option options [Boolean] :short whether the tag should try using short form
|
74
|
-
# @note only non-external tags support short forms.
|
71
|
+
# Returns the last part of the tag.
|
75
72
|
# @example
|
76
|
-
# Tag.new('Core/Class').name
|
77
|
-
#
|
78
|
-
# Tag.new('Core/Class', :package => core).name(:short => true) # => 'Class'
|
79
|
-
# @return [String] a well-formed name for the tag.
|
73
|
+
# Tag.new('Core/Class').name # => 'Class'
|
74
|
+
# @return [String] last part of the tag
|
80
75
|
# @api public
|
81
|
-
def name
|
82
|
-
|
83
|
-
@name
|
84
|
-
else
|
85
|
-
"#{package_name}/#{@name}"
|
86
|
-
end
|
76
|
+
def name
|
77
|
+
@name
|
87
78
|
end
|
88
|
-
alias_method :to_s, :name
|
89
79
|
|
90
|
-
#
|
80
|
+
# Set name.
|
81
|
+
# @param [String] name
|
82
|
+
# @api semipublic
|
83
|
+
def name=(name)
|
84
|
+
@name = normalize(name)
|
85
|
+
end # name=
|
86
|
+
|
87
|
+
|
88
|
+
# Name without namespace
|
89
|
+
# @return [String]
|
91
90
|
# @api public
|
92
|
-
|
93
|
-
|
94
|
-
|
91
|
+
attr_reader :namespace
|
92
|
+
|
93
|
+
# Set namespace
|
94
|
+
# @param [String] namespace
|
95
|
+
# @api semipublic
|
96
|
+
def namespace=(namespace)
|
97
|
+
@namespace = normalize(namespace)
|
98
|
+
end # namespace=
|
99
|
+
|
100
|
+
# Normalizes name or namespace (converts snake_case to MixedCase)
|
101
|
+
# @param [String] string
|
102
|
+
# @return [String]
|
103
|
+
# @api semipublic
|
104
|
+
def normalize(string)
|
105
|
+
return unless string
|
106
|
+
return string if string.include?("*")
|
107
|
+
parts = string.split(SEPARATOR)
|
108
|
+
parts.map {|part| Util::Inflection.random_case_to_mixed_case_preserve_dots(part) }.join(SEPARATOR)
|
109
|
+
end # normalize
|
95
110
|
|
96
111
|
# @return [Boolean] whether name is empty
|
97
112
|
# @api public
|
98
113
|
def empty?
|
99
|
-
@name.empty?
|
114
|
+
!@name || @name.empty?
|
100
115
|
end
|
101
116
|
|
102
117
|
# @api public
|
103
118
|
def ==(other)
|
104
119
|
if other.kind_of?(Tag)
|
105
|
-
self.name == other.name
|
120
|
+
self.name == other.name && self.namespace == other.namespace
|
106
121
|
else
|
107
122
|
super
|
108
123
|
end
|
@@ -115,62 +130,13 @@ module Jsus
|
|
115
130
|
|
116
131
|
# @api semipublic
|
117
132
|
def hash
|
118
|
-
self.name.hash
|
133
|
+
[self.name, self.namespace].hash
|
119
134
|
end
|
120
135
|
|
121
136
|
# @return [String] human-readable representation
|
122
137
|
# @api public
|
123
138
|
def inspect
|
124
|
-
"<Jsus::Tag: #{
|
125
|
-
end
|
126
|
-
|
127
|
-
# Private API
|
128
|
-
|
129
|
-
# @api private
|
130
|
-
def self.normalize_name_and_options(name, options = {})
|
131
|
-
result = {}
|
132
|
-
name.gsub!(%r(^(\.)?/), "")
|
133
|
-
if name.index("/")
|
134
|
-
parsed_name = name.split("/")
|
135
|
-
result[:package_name], result[:name] = parsed_name[0..-2].join("/"), parsed_name[-1]
|
136
|
-
result[:external] = options[:package] ? (result[:package_name] != options[:package].name) : true
|
137
|
-
else
|
138
|
-
if options[:package]
|
139
|
-
result[:package] = options[:package]
|
140
|
-
result[:package_name] = options[:package].name
|
141
|
-
end
|
142
|
-
result[:name] = name
|
143
|
-
end
|
144
|
-
result[:package_name] = normalize_package_name(result[:package_name]) if result[:package_name]
|
145
|
-
result
|
146
|
-
end
|
147
|
-
|
148
|
-
# @api private
|
149
|
-
def self.normalized_options_to_full_name(options)
|
150
|
-
[options[:package_name], options[:name]].compact.join("/")
|
151
|
-
end
|
152
|
-
|
153
|
-
# @api private
|
154
|
-
def self.name_and_options_to_full_name(name, options = {})
|
155
|
-
normalized_options_to_full_name(normalize_name_and_options(name, options))
|
156
|
-
end
|
157
|
-
|
158
|
-
# @api private
|
159
|
-
def self.normalize_package_name(name)
|
160
|
-
package_chunks = name.split("/")
|
161
|
-
package_chunks.map do |pc|
|
162
|
-
Jsus::Util::Inflection.random_case_to_mixed_case(pc)
|
163
|
-
end.join("/")
|
164
|
-
end # normalize_name
|
165
|
-
|
166
|
-
# @api private
|
167
|
-
def package_name=(new_value)
|
168
|
-
@package_name = new_value
|
169
|
-
end
|
170
|
-
|
171
|
-
# @api private
|
172
|
-
def name=(new_value)
|
173
|
-
@name = new_value
|
139
|
+
"<Jsus::Tag: #{full_name}>"
|
174
140
|
end
|
175
141
|
end
|
176
142
|
end
|
data/lib/jsus/util.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
module Jsus
|
2
2
|
# Utility namespace.
|
3
3
|
module Util
|
4
|
+
autoload :CodeGenerator, 'jsus/util/code_generator'
|
4
5
|
autoload :Compressor, 'jsus/util/compressor'
|
5
|
-
autoload :Tree, 'jsus/util/tree'
|
6
6
|
autoload :Documenter, 'jsus/util/documenter'
|
7
|
-
autoload :Validator, 'jsus/util/validator'
|
8
|
-
autoload :Inflection, 'jsus/util/inflection'
|
9
7
|
autoload :FileCache, 'jsus/util/file_cache'
|
10
|
-
autoload :
|
8
|
+
autoload :Inflection, 'jsus/util/inflection'
|
11
9
|
autoload :Logger, 'jsus/util/logger'
|
10
|
+
autoload :Mixins, 'jsus/util/mixins'
|
11
|
+
autoload :PostProcessor, 'jsus/util/post_processor'
|
12
|
+
autoload :Tree, 'jsus/util/tree'
|
13
|
+
autoload :Validator, 'jsus/util/validator'
|
12
14
|
autoload :Watcher, 'jsus/util/watcher'
|
13
15
|
|
14
16
|
class <<self
|
@@ -28,6 +30,14 @@ module Jsus
|
|
28
30
|
false
|
29
31
|
end
|
30
32
|
end
|
33
|
+
|
34
|
+
# Reads file in UTF-8 encoding in a safe way.
|
35
|
+
# Some ruby versions mess up the encodings and some spill out lots of warnings
|
36
|
+
# unless you do the right thing
|
37
|
+
def read_file(filename)
|
38
|
+
mode_string = RUBY_VERSION =~ /^1.9/ ? 'r:utf-8' : 'r'
|
39
|
+
File.open(filename, mode_string) {|f| f.read }
|
40
|
+
end # read_file
|
31
41
|
end # class <<self
|
32
42
|
end # Util
|
33
43
|
end # Jsus
|
data/lib/jsus/util/compressor.rb
CHANGED
data/lib/jsus/util/documenter.rb
CHANGED
@@ -127,7 +127,7 @@ module Jsus
|
|
127
127
|
# @api private
|
128
128
|
def create_documentation_for_source(source, template) # :nodoc:
|
129
129
|
skipped_lines = 0
|
130
|
-
content = source.
|
130
|
+
content = source.original_source.gsub(/\A\s*\/\*.*?\*\//m) {|w| skipped_lines += w.split("\n").size; "" }
|
131
131
|
annotator = Murdoc::Annotator.new(content, :javascript, options)
|
132
132
|
Murdoc::Formatter.new(template).render(:paragraphs => annotator.paragraphs, :header => source.header, :source => source, :skipped_lines => skipped_lines)
|
133
133
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Jsus
|
2
|
+
module Util
|
3
|
+
module Mixins
|
4
|
+
module OperatesOnSources
|
5
|
+
# @return [Array] source files for validation
|
6
|
+
# @api public
|
7
|
+
def source_files
|
8
|
+
@source_files ||= []
|
9
|
+
end
|
10
|
+
alias_method :sources, :source_files
|
11
|
+
|
12
|
+
# @param [Jsus::Pool, Jsus::Container, Array] pool_or_array_or_container
|
13
|
+
# source files for validation
|
14
|
+
# @api public
|
15
|
+
def source_files=(pool_or_array_or_container)
|
16
|
+
case pool_or_array_or_container
|
17
|
+
when Pool
|
18
|
+
@source_files = pool_or_array_or_container.sources.to_a
|
19
|
+
when Array
|
20
|
+
@source_files = pool_or_array_or_container
|
21
|
+
when Container
|
22
|
+
@source_files = pool_or_array_or_container.to_a
|
23
|
+
end
|
24
|
+
end
|
25
|
+
alias_method :sources=, :source_files=
|
26
|
+
end # module OperatesOnSources
|
27
|
+
end # module Mixins
|
28
|
+
end # module Util
|
29
|
+
end # module Jsus
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Jsus
|
2
|
+
module Util
|
3
|
+
module PostProcessor
|
4
|
+
autoload :Base, "jsus/util/post_processor/base"
|
5
|
+
autoload :Moocompat12, "jsus/util/post_processor/moocompat12"
|
6
|
+
autoload :MooltIE8, "jsus/util/post_processor/mooltie8"
|
7
|
+
autoload :Semicolon, "jsus/util/post_processor/semicolon"
|
8
|
+
|
9
|
+
AVAILABLE_PROCESSORS = ["mooltie8", "moocompat12", "semicolon"].freeze
|
10
|
+
# Accepts a collection of source files and list of processors and applies
|
11
|
+
# these processors to the sources.
|
12
|
+
#
|
13
|
+
# @param [Array, Pool, Container] source_files source files
|
14
|
+
# @param [Array] processors array with names of processors
|
15
|
+
# Available postprocs: "mooltie8", "moocompat12"
|
16
|
+
# @return [Array] processed sources
|
17
|
+
def self.process(source_files, processors)
|
18
|
+
Array(processors).each do |processor|
|
19
|
+
source_files = case processor.strip
|
20
|
+
when /moocompat12/i
|
21
|
+
Moocompat12.new(source_files).process
|
22
|
+
when /mooltie8/i
|
23
|
+
MooltIE8.new(source_files).process
|
24
|
+
when /semicolon/i
|
25
|
+
Semicolon.new(source_files).process
|
26
|
+
else
|
27
|
+
Jsus.logger.error "Unknown post-processor: #{processor}"
|
28
|
+
source_files
|
29
|
+
end
|
30
|
+
end
|
31
|
+
source_files
|
32
|
+
end # self.process
|
33
|
+
end # module PostProcessor
|
34
|
+
end # module Util
|
35
|
+
end # module Jsus
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Jsus
|
2
|
+
module Util
|
3
|
+
module PostProcessor
|
4
|
+
# Base class for post-processing routines.
|
5
|
+
# Post-processors are non-mutating boxes that accept a collection of
|
6
|
+
# SourceFile-s on input and return a collection of SourceFiles on output.
|
7
|
+
#
|
8
|
+
# Post-processing is not mutating the arguments, but dupes them instead
|
9
|
+
class Base
|
10
|
+
include Jsus::Util::Mixins::OperatesOnSources
|
11
|
+
|
12
|
+
# Constructor accepts pool or array or container and adds every file
|
13
|
+
# to its source files set.
|
14
|
+
# @param [Jsus::Pool, Jsus::Container, Array] source files to validate
|
15
|
+
# @api public
|
16
|
+
def initialize(pool_or_array_or_container = [])
|
17
|
+
self.source_files = pool_or_array_or_container
|
18
|
+
end # initialize
|
19
|
+
|
20
|
+
# Processes input source files, return a resulting collection
|
21
|
+
# @note This method should not mutate input sources
|
22
|
+
# @abstract Override in subclasses
|
23
|
+
# @param [Hash] options options hash
|
24
|
+
# @return [Array] processed source files
|
25
|
+
# @api public
|
26
|
+
def process(options = {})
|
27
|
+
raise NotImplementedError, "override #process in subclasses"
|
28
|
+
end # process
|
29
|
+
end # class Base
|
30
|
+
end # module PostProcessor
|
31
|
+
end # module Util
|
32
|
+
end # module Jsus
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Jsus
|
2
|
+
module Util
|
3
|
+
module PostProcessor
|
4
|
+
class Moocompat12 < Base
|
5
|
+
# Removes everything between <1.2compat> </1.2compat> tags
|
6
|
+
# @return [Array]
|
7
|
+
# @see Jsus::Util::PostProcessor::Base#process
|
8
|
+
def process(options = {})
|
9
|
+
source_files.map do |file|
|
10
|
+
file = file.dup
|
11
|
+
file.source = file.source.gsub(/\/\/<1.2compat>.*?\/\/<\/1.2compat>/m, '')
|
12
|
+
file.source = file.source.gsub(/\/\*<1.2compat>\*\/.*?\/\*<\/1.2compat>\*\//m, '')
|
13
|
+
file
|
14
|
+
end
|
15
|
+
end # process
|
16
|
+
end # class Moocompat12
|
17
|
+
end # module PostProcessor
|
18
|
+
end # module Util
|
19
|
+
end # module Jsus
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Jsus
|
2
|
+
module Util
|
3
|
+
module PostProcessor
|
4
|
+
class MooltIE8 < Base
|
5
|
+
# Removes everything between <ltIE8> </ltIE8> tags
|
6
|
+
# @return [Array]
|
7
|
+
# @see Jsus::Util::PostProcessor::Base#process
|
8
|
+
def process(options = {})
|
9
|
+
source_files.map do |file|
|
10
|
+
file = file.dup
|
11
|
+
file.source = file.source.gsub(/\/\/<ltIE8>.*?\/\/<\/ltIE8>/m, '')
|
12
|
+
file.source = file.source.gsub(/\/\*<ltIE8>\*\/.*?\/\*<\/ltIE8>\*\//m, '')
|
13
|
+
file
|
14
|
+
end
|
15
|
+
end # process
|
16
|
+
end # class MooltIE8
|
17
|
+
end # module PostProcessor
|
18
|
+
end # module Util
|
19
|
+
end # module Jsus
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Jsus
|
2
|
+
module Util
|
3
|
+
module PostProcessor
|
4
|
+
class Semicolon < Base
|
5
|
+
# Adds a semicolon to the beginning of every file
|
6
|
+
# @return [Array]
|
7
|
+
# @see Jsus::Util::PostProcessor::Base#process
|
8
|
+
def process(options = {})
|
9
|
+
source_files.map do |file|
|
10
|
+
file = file.dup
|
11
|
+
file.source = file.source.gsub(/^([^;])/, ";\n")
|
12
|
+
file
|
13
|
+
end
|
14
|
+
end # process
|
15
|
+
end # class Semicolon
|
16
|
+
end # module PostProcessor
|
17
|
+
end # module Util
|
18
|
+
end # module Jsus
|