jsduck 3.1.0 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/README.md +14 -9
  2. data/Rakefile +31 -230
  3. data/jsduck.gemspec +2 -2
  4. data/lib/jsduck/accessors.rb +14 -6
  5. data/lib/jsduck/aggregator.rb +9 -4
  6. data/lib/jsduck/app.rb +1 -0
  7. data/lib/jsduck/app_data.rb +14 -7
  8. data/lib/jsduck/app_exporter.rb +3 -3
  9. data/lib/jsduck/class.rb +8 -5
  10. data/lib/jsduck/class_formatter.rb +1 -3
  11. data/lib/jsduck/css_parser.rb +1 -1
  12. data/lib/jsduck/doc_formatter.rb +140 -36
  13. data/lib/jsduck/doc_parser.rb +27 -44
  14. data/lib/jsduck/index_html.rb +0 -3
  15. data/lib/jsduck/inherit_doc.rb +20 -4
  16. data/lib/jsduck/js_parser.rb +1 -1
  17. data/lib/jsduck/lint.rb +15 -0
  18. data/lib/jsduck/logger.rb +9 -7
  19. data/lib/jsduck/merger.rb +18 -16
  20. data/lib/jsduck/meta_tag.rb +28 -5
  21. data/lib/jsduck/meta_tag_loader.rb +38 -21
  22. data/lib/jsduck/meta_tag_registry.rb +79 -0
  23. data/lib/jsduck/options.rb +69 -12
  24. data/lib/jsduck/renderer.rb +10 -38
  25. data/lib/jsduck/search_data.rb +53 -3
  26. data/lib/jsduck/tag/abstract.rb +14 -0
  27. data/lib/jsduck/{author_tag.rb → tag/author.rb} +2 -2
  28. data/lib/jsduck/tag/deprecated.rb +33 -0
  29. data/lib/jsduck/{doc_author_tag.rb → tag/docauthor.rb} +2 -2
  30. data/lib/jsduck/tag/markdown.rb +12 -0
  31. data/lib/jsduck/tag/preventable.rb +28 -0
  32. data/lib/jsduck/tag/protected.rb +14 -0
  33. data/lib/jsduck/tag/readonly.rb +14 -0
  34. data/lib/jsduck/tag/required.rb +21 -0
  35. data/lib/jsduck/tag/static.rb +14 -0
  36. data/lib/jsduck/tag/template.rb +23 -0
  37. data/opt/example.js +149 -0
  38. metadata +17 -9
  39. data/opt/extjs-welcome.html +0 -74
  40. data/opt/touch-iframe.html +0 -85
  41. data/opt/touch-welcome.html +0 -122
@@ -85,15 +85,19 @@ module JsDuck
85
85
  # Merges new class-doc into old one.
86
86
  def merge_classes(old, new)
87
87
  # Merge booleans
88
- [:extends, :singleton, :private, :protected].each do |tag|
88
+ [:extends, :singleton, :private].each do |tag|
89
89
  old[tag] = old[tag] || new[tag]
90
90
  end
91
91
  # Merge arrays
92
92
  [:mixins, :alternateClassNames, :files].each do |tag|
93
93
  old[tag] = old[tag] + new[tag]
94
94
  end
95
+ # Merge meta hashes
96
+ new[:meta].each_pair do |name, value|
97
+ old[:meta][name] = old[:meta][name] || value
98
+ end
95
99
  # Merge hashes of arrays
96
- [:aliases, :meta].each do |tag|
100
+ [:aliases].each do |tag|
97
101
  new[tag].each_pair do |key, contents|
98
102
  old[tag][key] = (old[tag][key] || []) + contents
99
103
  end
@@ -129,7 +133,7 @@ module JsDuck
129
133
  end
130
134
 
131
135
  def add_to_class(cls, member)
132
- cls[member[:static] ? :statics : :members][member[:tagname]] << member
136
+ cls[member[:meta][:static] ? :statics : :members][member[:tagname]] << member
133
137
  end
134
138
 
135
139
  def add_orphan(node)
@@ -182,8 +186,9 @@ module JsDuck
182
186
  :alternateClassNames => [],
183
187
  :members => Class.default_members_hash,
184
188
  :statics => Class.default_members_hash,
189
+ :aliases => {},
185
190
  :meta => {},
186
- :files => [{:filename => "", :linenr => 0}],
191
+ :files => [{:filename => "", :linenr => 0, :href => ""}],
187
192
  })
188
193
  end
189
194
 
data/lib/jsduck/app.rb CHANGED
@@ -143,6 +143,7 @@ module JsDuck
143
143
  class_formatter.include_types = !@opts.export
144
144
  # Format all doc-objects in parallel
145
145
  formatted_classes = @parallel.map(@relations.classes) do |cls|
146
+ Logger.instance.log("Markdown formatting #{cls[:name]}")
146
147
  {
147
148
  :doc => class_formatter.format(cls.internal_doc),
148
149
  :images => doc_formatter.images
@@ -2,6 +2,7 @@ require 'jsduck/json_duck'
2
2
  require 'jsduck/icons'
3
3
  require 'jsduck/search_data'
4
4
  require 'jsduck/stats'
5
+ require 'jsduck/meta_tag_registry'
5
6
 
6
7
  module JsDuck
7
8
 
@@ -18,13 +19,19 @@ module JsDuck
18
19
 
19
20
  # Writes classes, guides, videos, and search data to one big .js file
20
21
  def write(filename)
21
- js = "Docs.data = " + JsonDuck.generate({
22
- :classes => Icons.new.create(@relations.classes),
23
- :guides => @guides.to_array,
24
- :videos => @videos.to_array,
25
- :examples => @examples.to_array,
26
- :search => SearchData.new.create(@relations.classes),
27
- :stats => @opts.stats ? Stats.new.create(@relations.classes) : [],
22
+ js = "Docs = " + JsonDuck.generate({
23
+ :data => {
24
+ :classes => Icons.new.create(@relations.classes),
25
+ :guides => @guides.to_array,
26
+ :videos => @videos.to_array,
27
+ :examples => @examples.to_array,
28
+ :search => SearchData.new.create(@relations.classes),
29
+ :stats => @opts.stats ? Stats.new.create(@relations.classes) : [],
30
+ :signatures => MetaTagRegistry.instance.signatures,
31
+ :localStorageDb => @opts.local_storage_db,
32
+ :showPrintButton => @opts.seo,
33
+ :touchExamplesUi => @opts.touch_examples_ui,
34
+ }
28
35
  }) + ";\n"
29
36
  File.open(filename, 'w') {|f| f.write(js) }
30
37
  end
@@ -1,6 +1,7 @@
1
1
  require 'jsduck/full_exporter'
2
2
  require 'jsduck/renderer'
3
3
  require 'jsduck/doc_formatter'
4
+ require 'jsduck/meta_tag_registry'
4
5
 
5
6
  module JsDuck
6
7
 
@@ -12,8 +13,7 @@ module JsDuck
12
13
  @renderer = Renderer.new
13
14
  # Inject formatter to all meta-tags.
14
15
  doc_formatter = DocFormatter.new(relations, opts)
15
- opts.meta_tags.each {|tag| tag.formatter = doc_formatter }
16
- @renderer.meta_tags = opts.meta_tags
16
+ MetaTagRegistry.instance.formatter = doc_formatter
17
17
  end
18
18
 
19
19
  # Returns compacted class data hash which contains an additional
@@ -45,7 +45,7 @@ module JsDuck
45
45
 
46
46
  def compact_member(m)
47
47
  m_copy = {}
48
- [:name, :tagname, :owner, :protected, :static, :deprecated, :required, :template, :id].each do |key|
48
+ [:name, :tagname, :owner, :meta, :id].each do |key|
49
49
  m_copy[key] = m[key]
50
50
  end
51
51
  m_copy
data/lib/jsduck/class.rb CHANGED
@@ -154,25 +154,28 @@ module JsDuck
154
154
  local_members
155
155
  end
156
156
 
157
- # Returns member by name.
157
+ # Returns members by name. An array of one or more members, or
158
+ # empty array when nothing matches.
158
159
  #
159
160
  # Optionally one can also specify type name to differenciate
160
161
  # between different types of members.
161
- def get_member(name, type_name=nil)
162
+ def get_members(name, type_name=nil, static=false)
162
163
  # build hash of all members
163
164
  unless @members_map
164
165
  @members_map = {}
165
166
  [:members, :statics].each do |group|
166
167
  @doc[group].each_key do |type|
167
168
  members_hash(type, group).each_pair do |key, member|
168
- @members_map["#{type}-#{key}"] = member
169
- @members_map[key] = member
169
+ @members_map[key] = (@members_map[key] || []) + [member]
170
170
  end
171
171
  end
172
172
  end
173
173
  end
174
174
 
175
- @members_map[type_name ? "#{type_name}-#{name}" : name]
175
+ ms = @members_map[name] || []
176
+ ms = ms.find_all {|m| m[:tagname] == type_name } if type_name
177
+ ms = ms.find_all {|m| m[:meta][:static] } if static
178
+ return ms
176
179
  end
177
180
 
178
181
  # Returns all public members of class, including the inherited and mixed in ones
@@ -14,7 +14,6 @@ module JsDuck
14
14
  @relations = relations
15
15
  @formatter = formatter
16
16
  @include_types = true
17
- @meta_tags = []
18
17
  end
19
18
 
20
19
  # Runs the formatter on doc object of a class.
@@ -36,7 +35,6 @@ module JsDuck
36
35
  def format_member(m)
37
36
  @formatter.doc_context = m[:files][0]
38
37
  m[:doc] = @formatter.format(m[:doc]) if m[:doc]
39
- m[:deprecated][:text] = @formatter.format(m[:deprecated][:text]) if m[:deprecated]
40
38
  if expandable?(m) || @formatter.too_long?(m[:doc])
41
39
  m[:shortDoc] = @formatter.shorten(m[:doc])
42
40
  end
@@ -52,7 +50,7 @@ module JsDuck
52
50
  end
53
51
 
54
52
  def expandable?(m)
55
- m[:params] || (m[:properties] && m[:properties].length > 0) || m[:default] || m[:deprecated] || m[:template]
53
+ m[:params] || (m[:properties] && m[:properties].length > 0) || m[:default] || m[:meta][:deprecated] || m[:meta][:template]
56
54
  end
57
55
 
58
56
  def format_item(it, is_css_tag)
@@ -6,7 +6,7 @@ module JsDuck
6
6
  class CssParser
7
7
  def initialize(input, options = {})
8
8
  @lex = Lexer.new(input)
9
- @doc_parser = DocParser.new(:css, options[:meta_tags])
9
+ @doc_parser = DocParser.new
10
10
  @docs = []
11
11
  end
12
12
 
@@ -78,27 +78,48 @@ module JsDuck
78
78
  #
79
79
  # Adds 'inline-example' class to code examples beginning with @example.
80
80
  #
81
- # Additionally replaces strings recognized as ClassNames with
82
- # links to these classes. So one doesn even need to use the @link
83
- # tag to create a link.
81
+ # Additionally replaces strings recognized as ClassNames or
82
+ # #members with links to these classes or members. So one doesn't
83
+ # even need to use the @link tag to create a link.
84
84
  def replace(input)
85
85
  s = StringScanner.new(input)
86
86
  out = ""
87
+
88
+ # Keep track of the nesting level of <a> tags. We're not
89
+ # auto-detecting class names when inside <a>. Normally links
90
+ # shouldn't be nested, but just to be extra safe.
91
+ open_a_tags = 0
92
+
87
93
  while !s.eos? do
88
94
  if s.check(@link_re)
89
95
  out += replace_link_tag(s.scan(@link_re))
90
96
  elsif s.check(@img_re)
91
97
  out += replace_img_tag(s.scan(@img_re))
98
+ elsif s.check(/[{]/)
99
+ # There might still be "{" that doesn't begin {@link} or {@img} - ignore it
100
+ out += s.scan(/[{]/)
92
101
  elsif s.check(@example_annotation_re)
93
102
  # Match possible classnames following @example and add them
94
103
  # as CSS classes inside <pre> element.
95
104
  s.scan(@example_annotation_re) =~ @example_annotation_re
96
105
  css_classes = ($1 || "").strip
97
106
  out += "<pre class='inline-example #{css_classes}'><code>"
98
- elsif s.check(/[{<]/)
99
- out += s.scan(/[{<]/)
107
+ elsif s.check(/<a\b/)
108
+ # Increment number of open <a> tags.
109
+ open_a_tags += 1
110
+ out += s.scan_until(/>|\Z/)
111
+ elsif s.check(/<\/a>/)
112
+ # <a> closed, auto-detection may continue when no more <a> tags open.
113
+ open_a_tags -= 1
114
+ out += s.scan(/<\/a>/)
115
+ elsif s.check(/</)
116
+ # Ignore all other HTML tags
117
+ out += s.scan_until(/>|\Z/)
100
118
  else
101
- out += replace_class_names(s.scan(/[^{<]+/))
119
+ # Replace class names in the following text up to next "<" or "{"
120
+ # but only when we're not inside <a>...</a>
121
+ text = s.scan(/[^{<]+/)
122
+ out += open_a_tags > 0 ? text : create_magic_links(text)
102
123
  end
103
124
  end
104
125
  out
@@ -108,12 +129,14 @@ module JsDuck
108
129
  input.sub(@link_re) do
109
130
  target = $1
110
131
  text = $2
111
- if target =~ /^(.*)#(?:(.*)-)?(.*)$/
132
+ if target =~ /^(.*)#(static-)?(?:(cfg|property|method|event|css_var|css_mixin)-)?(.*)$/
112
133
  cls = $1.empty? ? @class_context : $1
113
- type = $2 ? $2.intern : nil
114
- member = $3
134
+ static = !!$2
135
+ type = $3 ? $3.intern : nil
136
+ member = $4
115
137
  else
116
138
  cls = target
139
+ static = false
117
140
  type = false
118
141
  member = false
119
142
  end
@@ -131,15 +154,39 @@ module JsDuck
131
154
  line = @doc_context[:linenr]
132
155
  if !@relations[cls]
133
156
  Logger.instance.warn(:link, "#{input} links to non-existing class", file, line)
134
- text
135
- elsif member && !get_member(cls, member, type)
136
- Logger.instance.warn(:link, "#{input} links to non-existing member", file, line)
137
- text
138
- elsif member && !public_member?(cls, member, type)
139
- Logger.instance.warn(:link, "#{input} links to private member", file, line)
140
- text
157
+ return text
158
+ elsif member
159
+ ms = get_members(cls, member, type, static)
160
+ if ms.length == 0
161
+ Logger.instance.warn(:link, "#{input} links to non-existing member", file, line)
162
+ return text
163
+ end
164
+
165
+ ms = ms.find_all {|m| !m[:private] }
166
+ if ms.length == 0
167
+ Logger.instance.warn(:link_private, "#{input} links to private member", file, line)
168
+ return text
169
+ end
170
+
171
+ if ms.length > 1
172
+ # When multiple public members, see if there remains just
173
+ # one when we ignore the static members. If there's more,
174
+ # report ambiguity. If there's only static members, also
175
+ # report ambiguity.
176
+ instance_ms = ms.find_all {|m| !m[:meta][:static] }
177
+ if instance_ms.length > 1
178
+ alternatives = instance_ms.map {|m| m[:tagname].to_s }.join(", ")
179
+ Logger.instance.warn(:link_ambiguous, "#{input} is ambiguous: "+alternatives, file, line)
180
+ elsif instance_ms.length == 0
181
+ static_ms = ms.find_all {|m| m[:meta][:static] }
182
+ alternatives = static_ms.map {|m| "static " + m[:tagname].to_s }.join(", ")
183
+ Logger.instance.warn(:link_ambiguous, "#{input} is ambiguous: "+alternatives, file, line)
184
+ end
185
+ end
186
+
187
+ return link(cls, member, text, type, static)
141
188
  else
142
- link(cls, member, text, type)
189
+ return link(cls, false, text)
143
190
  end
144
191
  end
145
192
  end
@@ -148,21 +195,73 @@ module JsDuck
148
195
  input.sub(@img_re) { img($1, $2) }
149
196
  end
150
197
 
151
- def replace_class_names(input)
152
- input.gsub(/(\A|\s)([A-Z][A-Za-z0-9.]*[A-Za-z0-9])(?:(#)([A-Za-z0-9]+))?([.,]?(?:\s|\Z))/m) do
153
- before = $1
154
- cls = $2
155
- hash = $3
156
- member = $4
157
- after = $5
158
-
159
- if @relations[cls] && (member ? public_member?(cls, member) : cls =~ /\./)
160
- label = member ? cls+"."+member : cls
161
- before + link(cls, member, label) + after
198
+ # Looks input text for patterns like:
199
+ #
200
+ # My.ClassName
201
+ # MyClass#method
202
+ # #someProperty
203
+ #
204
+ # and converts them to links, as if they were surrounded with
205
+ # {@link} tag. One notable exception is that Foo is not created to
206
+ # link, even when Foo class exists, but Foo.Bar is. This is to
207
+ # avoid turning normal words into links. For example:
208
+ #
209
+ # Math involves a lot of numbers. Ext JS is a JavaScript framework.
210
+ #
211
+ # In these sentences we don't want to link "Math" and "Ext" to the
212
+ # corresponding JS classes. And that's why we auto-link only
213
+ # class names containing a dot "."
214
+ #
215
+ def create_magic_links(input)
216
+ cls_re = "([A-Z][A-Za-z0-9.]*[A-Za-z0-9])"
217
+ member_re = "(?:#([A-Za-z0-9]+))"
218
+
219
+ input.gsub(/\b#{cls_re}#{member_re}?\b|#{member_re}\b/m) do
220
+ replace_magic_link($1, $2 || $3)
221
+ end
222
+ end
223
+
224
+ def replace_magic_link(cls, member)
225
+ if cls && member
226
+ if @relations[cls] && get_matching_member(cls, member)
227
+ return link(cls, member, cls+"."+member)
228
+ else
229
+ warn_magic_link("#{cls}##{member} links to non-existing " + (@relations[cls] ? "member" : "class"))
230
+ end
231
+ elsif cls && cls =~ /\./
232
+ if @relations[cls]
233
+ return link(cls, nil, cls)
162
234
  else
163
- before + cls + (hash || "") + (member || "") + after
235
+ cls2, member2 = split_to_cls_and_member(cls)
236
+ if @relations[cls2] && get_matching_member(cls2, member2)
237
+ return link(cls2, member2, cls2+"."+member2)
238
+ elsif cls =~ /\.(js|css|html|php)\Z/
239
+ # Ignore common filenames
240
+ else
241
+ warn_magic_link("#{cls} links to non-existing class")
242
+ end
243
+ end
244
+ elsif !cls && member
245
+ if get_matching_member(@class_context, member)
246
+ return link(@class_context, member, member)
247
+ elsif member =~ /\A([A-F0-9]{3}|[A-F0-9]{6})\Z/i || member =~ /\A[0-9]/
248
+ # Ignore HEX color codes and
249
+ # member names beginning with number
250
+ else
251
+ warn_magic_link("##{member} links to non-existing member")
164
252
  end
165
253
  end
254
+
255
+ return "#{cls}#{member ? '#' : ''}#{member}"
256
+ end
257
+
258
+ def split_to_cls_and_member(str)
259
+ parts = str.split(/\./)
260
+ return [parts.slice(0, parts.length-1).join("."), parts.last]
261
+ end
262
+
263
+ def warn_magic_link(msg)
264
+ Logger.instance.warn(:link_auto, msg, @doc_context[:filename], @doc_context[:linenr])
166
265
  end
167
266
 
168
267
  # applies the image template
@@ -181,11 +280,11 @@ module JsDuck
181
280
  end
182
281
 
183
282
  # applies the link template
184
- def link(cls, member, anchor_text, type=nil)
283
+ def link(cls, member, anchor_text, type=nil, static=false)
185
284
  # Use the canonical class name for link (not some alternateClassName)
186
285
  cls = @relations[cls].full_name
187
286
  # prepend type name to member name
188
- member = member && get_member(cls, member, type)
287
+ member = member && get_matching_member(cls, member, type, static)
189
288
 
190
289
  @link_tpl.gsub(/(%[\w#-])/) do
191
290
  case $1
@@ -205,13 +304,18 @@ module JsDuck
205
304
  end
206
305
  end
207
306
 
208
- def public_member?(cls, member, type=nil)
209
- m = get_member(cls, member, type)
210
- return m && !m[:private]
307
+ def get_matching_member(cls, member, type=nil, static=false)
308
+ ms = get_members(cls, member, type, static).find_all {|m| !m[:private] }
309
+ if ms.length > 1
310
+ instance_ms = ms.find_all {|m| !m[:meta][:static] }
311
+ instance_ms.length > 0 ? instance_ms[0] : ms.find_all {|m| m[:meta][:static] }[0]
312
+ else
313
+ ms[0]
314
+ end
211
315
  end
212
316
 
213
- def get_member(cls, member, type=nil)
214
- return @relations[cls] && @relations[cls].get_member(member, type)
317
+ def get_members(cls, member, type=nil, static=false)
318
+ @relations[cls] ? @relations[cls].get_members(member, type, static) : []
215
319
  end
216
320
 
217
321
  # Formats doc-comment for placement into HTML.
@@ -1,6 +1,7 @@
1
1
  require 'strscan'
2
2
  require 'jsduck/js_literal_parser'
3
3
  require 'jsduck/js_literal_builder'
4
+ require 'jsduck/meta_tag_registry'
4
5
 
5
6
  module JsDuck
6
7
 
@@ -23,15 +24,10 @@ module JsDuck
23
24
  # @see and {@link} are parsed separately in JsDuck::DocFormatter.
24
25
  #
25
26
  class DocParser
26
- # Pass in :css to be able to parse CSS doc-comments
27
- def initialize(mode = :js, meta_tags = nil)
28
- @ident_pattern = (mode == :css) ? /\$?[\w-]+/ : /[$\w]\w*/
29
- @ident_chain_pattern = (mode == :css) ? /\$?[\w-]+(\.[\w-]+)*/ : /[$\w]\w*(\.\w+)*/
30
-
31
- @meta_tags_map = {}
32
- (meta_tags || []).each do |tag|
33
- @meta_tags_map[tag.name] = tag
34
- end
27
+ def initialize
28
+ @ident_pattern = /[$\w-]+/
29
+ @ident_chain_pattern = /[$\w-]+(\.[$\w-]+)*/
30
+ @meta_tags = MetaTagRegistry.instance
35
31
  end
36
32
 
37
33
  def parse(input)
@@ -134,33 +130,19 @@ module JsDuck
134
130
  at_inheritdoc
135
131
  elsif look(/@alias/)
136
132
  at_alias
137
- elsif look(/@deprecated\b/)
138
- at_deprecated
139
133
  elsif look(/@var\b/)
140
134
  at_var
141
- elsif look(/@static\b/)
142
- boolean_at_tag(/@static/, :static)
143
135
  elsif look(/@inheritable\b/)
144
136
  boolean_at_tag(/@inheritable/, :inheritable)
145
137
  elsif look(/@(private|ignore|hide)\b/)
146
138
  boolean_at_tag(/@(private|ignore|hide)/, :private)
147
- elsif look(/@protected\b/)
148
- boolean_at_tag(/@protected/, :protected)
149
139
  elsif look(/@accessor\b/)
150
140
  boolean_at_tag(/@accessor/, :accessor)
151
141
  elsif look(/@evented\b/)
152
142
  boolean_at_tag(/@evented/, :evented)
153
- elsif look(/@template\b/)
154
- boolean_at_tag(/@template/, :template)
155
- elsif look(/@markdown\b/)
156
- # this is detected just to be ignored
157
- boolean_at_tag(/@markdown/, :markdown)
158
- elsif look(/@abstract\b/)
159
- # this is detected just to be ignored
160
- boolean_at_tag(/@abstract/, :abstract)
161
143
  elsif look(/@/)
162
144
  @input.scan(/@/)
163
- tag = @meta_tags_map[look(/\w+/)]
145
+ tag = @meta_tags[look(/\w+/)]
164
146
  if tag
165
147
  meta_at_tag(tag)
166
148
  else
@@ -177,13 +159,21 @@ module JsDuck
177
159
  prev_tag = @current_tag
178
160
 
179
161
  add_tag(:meta)
180
- @current_tag[:name] = match(/\w+/)
162
+ @current_tag[:name] = tag.key
163
+ match(/\w+/)
181
164
  skip_horiz_white
182
165
 
183
- # Fors singleline tags, scan to the end of line and finish the
184
- # tag. For multiline tags we leave the tag open for :doc
185
- # addition just like with built-in multiline tags.
186
- unless tag.multiline
166
+ if tag.boolean
167
+ # For boolean tags, only scan the tag name and switch context
168
+ # back to previous tag.
169
+ skip_white
170
+ @current_tag = prev_tag
171
+ elsif tag.multiline
172
+ # For multiline tags we leave the tag open for :doc addition
173
+ # just like with built-in multiline tags.
174
+ else
175
+ # Fors singleline tags, scan to the end of line and finish the
176
+ # tag.
187
177
  @current_tag[:doc] = @input.scan(/.*$/).strip
188
178
  skip_white
189
179
  @current_tag = prev_tag
@@ -275,7 +265,7 @@ module JsDuck
275
265
  match(/@property/)
276
266
  add_tag(:property)
277
267
  maybe_type
278
- maybe_ident_chain(:name)
268
+ maybe_name_with_default
279
269
  skip_white
280
270
  end
281
271
 
@@ -331,7 +321,7 @@ module JsDuck
331
321
  skip_white
332
322
  end
333
323
 
334
- # matches @inheritdoc class.name#type-member
324
+ # matches @inheritdoc class.name#static-type-member
335
325
  def at_inheritdoc
336
326
  match(/@inherit[dD]oc|@alias/)
337
327
 
@@ -341,8 +331,12 @@ module JsDuck
341
331
  @current_tag[:cls] = ident_chain
342
332
  if look(/#\w/)
343
333
  @input.scan(/#/)
344
- if look(/\w+-\w+/)
345
- @current_tag[:type] = ident
334
+ if look(/static-/)
335
+ @current_tag[:static] = true
336
+ @input.scan(/static-/)
337
+ end
338
+ if look(/(cfg|property|method|event|css_var|css_mixin)-/)
339
+ @current_tag[:type] = ident.to_sym
346
340
  @input.scan(/-/)
347
341
  end
348
342
  @current_tag[:member] = ident
@@ -351,17 +345,6 @@ module JsDuck
351
345
  skip_white
352
346
  end
353
347
 
354
- # matches @deprecated <version> some text ... newline
355
- def at_deprecated
356
- match(/@deprecated/)
357
- add_tag(:deprecated)
358
- skip_horiz_white
359
- @current_tag[:version] = @input.scan(/[0-9.]+/)
360
- skip_horiz_white
361
- @current_tag[:text] = @input.scan(/.*$/)
362
- skip_white
363
- end
364
-
365
348
  # Used to match @private, @ignore, @hide, ...
366
349
  def boolean_at_tag(regex, propname)
367
350
  match(regex)