jsduck 5.0.0.beta2 → 5.0.0.beta3
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/Rakefile +14 -4
- data/bin/jsduck +3 -1
- data/jsduck.gemspec +2 -2
- data/lib/jsduck/app.rb +8 -0
- data/lib/jsduck/assets.rb +3 -0
- data/lib/jsduck/batch_processor.rb +2 -0
- data/lib/jsduck/categories/class_name.rb +2 -26
- data/lib/jsduck/categories/factory.rb +5 -43
- data/lib/jsduck/columns.rb +56 -0
- data/lib/jsduck/doc/delimited_parser.rb +105 -0
- data/lib/jsduck/doc/scanner.rb +2 -1
- data/lib/jsduck/doc/standard_tag_parser.rb +37 -71
- data/lib/jsduck/guide_anchors.rb +32 -0
- data/lib/jsduck/guide_toc.rb +49 -0
- data/lib/jsduck/guides.rb +14 -32
- data/lib/jsduck/inline/video.rb +2 -8
- data/lib/jsduck/js/ast.rb +13 -305
- data/lib/jsduck/js/class.rb +245 -0
- data/lib/jsduck/js/event.rb +34 -0
- data/lib/jsduck/js/fires.rb +42 -0
- data/lib/jsduck/js/method.rb +94 -0
- data/lib/jsduck/js/method_calls.rb +40 -0
- data/lib/jsduck/js/node.rb +29 -0
- data/lib/jsduck/js/property.rb +64 -0
- data/lib/jsduck/js/{function.rb → returns.rb} +8 -3
- data/lib/jsduck/js/scoped_traverser.rb +42 -0
- data/lib/jsduck/logger.rb +13 -1
- data/lib/jsduck/merger.rb +34 -27
- data/lib/jsduck/news.rb +128 -0
- data/lib/jsduck/options.rb +59 -2
- data/lib/jsduck/params_merger.rb +47 -0
- data/lib/jsduck/process/accessors.rb +8 -2
- data/lib/jsduck/process/fires.rb +71 -0
- data/lib/jsduck/process/importer.rb +19 -1
- data/lib/jsduck/render/class.rb +11 -4
- data/lib/jsduck/render/signature_util.rb +14 -0
- data/lib/jsduck/tag/alias.rb +0 -20
- data/lib/jsduck/tag/alternate_class_names.rb +0 -5
- data/lib/jsduck/tag/cfg.rb +30 -5
- data/lib/jsduck/tag/class.rb +45 -2
- data/lib/jsduck/tag/css_mixin.rb +8 -4
- data/lib/jsduck/tag/css_var.rb +26 -5
- data/lib/jsduck/tag/default.rb +2 -8
- data/lib/jsduck/tag/enum.rb +7 -10
- data/lib/jsduck/tag/event.rb +12 -4
- data/lib/jsduck/tag/extends.rb +0 -6
- data/lib/jsduck/tag/fires.rb +53 -0
- data/lib/jsduck/tag/icons/cfg.png +0 -0
- data/lib/jsduck/tag/icons/css_mixin.png +0 -0
- data/lib/jsduck/tag/icons/css_var.png +0 -0
- data/lib/jsduck/tag/icons/event.png +0 -0
- data/lib/jsduck/tag/icons/method.png +0 -0
- data/lib/jsduck/tag/icons/property.png +0 -0
- data/lib/jsduck/tag/member_tag.rb +130 -0
- data/lib/jsduck/tag/method.rb +44 -4
- data/lib/jsduck/tag/param.rb +8 -60
- data/lib/jsduck/tag/property.rb +28 -5
- data/lib/jsduck/tag/tag.rb +3 -75
- data/lib/jsduck/tag/type.rb +1 -11
- data/lib/jsduck/tag_registry.rb +6 -48
- data/lib/jsduck/web/css.rb +8 -1
- data/lib/jsduck/web/data.rb +2 -1
- data/lib/jsduck/web/index_html.rb +1 -0
- data/lib/jsduck/web/member_icons.rb +43 -0
- data/lib/jsduck/web/search.rb +3 -2
- data/lib/jsduck/web/writer.rb +8 -0
- metadata +31 -27
- data/lib/jsduck/docs_code_comparer.rb +0 -44
- data/lib/jsduck/render/signature.rb +0 -94
- data/lib/jsduck/tag/autodetected.rb +0 -21
- data/lib/jsduck/tag/name.rb +0 -36
data/Rakefile
CHANGED
@@ -159,6 +159,11 @@ class JsDuckRunner
|
|
159
159
|
add_options("--comments-domain", db_name+"/"+version)
|
160
160
|
end
|
161
161
|
|
162
|
+
def add_search(product, version)
|
163
|
+
add_options("--search-url", "http://support-test.sencha.com:8080/docsearch/search")
|
164
|
+
add_options("--search-domain", product+"/"+version)
|
165
|
+
end
|
166
|
+
|
162
167
|
def add_ext4
|
163
168
|
@options += [
|
164
169
|
"--title", "Sencha Docs - Ext JS 4.0",
|
@@ -263,6 +268,7 @@ task :sdk => :sass do
|
|
263
268
|
)
|
264
269
|
runner.add_debug
|
265
270
|
runner.add_comments('ext-js', '4')
|
271
|
+
runner.add_search('Ext JS', '4.2.0')
|
266
272
|
runner.run
|
267
273
|
|
268
274
|
system("ln -s #{EXT_BUILD} #{OUT_DIR}/extjs-build")
|
@@ -275,10 +281,14 @@ task :touch2 => :sass do
|
|
275
281
|
"--output", OUT_DIR,
|
276
282
|
"--config", "#{SDK_DIR}/touch/docs/config.json",
|
277
283
|
"--examples-base-url", "touch-build/examples/production/",
|
278
|
-
# "--import", "
|
279
|
-
# "--import", "
|
280
|
-
# "--import", "
|
281
|
-
# "--import", "
|
284
|
+
# "--import", "1.1.0:../docs.sencha.com/exports/touch-1.1.0",
|
285
|
+
# "--import", "1.1.1:../docs.sencha.com/exports/touch-1.1.1",
|
286
|
+
# "--import", "2.0.0:../docs.sencha.com/exports/touch-2.0.0",
|
287
|
+
# "--import", "2.0.1:../docs.sencha.com/exports/touch-2.0.1",
|
288
|
+
# "--import", "2.1.0:../docs.sencha.com/exports/touch-2.1.0",
|
289
|
+
# "--import", "2.1.1:../docs.sencha.com/exports/touch-2.1.1",
|
290
|
+
# "--import", "2.2.0:../docs.sencha.com/exports/touch-2.2.0",
|
291
|
+
# "--import", "2.2.1",
|
282
292
|
"--seo"
|
283
293
|
)
|
284
294
|
|
data/bin/jsduck
CHANGED
data/jsduck.gemspec
CHANGED
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
|
|
2
2
|
s.required_rubygems_version = ">= 1.3.5"
|
3
3
|
|
4
4
|
s.name = 'jsduck'
|
5
|
-
s.version = '5.0.0.
|
5
|
+
s.version = '5.0.0.beta3'
|
6
6
|
s.date = Time.new.strftime('%Y-%m-%d')
|
7
7
|
s.summary = "Simple JavaScript Duckumentation generator"
|
8
8
|
s.description = "Documentation generator for Sencha JS frameworks"
|
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.add_dependency 'json'
|
24
24
|
s.add_dependency 'parallel'
|
25
25
|
s.add_dependency 'execjs'
|
26
|
-
s.add_dependency 'therubyracer', '>= 0.10.0'
|
26
|
+
s.add_dependency 'therubyracer', '>= 0.10.0'
|
27
27
|
s.add_dependency 'dimensions'
|
28
28
|
|
29
29
|
s.add_development_dependency 'rspec'
|
data/lib/jsduck/app.rb
CHANGED
@@ -4,6 +4,7 @@ require 'jsduck/assets'
|
|
4
4
|
require 'jsduck/tag_registry'
|
5
5
|
require 'jsduck/export_writer'
|
6
6
|
require 'jsduck/web/writer'
|
7
|
+
require 'jsduck/logger'
|
7
8
|
|
8
9
|
module JsDuck
|
9
10
|
|
@@ -15,6 +16,7 @@ module JsDuck
|
|
15
16
|
end
|
16
17
|
|
17
18
|
# Main App logic.
|
19
|
+
# Returns application exit code.
|
18
20
|
def run
|
19
21
|
parse
|
20
22
|
|
@@ -25,6 +27,12 @@ module JsDuck
|
|
25
27
|
else
|
26
28
|
generate_web_page
|
27
29
|
end
|
30
|
+
|
31
|
+
if @opts.warnings_exit_nonzero && Logger.warnings_logged?
|
32
|
+
return 2
|
33
|
+
else
|
34
|
+
return 0
|
35
|
+
end
|
28
36
|
end
|
29
37
|
|
30
38
|
private
|
data/lib/jsduck/assets.rb
CHANGED
@@ -6,6 +6,7 @@ require 'jsduck/videos'
|
|
6
6
|
require 'jsduck/examples'
|
7
7
|
require 'jsduck/categories/factory'
|
8
8
|
require 'jsduck/format/doc'
|
9
|
+
require 'jsduck/news'
|
9
10
|
|
10
11
|
module JsDuck
|
11
12
|
|
@@ -22,6 +23,7 @@ module JsDuck
|
|
22
23
|
attr_reader :videos
|
23
24
|
attr_reader :examples
|
24
25
|
attr_reader :categories
|
26
|
+
attr_reader :news
|
25
27
|
|
26
28
|
def initialize(relations, opts)
|
27
29
|
@relations = relations
|
@@ -35,6 +37,7 @@ module JsDuck
|
|
35
37
|
@videos = Videos.create(@opts.videos)
|
36
38
|
@examples = Examples.create(@opts.examples, @opts)
|
37
39
|
@categories = Categories::Factory.create(@opts.categories_path, doc_formatter, @relations)
|
40
|
+
@news = News.create(@relations, doc_formatter, @opts)
|
38
41
|
end
|
39
42
|
|
40
43
|
# Writes out the assets that can be written out separately:
|
@@ -12,6 +12,7 @@ require 'jsduck/process/overrides'
|
|
12
12
|
require 'jsduck/process/inherit_doc'
|
13
13
|
require 'jsduck/process/versions'
|
14
14
|
require 'jsduck/process/return_values'
|
15
|
+
require 'jsduck/process/fires'
|
15
16
|
require 'jsduck/process/lint'
|
16
17
|
require 'jsduck/process/circular_deps'
|
17
18
|
|
@@ -68,6 +69,7 @@ module JsDuck
|
|
68
69
|
Process::InheritDoc.new(relations).process_all!
|
69
70
|
Process::Versions.new(relations, opts).process_all!
|
70
71
|
Process::ReturnValues.new(relations).process_all!
|
72
|
+
Process::Fires.new(relations).process_all!
|
71
73
|
Process::Lint.new(relations).process_all!
|
72
74
|
relations
|
73
75
|
end
|
@@ -27,36 +27,12 @@ module JsDuck
|
|
27
27
|
# Adds small star to new classes in the current version.
|
28
28
|
def render_new_label(cls)
|
29
29
|
if cls[:new]
|
30
|
-
" <span class='new-class' title='New class'
|
30
|
+
" <span class='new-class' title='New class'>★</span>"
|
31
31
|
else
|
32
|
-
|
33
|
-
if n > 0
|
34
|
-
title = "#{n} new member#{(n>1) ? 's' : ''}"
|
35
|
-
" <span class='new-members' title='#{title}'>#{stars(n)}</span>"
|
36
|
-
else
|
37
|
-
""
|
38
|
-
end
|
32
|
+
""
|
39
33
|
end
|
40
34
|
end
|
41
35
|
|
42
|
-
# Produces string of n stars.
|
43
|
-
# First 3 stars are rendered as "<unicode-star>", the following as "+".
|
44
|
-
# At max 15 stars are rendered.
|
45
|
-
def stars(n)
|
46
|
-
if n > 15
|
47
|
-
stars(3) + ("+" * (15-3))
|
48
|
-
elsif n > 3
|
49
|
-
stars(3) + ("+" * (n-3))
|
50
|
-
else
|
51
|
-
"★" * n
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Returns number of new members the class has in the current version
|
56
|
-
def new_members_count(cls)
|
57
|
-
cls.find_members(:local => true).find_all {|m| m[:new] && !m[:private] }.length
|
58
|
-
end
|
59
|
-
|
60
36
|
end
|
61
37
|
|
62
38
|
end
|
@@ -2,6 +2,7 @@ require 'jsduck/logger'
|
|
2
2
|
require 'jsduck/categories/file'
|
3
3
|
require 'jsduck/categories/auto'
|
4
4
|
require 'jsduck/categories/class_name'
|
5
|
+
require 'jsduck/columns'
|
5
6
|
|
6
7
|
module JsDuck
|
7
8
|
module Categories
|
@@ -20,6 +21,7 @@ module JsDuck
|
|
20
21
|
def initialize(categories, doc_formatter, relations={})
|
21
22
|
@categories = categories
|
22
23
|
@class_name = Categories::ClassName.new(doc_formatter, relations)
|
24
|
+
@columns = Columns.new("classes")
|
23
25
|
end
|
24
26
|
|
25
27
|
# Returns HTML listing of classes divided into categories
|
@@ -41,10 +43,12 @@ module JsDuck
|
|
41
43
|
EOHTML
|
42
44
|
end
|
43
45
|
|
46
|
+
private
|
47
|
+
|
44
48
|
def render_columns(groups)
|
45
49
|
align = ["left-column", "middle-column", "right-column"]
|
46
50
|
i = -1
|
47
|
-
return split(groups, 3).map do |col|
|
51
|
+
return @columns.split(groups, 3).map do |col|
|
48
52
|
i += 1
|
49
53
|
[
|
50
54
|
"<div class='#{align[i]}'>",
|
@@ -65,48 +69,6 @@ module JsDuck
|
|
65
69
|
end
|
66
70
|
end
|
67
71
|
|
68
|
-
# Splits the array of items into n chunks so that the sum of
|
69
|
-
# largest chunk is as small as possible.
|
70
|
-
#
|
71
|
-
# This is a brute-force implementation - we just try all the
|
72
|
-
# combinations and choose the best one.
|
73
|
-
def split(items, n)
|
74
|
-
if n == 1
|
75
|
-
[items]
|
76
|
-
elsif items.length <= n
|
77
|
-
Array.new(n) {|i| items[i] ? [items[i]] : [] }
|
78
|
-
else
|
79
|
-
min_max = nil
|
80
|
-
min_arr = nil
|
81
|
-
i = 0
|
82
|
-
while i <= items.length-n
|
83
|
-
i += 1
|
84
|
-
# Try placing 1, 2, 3, ... items to first chunk.
|
85
|
-
# Calculate the remaining chunks recursively.
|
86
|
-
cols = [items[0,i]] + split(items[i, items.length], n-1)
|
87
|
-
max = max_sum(cols)
|
88
|
-
# Is this the optimal solution so far? Remember it.
|
89
|
-
if !min_max || max < min_max
|
90
|
-
min_max = max
|
91
|
-
min_arr = cols
|
92
|
-
end
|
93
|
-
end
|
94
|
-
min_arr
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def max_sum(cols)
|
99
|
-
cols.map {|col| sum(col) }.max
|
100
|
-
end
|
101
|
-
|
102
|
-
# Finds the total size of items in array
|
103
|
-
#
|
104
|
-
# The size of one item is it's number of classes + the space for header
|
105
|
-
def sum(arr)
|
106
|
-
header_size = 3
|
107
|
-
arr.reduce(0) {|sum, item| sum + item["classes"].length + header_size }
|
108
|
-
end
|
109
|
-
|
110
72
|
end
|
111
73
|
|
112
74
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module JsDuck
|
2
|
+
|
3
|
+
# Splits array of items with subitems into roughly equal size groups.
|
4
|
+
class Columns
|
5
|
+
# Initialized with the name of subitems field.
|
6
|
+
def initialize(subitems_field)
|
7
|
+
@header_size = 3
|
8
|
+
@subitems_field = subitems_field
|
9
|
+
end
|
10
|
+
|
11
|
+
# Splits the array of items into n chunks so that the sum of
|
12
|
+
# largest chunk is as small as possible.
|
13
|
+
#
|
14
|
+
# This is a brute-force implementation - we just try all the
|
15
|
+
# combinations and choose the best one.
|
16
|
+
def split(items, n)
|
17
|
+
if n == 1
|
18
|
+
[items]
|
19
|
+
elsif items.length <= n
|
20
|
+
Array.new(n) {|i| items[i] ? [items[i]] : [] }
|
21
|
+
else
|
22
|
+
min_max = nil
|
23
|
+
min_arr = nil
|
24
|
+
i = 0
|
25
|
+
while i <= items.length-n
|
26
|
+
i += 1
|
27
|
+
# Try placing 1, 2, 3, ... items to first chunk.
|
28
|
+
# Calculate the remaining chunks recursively.
|
29
|
+
cols = [items[0,i]] + split(items[i, items.length], n-1)
|
30
|
+
max = max_sum(cols)
|
31
|
+
# Is this the optimal solution so far? Remember it.
|
32
|
+
if !min_max || max < min_max
|
33
|
+
min_max = max
|
34
|
+
min_arr = cols
|
35
|
+
end
|
36
|
+
end
|
37
|
+
min_arr
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def max_sum(cols)
|
44
|
+
cols.map {|col| sum(col) }.max
|
45
|
+
end
|
46
|
+
|
47
|
+
# Finds the total size of items in array
|
48
|
+
#
|
49
|
+
# The size of one item is it's number of classes + the space for header
|
50
|
+
def sum(arr)
|
51
|
+
arr.reduce(0) {|sum, item| sum + item[@subitems_field].length + @header_size }
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module JsDuck
|
2
|
+
module Doc
|
3
|
+
|
4
|
+
# Helper in parsing the default values and type definitions where
|
5
|
+
# we take into account correctly nested parenthesis and strings.
|
6
|
+
# But at the same time we don't care much about the actual
|
7
|
+
# contents.
|
8
|
+
class DelimitedParser
|
9
|
+
# Initialized with Doc::Scanner instance
|
10
|
+
def initialize(doc_scanner)
|
11
|
+
@ds = doc_scanner
|
12
|
+
end
|
13
|
+
|
14
|
+
# Parses until a closing "}".
|
15
|
+
def parse_until_close_curly
|
16
|
+
parse_until_close_paren(/\}/, /[^\}]*/)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Parses until a closing "]".
|
20
|
+
def parse_until_close_square
|
21
|
+
parse_until_close_paren(/\]/, /[^\]]*/)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Parses until a closing parenthesis or space.
|
25
|
+
def parse_until_space
|
26
|
+
begin
|
27
|
+
parse_while(/[^\[\]\{\}\(\)'"\s]/)
|
28
|
+
rescue
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Parses until a given closing parenthesis.
|
36
|
+
# When unsuccessful, try simple parsing.
|
37
|
+
def parse_until_close_paren(re_paren, re_simple)
|
38
|
+
begin
|
39
|
+
start_pos = @ds.input.pos
|
40
|
+
result = parse_while(/[^\[\]\{\}\(\)'"]/)
|
41
|
+
if look(re_paren)
|
42
|
+
result
|
43
|
+
else
|
44
|
+
throw "Closing brace expected"
|
45
|
+
end
|
46
|
+
rescue
|
47
|
+
@ds.input.pos = start_pos
|
48
|
+
match(re_simple)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse_while(regex)
|
53
|
+
result = ""
|
54
|
+
while r = parse_compound || match(regex)
|
55
|
+
result += r
|
56
|
+
end
|
57
|
+
result
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_compound
|
61
|
+
if look(/\[/)
|
62
|
+
parse_balanced(/\[/, /\]/)
|
63
|
+
elsif look(/\{/)
|
64
|
+
parse_balanced(/\{/, /\}/)
|
65
|
+
elsif look(/\(/)
|
66
|
+
parse_balanced(/\(/, /\)/)
|
67
|
+
elsif look(/"/)
|
68
|
+
parse_string('"')
|
69
|
+
elsif look(/'/)
|
70
|
+
parse_string("'")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse_balanced(re_open, re_close)
|
75
|
+
result = match(re_open)
|
76
|
+
|
77
|
+
result += parse_while(/[^\[\]\{\}\(\)'"]/)
|
78
|
+
|
79
|
+
if r = match(re_close)
|
80
|
+
result + r
|
81
|
+
else
|
82
|
+
throw "Unbalanced parenthesis"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Parses "..." or '...' including the escape sequence \' or '\"
|
87
|
+
def parse_string(quote)
|
88
|
+
re_quote = Regexp.new(quote)
|
89
|
+
re_rest = Regexp.new("(?:[^"+quote+"\\\\]|\\\\.)*")
|
90
|
+
match(re_quote) + match(re_rest) + (match(re_quote) || "")
|
91
|
+
end
|
92
|
+
|
93
|
+
### Forward these calls to Doc::Scanner
|
94
|
+
|
95
|
+
def look(re)
|
96
|
+
@ds.look(re)
|
97
|
+
end
|
98
|
+
|
99
|
+
def match(re)
|
100
|
+
@ds.match(re)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
data/lib/jsduck/doc/scanner.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'jsduck/doc/standard_tag_parser'
|
2
|
+
require 'jsduck/logger'
|
2
3
|
|
3
4
|
module JsDuck
|
4
5
|
module Doc
|
@@ -20,7 +21,7 @@ module JsDuck
|
|
20
21
|
end
|
21
22
|
|
22
23
|
# Provides access to StringScanner
|
23
|
-
|
24
|
+
attr_accessor :input
|
24
25
|
|
25
26
|
# Parses standard pattern common in several builtin tags, which
|
26
27
|
# goes like this:
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'jsduck/doc/delimited_parser'
|
2
|
+
|
1
3
|
module JsDuck
|
2
4
|
module Doc
|
3
5
|
|
@@ -10,6 +12,7 @@ module JsDuck
|
|
10
12
|
# Initialized with Doc::Scanner instance
|
11
13
|
def initialize(doc_scanner)
|
12
14
|
@ds = doc_scanner
|
15
|
+
@delimited_parser = Doc::DelimitedParser.new(doc_scanner)
|
13
16
|
end
|
14
17
|
|
15
18
|
# Parses the standard tag pattern.
|
@@ -19,21 +22,25 @@ module JsDuck
|
|
19
22
|
#
|
20
23
|
# - :tagname => The :tagname of the hash to return.
|
21
24
|
#
|
22
|
-
# - :type => True to parse {Type} section.
|
23
|
-
#
|
25
|
+
# - :type => True to parse `{Type}` section.
|
26
|
+
#
|
27
|
+
# - :name => True to parse `some.name` section.
|
28
|
+
#
|
29
|
+
# - :default => True to parse `=<default-value>` after name.
|
24
30
|
#
|
25
|
-
# - :
|
26
|
-
#
|
31
|
+
# - :optional => True to allow placing name and default value
|
32
|
+
# inside [ and ] brackets to denote optionality.
|
33
|
+
# Also returns :optional=>true when {SomType=} syntax used.
|
27
34
|
#
|
28
|
-
# Returns tag definition hash containing the
|
29
|
-
#
|
30
|
-
# were specified and how their matching succeeded.
|
35
|
+
# Returns tag definition hash containing the fields specified by
|
36
|
+
# config.
|
31
37
|
#
|
32
38
|
def parse(cfg)
|
33
39
|
@tagname = cfg[:tagname]
|
34
|
-
tag = {
|
35
|
-
|
36
|
-
|
40
|
+
tag = {}
|
41
|
+
tag[:tagname] = cfg[:tagname] if cfg[:tagname]
|
42
|
+
add_type(tag, cfg) if cfg[:type]
|
43
|
+
add_name_with_default(tag, cfg) if cfg[:name]
|
37
44
|
tag
|
38
45
|
end
|
39
46
|
|
@@ -41,11 +48,11 @@ module JsDuck
|
|
41
48
|
|
42
49
|
# matches {type} if possible and sets it on given tag hash.
|
43
50
|
# Also checks for {optionality=} in type definition.
|
44
|
-
def add_type(tag)
|
51
|
+
def add_type(tag, cfg)
|
45
52
|
if hw.look(/\{/)
|
46
53
|
tdf = typedef
|
47
54
|
tag[:type] = tdf[:type]
|
48
|
-
tag[:optional] = true if tdf[:optional]
|
55
|
+
tag[:optional] = true if tdf[:optional] && cfg[:optional]
|
49
56
|
end
|
50
57
|
end
|
51
58
|
|
@@ -53,7 +60,11 @@ module JsDuck
|
|
53
60
|
def typedef
|
54
61
|
match(/\{/)
|
55
62
|
|
56
|
-
name =
|
63
|
+
name = @delimited_parser.parse_until_close_curly
|
64
|
+
|
65
|
+
unless match(/\}/)
|
66
|
+
warn("@#{@tagname} tag syntax: '}' expected")
|
67
|
+
end
|
57
68
|
|
58
69
|
if name =~ /=$/
|
59
70
|
name = name.chop
|
@@ -62,74 +73,29 @@ module JsDuck
|
|
62
73
|
optional = nil
|
63
74
|
end
|
64
75
|
|
65
|
-
match(/\}/) or warn("@#{@tagname} tag syntax: '}' expected")
|
66
|
-
|
67
76
|
return {:type => name, :optional => optional}
|
68
77
|
end
|
69
78
|
|
70
|
-
# matches:
|
71
|
-
|
72
|
-
|
79
|
+
# matches: <ident-chain>
|
80
|
+
# | <ident-chain> [ "=" <default-value>
|
81
|
+
# | "[" <ident-chain> [ "=" <default-value> ] "]"
|
82
|
+
def add_name_with_default(tag, cfg)
|
83
|
+
if hw.look(/\[/) && cfg[:optional]
|
84
|
+
match(/\[/)
|
73
85
|
tag[:name] = hw.ident_chain
|
74
86
|
if hw.match(/=/)
|
75
87
|
hw
|
76
|
-
tag[:default] =
|
88
|
+
tag[:default] = @delimited_parser.parse_until_close_square
|
77
89
|
end
|
78
90
|
hw.match(/\]/) or warn("@#{@tagname} tag syntax: ']' expected")
|
79
91
|
tag[:optional] = true
|
80
|
-
|
81
|
-
tag[:name] =
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
# When the nested parsing doesn't finish at closing "]",
|
87
|
-
# roll back to beginning and simply grab anything up to closing "]".
|
88
|
-
def default_value
|
89
|
-
start_pos = @ds.input.pos
|
90
|
-
value = parse_balanced(/\[/, /\]/, /[^\[\]'"]*/)
|
91
|
-
if look(/\]/)
|
92
|
-
value
|
93
|
-
else
|
94
|
-
@ds.input.pos = start_pos
|
95
|
-
match(/[^\]]*/)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# Helper method to parse a string up to a closing brace,
|
100
|
-
# balancing opening-closing braces in between.
|
101
|
-
#
|
102
|
-
# @param re_open The beginning brace regex
|
103
|
-
# @param re_close The closing brace regex
|
104
|
-
# @param re_rest Regex to match text without any braces and strings
|
105
|
-
def parse_balanced(re_open, re_close, re_rest)
|
106
|
-
result = parse_with_strings(re_rest)
|
107
|
-
while look(re_open)
|
108
|
-
result += match(re_open)
|
109
|
-
result += parse_balanced(re_open, re_close, re_rest)
|
110
|
-
result += match(re_close)
|
111
|
-
result += parse_with_strings(re_rest)
|
112
|
-
end
|
113
|
-
result
|
114
|
-
end
|
115
|
-
|
116
|
-
# Helper for parse_balanced to parse rest of the text between
|
117
|
-
# braces, taking account the strings which might occur there.
|
118
|
-
def parse_with_strings(re_rest)
|
119
|
-
result = match(re_rest)
|
120
|
-
while look(/['"]/)
|
121
|
-
result += parse_string('"') if look(/"/)
|
122
|
-
result += parse_string("'") if look(/'/)
|
123
|
-
result += match(re_rest)
|
92
|
+
elsif name = ident_chain
|
93
|
+
tag[:name] = name
|
94
|
+
if cfg[:default] && hw.match(/=/)
|
95
|
+
hw
|
96
|
+
tag[:default] = @delimited_parser.parse_until_space
|
97
|
+
end
|
124
98
|
end
|
125
|
-
result
|
126
|
-
end
|
127
|
-
|
128
|
-
# Parses "..." or '...' including the escape sequence \' or '\"
|
129
|
-
def parse_string(quote)
|
130
|
-
re_quote = Regexp.new(quote)
|
131
|
-
re_rest = Regexp.new("(?:[^"+quote+"\\\\]|\\\\.)*")
|
132
|
-
match(re_quote) + match(re_rest) + (match(re_quote) || "")
|
133
99
|
end
|
134
100
|
|
135
101
|
### Forward these calls to Doc::Scanner
|