jsduck 4.0.1 → 4.1.1

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.
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
@@ -0,0 +1,89 @@
1
+ require 'jsduck/logger'
2
+ require 'jsduck/util/parallel'
3
+ require 'fileutils'
4
+
5
+ module JsDuck
6
+ module Source
7
+
8
+ # Writes HTML JavaScript/CSS source into HTML files.
9
+ class Writer
10
+ def initialize(source_files)
11
+ @source_files = source_files
12
+ end
13
+
14
+ # Writes all source files as HTML files into destination dir.
15
+ def write(destination)
16
+ generate_html_filenames
17
+
18
+ FileUtils.mkdir(destination)
19
+ Util::Parallel.each(@source_files) do |file|
20
+ Logger.log("Writing source", file.html_filename)
21
+ write_single(destination + "/" + file.html_filename, file.to_html)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ # Generates unique HTML filenames for each file.
28
+ #
29
+ # Can't be done in parallel for obvious reasons, but also
30
+ # because file.html_filename= method updates all the doc-objects
31
+ # related to the file.
32
+ def generate_html_filenames
33
+ filenames = {}
34
+ @source_files.each do |file|
35
+ i = 0
36
+ begin
37
+ name = html_filename(file.filename, i)
38
+ ci_name = name.downcase # case insensitive name
39
+ i += 1
40
+ end while filenames.has_key?(ci_name)
41
+ filenames[ci_name] = true
42
+ file.html_filename = name
43
+ end
44
+ end
45
+
46
+ # Returns HTML filename for n'th file with given name.
47
+ #
48
+ # html_filename("Foo.js", 0) => "Foo.html"
49
+ # html_filename("Foo.js", 1) => "Foo2.html"
50
+ # html_filename("Foo.js", 2) => "Foo3.html"
51
+ #
52
+ def html_filename(filename, nr=0)
53
+ ::File.basename(filename, ".js") + (nr > 0 ? (nr+1).to_s : "") + ".html"
54
+ end
55
+
56
+ def write_single(filename, source)
57
+ ::File.open(filename, 'w') {|f| f.write(wrap_page(source)) }
58
+ end
59
+
60
+ # Returns source wrapped inside HTML page
61
+ def wrap_page(source)
62
+ return <<-EOHTML
63
+ <!DOCTYPE html>
64
+ <html>
65
+ <head>
66
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
67
+ <title>The source code</title>
68
+ <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
69
+ <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
70
+ <style type="text/css">
71
+ .highlight { display: block; background-color: #ddd; }
72
+ </style>
73
+ <script type="text/javascript">
74
+ function highlight() {
75
+ document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
76
+ }
77
+ </script>
78
+ </head>
79
+ <body onload="prettyPrint(); highlight();">
80
+ <pre class="prettyprint lang-js">#{source}</pre>
81
+ </body>
82
+ </html>
83
+ EOHTML
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+ end
@@ -65,7 +65,7 @@ module JsDuck::Tag
65
65
 
66
66
  def warn(msg)
67
67
  ctx = @context ? @context[:files][0] : {}
68
- JsDuck::Logger.instance.warn(:aside, msg, ctx[:filename], ctx[:linenr])
68
+ JsDuck::Logger.warn(:aside, msg, ctx[:filename], ctx[:linenr])
69
69
  nil
70
70
  end
71
71
 
@@ -11,7 +11,7 @@ module JsDuck::Tag
11
11
 
12
12
  def to_value(contents)
13
13
  if contents.length > 1
14
- JsDuck::Logger.instance.warn(nil, "Only one @since tag allowed per class/member.")
14
+ JsDuck::Logger.warn(nil, "Only one @since tag allowed per class/member.")
15
15
  end
16
16
  contents[0]
17
17
  end
@@ -21,10 +21,10 @@ module JsDuck
21
21
  def write
22
22
  FileUtils.mkdir(@opts.output_dir)
23
23
  if @opts.template_links
24
- Logger.instance.log("Linking template files to", @opts.output_dir)
24
+ Logger.log("Linking template files to", @opts.output_dir)
25
25
  move_files(:symlink)
26
26
  else
27
- Logger.instance.log("Copying template files to", @opts.output_dir)
27
+ Logger.log("Copying template files to", @opts.output_dir)
28
28
  move_files(:cp_r)
29
29
  end
30
30
 
@@ -0,0 +1,27 @@
1
+ require 'cgi'
2
+
3
+ module JsDuck
4
+ module Util
5
+
6
+ # Helpers for dealing with HTML
7
+ class HTML
8
+
9
+ # Strips tags from HTML text
10
+ def self.strip_tags(html)
11
+ html.gsub(/<.*?>/, "")
12
+ end
13
+
14
+ # Escapes HTML, replacing < with &lt; ...
15
+ def self.escape(html)
16
+ CGI.escapeHTML(html)
17
+ end
18
+
19
+ # Unescapes HTML, replacing &lt; with < ...
20
+ def self.unescape(html)
21
+ CGI.unescapeHTML(html)
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,32 @@
1
+ module JsDuck
2
+ module Util
3
+
4
+ # A helper to use instead the builtin IO class to read files in
5
+ # correct encoding.
6
+ #
7
+ # By default in Ruby 1.9 the encoding is auto-detected, which can
8
+ # have surprising results. So in here we read in all files in UTF-8
9
+ # (the default) or in some other encoding specified through --encoding
10
+ # option and convert it to UTF-8 internally.
11
+ class IO
12
+ @@encoding = "UTF-8"
13
+
14
+ # Sets the external encoding to be used for reading files.
15
+ # When it's different from UTF-8, the input will be converted to UTF-8.
16
+ def self.encoding=(e)
17
+ if e =~ /^UTF-8$/i
18
+ @@encoding = e
19
+ else
20
+ @@encoding = e+":UTF-8"
21
+ end
22
+ end
23
+
24
+ # Reads given filename into string
25
+ def self.read(filename)
26
+ File.open(filename, "r:"+@@encoding) {|f| f.read }
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,60 @@
1
+ require 'jsduck/util/singleton'
2
+ require 'jsduck/util/io'
3
+ require 'jsduck/logger'
4
+ require 'json'
5
+
6
+ module JsDuck
7
+ module Util
8
+
9
+ # Wrapper around the json gem for use in JsDuck.
10
+ #
11
+ # The main benefit of it is that we have a central place for
12
+ # controlling how the JSON is created (pretty-formatted or not).
13
+ class Json
14
+ include Util::Singleton
15
+
16
+ def initialize
17
+ @pretty = false
18
+ end
19
+
20
+ # Set to true to turn on pretty-formatting of JSON
21
+ def pretty=(pretty)
22
+ @pretty = pretty
23
+ end
24
+
25
+ # Turns object into JSON, places it inside JavaScript that calls the
26
+ # given callback name, and writes the result to file.
27
+ def write_jsonp(filename, callback_name, data)
28
+ jsonp = "Ext.data.JsonP." + callback_name + "(" + generate(data) + ");"
29
+ File.open(filename, 'w') {|f| f.write(jsonp) }
30
+ end
31
+
32
+ # Turns object into JSON and writes inside a file
33
+ def write_json(filename, data)
34
+ File.open(filename, 'w') {|f| f.write(generate(data)) }
35
+ end
36
+
37
+ # Generates JSON from object
38
+ def generate(data)
39
+ @pretty ? JSON.pretty_generate(data) : JSON.generate(data)
40
+ end
41
+
42
+ # Reads and parses JSON from file
43
+ def read(filename)
44
+ begin
45
+ parse(Util::IO.read(filename))
46
+ rescue
47
+ Logger.fatal("#{filename} is not a valid JSON file")
48
+ exit(1)
49
+ end
50
+ end
51
+
52
+ # Parses JSON string
53
+ def parse(string, opts = {})
54
+ JSON.parse(string, opts)
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,23 @@
1
+ module JsDuck
2
+ module Util
3
+
4
+ # A class that does nothing.
5
+ # Responds to all methods by returning self, unless a hash passed to
6
+ # constructor.
7
+ # See: http://en.wikipedia.org/wiki/Null_Object_pattern
8
+ class NullObject
9
+ # Optionally takes a hash of method_name => return_value pairs,
10
+ # making it return those values for those methods, sort of like
11
+ # OpenStruct, but for all other methods self is still returned and
12
+ # any number of arguments is accepted.
13
+ def initialize(methods={})
14
+ @methods = methods
15
+ end
16
+
17
+ def method_missing(meth, *args, &block)
18
+ @methods.has_key?(meth) ? @methods[meth] : self
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ require 'rbconfig'
2
+
3
+ module JsDuck
4
+ module Util
5
+
6
+ # Simple helper class to detect operating system
7
+ class OS
8
+ def self.windows?
9
+ RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,34 @@
1
+ require 'parallel'
2
+
3
+ module JsDuck
4
+ module Util
5
+
6
+ # Wrapper around the parallel gem that falls back to simple
7
+ # Array#map and Array#each when :in_processes => 0 specified.
8
+ class Parallel
9
+ @@in_processes = nil
10
+
11
+ # Sets globally the nr of processes to use.
12
+ def self.in_processes=(n)
13
+ @@in_processes = n
14
+ end
15
+
16
+ def self.each(arr, &block)
17
+ if @@in_processes == 0
18
+ arr.each &block
19
+ else
20
+ ::Parallel.each(arr, {:in_processes => @@in_processes}, &block)
21
+ end
22
+ end
23
+
24
+ def self.map(arr, &block)
25
+ if @@in_processes == 0
26
+ arr.map &block
27
+ else
28
+ ::Parallel.map(arr, {:in_processes => @@in_processes}, &block)
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,35 @@
1
+ require 'singleton'
2
+
3
+ module JsDuck
4
+ module Util
5
+
6
+ # A more convenient Singleton implementation.
7
+ #
8
+ # With the standard ruby Singleton you need to call the methods of
9
+ # your singleton instance as follows:
10
+ #
11
+ # MyClass.instance.my_method()
12
+ #
13
+ # But with JsDuck::Util::Singleton you can skip the .instance. part:
14
+ #
15
+ # MyClass.my_method()
16
+ #
17
+ # This also conveniently hides from the calling code the fact that
18
+ # a class is implemented as Singleton - it could just as well only
19
+ # have static methods.
20
+ #
21
+ module Singleton
22
+ def self.included(base)
23
+ base.class_eval do
24
+ include ::Singleton
25
+
26
+ # Redirect calls from MyClass.method to MyClass.instance.method
27
+ def self.method_missing(meth, *args, &block)
28
+ self.instance.send(meth, *args, &block)
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,33 @@
1
+ require 'jsduck/util/json'
2
+ require 'jsduck/util/singleton'
3
+
4
+ module JsDuck
5
+ module Util
6
+
7
+ # Central place for buffering JSON data that's meant to be written to STDOUT
8
+ class Stdout
9
+ include Util::Singleton
10
+
11
+ def initialize
12
+ @data = nil
13
+ end
14
+
15
+ # Adds array of new data
16
+ def add(data)
17
+ if @data
18
+ @data += data
19
+ else
20
+ @data = data
21
+ end
22
+ end
23
+
24
+ # Writes data to STDOUT in JSON format,
25
+ # but only if some data was added.
26
+ def flush
27
+ puts Util::Json.generate(@data) if @data
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
@@ -1,5 +1,5 @@
1
- require 'jsduck/json_duck'
2
- require 'jsduck/null_object'
1
+ require 'jsduck/util/json'
2
+ require 'jsduck/util/null_object'
3
3
  require 'jsduck/grouped_asset'
4
4
 
5
5
  module JsDuck
@@ -11,14 +11,14 @@ module JsDuck
11
11
  if filename
12
12
  Videos.new(filename)
13
13
  else
14
- NullObject.new(:to_array => [], :[] => nil)
14
+ Util::NullObject.new(:to_array => [], :[] => nil)
15
15
  end
16
16
  end
17
17
 
18
18
  def initialize(filename)
19
- @groups = JsonDuck.read(filename)
19
+ @groups = Util::Json.read(filename)
20
20
  add_names_if_missing
21
- build_map_by_name("Two videos have the same name", filename)
21
+ build_map_by_name
22
22
  end
23
23
 
24
24
  # Each video should have a name, which is used in URL to reference the video.
@@ -0,0 +1,79 @@
1
+ require 'jsduck/exporter/app'
2
+ require 'jsduck/batch_formatter'
3
+ require 'jsduck/template_dir'
4
+ require 'jsduck/index_html'
5
+ require 'jsduck/app_data'
6
+ require 'jsduck/class_writer'
7
+ require 'jsduck/source/writer'
8
+ require 'jsduck/inline_examples'
9
+ require 'fileutils'
10
+
11
+ module JsDuck
12
+
13
+ # Performs the generation of docs web app.
14
+ class WebWriter
15
+ def initialize(relations, assets, parsed_files, opts)
16
+ @relations = relations
17
+ @assets = assets
18
+ @parsed_files = parsed_files
19
+ @opts = opts
20
+ end
21
+
22
+ def write
23
+ clean_output_dir
24
+
25
+ write_template_files
26
+ write_app_data
27
+
28
+ # class-formatting is done in parallel which breaks the links
29
+ # between source files and classes. Therefore it MUST to be done
30
+ # after writing sources which needs the links to work.
31
+ write_source if @opts.source
32
+ format_classes
33
+
34
+ write_inline_examples if @opts.tests
35
+
36
+ write_classes
37
+
38
+ @assets.write
39
+ end
40
+
41
+ def write_template_files
42
+ TemplateDir.new(@opts).write
43
+ IndexHtml.new(@assets, @opts).write
44
+ end
45
+
46
+ def write_app_data
47
+ AppData.new(@relations, @assets, @opts).write(@opts.output_dir+"/data.js")
48
+ end
49
+
50
+ def write_source
51
+ source_writer = Source::Writer.new(@parsed_files)
52
+ source_writer.write(@opts.output_dir + "/source")
53
+ end
54
+
55
+ def write_inline_examples
56
+ examples = InlineExamples.new
57
+ examples.add_classes(@relations)
58
+ examples.add_guides(@assets.guides)
59
+ examples.write(@opts.output_dir+"/inline-examples.js")
60
+ end
61
+
62
+ def write_classes
63
+ class_writer = ClassWriter.new(Exporter::App, @relations, @opts)
64
+ class_writer.write(@opts.output_dir+"/output", ".js")
65
+ end
66
+
67
+ # -- util routines --
68
+
69
+ def clean_output_dir
70
+ FileUtils.rm_rf(@opts.output_dir)
71
+ end
72
+
73
+ def format_classes
74
+ BatchFormatter.format_all!(@relations, @assets, @opts)
75
+ end
76
+
77
+ end
78
+
79
+ end