jsduck 4.10.4 → 5.0.0.beta01
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 +0 -1
- data/README.md +32 -6
- data/Rakefile +10 -18
- data/bin/compare +5 -5
- data/bin/jsduck +2 -3
- data/jsduck.gemspec +3 -4
- data/lib/jsduck/aggregator.rb +21 -80
- data/lib/jsduck/app.rb +7 -14
- data/lib/jsduck/app_data.rb +4 -5
- data/lib/jsduck/assets.rb +4 -7
- data/lib/jsduck/base_type.rb +53 -0
- data/lib/jsduck/batch_parser.rb +8 -87
- data/lib/jsduck/batch_processor.rb +77 -0
- data/lib/jsduck/categories/auto.rb +83 -0
- data/lib/jsduck/categories/class_name.rb +63 -0
- data/lib/jsduck/categories/factory.rb +113 -0
- data/lib/jsduck/categories/file.rb +75 -0
- data/lib/jsduck/class.rb +3 -9
- data/lib/jsduck/class_doc_expander.rb +1 -1
- data/lib/jsduck/css/lexer.rb +203 -0
- data/lib/jsduck/css/parser.rb +121 -0
- data/lib/jsduck/doc/comment.rb +40 -0
- data/lib/jsduck/doc/map.rb +23 -0
- data/lib/jsduck/doc/parser.rb +128 -0
- data/lib/jsduck/doc/processor.rb +52 -0
- data/lib/jsduck/doc/scanner.rb +76 -0
- data/lib/jsduck/doc/standard_tag_parser.rb +154 -0
- data/lib/jsduck/doc/subproperties.rb +64 -0
- data/lib/jsduck/docs_code_comparer.rb +31 -0
- data/lib/jsduck/export_writer.rb +2 -2
- data/lib/jsduck/exporter/app.rb +16 -4
- data/lib/jsduck/exporter/full.rb +2 -2
- data/lib/jsduck/format/batch.rb +58 -0
- data/lib/jsduck/format/class.rb +62 -0
- data/lib/jsduck/format/doc.rb +172 -0
- data/lib/jsduck/format/html_stack.rb +109 -0
- data/lib/jsduck/format/shortener.rb +55 -0
- data/lib/jsduck/format/subproperties.rb +64 -0
- data/lib/jsduck/guides.rb +32 -14
- data/lib/jsduck/index_html.rb +3 -1
- data/lib/jsduck/inline/auto_link.rb +2 -2
- data/lib/jsduck/inline/link.rb +4 -3
- data/lib/jsduck/inline/link_renderer.rb +2 -2
- data/lib/jsduck/inline/video.rb +8 -2
- data/lib/jsduck/js/ast.rb +361 -0
- data/lib/jsduck/js/esprima.rb +39 -0
- data/lib/jsduck/{esprima → js/esprima}/esprima.js +0 -0
- data/lib/jsduck/js/evaluator.rb +70 -0
- data/lib/jsduck/js/ext_patterns.rb +70 -0
- data/lib/jsduck/js/function.rb +206 -0
- data/lib/jsduck/js/node.rb +194 -0
- data/lib/jsduck/js/node_array.rb +36 -0
- data/lib/jsduck/js/parser.rb +223 -0
- data/lib/jsduck/js/serializer.rb +263 -0
- data/lib/jsduck/js/utils.rb +21 -0
- data/lib/jsduck/logger.rb +3 -13
- data/lib/jsduck/members_index.rb +3 -4
- data/lib/jsduck/merger.rb +25 -145
- data/lib/jsduck/options.rb +29 -132
- data/lib/jsduck/parser.rb +76 -0
- data/lib/jsduck/process/accessors.rb +133 -0
- data/lib/jsduck/process/circular_deps.rb +58 -0
- data/lib/jsduck/process/enums.rb +91 -0
- data/lib/jsduck/process/ext4_events.rb +43 -0
- data/lib/jsduck/process/global_members.rb +36 -0
- data/lib/jsduck/process/ignored_classes.rb +16 -0
- data/lib/jsduck/process/importer.rb +58 -0
- data/lib/jsduck/process/inherit_doc.rb +197 -0
- data/lib/jsduck/process/lint.rb +135 -0
- data/lib/jsduck/process/overrides.rb +99 -0
- data/lib/jsduck/process/return_values.rb +72 -0
- data/lib/jsduck/process/versions.rb +102 -0
- data/lib/jsduck/relations.rb +5 -0
- data/lib/jsduck/render/class.rb +144 -0
- data/lib/jsduck/render/sidebar.rb +97 -0
- data/lib/jsduck/render/signature.rb +94 -0
- data/lib/jsduck/render/subproperties.rb +99 -0
- data/lib/jsduck/render/tags.rb +38 -0
- data/lib/jsduck/search_data.rb +19 -13
- data/lib/jsduck/source/file.rb +8 -17
- data/lib/jsduck/tag/abstract.rb +4 -7
- data/lib/jsduck/tag/accessor.rb +10 -0
- data/lib/jsduck/tag/alias.rb +61 -0
- data/lib/jsduck/tag/alternate_class_names.rb +17 -0
- data/lib/jsduck/tag/aside.rb +28 -31
- data/lib/jsduck/tag/author.rb +9 -5
- data/lib/jsduck/tag/boolean_tag.rb +24 -0
- data/lib/jsduck/tag/cfg.rb +45 -0
- data/lib/jsduck/tag/chainable.rb +5 -7
- data/lib/jsduck/tag/class.rb +28 -0
- data/lib/jsduck/tag/class_list_tag.rb +40 -0
- data/lib/jsduck/tag/constructor.rb +24 -0
- data/lib/jsduck/tag/css_mixin.rb +17 -0
- data/lib/jsduck/tag/css_var.rb +29 -0
- data/lib/jsduck/tag/default.rb +31 -0
- data/lib/jsduck/tag/deprecated.rb +13 -27
- data/lib/jsduck/tag/deprecated_tag.rb +58 -0
- data/lib/jsduck/tag/doc.rb +32 -0
- data/lib/jsduck/tag/docauthor.rb +4 -5
- data/lib/jsduck/tag/enum.rb +70 -0
- data/lib/jsduck/tag/event.rb +28 -0
- data/lib/jsduck/tag/evented.rb +10 -0
- data/lib/jsduck/tag/extends.rb +45 -0
- data/lib/jsduck/tag/ftype.rb +18 -0
- data/lib/jsduck/tag/hide.rb +4 -11
- data/lib/jsduck/tag/ignore.rb +6 -7
- data/lib/jsduck/tag/inheritable.rb +10 -0
- data/lib/jsduck/tag/inheritdoc.rb +48 -0
- data/lib/jsduck/tag/markdown.rb +8 -6
- data/lib/jsduck/tag/member.rb +24 -0
- data/lib/jsduck/tag/method.rb +35 -0
- data/lib/jsduck/tag/mixins.rb +26 -0
- data/lib/jsduck/tag/name.rb +36 -0
- data/lib/jsduck/tag/new.rb +13 -27
- data/lib/jsduck/tag/override.rb +37 -0
- data/lib/jsduck/tag/overrides.rb +29 -0
- data/lib/jsduck/tag/param.rb +87 -0
- data/lib/jsduck/tag/preventable.rb +19 -10
- data/lib/jsduck/tag/private.rb +28 -13
- data/lib/jsduck/tag/property.rb +39 -0
- data/lib/jsduck/tag/protected.rb +5 -7
- data/lib/jsduck/tag/ptype.rb +18 -0
- data/lib/jsduck/tag/readonly.rb +4 -7
- data/lib/jsduck/tag/removed.rb +21 -29
- data/lib/jsduck/tag/required.rb +11 -9
- data/lib/jsduck/tag/requires.rb +12 -0
- data/lib/jsduck/tag/return.rb +47 -0
- data/lib/jsduck/tag/since.rb +19 -11
- data/lib/jsduck/tag/singleton.rb +15 -0
- data/lib/jsduck/tag/static.rb +5 -7
- data/lib/jsduck/tag/subproperties.rb +23 -0
- data/lib/jsduck/tag/tag.rb +208 -0
- data/lib/jsduck/tag/template.rb +14 -9
- data/lib/jsduck/tag/throws.rb +38 -0
- data/lib/jsduck/tag/type.rb +48 -0
- data/lib/jsduck/tag/uses.rb +12 -0
- data/lib/jsduck/tag/xtype.rb +30 -0
- data/lib/jsduck/tag_loader.rb +39 -0
- data/lib/jsduck/tag_registry.rb +189 -0
- data/lib/jsduck/type_parser.rb +3 -3
- data/lib/jsduck/web_writer.rb +2 -2
- data/lib/jsduck/welcome.rb +1 -1
- metadata +578 -538
- data/lib/jsduck/accessors.rb +0 -136
- data/lib/jsduck/ast.rb +0 -524
- data/lib/jsduck/auto_categories.rb +0 -80
- data/lib/jsduck/batch_formatter.rb +0 -60
- data/lib/jsduck/categories.rb +0 -73
- data/lib/jsduck/categories_class_name.rb +0 -37
- data/lib/jsduck/circular_deps.rb +0 -56
- data/lib/jsduck/class_formatter.rb +0 -102
- data/lib/jsduck/columns.rb +0 -56
- data/lib/jsduck/css_lexer.rb +0 -201
- data/lib/jsduck/css_parser.rb +0 -119
- data/lib/jsduck/doc_ast.rb +0 -319
- data/lib/jsduck/doc_formatter.rb +0 -142
- data/lib/jsduck/doc_parser.rb +0 -611
- data/lib/jsduck/doc_type.rb +0 -59
- data/lib/jsduck/enum.rb +0 -73
- data/lib/jsduck/esprima.rb +0 -51
- data/lib/jsduck/evaluator.rb +0 -69
- data/lib/jsduck/ext_patterns.rb +0 -58
- data/lib/jsduck/file_categories.rb +0 -76
- data/lib/jsduck/function_ast.rb +0 -206
- data/lib/jsduck/guide_anchors.rb +0 -32
- data/lib/jsduck/guide_toc.rb +0 -49
- data/lib/jsduck/html_stack.rb +0 -105
- data/lib/jsduck/importer.rb +0 -121
- data/lib/jsduck/inherit_doc.rb +0 -193
- data/lib/jsduck/js_parser.rb +0 -221
- data/lib/jsduck/lint.rb +0 -133
- data/lib/jsduck/meta_tag.rb +0 -88
- data/lib/jsduck/meta_tag_loader.rb +0 -67
- data/lib/jsduck/meta_tag_registry.rb +0 -111
- data/lib/jsduck/meta_tag_renderer.rb +0 -34
- data/lib/jsduck/news.rb +0 -128
- data/lib/jsduck/override.rb +0 -87
- data/lib/jsduck/renderer.rb +0 -361
- data/lib/jsduck/return_values.rb +0 -72
- data/lib/jsduck/serializer.rb +0 -262
- data/lib/jsduck/shortener.rb +0 -58
- data/lib/jsduck/signature_renderer.rb +0 -91
- data/lib/jsduck/source/file_parser.rb +0 -72
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'jsduck/logger'
|
2
|
+
require 'jsduck/util/json'
|
3
|
+
|
4
|
+
module JsDuck
|
5
|
+
module Categories
|
6
|
+
|
7
|
+
# Reads categories info from config file
|
8
|
+
class File
|
9
|
+
def initialize(filename, relations)
|
10
|
+
@filename = filename
|
11
|
+
@relations = relations
|
12
|
+
end
|
13
|
+
|
14
|
+
# Parses categories in JSON file
|
15
|
+
def generate
|
16
|
+
@categories = Util::Json.read(@filename)
|
17
|
+
|
18
|
+
# Don't crash if old syntax is used.
|
19
|
+
if @categories.is_a?(Hash) && @categories["categories"]
|
20
|
+
Logger.warn(nil, 'Update categories file to contain just the array inside {"categories": [...]}', @filename)
|
21
|
+
@categories = @categories["categories"]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Perform expansion on all class names containing * wildcard
|
25
|
+
@categories.each do |cat|
|
26
|
+
cat["groups"].each do |group|
|
27
|
+
group["classes"] = group["classes"].map do |name|
|
28
|
+
expand(name)
|
29
|
+
end.flatten
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
validate
|
34
|
+
|
35
|
+
@categories
|
36
|
+
end
|
37
|
+
|
38
|
+
# Expands class name like 'Foo.*' into multiple class names.
|
39
|
+
def expand(name)
|
40
|
+
re = Regexp.new("^" + name.split(/\*/, -1).map {|part| Regexp.escape(part) }.join('.*') + "$")
|
41
|
+
|
42
|
+
classes = @relations.to_a.find_all do |cls|
|
43
|
+
re =~ cls[:name] && !cls[:private] && !cls[:deprecated]
|
44
|
+
end.map {|cls| cls[:name] }.sort
|
45
|
+
|
46
|
+
if classes.length == 0
|
47
|
+
Logger.warn(:cat_no_match, "No class found matching a pattern '#{name}' in categories file", @filename)
|
48
|
+
end
|
49
|
+
classes
|
50
|
+
end
|
51
|
+
|
52
|
+
# Prints warnings for missing classes in categories file
|
53
|
+
def validate
|
54
|
+
# Build a map of all classes listed in categories
|
55
|
+
listed_classes = {}
|
56
|
+
@categories.each do |cat|
|
57
|
+
cat["groups"].each do |group|
|
58
|
+
group["classes"].each do |cls_name|
|
59
|
+
listed_classes[cls_name] = true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Check that each existing non-private & non-deprecated class is listed
|
65
|
+
@relations.each do |cls|
|
66
|
+
unless listed_classes[cls[:name]] || cls[:private] || cls[:deprecated]
|
67
|
+
Logger.warn(:cat_class_missing, "Class '#{cls[:name]}' not found in categories file", @filename)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
data/lib/jsduck/class.rb
CHANGED
@@ -162,9 +162,9 @@ module JsDuck
|
|
162
162
|
end
|
163
163
|
|
164
164
|
if query[:static] == true
|
165
|
-
ms = ms.find_all {|m| m[:
|
165
|
+
ms = ms.find_all {|m| m[:static] }
|
166
166
|
elsif query[:static] == false
|
167
|
-
ms = ms.reject {|m| m[:
|
167
|
+
ms = ms.reject {|m| m[:static] }
|
168
168
|
end
|
169
169
|
|
170
170
|
ms
|
@@ -190,13 +190,7 @@ module JsDuck
|
|
190
190
|
def self.member_id(m)
|
191
191
|
# Sanitize $ in member names with something safer
|
192
192
|
name = m[:name].gsub(/\$/, 'S-')
|
193
|
-
"#{m[:
|
194
|
-
end
|
195
|
-
|
196
|
-
# Loops through all available member types,
|
197
|
-
# passing the tagname of the member to the block.
|
198
|
-
def self.each_member_type(&block)
|
199
|
-
[:cfg, :property, :method, :event, :css_var, :css_mixin].each(&block)
|
193
|
+
"#{m[:static] ? 'static-' : ''}#{m[:tagname]}-#{name}"
|
200
194
|
end
|
201
195
|
|
202
196
|
# True if the given member is a constructor method
|
@@ -0,0 +1,203 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
|
3
|
+
module JsDuck
|
4
|
+
module Css
|
5
|
+
|
6
|
+
# Tokenizes CSS or SCSS code into lexical tokens.
|
7
|
+
#
|
8
|
+
# Each token has a type and value.
|
9
|
+
# Types and possible values for them are as follows:
|
10
|
+
#
|
11
|
+
# - :number -- "25.8"
|
12
|
+
# - :percentage -- "25%"
|
13
|
+
# - :dimension -- "2em"
|
14
|
+
# - :string -- '"Hello world"'
|
15
|
+
# - :ident -- "foo-bar"
|
16
|
+
# - :at_keyword -- "@mixin"
|
17
|
+
# - :hash -- "#00FF66"
|
18
|
+
# - :delim -- "{"
|
19
|
+
# - :doc_comment -- "/** My comment */"
|
20
|
+
#
|
21
|
+
# Notice that doc-comments are recognized as tokens while normal
|
22
|
+
# comments are ignored just as whitespace.
|
23
|
+
#
|
24
|
+
class Lexer
|
25
|
+
# Initializes lexer with input string.
|
26
|
+
def initialize(input)
|
27
|
+
@input = StringScanner.new(input)
|
28
|
+
@buffer = []
|
29
|
+
end
|
30
|
+
|
31
|
+
# Tests if given pattern matches the tokens that follow at current
|
32
|
+
# position.
|
33
|
+
#
|
34
|
+
# Takes list of strings and symbols. Symbols are compared to
|
35
|
+
# token type, while strings to token value. For example:
|
36
|
+
#
|
37
|
+
# look(:ident, ":", :dimension)
|
38
|
+
#
|
39
|
+
def look(*tokens)
|
40
|
+
buffer_tokens(tokens.length)
|
41
|
+
i = 0
|
42
|
+
tokens.all? do |t|
|
43
|
+
tok = @buffer[i]
|
44
|
+
i += 1
|
45
|
+
if !tok
|
46
|
+
false
|
47
|
+
elsif t.instance_of?(Symbol)
|
48
|
+
tok[:type] == t
|
49
|
+
else
|
50
|
+
tok[:value] == t
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the value of next token, moving the current token cursor
|
56
|
+
# also to next token.
|
57
|
+
#
|
58
|
+
# When full=true, returns full token as hash like so:
|
59
|
+
#
|
60
|
+
# {:type => :ident, :value => "foo"}
|
61
|
+
#
|
62
|
+
# For doc-comments the full token also contains the field :linenr,
|
63
|
+
# pointing to the line where the doc-comment began.
|
64
|
+
#
|
65
|
+
def next(full=false)
|
66
|
+
buffer_tokens(1)
|
67
|
+
tok = @buffer.shift
|
68
|
+
# advance the scanpointer to the position after this token
|
69
|
+
@input.pos = tok[:pos]
|
70
|
+
full ? tok : tok[:value]
|
71
|
+
end
|
72
|
+
|
73
|
+
# True when no more tokens.
|
74
|
+
def empty?
|
75
|
+
buffer_tokens(1)
|
76
|
+
return !@buffer.first
|
77
|
+
end
|
78
|
+
|
79
|
+
# Ensures next n tokens are read in buffer
|
80
|
+
#
|
81
|
+
# At the end of buffering the initial position scanpointer is
|
82
|
+
# restored. Only the #next method will advance the scanpointer in
|
83
|
+
# a way that's visible outside this class.
|
84
|
+
def buffer_tokens(n)
|
85
|
+
prev_pos = @input.pos
|
86
|
+
@input.pos = @buffer.last[:pos] if @buffer.last
|
87
|
+
(n - @buffer.length).times do
|
88
|
+
@previous_token = tok = next_token
|
89
|
+
if tok
|
90
|
+
# remember scanpointer position after each token
|
91
|
+
tok[:pos] = @input.pos
|
92
|
+
@buffer << tok
|
93
|
+
end
|
94
|
+
end
|
95
|
+
@input.pos = prev_pos
|
96
|
+
end
|
97
|
+
|
98
|
+
# Parses out next token from input stream.
|
99
|
+
def next_token
|
100
|
+
while !@input.eos? do
|
101
|
+
skip_white
|
102
|
+
if @input.check(IDENT)
|
103
|
+
return {
|
104
|
+
:type => :ident,
|
105
|
+
:value => @input.scan(IDENT)
|
106
|
+
}
|
107
|
+
elsif @input.check(/'/)
|
108
|
+
return {
|
109
|
+
:type => :string,
|
110
|
+
:value => @input.scan(/'([^'\\]|\\.)*('|\z)/m)
|
111
|
+
}
|
112
|
+
elsif @input.check(/"/)
|
113
|
+
return {
|
114
|
+
:type => :string,
|
115
|
+
:value => @input.scan(/"([^"\\]|\\.)*("|\z)/m)
|
116
|
+
}
|
117
|
+
elsif @input.check(/\//)
|
118
|
+
# Several things begin with dash:
|
119
|
+
# - comments, regexes, division-operators
|
120
|
+
if @input.check(/\/\*\*[^\/]/)
|
121
|
+
return {
|
122
|
+
:type => :doc_comment,
|
123
|
+
# Calculate current line number, starting with 1
|
124
|
+
:linenr => @input.string[0...@input.pos].count("\n") + 1,
|
125
|
+
:value => @input.scan_until(/\*\/|\z/).sub(/\A\/\*\*/, "").sub(/\*\/\z/, "")
|
126
|
+
}
|
127
|
+
elsif @input.check(/\/\*/)
|
128
|
+
# skip multiline comment
|
129
|
+
@input.scan_until(/\*\/|\z/)
|
130
|
+
elsif @input.check(/\/\//)
|
131
|
+
# skip line comment
|
132
|
+
@input.scan_until(/\n|\z/)
|
133
|
+
else
|
134
|
+
return {
|
135
|
+
:type => :operator,
|
136
|
+
:value => @input.scan(/\//)
|
137
|
+
}
|
138
|
+
end
|
139
|
+
elsif @input.check(NUM)
|
140
|
+
nr = @input.scan(NUM)
|
141
|
+
if @input.check(/%/)
|
142
|
+
return {
|
143
|
+
:type => :percentage,
|
144
|
+
:value => nr + @input.scan(/%/)
|
145
|
+
}
|
146
|
+
elsif @input.check(IDENT)
|
147
|
+
return {
|
148
|
+
:type => :dimension,
|
149
|
+
:value => nr + @input.scan(IDENT)
|
150
|
+
}
|
151
|
+
else
|
152
|
+
return {
|
153
|
+
:type => :number,
|
154
|
+
:value => nr
|
155
|
+
}
|
156
|
+
end
|
157
|
+
elsif @input.check(/@/)
|
158
|
+
return maybe(:at_keyword, /@/, IDENT)
|
159
|
+
elsif @input.check(/#/)
|
160
|
+
return maybe(:hash, /#/, NAME)
|
161
|
+
elsif @input.check(/\$/)
|
162
|
+
return maybe(:var, /\$/, IDENT)
|
163
|
+
elsif @input.check(/./)
|
164
|
+
return {
|
165
|
+
:type => :delim,
|
166
|
+
:value => @input.scan(/./)
|
167
|
+
}
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Returns token of given type when both regexes match.
|
173
|
+
# Otherwise returns :delim token with value of first regex match.
|
174
|
+
# First regex must always match.
|
175
|
+
def maybe(token_type, before_re, after_re)
|
176
|
+
before = @input.scan(before_re)
|
177
|
+
if @input.check(after_re)
|
178
|
+
return {
|
179
|
+
:type => token_type,
|
180
|
+
:value => before + @input.scan(after_re)
|
181
|
+
}
|
182
|
+
else
|
183
|
+
return {
|
184
|
+
:type => :delim,
|
185
|
+
:value => before
|
186
|
+
}
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def skip_white
|
191
|
+
@input.scan(/\s+/)
|
192
|
+
end
|
193
|
+
|
194
|
+
# Simplified token syntax based on:
|
195
|
+
# http://www.w3.org/TR/CSS21/syndata.html
|
196
|
+
IDENT = /-?[_a-z][_a-z0-9-]*/i
|
197
|
+
NAME = /[_a-z0-9-]+/i
|
198
|
+
NUM = /[0-9]*\.[0-9]+|[0-9]+/
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'jsduck/css/lexer'
|
2
|
+
|
3
|
+
module JsDuck
|
4
|
+
module Css
|
5
|
+
|
6
|
+
class Parser
|
7
|
+
def initialize(input, options = {})
|
8
|
+
@lex = Css::Lexer.new(input)
|
9
|
+
@docs = []
|
10
|
+
end
|
11
|
+
|
12
|
+
# Parses the whole CSS block and returns same kind of structure
|
13
|
+
# that JavaScript parser does.
|
14
|
+
def parse
|
15
|
+
while !@lex.empty? do
|
16
|
+
if look(:doc_comment)
|
17
|
+
comment = @lex.next(true)
|
18
|
+
@docs << {
|
19
|
+
:comment => comment[:value],
|
20
|
+
:linenr => comment[:linenr],
|
21
|
+
:code => code_block,
|
22
|
+
:type => :doc_comment,
|
23
|
+
}
|
24
|
+
else
|
25
|
+
@lex.next
|
26
|
+
end
|
27
|
+
end
|
28
|
+
@docs
|
29
|
+
end
|
30
|
+
|
31
|
+
# <code-block> := <mixin-declaration> | <var-declaration> | <property>
|
32
|
+
def code_block
|
33
|
+
if look("@mixin")
|
34
|
+
mixin_declaration
|
35
|
+
elsif look(:var, ":")
|
36
|
+
var_declaration
|
37
|
+
else
|
38
|
+
# Default to property like in Js::Parser.
|
39
|
+
{:tagname => :property}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# <mixin-declaration> := "@mixin" <ident>
|
44
|
+
def mixin_declaration
|
45
|
+
match("@mixin")
|
46
|
+
return {
|
47
|
+
:tagname => :css_mixin,
|
48
|
+
:name => look(:ident) ? match(:ident) : nil,
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
# <var-declaration> := <var> ":" <css-value>
|
53
|
+
def var_declaration
|
54
|
+
name = match(:var)
|
55
|
+
match(":")
|
56
|
+
value_list = css_value
|
57
|
+
return {
|
58
|
+
:tagname => :css_var,
|
59
|
+
:name => name,
|
60
|
+
:default => value_list.map {|v| v[:value] }.join(" "),
|
61
|
+
:type => value_type(value_list),
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
# <css-value> := ...anything up to... [ ";" | "}" | "!default" ]
|
66
|
+
def css_value
|
67
|
+
val = []
|
68
|
+
while !look(";") && !look("}") && !look("!", "default")
|
69
|
+
val << @lex.next(true)
|
70
|
+
end
|
71
|
+
val
|
72
|
+
end
|
73
|
+
|
74
|
+
# Determines type of CSS value
|
75
|
+
def value_type(val)
|
76
|
+
case val[0][:type]
|
77
|
+
when :number
|
78
|
+
"number"
|
79
|
+
when :dimension
|
80
|
+
"length"
|
81
|
+
when :percentage
|
82
|
+
"percentage"
|
83
|
+
when :string
|
84
|
+
"string"
|
85
|
+
when :hash
|
86
|
+
"color"
|
87
|
+
when :ident
|
88
|
+
case val[0][:value]
|
89
|
+
when "true", "false"
|
90
|
+
return "boolean"
|
91
|
+
when "rgb", "rgba", "hsl", "hsla"
|
92
|
+
return "color"
|
93
|
+
when "black", "silver", "gray", "white", "maroon",
|
94
|
+
"red", "purple", "fuchsia", "green", "lime", "olive",
|
95
|
+
"yellow", "navy", "blue", "teal", "aqua", "orange"
|
96
|
+
return "color"
|
97
|
+
when "transparent"
|
98
|
+
return "color"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Matches all arguments, returns the value of last match
|
104
|
+
# When the whole sequence doesn't match, throws exception
|
105
|
+
def match(*args)
|
106
|
+
if look(*args)
|
107
|
+
last = nil
|
108
|
+
args.length.times { last = @lex.next }
|
109
|
+
last
|
110
|
+
else
|
111
|
+
throw "Expected: " + args.join(", ")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def look(*args)
|
116
|
+
@lex.look(*args)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module JsDuck
|
2
|
+
module Doc
|
3
|
+
|
4
|
+
# A simple helper to extract doc comment contents.
|
5
|
+
class Comment
|
6
|
+
|
7
|
+
# Extracts content inside /** ... */
|
8
|
+
def self.purify(input)
|
9
|
+
result = []
|
10
|
+
|
11
|
+
# We can have two types of lines:
|
12
|
+
# - those beginning with *
|
13
|
+
# - and those without it
|
14
|
+
indent = nil
|
15
|
+
input.each_line do |line|
|
16
|
+
line.chomp!
|
17
|
+
if line =~ /\A\s*\*\s?(.*)\z/
|
18
|
+
# When comment contains *-lines, switch indent-trimming off
|
19
|
+
indent = 0
|
20
|
+
result << $1
|
21
|
+
elsif line =~ /\A\s*\z/
|
22
|
+
# pass-through empty lines
|
23
|
+
result << line
|
24
|
+
elsif indent == nil && line =~ /\A(\s*)(.*?\z)/
|
25
|
+
# When indent not measured, measure it and remember
|
26
|
+
indent = $1.length
|
27
|
+
result << $2
|
28
|
+
else
|
29
|
+
# Trim away indent if available
|
30
|
+
result << line.sub(/\A\s{0,#{indent||0}}/, "")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
result.join("\n")
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|