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/util/tree.rb
CHANGED
@@ -6,8 +6,7 @@ module Jsus
|
|
6
6
|
# structure (with node names like /namespace/inner/item) and supporting
|
7
7
|
# lookups via #glob method.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# @example
|
11
10
|
# tree = Jsus::Tree.new
|
12
11
|
# tree["/folder/item_0"] = "Hello"
|
13
12
|
# tree["/folder/item_1"] = "World"
|
@@ -29,6 +28,7 @@ module Jsus
|
|
29
28
|
|
30
29
|
# Splits path into components
|
31
30
|
# Jsus::Tree.components_from_path("/hello/world") # => ["hello", "world"]
|
31
|
+
# @api semipublic
|
32
32
|
def components_from_path(path)
|
33
33
|
raise "Empty path given: #{path.inspect}" if !path || path == ""
|
34
34
|
path = path.to_s.dup
|
@@ -68,23 +68,31 @@ module Jsus
|
|
68
68
|
attr_reader :name
|
69
69
|
# Assigns node's full path and automatically deduces path components,
|
70
70
|
# basename etc.
|
71
|
+
# @api semipublic
|
71
72
|
def full_path=(full_path)
|
72
73
|
@full_path = full_path
|
73
74
|
@path_components = Tree.get_path_components(full_path)
|
74
75
|
@name = @path_components[-1]
|
75
76
|
end
|
76
77
|
|
77
|
-
#
|
78
|
+
# @return [Array] node's direct descendants
|
79
|
+
# @api public
|
78
80
|
def children
|
79
81
|
@children ||= []
|
80
82
|
end
|
81
83
|
|
82
|
-
#
|
84
|
+
# @param [String] basename
|
85
|
+
# @return [Jsus::Util::Tree::Node] direct node child with given basename
|
86
|
+
# @api public
|
83
87
|
def find_child(name)
|
84
88
|
children.detect {|child| child.name == name }
|
85
89
|
end
|
86
90
|
|
87
91
|
# Creates a child with given name and value
|
92
|
+
# @param [String] node name
|
93
|
+
# @param [Object] value
|
94
|
+
# @return [Jsus::Util::Tree::Node]
|
95
|
+
# @api public
|
88
96
|
def create_child(name, value = nil)
|
89
97
|
full_path = Tree.path_from_components(path_components + [name])
|
90
98
|
node = Node.new(full_path, value)
|
@@ -94,7 +102,11 @@ module Jsus
|
|
94
102
|
end
|
95
103
|
|
96
104
|
# Finds a child with given name or creates a child with given name and
|
97
|
-
# value
|
105
|
+
# value.
|
106
|
+
#
|
107
|
+
# @param [String] name
|
108
|
+
# @param [Object] value
|
109
|
+
# @api public
|
98
110
|
def find_or_create_child(name, value = nil)
|
99
111
|
find_child(name) || create_child(name, value)
|
100
112
|
end
|
@@ -105,7 +117,10 @@ module Jsus
|
|
105
117
|
# 'smth*' -- nodes beginning with smth
|
106
118
|
# 'smth*else' -- nodes beginning with smth and ending with else
|
107
119
|
# <string without asterisks> -- plain node lookup by name
|
108
|
-
#
|
120
|
+
#
|
121
|
+
# @param [String] pathspec
|
122
|
+
# @return [Array] array with search results
|
123
|
+
# @api public
|
109
124
|
def find_children_matching(pathspec)
|
110
125
|
case pathspec
|
111
126
|
when "**"
|
@@ -118,18 +133,23 @@ module Jsus
|
|
118
133
|
end
|
119
134
|
end
|
120
135
|
|
121
|
-
#
|
136
|
+
# @return [Boolean] whether this node has children
|
137
|
+
# @api public
|
122
138
|
def has_children?
|
123
139
|
!children.empty?
|
124
140
|
end
|
125
141
|
end
|
126
142
|
|
127
|
-
#
|
143
|
+
# @return [Jsus::Util::Tree::Node] root node of the tree
|
144
|
+
# @api public
|
128
145
|
def root
|
129
146
|
@root ||= Node.new("/", nil)
|
130
147
|
end
|
131
148
|
|
132
149
|
# Looks up a node by direct path. Does not support wildcards
|
150
|
+
# @param [String] path
|
151
|
+
# @return [Jsus::Util::Tree::Node]
|
152
|
+
# @api public
|
133
153
|
def lookup(path)
|
134
154
|
path_components = self.class.get_path_components(path)
|
135
155
|
path_components.inject(root) do |result, component|
|
@@ -139,6 +159,11 @@ module Jsus
|
|
139
159
|
end
|
140
160
|
end
|
141
161
|
|
162
|
+
# @see lookup
|
163
|
+
# @param [String] path
|
164
|
+
# @return [Jsus::Util::Tree::Node]
|
165
|
+
# @note returns nil when node has no assigned value
|
166
|
+
# @api public
|
142
167
|
def [](path)
|
143
168
|
node = lookup(path)
|
144
169
|
node ? node.value : nil
|
@@ -147,20 +172,28 @@ module Jsus
|
|
147
172
|
|
148
173
|
|
149
174
|
# Searches for nodes by a given pathspec
|
150
|
-
#
|
175
|
+
# @see Jsus::Util::Tree::Node#find_children_matching for more details
|
176
|
+
# @param [String] pathspec
|
177
|
+
# @return [Array] nodes for given pathspec
|
178
|
+
# @api semipublic
|
151
179
|
def find_nodes_matching(pathspec)
|
152
180
|
self.class.get_path_components(pathspec).inject([root]) do |nodes, component|
|
153
181
|
nodes.map {|node| node.find_children_matching(component) }.flatten
|
154
182
|
end
|
155
183
|
end
|
156
184
|
|
157
|
-
#
|
158
|
-
#
|
185
|
+
# @param [String] pathspec
|
186
|
+
# @return [Array] values for nodes matching given pathspec
|
187
|
+
# @see Jsus::Util::Tree::Node#find_children_matching for more details
|
188
|
+
# @api public
|
159
189
|
def glob(pathspec)
|
160
190
|
find_nodes_matching(pathspec).map {|node| node.value }
|
161
191
|
end
|
162
192
|
|
163
193
|
# Inserts a node with given value into the tree
|
194
|
+
# @param [String] full node path
|
195
|
+
# @param [Object] value
|
196
|
+
# @api public
|
164
197
|
def insert(full_path, value = nil)
|
165
198
|
node = create_all_nodes_if_needed(full_path)
|
166
199
|
node.value = value
|
@@ -168,9 +201,10 @@ module Jsus
|
|
168
201
|
end
|
169
202
|
alias_method :[]=, :insert
|
170
203
|
|
171
|
-
# Traverses the tree.
|
172
|
-
#
|
173
|
-
#
|
204
|
+
# Traverses the tree (BFS).
|
205
|
+
# @param [Boolean] whether to traverse non-leaves nodes
|
206
|
+
# @yield traversed node
|
207
|
+
# @api public
|
174
208
|
def traverse(all_nodes = false)
|
175
209
|
node_list = [root]
|
176
210
|
while !node_list.empty?
|
@@ -180,8 +214,9 @@ module Jsus
|
|
180
214
|
end
|
181
215
|
end
|
182
216
|
|
183
|
-
#
|
184
|
-
#
|
217
|
+
# @param [Boolean] whether to return only leaves with values
|
218
|
+
# @return [Array] list of leaves
|
219
|
+
# @api public
|
185
220
|
def leaves(only_with_value = true)
|
186
221
|
result = []
|
187
222
|
traverse {|node| result << node if !only_with_value || node.value }
|
@@ -190,7 +225,8 @@ module Jsus
|
|
190
225
|
|
191
226
|
protected
|
192
227
|
|
193
|
-
|
228
|
+
# @api private
|
229
|
+
def create_all_nodes_if_needed(full_path)
|
194
230
|
self.class.get_path_components(full_path).inject(root) do |result, component|
|
195
231
|
result.find_or_create_child(component)
|
196
232
|
end
|
@@ -198,4 +234,4 @@ module Jsus
|
|
198
234
|
|
199
235
|
end
|
200
236
|
end
|
201
|
-
end
|
237
|
+
end
|
@@ -5,17 +5,21 @@ module Jsus
|
|
5
5
|
class Base
|
6
6
|
# Constructor accepts pool or array or container and adds every file
|
7
7
|
# to its source files set.
|
8
|
+
# @param [Jsus::Pool, Jsus::Container, Array] source files to validate
|
9
|
+
# @api public
|
8
10
|
def initialize(pool_or_array_or_container)
|
9
11
|
self.source_files = pool_or_array_or_container
|
10
12
|
end
|
11
13
|
|
12
|
-
#
|
14
|
+
# @return [Array] source files for validation
|
15
|
+
# @api public
|
13
16
|
def source_files
|
14
17
|
@source_files ||= []
|
15
18
|
end
|
16
19
|
alias_method :sources, :source_files
|
17
20
|
|
18
|
-
#
|
21
|
+
# @param [Jsus::Pool, Jsus::Container, Array] source files for validation
|
22
|
+
# @api public
|
19
23
|
def source_files=(pool_or_array_or_container)
|
20
24
|
case pool_or_array_or_container
|
21
25
|
when Pool
|
@@ -28,21 +32,25 @@ module Jsus
|
|
28
32
|
end
|
29
33
|
alias_method :sources=, :source_files=
|
30
34
|
|
31
|
-
#
|
35
|
+
# @return [Boolean] whether or not given sources conform to given set of rules
|
36
|
+
# @api public
|
32
37
|
def validate
|
33
38
|
validation_errors.empty?
|
34
39
|
end
|
35
40
|
|
36
|
-
#
|
41
|
+
# @return [Array] list of validation errors
|
42
|
+
# @override
|
37
43
|
def validation_errors
|
38
44
|
[]
|
39
45
|
end
|
40
46
|
|
41
47
|
# Shortcut for creating and validating a list of items
|
48
|
+
# @param [*Array] args for #new
|
49
|
+
# @api public
|
42
50
|
def self.validate(*args)
|
43
51
|
new(*args).validate
|
44
52
|
end
|
45
53
|
end
|
46
54
|
end
|
47
55
|
end # Util
|
48
|
-
end
|
56
|
+
end
|
@@ -6,7 +6,13 @@ module Jsus
|
|
6
6
|
# * Presence of authors field
|
7
7
|
# * Presence of license field
|
8
8
|
class Mooforge < Base
|
9
|
-
|
9
|
+
# Mooforge validator checks every file for the following:
|
10
|
+
# * Presence of header
|
11
|
+
# * Presence of authors field
|
12
|
+
# * Presence of license field
|
13
|
+
# @return [Array] list oferrors
|
14
|
+
# @api public
|
15
|
+
def validation_errors
|
10
16
|
@validation_errors ||= sources.inject([]) do |result, sf|
|
11
17
|
if !sf.header
|
12
18
|
result << "#{sf.filename} is missing header"
|
@@ -22,4 +28,4 @@ module Jsus
|
|
22
28
|
end
|
23
29
|
end
|
24
30
|
end # Util
|
25
|
-
end
|
31
|
+
end
|
data/markup/stylesheet.css
CHANGED
@@ -6,6 +6,10 @@ p, h1, h2, h3, ol, li, ul, dt, dd, dl, body, html {
|
|
6
6
|
padding: 0;
|
7
7
|
margin: 0; }
|
8
8
|
|
9
|
+
p + br {
|
10
|
+
display: none;
|
11
|
+
}
|
12
|
+
|
9
13
|
body {
|
10
14
|
width: 40%;
|
11
15
|
padding-left: 2.5%;
|
@@ -27,7 +31,7 @@ body > * {
|
|
27
31
|
padding-right: 6%; }
|
28
32
|
|
29
33
|
html {
|
30
|
-
background: #
|
34
|
+
background: #FFC873; }
|
31
35
|
|
32
36
|
header {
|
33
37
|
background: rgba(255, 255, 255, 0.1);
|
@@ -41,10 +45,23 @@ header {
|
|
41
45
|
width: 5em;
|
42
46
|
font-weight: bold; }
|
43
47
|
|
44
|
-
section
|
48
|
+
section {
|
45
49
|
float: left;
|
46
50
|
clear: both;
|
47
|
-
width:
|
51
|
+
width: 85%; }
|
52
|
+
|
53
|
+
section iframe {
|
54
|
+
width: 260%;
|
55
|
+
height: 250px;
|
56
|
+
border: 1px solid #333;
|
57
|
+
margin-bottom: 1em;
|
58
|
+
margin-top: 1.5em;
|
59
|
+
}
|
60
|
+
|
61
|
+
section iframe.high {
|
62
|
+
height: 300px;
|
63
|
+
}
|
64
|
+
|
48
65
|
|
49
66
|
p, dl, li {
|
50
67
|
color: #665504;
|
@@ -57,12 +74,42 @@ a {
|
|
57
74
|
a:visited {
|
58
75
|
color: #A64E00; }
|
59
76
|
|
60
|
-
p {
|
77
|
+
p + p, h2 + p, h1 + p, ul + p, ol + p{
|
61
78
|
margin-top: 1.5em; }
|
62
79
|
|
80
|
+
p code {
|
81
|
+
background-color: rgba(200, 220, 200, 0.2);
|
82
|
+
display: inline-block;
|
83
|
+
-moz-border-radius: 4px;
|
84
|
+
-webkit-border-radius: 4px;
|
85
|
+
border-radius: 4px;
|
86
|
+
padding: 0 0.2em;
|
87
|
+
font-family: "monaco", "Courier New", Courier, monospace, serif;
|
88
|
+
font-size:0.8em;
|
89
|
+
line-height:1.5em;
|
90
|
+
}
|
91
|
+
p:last-child {
|
92
|
+
margin-bottom: 1.5em;
|
93
|
+
}
|
94
|
+
|
63
95
|
h1 {
|
64
96
|
font-size: 2em; }
|
65
97
|
|
98
|
+
h1 + ul {
|
99
|
+
float: right;
|
100
|
+
width: 140%;
|
101
|
+
margin-right: -160%;
|
102
|
+
margin-top: -2em;
|
103
|
+
}
|
104
|
+
|
105
|
+
h1 + ul li {
|
106
|
+
display: inline;
|
107
|
+
}
|
108
|
+
|
109
|
+
h1 + ul li + li{
|
110
|
+
margin-left: 1em;
|
111
|
+
}
|
112
|
+
|
66
113
|
h2 {
|
67
114
|
font-size: 1em; }
|
68
115
|
|
@@ -72,13 +119,18 @@ h1, h2, h3 {
|
|
72
119
|
ol, li {
|
73
120
|
margin-left: 1em; }
|
74
121
|
|
75
|
-
body > p, body > h1
|
122
|
+
body > p, body > h1 {
|
76
123
|
clear: left; }
|
77
124
|
|
125
|
+
body > h2 {
|
126
|
+
clear: both;
|
127
|
+
}
|
128
|
+
|
78
129
|
header {
|
79
130
|
padding-bottom: 1em;
|
80
131
|
overflow: hidden; }
|
81
132
|
|
133
|
+
|
82
134
|
dl {
|
83
135
|
clear: left; }
|
84
136
|
dl dt, dl dd {
|
@@ -91,29 +143,45 @@ dl {
|
|
91
143
|
figure {
|
92
144
|
display: block;
|
93
145
|
float: right;
|
94
|
-
margin-right: -
|
146
|
+
margin-right: -135%;
|
95
147
|
width: 122.75%;
|
96
148
|
clear: right;
|
97
|
-
|
149
|
+
margin-top: -0.1em;
|
150
|
+
padding: 0 0 3em; }
|
98
151
|
figure > ol {
|
99
|
-
|
100
|
-
|
101
|
-
-
|
152
|
+
font-family: 0.75em/2.25em Arial;
|
153
|
+
text-shadow: 0 1px 0 #eee;
|
154
|
+
-moz-text-shadow: 0 1px 0 #eee;
|
155
|
+
-webkit-text-shadow: 0 1px 0 #eee;
|
156
|
+
box-shadow: 0 1px 2px #333;
|
157
|
+
-moz-box-shadow: 0 1px 2px #333;
|
158
|
+
-webkit-box-shadow: 0 1px 2px #333;
|
102
159
|
width: 7.5%;
|
103
160
|
text-align: right;
|
104
161
|
float: left;
|
105
|
-
|
162
|
+
-moz-border-radius: 0.2em;
|
106
163
|
-webkit-border-radius: 0.2em;
|
107
|
-
|
108
|
-
border: 1px solid rgba(0, 0, 0, 0.
|
164
|
+
border-radius: 0.2em;
|
165
|
+
border: 1px solid rgba(0, 0, 0, 0.5);
|
109
166
|
list-style: none;
|
110
167
|
margin-left: -9.25%; }
|
111
168
|
figure > ol li {
|
169
|
+
background: rgba(125, 125, 125, 0.4);
|
112
170
|
margin: 0; }
|
113
|
-
|
114
|
-
|
115
|
-
|
171
|
+
figure > ol li:first-child {
|
172
|
+
border-top-left-radius: 0.2em;
|
173
|
+
border-top-right-radius: 0.2em; }
|
174
|
+
figure > ol li:last-child {
|
175
|
+
border-bottom-left-radius: 0.2em;
|
176
|
+
border-bottom-right-radius: 0.2em; }
|
177
|
+
figure > ol li.new {
|
178
|
+
background: #98B72E; }
|
179
|
+
figure > ol li.changed {
|
180
|
+
background: #FFBD40; }
|
116
181
|
figure > code {
|
182
|
+
font-size: 1em;
|
183
|
+
line-height: 1.5em;
|
184
|
+
font-family: "monaco", "Courier New", Courier, monospace, serif;
|
117
185
|
white-space: pre; }
|
118
186
|
|
119
187
|
body .hll {
|
@@ -205,6 +205,31 @@ describe Jsus::Middleware do
|
|
205
205
|
body.index("script: Color.js").should > body.index("script: Core.js")
|
206
206
|
end
|
207
207
|
end
|
208
|
+
|
209
|
+
describe "using /include/ pattern" do
|
210
|
+
let(:path) { "/javascripts/jsus/include/Package:Input.Color.js" }
|
211
|
+
|
212
|
+
it "should be successful" do
|
213
|
+
get(path).should be_successful
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should respond with type text/javascript" do
|
217
|
+
get(path).content_type.should == "text/javascript"
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should contain filenames for required files" do
|
221
|
+
get(path).body.should include("/Color.js")
|
222
|
+
get(path).body.should include("/Input.js")
|
223
|
+
get(path).body.should include("/Input.Color.js")
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should respect :includes_root setting" do
|
227
|
+
old_settings = Jsus::Middleware.settings
|
228
|
+
Jsus::Middleware.settings = {:includes_root => File.expand_path("../../data/ComplexDependencies/Mootools/Source", __FILE__)}
|
229
|
+
get(path).body.should include("../../Source/Library/Color.js")
|
230
|
+
Jsus::Middleware.settings = old_settings
|
231
|
+
end
|
232
|
+
end
|
208
233
|
end
|
209
234
|
|
210
235
|
describe "for invalid paths" do
|