jsduck 3.10.5 → 3.11.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
- JsDuck
1
+ JSDuck
2
2
  ======
3
3
 
4
4
  API documentation generator for Sencha JavaScript frameworks.
5
5
 
6
- JsDuck aims to be a better documentation generator for [Ext JS][] than
6
+ JSDuck aims to be a better documentation generator for [Ext JS][] than
7
7
  the old [ext-doc][] was. It is used by Sencha to document [Ext JS
8
8
  4][ext4-docs], [Sencha Touch][touch2-docs] and [several other][other-docs]
9
9
  products.
@@ -108,13 +108,26 @@ Hacking it
108
108
  See [Hacking guide](https://github.com/senchalabs/jsduck/wiki/Hacking) in wiki.
109
109
 
110
110
 
111
+ Who's using JSDuck?
112
+ -------------------
113
+
114
+ - Appcelerator [Titanium SDK](http://docs.appcelerator.com/titanium/2.0/index.html)
115
+ - AT&T [API Platform SDK for HTML5](https://code-api-att.com/SenchaSdk20Drop23Docs/)
116
+ - Bryntum [Siesta unit testing framework](http://www.bryntum.com/products/siesta/docs/)
117
+ - [GeoExt 2](https://github.com/geoext/geoext2)
118
+ - Rally Software [Rally App SDK](https://rally1.rallydev.com/apps/2.0p/doc/)
119
+ - [Sencha](http://docs.sencha.com) - obviously :)
120
+
121
+ These are some that we know of. Want your project listed here? Drop us a line.
122
+
123
+
111
124
  Copying
112
125
  -------
113
126
 
114
- JsDuck is distributed under the terms of the GNU General Public
127
+ JSDuck is distributed under the terms of the GNU General Public
115
128
  License version 3.
116
129
 
117
- JsDuck was developed by [Rene Saarsoo](http://triin.net),
130
+ JSDuck was developed by [Rene Saarsoo](http://triin.net),
118
131
  with many contributions from [Nick Poulden](https://github.com/nick).
119
132
 
120
133
  Thanks to [Ondřej Jirman](https://github.com/megous),
@@ -136,3 +149,12 @@ Changelog
136
149
  ---------
137
150
 
138
151
  See [Changelog](https://github.com/senchalabs/jsduck/wiki/Changelog) page in wiki.
152
+
153
+
154
+ More questions?
155
+ ---------------
156
+
157
+ Feel free to [post an issue][issues], but read the [FAQ][] first.
158
+
159
+ [issues]: https://github.com/senchalabs/jsduck/issues
160
+ [FAQ]: https://github.com/senchalabs/jsduck/wiki/FAQ
@@ -2,8 +2,8 @@ Gem::Specification.new do |s|
2
2
  s.required_rubygems_version = ">= 1.3.5"
3
3
 
4
4
  s.name = 'jsduck'
5
- s.version = '3.10.5'
6
- s.date = '2012-05-23'
5
+ s.version = '3.11.0'
6
+ s.date = '2012-06-05'
7
7
  s.summary = "Simple JavaScript Duckumentation generator"
8
8
  s.description = "Documentation generator for Sencha JS frameworks"
9
9
  s.homepage = "https://github.com/senchalabs/jsduck"
@@ -48,6 +48,7 @@ module JsDuck
48
48
  m[:html_type] = (@include_types && !is_css_tag) ? format_type(m[:type]) : m[:type] if m[:type]
49
49
  m[:params] = m[:params].map {|p| format_item(p, is_css_tag) } if m[:params]
50
50
  m[:return] = format_item(m[:return], is_css_tag) if m[:return]
51
+ m[:throws] = m[:throws].map {|t| format_item(t, is_css_tag) } if m[:throws]
51
52
  m[:properties] = m[:properties].map {|b| format_item(b, is_css_tag) } if m[:properties]
52
53
  m[:html_meta] = format_meta_data(m)
53
54
  m
@@ -0,0 +1,201 @@
1
+ require 'strscan'
2
+
3
+ module JsDuck
4
+
5
+ # Tokenizes CSS or SCSS code into lexical tokens.
6
+ #
7
+ # Each token has a type and value.
8
+ # Types and possible values for them are as follows:
9
+ #
10
+ # - :number -- "25.8"
11
+ # - :percentage -- "25%"
12
+ # - :dimension -- "2em"
13
+ # - :string -- '"Hello world"'
14
+ # - :ident -- "foo-bar"
15
+ # - :at_keyword -- "@mixin"
16
+ # - :hash -- "#00FF66"
17
+ # - :delim -- "{"
18
+ # - :doc_comment -- "/** My comment */"
19
+ #
20
+ # Notice that doc-comments are recognized as tokens while normal
21
+ # comments are ignored just as whitespace.
22
+ #
23
+ class CssLexer
24
+ # Initializes lexer with input string.
25
+ def initialize(input)
26
+ @input = StringScanner.new(input)
27
+ @buffer = []
28
+ end
29
+
30
+ # Tests if given pattern matches the tokens that follow at current
31
+ # position.
32
+ #
33
+ # Takes list of strings and symbols. Symbols are compared to
34
+ # token type, while strings to token value. For example:
35
+ #
36
+ # look(:ident, ":", :dimension)
37
+ #
38
+ def look(*tokens)
39
+ buffer_tokens(tokens.length)
40
+ i = 0
41
+ tokens.all? do |t|
42
+ tok = @buffer[i]
43
+ i += 1
44
+ if !tok
45
+ false
46
+ elsif t.instance_of?(Symbol)
47
+ tok[:type] == t
48
+ else
49
+ tok[:value] == t
50
+ end
51
+ end
52
+ end
53
+
54
+ # Returns the value of next token, moving the current token cursor
55
+ # also to next token.
56
+ #
57
+ # When full=true, returns full token as hash like so:
58
+ #
59
+ # {:type => :ident, :value => "foo"}
60
+ #
61
+ # For doc-comments the full token also contains the field :linenr,
62
+ # pointing to the line where the doc-comment began.
63
+ #
64
+ def next(full=false)
65
+ buffer_tokens(1)
66
+ tok = @buffer.shift
67
+ # advance the scanpointer to the position after this token
68
+ @input.pos = tok[:pos]
69
+ full ? tok : tok[:value]
70
+ end
71
+
72
+ # True when no more tokens.
73
+ def empty?
74
+ buffer_tokens(1)
75
+ return !@buffer.first
76
+ end
77
+
78
+ # Ensures next n tokens are read in buffer
79
+ #
80
+ # At the end of buffering the initial position scanpointer is
81
+ # restored. Only the #next method will advance the scanpointer in
82
+ # a way that's visible outside this class.
83
+ def buffer_tokens(n)
84
+ prev_pos = @input.pos
85
+ @input.pos = @buffer.last[:pos] if @buffer.last
86
+ (n - @buffer.length).times do
87
+ @previous_token = tok = next_token
88
+ if tok
89
+ # remember scanpointer position after each token
90
+ tok[:pos] = @input.pos
91
+ @buffer << tok
92
+ end
93
+ end
94
+ @input.pos = prev_pos
95
+ end
96
+
97
+ # Parses out next token from input stream.
98
+ def next_token
99
+ while !@input.eos? do
100
+ skip_white
101
+ if @input.check(IDENT)
102
+ return {
103
+ :type => :ident,
104
+ :value => @input.scan(IDENT)
105
+ }
106
+ elsif @input.check(/'/)
107
+ return {
108
+ :type => :string,
109
+ :value => @input.scan(/'([^'\\]|\\.)*('|\Z)/m)
110
+ }
111
+ elsif @input.check(/"/)
112
+ return {
113
+ :type => :string,
114
+ :value => @input.scan(/"([^"\\]|\\.)*("|\Z)/m)
115
+ }
116
+ elsif @input.check(/\//)
117
+ # Several things begin with dash:
118
+ # - comments, regexes, division-operators
119
+ if @input.check(/\/\*\*[^\/]/)
120
+ return {
121
+ :type => :doc_comment,
122
+ # Calculate current line number, starting with 1
123
+ :linenr => @input.string[0...@input.pos].count("\n") + 1,
124
+ :value => @input.scan_until(/\*\/|\Z/)
125
+ }
126
+ elsif @input.check(/\/\*/)
127
+ # skip multiline comment
128
+ @input.scan_until(/\*\/|\Z/)
129
+ elsif @input.check(/\/\//)
130
+ # skip line comment
131
+ @input.scan_until(/\n|\Z/)
132
+ else
133
+ return {
134
+ :type => :operator,
135
+ :value => @input.scan(/\//)
136
+ }
137
+ end
138
+ elsif @input.check(NUM)
139
+ nr = @input.scan(NUM)
140
+ if @input.check(/%/)
141
+ return {
142
+ :type => :percentage,
143
+ :value => nr + @input.scan(/%/)
144
+ }
145
+ elsif @input.check(IDENT)
146
+ return {
147
+ :type => :dimension,
148
+ :value => nr + @input.scan(IDENT)
149
+ }
150
+ else
151
+ return {
152
+ :type => :number,
153
+ :value => nr
154
+ }
155
+ end
156
+ elsif @input.check(/@/)
157
+ return maybe(:at_keyword, /@/, IDENT)
158
+ elsif @input.check(/#/)
159
+ return maybe(:hash, /#/, NAME)
160
+ elsif @input.check(/\$/)
161
+ return maybe(:var, /\$/, IDENT)
162
+ elsif @input.check(/./)
163
+ return {
164
+ :type => :delim,
165
+ :value => @input.scan(/./)
166
+ }
167
+ end
168
+ end
169
+ end
170
+
171
+ # Returns token of given type when both regexes match.
172
+ # Otherwise returns :delim token with value of first regex match.
173
+ # First regex must always match.
174
+ def maybe(token_type, before_re, after_re)
175
+ before = @input.scan(before_re)
176
+ if @input.check(after_re)
177
+ return {
178
+ :type => token_type,
179
+ :value => before + @input.scan(after_re)
180
+ }
181
+ else
182
+ return {
183
+ :type => :delim,
184
+ :value => before
185
+ }
186
+ end
187
+ end
188
+
189
+ def skip_white
190
+ @input.scan(/\s+/)
191
+ end
192
+
193
+ # Simplified token syntax based on:
194
+ # http://www.w3.org/TR/CSS21/syndata.html
195
+ IDENT = /-?[_a-z][_a-z0-9-]*/i
196
+ NAME = /[_a-z0-9-]+/i
197
+ NUM = /[0-9]*\.[0-9]+|[0-9]+/
198
+
199
+ end
200
+
201
+ end
@@ -1,11 +1,11 @@
1
- require 'jsduck/lexer'
1
+ require 'jsduck/css_lexer'
2
2
  require 'jsduck/doc_parser'
3
3
 
4
4
  module JsDuck
5
5
 
6
6
  class CssParser
7
7
  def initialize(input, options = {})
8
- @lex = Lexer.new(input)
8
+ @lex = CssLexer.new(input)
9
9
  @doc_parser = DocParser.new
10
10
  @docs = []
11
11
  end
@@ -28,31 +28,77 @@ module JsDuck
28
28
  @docs
29
29
  end
30
30
 
31
- # <code-block> := <mixin> | <nop>
31
+ # <code-block> := <mixin-declaration> | <var-declaration> | <nop>
32
32
  def code_block
33
- if look("@", "mixin")
34
- mixin
33
+ if look("@mixin")
34
+ mixin_declaration
35
+ elsif look(:var, ":")
36
+ var_declaration
35
37
  else
36
38
  {:type => :nop}
37
39
  end
38
40
  end
39
41
 
40
- # <mixin> := "@mixin" <css-ident>
41
- def mixin
42
- match("@", "mixin")
42
+ # <mixin-declaration> := "@mixin" <ident>
43
+ def mixin_declaration
44
+ match("@mixin")
43
45
  return {
44
46
  :type => :css_mixin,
45
- :name => look(:ident) ? css_ident : nil,
47
+ :name => look(:ident) ? match(:ident) : nil,
46
48
  }
47
49
  end
48
50
 
49
- # <css-ident> := <ident> [ "-" <ident> ]*
50
- def css_ident
51
- chain = [match(:ident)]
52
- while look("-", :ident) do
53
- chain << match("-", :ident)
51
+ # <var-declaration> := <var> ":" <css-value>
52
+ def var_declaration
53
+ name = match(:var)
54
+ match(":")
55
+ value_list = css_value
56
+ return {
57
+ :type => :css_var,
58
+ :name => name,
59
+ :value => {
60
+ :default => value_list.map {|v| v[:value] }.join(" "),
61
+ :type => value_type(value_list),
62
+ }
63
+ }
64
+ end
65
+
66
+ # <css-value> := ...anything up to... [ ";" | "}" | "!default" ]
67
+ def css_value
68
+ val = []
69
+ while !look(";") && !look("}") && !look("!", "default")
70
+ val << @lex.next(true)
71
+ end
72
+ val
73
+ end
74
+
75
+ # Determines type of CSS value
76
+ def value_type(val)
77
+ case val[0][:type]
78
+ when :number
79
+ "number"
80
+ when :dimension
81
+ "length"
82
+ when :percentage
83
+ "percentage"
84
+ when :string
85
+ "string"
86
+ when :hash
87
+ "color"
88
+ when :ident
89
+ case val[0][:value]
90
+ when "true", "false"
91
+ return "boolean"
92
+ when "rgb", "rgba", "hsl", "hsla"
93
+ return "color"
94
+ when "black", "silver", "gray", "white", "maroon",
95
+ "red", "purple", "fuchsia", "green", "lime", "olive",
96
+ "yellow", "navy", "blue", "teal", "aqua", "orange"
97
+ return "color"
98
+ when "transparent"
99
+ return "color"
100
+ end
54
101
  end
55
- return chain.join("-")
56
102
  end
57
103
 
58
104
  # Matches all arguments, returns the value of last match
@@ -132,6 +132,8 @@ module JsDuck
132
132
  at_alias
133
133
  elsif look(/@var\b/)
134
134
  at_var
135
+ elsif look(/@throws\b/)
136
+ at_throws
135
137
  elsif look(/@inheritable\b/)
136
138
  boolean_at_tag(/@inheritable/, :inheritable)
137
139
  elsif look(/@accessor\b/)
@@ -272,7 +274,15 @@ module JsDuck
272
274
  match(/@var/)
273
275
  add_tag(:css_var)
274
276
  maybe_type
275
- maybe_name
277
+ maybe_name_with_default
278
+ skip_white
279
+ end
280
+
281
+ # matches @throws {type} ...
282
+ def at_throws
283
+ match(/@throws/)
284
+ add_tag(:throws)
285
+ maybe_type
276
286
  skip_white
277
287
  end
278
288
 
@@ -10,7 +10,18 @@ module JsDuck
10
10
  super(input)
11
11
  @doc_parser = DocParser.new
12
12
  @docs = []
13
- @ext_namespaces = options[:ext_namespaces] || ["Ext"]
13
+ @ext_namespaces = (options[:ext_namespaces] || ["Ext"]).map {|ns| tokenize_ns(ns) }
14
+ end
15
+
16
+ # Splits namespace string into array like so:
17
+ #
18
+ # "Foo.Bar.Baz" --> ["Foo", ".", "Bar", ".", "Baz"]
19
+ #
20
+ def tokenize_ns(ns)
21
+ ns.split(".").reduce([]) do |res, x|
22
+ res << "." unless res.length == 0
23
+ res << x
24
+ end
14
25
  end
15
26
 
16
27
  # Parses the whole JavaScript block and returns array where for
@@ -78,9 +89,9 @@ module JsDuck
78
89
  elsif look(:var)
79
90
  var_declaration
80
91
  elsif ext_look(:ns, ".", "define", "(", :string)
81
- ext_define
92
+ ext_define(:ns, ".", "define", "(", :string)
82
93
  elsif ext_look(:ns, ".", "ClassManager", ".", "create", "(", :string)
83
- ext_define
94
+ ext_define(:ns, ".", "ClassManager", ".", "create", "(", :string)
84
95
  elsif look(:ident, ":") || look(:string, ":")
85
96
  property_literal
86
97
  elsif look(",", :ident, ":") || look(",", :string, ":")
@@ -244,10 +255,8 @@ module JsDuck
244
255
  end
245
256
 
246
257
  # <ext-define> := "Ext" "." ["define" | "ClassManager" "." "create" ] "(" <string> "," <ext-define-cfg>
247
- def ext_define
248
- match(:ident, ".");
249
- look("define") ? match("define") : match("ClassManager", ".", "create");
250
- name = match("(", :string)[:value]
258
+ def ext_define(*pattern)
259
+ name = ext_match(*pattern)[:value]
251
260
 
252
261
  if look(",", "{")
253
262
  match(",")
@@ -400,11 +409,22 @@ module JsDuck
400
409
  # names listed in @ext_namespaces
401
410
  def ext_look(placeholder, *args)
402
411
  @ext_namespaces.each do |ns|
403
- return true if look(ns, *args)
412
+ return true if look(*(ns + args))
404
413
  end
405
414
  return false
406
415
  end
407
416
 
417
+ # Like match() but tries as the first argument all the names
418
+ # listed in @ext_namespaces
419
+ def ext_match(placeholder, *args)
420
+ @ext_namespaces.each do |ns|
421
+ pattern = ns + args
422
+ if look(*pattern)
423
+ return match(*pattern)
424
+ end
425
+ end
426
+ end
427
+
408
428
  end
409
429
 
410
430
  end
@@ -63,6 +63,8 @@ module JsDuck
63
63
  :class
64
64
  elsif code[:type] == :css_mixin
65
65
  :css_mixin
66
+ elsif code[:type] == :css_var
67
+ :css_var
66
68
  elsif doc_map[:cfg]
67
69
  :cfg
68
70
  elsif code[:type] == :function
@@ -160,6 +162,7 @@ module JsDuck
160
162
  :doc => detect_doc(docs),
161
163
  :params => detect_params(:method, doc_map, code),
162
164
  :return => detect_return(doc_map, name == "constructor" ? "Object" : "undefined"),
165
+ :throws => detect_throws(doc_map),
163
166
  }, doc_map)
164
167
  end
165
168
 
@@ -209,6 +212,7 @@ module JsDuck
209
212
  :name => detect_name(:css_var, doc_map, code),
210
213
  :owner => detect_owner(doc_map),
211
214
  :type => detect_type(:css_var, doc_map, code),
215
+ :default => detect_default(:css_var, doc_map, code),
212
216
  :doc => detect_doc(docs),
213
217
  }, doc_map)
214
218
  end
@@ -251,7 +255,7 @@ module JsDuck
251
255
  main_tag[:name]
252
256
  elsif doc_map[:constructor]
253
257
  "constructor"
254
- elsif code[:type] == :function || code[:type] == :css_mixin
258
+ elsif code[:type] == :function || code[:type] == :css_mixin || code[:type] == :css_var
255
259
  code[:name]
256
260
  elsif code[:type] == :assignment
257
261
  name_type == :full_name ? code[:left].join(".") : code[:left].last
@@ -285,6 +289,8 @@ module JsDuck
285
289
  elsif code[:right][:type] == :literal && code[:right][:class] != nil
286
290
  return code[:right][:class]
287
291
  end
292
+ elsif code[:type] == :css_var && code[:value][:type] != nil
293
+ return code[:value][:type]
288
294
  end
289
295
  end
290
296
  return "Object"
@@ -311,6 +317,8 @@ module JsDuck
311
317
  main_tag[:default]
312
318
  elsif code_matches_doc?(tagname, doc_map, code) && code[:type] == :assignment && code[:right]
313
319
  code[:right][:value]
320
+ elsif code_matches_doc?(tagname, doc_map, code) && code[:type] == :css_var && code[:value][:default]
321
+ code[:value][:default]
314
322
  end
315
323
  end
316
324
 
@@ -470,6 +478,17 @@ module JsDuck
470
478
  }
471
479
  end
472
480
 
481
+ def detect_throws(doc_map)
482
+ return unless doc_map[:throws]
483
+
484
+ doc_map[:throws].map do |throws|
485
+ {
486
+ :type => throws[:type] || "Object",
487
+ :doc => throws[:doc] || "",
488
+ }
489
+ end
490
+ end
491
+
473
492
  # Combines :doc-s of most tags
474
493
  # Ignores tags that have doc comment themselves and subproperty tags
475
494
  def detect_doc(docs)
@@ -75,7 +75,7 @@ module JsDuck
75
75
  ]
76
76
  @meta_tag_paths = []
77
77
 
78
- @version = "3.10.5"
78
+ @version = "3.11.0"
79
79
 
80
80
  # Customizing output
81
81
  @title = "Sencha Docs - Ext JS"
@@ -318,6 +318,10 @@ module JsDuck
318
318
  doc << render_return(ret)
319
319
  end
320
320
 
321
+ if item[:throws]
322
+ doc << render_throws(item[:throws])
323
+ end
324
+
321
325
  doc
322
326
  end
323
327
 
@@ -351,6 +355,22 @@ module JsDuck
351
355
  "</ul>",
352
356
  ]
353
357
  end
358
+
359
+ def render_throws(throws)
360
+ return [
361
+ "<h3 class='pa'>Throws</h3>",
362
+ "<ul>",
363
+ throws.map do |thr|
364
+ [
365
+ "<li>",
366
+ "<span class='pre'>#{thr[:html_type]}</span>",
367
+ "<div class='sub-desc'>#{thr[:doc]}</div>",
368
+ "</li>",
369
+ ]
370
+ end,
371
+ "</ul>",
372
+ ]
373
+ end
354
374
  end
355
375
 
356
376
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsduck
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.10.5
4
+ version: 3.11.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-05-23 00:00:00.000000000 Z
13
+ date: 2012-06-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rdiscount
@@ -144,6 +144,7 @@ files:
144
144
  - lib/jsduck/class.rb
145
145
  - lib/jsduck/class_formatter.rb
146
146
  - lib/jsduck/class_writer.rb
147
+ - lib/jsduck/css_lexer.rb
147
148
  - lib/jsduck/css_parser.rb
148
149
  - lib/jsduck/doc_formatter.rb
149
150
  - lib/jsduck/doc_parser.rb