jsduck 4.0.1 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/Rakefile +14 -0
  2. data/esprima/esprima.js +210 -85
  3. data/jsduck.gemspec +3 -3
  4. data/lib/jsduck/accessors.rb +10 -8
  5. data/lib/jsduck/aggregator.rb +7 -7
  6. data/lib/jsduck/app.rb +24 -164
  7. data/lib/jsduck/app_data.rb +2 -4
  8. data/lib/jsduck/assets.rb +5 -2
  9. data/lib/jsduck/ast.rb +9 -4
  10. data/lib/jsduck/batch_formatter.rb +54 -0
  11. data/lib/jsduck/batch_parser.rb +106 -0
  12. data/lib/jsduck/categories.rb +5 -6
  13. data/lib/jsduck/class.rb +77 -239
  14. data/lib/jsduck/class_doc_expander.rb +0 -5
  15. data/lib/jsduck/class_formatter.rb +14 -10
  16. data/lib/jsduck/class_name.rb +23 -0
  17. data/lib/jsduck/class_writer.rb +9 -8
  18. data/lib/jsduck/doc_ast.rb +5 -6
  19. data/lib/jsduck/doc_formatter.rb +61 -272
  20. data/lib/jsduck/enum.rb +4 -4
  21. data/lib/jsduck/esprima.rb +10 -4
  22. data/lib/jsduck/examples.rb +5 -5
  23. data/lib/jsduck/export_writer.rb +62 -0
  24. data/lib/jsduck/exporter/app.rb +62 -0
  25. data/lib/jsduck/exporter/examples.rb +58 -0
  26. data/lib/jsduck/exporter/full.rb +60 -0
  27. data/lib/jsduck/file_categories.rb +7 -4
  28. data/lib/jsduck/function_ast.rb +99 -0
  29. data/lib/jsduck/grouped_asset.rb +27 -16
  30. data/lib/jsduck/guide_writer.rb +8 -7
  31. data/lib/jsduck/guides.rb +31 -29
  32. data/lib/jsduck/icons.rb +12 -1
  33. data/lib/jsduck/images.rb +3 -3
  34. data/lib/jsduck/importer.rb +7 -7
  35. data/lib/jsduck/index_html.rb +20 -6
  36. data/lib/jsduck/inherit_doc.rb +9 -12
  37. data/lib/jsduck/inline/example.rb +42 -0
  38. data/lib/jsduck/inline/img.rb +55 -0
  39. data/lib/jsduck/inline/link.rb +227 -0
  40. data/lib/jsduck/inline/video.rb +67 -0
  41. data/lib/jsduck/inline_examples.rb +7 -7
  42. data/lib/jsduck/js_parser.rb +5 -4
  43. data/lib/jsduck/lint.rb +14 -2
  44. data/lib/jsduck/logger.rb +5 -6
  45. data/lib/jsduck/members_index.rb +132 -0
  46. data/lib/jsduck/merger.rb +3 -9
  47. data/lib/jsduck/options.rb +39 -41
  48. data/lib/jsduck/override.rb +3 -7
  49. data/lib/jsduck/relations.rb +9 -9
  50. data/lib/jsduck/renderer.rb +3 -3
  51. data/lib/jsduck/return_values.rb +72 -0
  52. data/lib/jsduck/search_data.rb +16 -20
  53. data/lib/jsduck/shortener.rb +58 -0
  54. data/lib/jsduck/signature_renderer.rb +1 -2
  55. data/lib/jsduck/source/file.rb +98 -0
  56. data/lib/jsduck/source/file_parser.rb +72 -0
  57. data/lib/jsduck/source/writer.rb +89 -0
  58. data/lib/jsduck/tag/aside.rb +1 -1
  59. data/lib/jsduck/tag/since.rb +1 -1
  60. data/lib/jsduck/template_dir.rb +2 -2
  61. data/lib/jsduck/util/html.rb +27 -0
  62. data/lib/jsduck/util/io.rb +32 -0
  63. data/lib/jsduck/util/json.rb +60 -0
  64. data/lib/jsduck/util/null_object.rb +23 -0
  65. data/lib/jsduck/util/os.rb +14 -0
  66. data/lib/jsduck/util/parallel.rb +34 -0
  67. data/lib/jsduck/util/singleton.rb +35 -0
  68. data/lib/jsduck/util/stdout.rb +33 -0
  69. data/lib/jsduck/videos.rb +5 -5
  70. data/lib/jsduck/web_writer.rb +79 -0
  71. data/lib/jsduck/welcome.rb +6 -6
  72. data/spec/class_factory.rb +20 -0
  73. metadata +32 -20
  74. data/lib/jsduck/api_exporter.rb +0 -48
  75. data/lib/jsduck/app_exporter.rb +0 -60
  76. data/lib/jsduck/examples_exporter.rb +0 -56
  77. data/lib/jsduck/full_exporter.rb +0 -35
  78. data/lib/jsduck/html.rb +0 -25
  79. data/lib/jsduck/inline_img.rb +0 -53
  80. data/lib/jsduck/inline_video.rb +0 -58
  81. data/lib/jsduck/io.rb +0 -30
  82. data/lib/jsduck/json_duck.rb +0 -52
  83. data/lib/jsduck/lexer.rb +0 -251
  84. data/lib/jsduck/null_object.rb +0 -19
  85. data/lib/jsduck/os.rb +0 -11
  86. data/lib/jsduck/parallel_wrap.rb +0 -32
  87. data/lib/jsduck/source_file.rb +0 -97
  88. data/lib/jsduck/source_file_parser.rb +0 -70
  89. data/lib/jsduck/source_writer.rb +0 -87
  90. data/lib/jsduck/stats.rb +0 -103
  91. data/lib/jsduck/stdout.rb +0 -31
@@ -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 = '4.0.1'
6
- s.date = '2012-08-21'
5
+ s.version = '4.1.1'
6
+ s.date = '2012-09-14'
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"
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
  s.rubyforge_project = s.name
13
13
 
14
14
  s.files = `git ls-files`.split("\n").find_all do |file|
15
- file !~ /spec.rb$/ && file !~ /benchmark/ && file !~ /template\// && file !~ /opt\//
15
+ file !~ /spec.rb$/ && file !~ /benchmark/ && file !~ /template\// && file !~ /opt\// && file !~ /comments\//
16
16
  end
17
17
  # Add files not in git
18
18
  s.files += Dir['template-min/**/*']
@@ -9,37 +9,39 @@ module JsDuck
9
9
  # not added.
10
10
  def create(cls)
11
11
  # Grab all configs tagged as @accessor
12
- accessors = cls[:members][:cfg].find_all {|cfg| cfg[:accessor] }
12
+ accessors = cls[:members].find_all {|m| m[:tagname] == :cfg && m[:accessor] }
13
13
 
14
14
  # Build lookup tables of method and event names
15
- methods = build_lookup_table(cls[:members][:method])
16
- events = build_lookup_table(cls[:members][:event])
15
+ methods = build_lookup_table(cls[:members], :method)
16
+ events = build_lookup_table(cls[:members], :event)
17
17
 
18
18
  accessors.each do |cfg|
19
19
  # add getter if no method with same name exists
20
20
  get = create_getter(cfg)
21
21
  if !methods[get[:name]]
22
- cls[:members][:method] << get
22
+ cls[:members] << get
23
23
  end
24
24
  # add setter if no method with same name exists
25
25
  set = create_setter(cfg)
26
26
  if !methods[set[:name]]
27
- cls[:members][:method] << set
27
+ cls[:members] << set
28
28
  end
29
29
  # for evented accessors
30
30
  if cfg[:evented]
31
31
  # add event if no event with same name exists
32
32
  ev = create_event(cfg)
33
33
  if !events[ev[:name]]
34
- cls[:members][:event] << ev
34
+ cls[:members] << ev
35
35
  end
36
36
  end
37
37
  end
38
38
  end
39
39
 
40
- def build_lookup_table(members)
40
+ def build_lookup_table(members, tagname)
41
41
  map = {}
42
- members.each {|m| map[m[:name]] = m }
42
+ members.each do |m|
43
+ map[m[:name]] = m if m[:tagname] == tagname
44
+ end
43
45
  map
44
46
  end
45
47
 
@@ -81,7 +81,7 @@ module JsDuck
81
81
  def warn_alt_name(cls)
82
82
  file = cls[:files][0][:filename]
83
83
  line = cls[:files][0][:linenr]
84
- Logger.instance.warn(:alt_name, "Name #{cls[:name]} used as both classname and alternate classname", file, line)
84
+ Logger.warn(:alt_name, "Name #{cls[:name]} used as both classname and alternate classname", file, line)
85
85
  end
86
86
 
87
87
  # Merges new class-doc into old one.
@@ -106,8 +106,7 @@ module JsDuck
106
106
  end
107
107
  old[:doc] = old[:doc].length > 0 ? old[:doc] : new[:doc]
108
108
  # Additionally the doc-comment can contain configs and constructor
109
- old[:members][:cfg] += new[:members][:cfg]
110
- old[:members][:method] += new[:members][:method]
109
+ old[:members] += new[:members]
111
110
  end
112
111
 
113
112
  # Tries to place members into classes where they belong.
@@ -138,7 +137,7 @@ module JsDuck
138
137
  end
139
138
 
140
139
  def add_to_class(cls, member)
141
- cls[member[:meta][:static] ? :statics : :members][member[:tagname]] << member
140
+ cls[:members] << member
142
141
  end
143
142
 
144
143
  def add_orphan(node)
@@ -188,8 +187,7 @@ module JsDuck
188
187
  :doc => doc,
189
188
  :mixins => [],
190
189
  :alternateClassNames => [],
191
- :members => Class.default_members_hash,
192
- :statics => Class.default_members_hash,
190
+ :members => [],
193
191
  :aliases => {},
194
192
  :meta => {},
195
193
  :files => [{:filename => "", :linenr => 0, :href => ""}],
@@ -215,7 +213,9 @@ module JsDuck
215
213
  :doc => "The options object passed to {@link Ext.util.Observable#addListener}."
216
214
  }
217
215
  @classes.each_value do |cls|
218
- cls[:members][:event].each {|e| e[:params] << options }
216
+ cls[:members].each do |m|
217
+ m[:params] << options if m[:tagname] == :event
218
+ end
219
219
  end
220
220
  end
221
221
 
@@ -1,31 +1,8 @@
1
- require 'rubygems'
2
- require 'jsduck/aggregator'
3
- require 'jsduck/source_file'
4
- require 'jsduck/doc_formatter'
5
- require 'jsduck/class_formatter'
6
- require 'jsduck/class'
7
- require 'jsduck/relations'
8
- require 'jsduck/inherit_doc'
9
- require 'jsduck/parallel_wrap'
10
- require 'jsduck/logger'
1
+ require 'jsduck/batch_parser'
11
2
  require 'jsduck/assets'
12
- require 'jsduck/json_duck'
13
- require 'jsduck/io'
14
- require 'jsduck/importer'
15
- require 'jsduck/lint'
16
- require 'jsduck/template_dir'
17
- require 'jsduck/class_writer'
18
- require 'jsduck/source_writer'
19
- require 'jsduck/app_data'
20
- require 'jsduck/index_html'
21
- require 'jsduck/api_exporter'
22
- require 'jsduck/full_exporter'
23
- require 'jsduck/app_exporter'
24
- require 'jsduck/examples_exporter'
25
- require 'jsduck/inline_examples'
26
- require 'jsduck/guide_writer'
27
- require 'jsduck/stdout'
28
- require 'fileutils'
3
+ require 'jsduck/meta_tag_registry'
4
+ require 'jsduck/export_writer'
5
+ require 'jsduck/web_writer'
29
6
 
30
7
  module JsDuck
31
8
 
@@ -34,159 +11,42 @@ module JsDuck
34
11
  # Initializes app with JsDuck::Options object
35
12
  def initialize(opts)
36
13
  @opts = opts
37
- # Sets the nr of parallel processes to use.
38
- # Set to 0 to disable parallelization completely.
39
- ParallelWrap.in_processes = @opts.processes
40
- # Turn JSON pretty-printing on/off
41
- JsonDuck.pretty = @opts.pretty_json
42
14
  end
43
15
 
44
- # Call this after input parameters set
16
+ # Main App logic.
45
17
  def run
46
- parsed_files = parallel_parse(@opts.input_files)
47
- result = aggregate(parsed_files)
48
- @relations = filter_classes(result)
49
- InheritDoc.new(@relations).resolve_all
50
- Importer.import(@opts.imports, @relations, @opts.new_since)
51
- Lint.new(@relations).run
18
+ parse
52
19
 
53
- # Initialize guides, videos, examples, ...
54
- @assets = Assets.new(@relations, @opts)
55
-
56
- # Give access to assets from all meta-tags
57
- MetaTagRegistry.instance.assets = @assets
20
+ init_assets
58
21
 
59
22
  if @opts.export
60
- format_classes
61
- FileUtils.rm_rf(@opts.output_dir) unless @opts.output_dir == :stdout
62
- exporters = {
63
- :full => FullExporter,
64
- :api => ApiExporter,
65
- :examples => ExamplesExporter,
66
- }
67
- cw = ClassWriter.new(exporters[@opts.export], @relations, @opts)
68
- cw.write(@opts.output_dir, ".json")
69
- if @opts.export == :examples
70
- gw = GuideWriter.new(exporters[@opts.export], @assets.guides, @opts)
71
- gw.write(@opts.output_dir, ".json")
72
- end
73
- Stdout.instance.flush
23
+ generate_export
74
24
  else
75
- FileUtils.rm_rf(@opts.output_dir)
76
- TemplateDir.new(@opts).write
77
-
78
- IndexHtml.new(@assets, @opts).write
79
-
80
- AppData.new(@relations, @assets, @opts).write(@opts.output_dir+"/data.js")
81
-
82
- # class-formatting is done in parallel which breaks the links
83
- # between source files and classes. Therefore it MUST to be done
84
- # after writing sources which needs the links to work.
85
- if @opts.source
86
- source_writer = SourceWriter.new(parsed_files)
87
- source_writer.write(@opts.output_dir + "/source")
88
- end
89
- format_classes
90
-
91
- if @opts.tests
92
- examples = InlineExamples.new
93
- examples.add_classes(@relations)
94
- examples.add_guides(@assets.guides)
95
- examples.write(@opts.output_dir+"/inline-examples.js")
96
- end
97
-
98
- cw = ClassWriter.new(AppExporter, @relations, @opts)
99
- cw.write(@opts.output_dir+"/output", ".js")
100
-
101
- @assets.write
25
+ generate_web_page
102
26
  end
103
27
  end
104
28
 
105
- # Parses the files in parallel using as many processes as available CPU-s
106
- def parallel_parse(filenames)
107
- ParallelWrap.map(filenames) do |fname|
108
- Logger.instance.log("Parsing", fname)
109
- begin
110
- SourceFile.new(JsDuck::IO.read(fname), fname, @opts)
111
- rescue
112
- Logger.instance.fatal_backtrace("Error while parsing #{fname}", $!)
113
- exit(1)
114
- end
115
- end
116
- end
29
+ private
117
30
 
118
- # Aggregates parsing results sequencially
119
- def aggregate(parsed_files)
120
- agr = Aggregator.new
121
- parsed_files.each do |file|
122
- Logger.instance.log("Aggregating", file.filename)
123
- agr.aggregate(file)
124
- end
125
- agr.classify_orphans
126
- agr.create_global_class
127
- agr.remove_ignored_classes
128
- agr.create_accessors
129
- if @opts.ext4_events == true || (@opts.ext4_events == nil && agr.ext4?)
130
- agr.append_ext4_event_options
131
- end
132
- agr.process_enums
133
- # Ignore override classes after applying them to actual classes
134
- @opts.external_classes += agr.process_overrides.map {|o| o[:name] }
135
- agr.result
31
+ def parse
32
+ @batch_parser = BatchParser.new(@opts)
33
+ @relations = @batch_parser.run
136
34
  end
137
35
 
138
- # Turns all aggregated data into Class objects.
139
- # Depending on --ignore-global either keeps or discards the global class.
140
- # Warnings for global members are printed regardless of that setting,
141
- # but of course can be turned off using --warnings=-global
142
- def filter_classes(docs)
143
- classes = []
144
- docs.each do |d|
145
- cls = Class.new(d)
146
- if d[:name] != "global"
147
- classes << cls
148
- else
149
- # add global class only if --ignore-global not specified
150
- classes << cls unless @opts.ignore_global
36
+ def init_assets
37
+ # Initialize guides, videos, examples, ...
38
+ @assets = Assets.new(@relations, @opts)
151
39
 
152
- # Print warning for each global member
153
- cls.all_local_members.each do |m|
154
- type = m[:tagname].to_s
155
- name = m[:name]
156
- file = m[:files][0]
157
- Logger.instance.warn(:global, "Global #{type}: #{name}", file[:filename], file[:linenr])
158
- end
159
- end
160
- end
161
- Relations.new(classes, @opts.external_classes)
40
+ # Give access to assets from all meta-tags
41
+ MetaTagRegistry.instance.assets = @assets
162
42
  end
163
43
 
164
- # Formats each class
165
- def format_classes
166
- doc_formatter = DocFormatter.new(@relations, @opts)
167
- doc_formatter.img_path = "images"
168
- class_formatter = ClassFormatter.new(@relations, doc_formatter)
169
- # Don't format types when exporting
170
- class_formatter.include_types = !@opts.export
171
- # Format all doc-objects in parallel
172
- formatted_classes = ParallelWrap.map(@relations.classes) do |cls|
173
- files = cls[:files].map {|f| f[:filename] }.join(" ")
174
- Logger.instance.log("Markdown formatting #{cls[:name]}", files)
175
- begin
176
- {
177
- :doc => class_formatter.format(cls.internal_doc),
178
- :images => doc_formatter.images
179
- }
180
- rescue
181
- Logger.instance.fatal_backtrace("Error while formatting #{cls[:name]} #{files}", $!)
182
- exit(1)
183
- end
184
- end
185
- # Then merge the data back to classes sequentially
186
- formatted_classes.each do |cls|
187
- @relations[cls[:doc][:name]].internal_doc = cls[:doc]
188
- cls[:images].each {|img| @assets.images.add(img) }
189
- end
44
+ def generate_export
45
+ ExportWriter.new(@relations, @assets, @opts).write
46
+ end
47
+
48
+ def generate_web_page
49
+ WebWriter.new(@relations, @assets, @batch_parser.parsed_files, @opts).write
190
50
  end
191
51
 
192
52
  end
@@ -1,7 +1,6 @@
1
- require 'jsduck/json_duck'
1
+ require 'jsduck/util/json'
2
2
  require 'jsduck/icons'
3
3
  require 'jsduck/search_data'
4
- require 'jsduck/stats'
5
4
  require 'jsduck/meta_tag_registry'
6
5
 
7
6
  module JsDuck
@@ -16,14 +15,13 @@ module JsDuck
16
15
 
17
16
  # Writes classes, guides, videos, and search data to one big .js file
18
17
  def write(filename)
19
- js = "Docs = " + JsonDuck.generate({
18
+ js = "Docs = " + Util::Json.generate({
20
19
  :data => {
21
20
  :classes => Icons.new.create(@relations.classes),
22
21
  :guides => @assets.guides.to_array,
23
22
  :videos => @assets.videos.to_array,
24
23
  :examples => @assets.examples.to_array,
25
24
  :search => SearchData.new.create(@relations.classes, @assets),
26
- :stats => @opts.stats ? Stats.new.create(@relations.classes) : [],
27
25
  :tests => @opts.tests,
28
26
  :signatures => MetaTagRegistry.instance.signatures,
29
27
  :localStorageDb => @opts.local_storage_db,
@@ -26,12 +26,15 @@ module JsDuck
26
26
  @relations = relations
27
27
  @opts = opts
28
28
 
29
+ doc_formatter = DocFormatter.new(@opts)
30
+ doc_formatter.relations = @relations
31
+
29
32
  @images = Images.new(@opts.images)
30
33
  @welcome = Welcome.create(@opts.welcome)
31
- @guides = Guides.create(@opts.guides, DocFormatter.new(@relations, @opts), @opts)
34
+ @guides = Guides.create(@opts.guides, doc_formatter, @opts)
32
35
  @videos = Videos.create(@opts.videos)
33
36
  @examples = Examples.create(@opts.examples, @opts)
34
- @categories = Categories.create(@opts.categories_path, DocFormatter.new(@relations, @opts), @relations)
37
+ @categories = Categories.create(@opts.categories_path, doc_formatter, @relations)
35
38
  end
36
39
 
37
40
  # Writes out the assets that can be written out separately:
@@ -1,5 +1,6 @@
1
1
  require "jsduck/serializer"
2
2
  require "jsduck/evaluator"
3
+ require "jsduck/function_ast"
3
4
 
4
5
  module JsDuck
5
6
 
@@ -224,7 +225,6 @@ module JsDuck
224
225
  cls[:mixins] = []
225
226
  cls[:aliases] = []
226
227
  cls[:members] = []
227
- cls[:statics] = []
228
228
  cls[:code_type] = :ext_define
229
229
 
230
230
  each_pair_in_object_expression(ast["arguments"][1]) do |key, value, pair|
@@ -254,9 +254,9 @@ module JsDuck
254
254
  when "eventedConfig"
255
255
  cls[:members] += make_configs(value, {:accessor => true, :evented => true})
256
256
  when "statics"
257
- cls[:statics] += make_statics(value)
257
+ cls[:members] += make_statics(value)
258
258
  when "inheritableStatics"
259
- cls[:statics] += make_statics(value, {:inheritable => true})
259
+ cls[:members] += make_statics(value, {:inheritable => true})
260
260
  else
261
261
  detect_method_or_property(cls, key, value, pair)
262
262
  end
@@ -393,7 +393,8 @@ module JsDuck
393
393
  return {
394
394
  :tagname => :method,
395
395
  :name => name,
396
- :params => make_params(ast)
396
+ :params => make_params(ast),
397
+ :chainable => chainable?(ast) && name != "constructor",
397
398
  }
398
399
  end
399
400
 
@@ -405,6 +406,10 @@ module JsDuck
405
406
  end
406
407
  end
407
408
 
409
+ def chainable?(ast)
410
+ FunctionAst.chainable?(ast)
411
+ end
412
+
408
413
  def make_property(name=nil, ast=nil, tagname=:property)
409
414
  return {
410
415
  :tagname => tagname,
@@ -0,0 +1,54 @@
1
+ require 'jsduck/util/parallel'
2
+ require 'jsduck/class_formatter'
3
+ require 'jsduck/doc_formatter'
4
+ require 'jsduck/logger'
5
+
6
+ module JsDuck
7
+
8
+ # Performs the formatting of the doc-object of all classes.
9
+ class BatchFormatter
10
+
11
+ # Formats all classes.
12
+ # Also registers found images in assets.
13
+ def self.format_all!(relations, assets, opts)
14
+ # Format all doc-objects in parallel
15
+ formatted_classes = Util::Parallel.map(relations.classes) do |cls|
16
+
17
+ files = cls[:files].map {|f| f[:filename] }.join(" ")
18
+ Logger.log("Markdown formatting #{cls[:name]}", files)
19
+
20
+ formatter = create_class_formatter(relations, opts)
21
+ begin
22
+ {
23
+ :doc => formatter.format(cls.internal_doc),
24
+ :images => formatter.images
25
+ }
26
+ rescue
27
+ Logger.fatal_backtrace("Error while formatting #{cls[:name]} #{files}", $!)
28
+ exit(1)
29
+ end
30
+ end
31
+
32
+ # Then merge the data back to classes sequentially
33
+ formatted_classes.each do |cls|
34
+ relations[cls[:doc][:name]].internal_doc = cls[:doc]
35
+ cls[:images].each {|img| assets.images.add(img) }
36
+ end
37
+ end
38
+
39
+ # Factory method to create new ClassFormatter instances.
40
+ def self.create_class_formatter(relations, opts)
41
+ doc_formatter = DocFormatter.new(opts)
42
+ doc_formatter.relations = relations
43
+ doc_formatter.img_path = "images"
44
+
45
+ class_formatter = ClassFormatter.new(relations, doc_formatter)
46
+ # Don't format types when exporting
47
+ class_formatter.include_types = !opts.export
48
+
49
+ class_formatter
50
+ end
51
+
52
+ end
53
+
54
+ end