jsduck 5.0.0.beta01 → 5.0.0.beta2

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 (95) hide show
  1. data/.travis.yml +1 -0
  2. data/README.md +6 -32
  3. data/Rakefile +5 -5
  4. data/bin/jsduck +0 -1
  5. data/js-classes/String.js +3 -5
  6. data/jsduck.gemspec +3 -2
  7. data/lib/jsduck/aggregator.rb +1 -3
  8. data/lib/jsduck/app.rb +2 -2
  9. data/lib/jsduck/categories/file.rb +0 -6
  10. data/lib/jsduck/class.rb +1 -2
  11. data/lib/jsduck/doc/parser.rb +12 -5
  12. data/lib/jsduck/doc/scanner.rb +6 -0
  13. data/lib/jsduck/doc/standard_tag_parser.rb +10 -5
  14. data/lib/jsduck/doc/subproperties.rb +9 -2
  15. data/lib/jsduck/docs_code_comparer.rb +20 -7
  16. data/lib/jsduck/exporter/app.rb +18 -13
  17. data/lib/jsduck/exporter/full.rb +18 -21
  18. data/lib/jsduck/format/doc.rb +0 -1
  19. data/lib/jsduck/format/html_stack.rb +1 -2
  20. data/lib/jsduck/format/subproperties.rb +2 -2
  21. data/lib/jsduck/inline/auto_link.rb +1 -1
  22. data/lib/jsduck/inline/img.rb +1 -1
  23. data/lib/jsduck/inline/link.rb +4 -6
  24. data/lib/jsduck/inline/video.rb +1 -2
  25. data/lib/jsduck/js/ast.rb +1 -1
  26. data/lib/jsduck/js/esprima.rb +24 -9
  27. data/lib/jsduck/logger.rb +50 -12
  28. data/lib/jsduck/members_index.rb +1 -2
  29. data/lib/jsduck/merger.rb +20 -2
  30. data/lib/jsduck/options.rb +125 -24
  31. data/lib/jsduck/process/accessors.rb +21 -8
  32. data/lib/jsduck/process/enums.rb +2 -3
  33. data/lib/jsduck/process/ext4_events.rb +2 -1
  34. data/lib/jsduck/process/global_members.rb +1 -2
  35. data/lib/jsduck/process/importer.rb +2 -6
  36. data/lib/jsduck/process/inherit_class.rb +58 -0
  37. data/lib/jsduck/process/inherit_doc.rb +6 -175
  38. data/lib/jsduck/process/inherit_members.rb +257 -0
  39. data/lib/jsduck/process/lint.rb +18 -7
  40. data/lib/jsduck/process/overrides.rb +1 -2
  41. data/lib/jsduck/render/class.rb +1 -1
  42. data/lib/jsduck/tag/alias.rb +2 -1
  43. data/lib/jsduck/tag/alternate_class_names.rb +1 -0
  44. data/lib/jsduck/tag/aside.rb +3 -3
  45. data/lib/jsduck/tag/author.rb +18 -3
  46. data/lib/jsduck/tag/autodetected.rb +21 -0
  47. data/lib/jsduck/tag/boolean_tag.rb +1 -1
  48. data/lib/jsduck/tag/cfg.rb +7 -3
  49. data/lib/jsduck/tag/class.rb +1 -1
  50. data/lib/jsduck/tag/class_list_tag.rb +1 -1
  51. data/lib/jsduck/tag/constructor.rb +1 -1
  52. data/lib/jsduck/tag/css_var.rb +1 -1
  53. data/lib/jsduck/tag/default.rb +1 -1
  54. data/lib/jsduck/tag/deprecated_tag.rb +1 -1
  55. data/lib/jsduck/tag/docauthor.rb +2 -0
  56. data/lib/jsduck/tag/enum.rb +2 -2
  57. data/lib/jsduck/tag/event.rb +1 -1
  58. data/lib/jsduck/tag/extends.rb +1 -1
  59. data/lib/jsduck/tag/ftype.rb +2 -1
  60. data/lib/jsduck/tag/inheritdoc.rb +1 -1
  61. data/lib/jsduck/tag/localdoc.rb +33 -0
  62. data/lib/jsduck/tag/markdown.rb +1 -1
  63. data/lib/jsduck/tag/member.rb +1 -1
  64. data/lib/jsduck/tag/method.rb +1 -1
  65. data/lib/jsduck/tag/mixins.rb +1 -0
  66. data/lib/jsduck/tag/override.rb +1 -1
  67. data/lib/jsduck/tag/param.rb +16 -5
  68. data/lib/jsduck/tag/preventable.rb +1 -1
  69. data/lib/jsduck/tag/property.rb +7 -3
  70. data/lib/jsduck/tag/ptype.rb +2 -1
  71. data/lib/jsduck/tag/requires.rb +1 -0
  72. data/lib/jsduck/tag/return.rb +2 -1
  73. data/lib/jsduck/tag/since.rb +1 -5
  74. data/lib/jsduck/tag/tag.rb +21 -12
  75. data/lib/jsduck/tag/throws.rb +2 -1
  76. data/lib/jsduck/tag/type.rb +2 -2
  77. data/lib/jsduck/tag/uses.rb +1 -0
  78. data/lib/jsduck/tag/xtype.rb +2 -1
  79. data/lib/jsduck/tag_loader.rb +26 -15
  80. data/lib/jsduck/tag_registry.rb +20 -11
  81. data/lib/jsduck/web/css.rb +22 -0
  82. data/lib/jsduck/web/data.rb +50 -0
  83. data/lib/jsduck/web/icons.rb +31 -0
  84. data/lib/jsduck/web/index_html.rb +88 -0
  85. data/lib/jsduck/web/search.rb +148 -0
  86. data/lib/jsduck/{source/writer.rb → web/source.rb} +2 -2
  87. data/lib/jsduck/web/template.rb +52 -0
  88. data/lib/jsduck/web/writer.rb +84 -0
  89. metadata +513 -488
  90. data/lib/jsduck/app_data.rb +0 -41
  91. data/lib/jsduck/icons.rb +0 -29
  92. data/lib/jsduck/index_html.rb +0 -84
  93. data/lib/jsduck/search_data.rb +0 -146
  94. data/lib/jsduck/template_dir.rb +0 -50
  95. data/lib/jsduck/web_writer.rb +0 -87
@@ -16,7 +16,7 @@ module JsDuck::Tag
16
16
 
17
17
  # @preventable is optionally followed by some method name, but we
18
18
  # don't document it.
19
- def parse_doc(p)
19
+ def parse_doc(p, pos)
20
20
  p.match(/.*$/)
21
21
  {:tagname => :preventable}
22
22
  end
@@ -6,6 +6,7 @@ module JsDuck::Tag
6
6
  def initialize
7
7
  @pattern = "property"
8
8
  @tagname = :property
9
+ @repeatable = true
9
10
  @member_type = {
10
11
  :name => :property,
11
12
  :category => :property_like,
@@ -19,7 +20,7 @@ module JsDuck::Tag
19
20
  end
20
21
 
21
22
  # @property {Type} [name=default] ...
22
- def parse_doc(p)
23
+ def parse_doc(p, pos)
23
24
  tag = p.standard_tag({:tagname => :property, :type => true, :name => true})
24
25
  tag[:doc] = :multiline
25
26
  tag
@@ -27,13 +28,16 @@ module JsDuck::Tag
27
28
 
28
29
  def process_doc(h, tags, pos)
29
30
  p = tags[0]
30
- h[:name] = p[:name]
31
31
  # Type might also come from @type, don't overwrite it with nil.
32
32
  h[:type] = p[:type] if p[:type]
33
33
  h[:default] = p[:default]
34
- h[:properties] = JsDuck::Doc::Subproperties.nest(tags, pos)[0][:properties]
34
+
35
35
  # Documentation after the first @property is part of the top-level docs.
36
36
  h[:doc] += p[:doc]
37
+
38
+ nested = JsDuck::Doc::Subproperties.nest(tags, pos)[0]
39
+ h[:properties] = nested[:properties]
40
+ h[:name] = nested[:name]
37
41
  end
38
42
  end
39
43
  end
@@ -4,10 +4,11 @@ module JsDuck::Tag
4
4
  class Ptype < Xtype
5
5
  def initialize
6
6
  @pattern = "ptype"
7
+ @repeatable = true
7
8
  end
8
9
 
9
10
  # @ptype name
10
- def parse_doc(p)
11
+ def parse_doc(p, pos)
11
12
  {
12
13
  :tagname => :aliases,
13
14
  :name => parse_alias_shorthand(p, "plugin")
@@ -5,6 +5,7 @@ module JsDuck::Tag
5
5
  def initialize
6
6
  @pattern = "requires"
7
7
  @tagname = :requires
8
+ @repeatable = true
8
9
  @ext_define_pattern = "requires"
9
10
  @ext_define_default = {:requires => []}
10
11
  end
@@ -7,11 +7,12 @@ module JsDuck::Tag
7
7
  def initialize
8
8
  @pattern = ["return", "returns"]
9
9
  @tagname = :return
10
+ @repeatable = true
10
11
  @html_position = POS_RETURN
11
12
  end
12
13
 
13
14
  # @return {Type} return.name ...
14
- def parse_doc(p)
15
+ def parse_doc(p, pos)
15
16
  tag = p.standard_tag({:tagname => :return, :type => true})
16
17
  tag[:name] = subproperty_name(p)
17
18
  tag[:doc] = :multiline
@@ -9,7 +9,7 @@ module JsDuck::Tag
9
9
  @html_position = POS_SINCE
10
10
  end
11
11
 
12
- def parse_doc(p)
12
+ def parse_doc(p, pos)
13
13
  {
14
14
  :tagname => :since,
15
15
  :version => p.match(/.*$/).strip,
@@ -17,10 +17,6 @@ module JsDuck::Tag
17
17
  end
18
18
 
19
19
  def process_doc(h, tags, pos)
20
- if tags.length > 1
21
- JsDuck::Logger.warn(nil, "Only one @since tag allowed per class/member.")
22
- end
23
-
24
20
  h[:since] = tags[0][:version]
25
21
  end
26
22
 
@@ -6,6 +6,11 @@ module JsDuck::Tag
6
6
  # For example: "cfg"
7
7
  attr_reader :pattern
8
8
 
9
+ # Set to true to allow the tag to occour multiple times within one
10
+ # doc-comment. By default a tag can only appear once and when
11
+ # it's detected several times a warning will be generated.
12
+ attr_reader :repeatable
13
+
9
14
  # Called by DocParser when the @tag is reached to do the parsing
10
15
  # from that point forward. Gets passed an instance of DocScanner.
11
16
  #
@@ -23,7 +28,10 @@ module JsDuck::Tag
23
28
  # the documentation following this tag will get added to the :doc
24
29
  # field of the tag and will later be accessible in #process_doc
25
30
  # method.
26
- def parse_doc(p)
31
+ #
32
+ # Also a hash with position information {:filename, :linenr} is
33
+ # passed in.
34
+ def parse_doc(scanner, position)
27
35
  end
28
36
 
29
37
  # Defines the symbol under which the tag data is stored in final
@@ -163,17 +171,18 @@ module JsDuck::Tag
163
171
  POS_ASIDE = 1
164
172
  POS_PRIVATE = 2
165
173
  POS_DOC = 3
166
- POS_DEFAULT = 4
167
- POS_SINCE = 5
168
- POS_DEPRECATED = 6
169
- POS_ENUM = 7
170
- POS_TEMPLATE = 8
171
- POS_PREVENTABLE = 9
172
- POS_PARAM = 10
173
- POS_SUBPROPERTIES = 11
174
- POS_RETURN = 12
175
- POS_THROWS = 13
176
- POS_OVERRIDES = 14
174
+ POS_LOCALDOC = 4
175
+ POS_DEFAULT = 5
176
+ POS_SINCE = 6
177
+ POS_DEPRECATED = 7
178
+ POS_ENUM = 8
179
+ POS_TEMPLATE = 9
180
+ POS_PREVENTABLE = 10
181
+ POS_PARAM = 11
182
+ POS_SUBPROPERTIES = 12
183
+ POS_RETURN = 13
184
+ POS_THROWS = 14
185
+ POS_OVERRIDES = 15
177
186
 
178
187
  # Called before #to_html to allow rendering of Markdown content.
179
188
  # For this an instance of DocFormatter is passed in, on which one
@@ -6,11 +6,12 @@ module JsDuck::Tag
6
6
  def initialize
7
7
  @pattern = "throws"
8
8
  @tagname = :throws
9
+ @repeatable = true
9
10
  @html_position = POS_THROWS
10
11
  end
11
12
 
12
13
  # @throws {Type} ...
13
- def parse_doc(p)
14
+ def parse_doc(p, pos)
14
15
  tag = p.standard_tag({:tagname => :throws, :type => true})
15
16
  tag[:doc] = :multiline
16
17
  tag
@@ -18,7 +18,7 @@ module JsDuck::Tag
18
18
  # The presence of @type implies that we are dealing with property.
19
19
  # ext-doc allows type name to be either inside curly braces or
20
20
  # without them at all.
21
- def parse_doc(p)
21
+ def parse_doc(p, pos)
22
22
  tag = p.standard_tag({:tagname => :type, :type => true})
23
23
  tag[:type] = curlyless_type(p) unless tag[:type]
24
24
  tag
@@ -34,7 +34,7 @@ module JsDuck::Tag
34
34
 
35
35
  # Do the merging of :type field
36
36
  def merge(h, docs, code)
37
- h[:type] = JsDuck::DocsCodeComparer.merge_if_matches(:type, docs, code)
37
+ JsDuck::DocsCodeComparer.merge_if_matches(h, :type, docs, code)
38
38
  if h[:type] == nil
39
39
  h[:type] = code[:tagname] == :method ? "Function" : "Object"
40
40
  end
@@ -5,6 +5,7 @@ module JsDuck::Tag
5
5
  def initialize
6
6
  @pattern = "uses"
7
7
  @tagname = :uses
8
+ @repeatable = true
8
9
  @ext_define_pattern = "uses"
9
10
  @ext_define_default = {:uses => []}
10
11
  end
@@ -6,10 +6,11 @@ module JsDuck::Tag
6
6
  def initialize
7
7
  @pattern = "xtype"
8
8
  @ext_define_pattern = "xtype"
9
+ @repeatable = true
9
10
  end
10
11
 
11
12
  # @xtype name
12
- def parse_doc(p)
13
+ def parse_doc(p, pos)
13
14
  {
14
15
  :tagname => :aliases,
15
16
  :name => parse_alias_shorthand(p, "widget")
@@ -2,35 +2,46 @@ require "jsduck/tag/tag"
2
2
 
3
3
  module JsDuck
4
4
 
5
+ # Loads Tag classes from the builtin tags/ dir and optionally also
6
+ # from additional paths.
5
7
  class TagLoader
6
- def initialize
7
- @already_loaded = {}
8
+ def initialize(extra_paths=[])
9
+ @paths = [File.dirname(__FILE__) + "/tag"]
10
+ @paths += extra_paths
8
11
  end
9
12
 
10
- # Loads tag classes from given dir or single file.
13
+ # Loads Tag classes from all supplied paths.
11
14
  #
12
15
  # Returns the tag classes that got loaded, sorted alphabetically
13
- # by class name. This ensures attributes in member signatures are
14
- # always rendered in the same order.
15
- def load_from(path)
16
+ # by class name.
17
+ def load_all
18
+ @paths.each {|path| load(path) }
19
+ tag_classes
20
+ end
21
+
22
+ private
23
+
24
+ # Loads tag classes from given dir or single file.
25
+ def load(path)
16
26
  if File.directory?(path)
17
- Dir[path+"/**/*.rb"].each {|file| require(file) }
27
+ Dir[path+"/**/*.rb"].each do |file|
28
+ # Ruby 1.8 doesn't understand that "jsduck/tag/tag" and
29
+ # "./lib/jsduck/tag/tag.rb" refer to the same file. So
30
+ # explicitly avoid loading this file (as it's required on
31
+ # top already) to prevent warnings of constants getting
32
+ # defined multiple times.
33
+ require(file) unless file =~ /jsduck\/tag\/tag\.rb$/
34
+ end
18
35
  else
19
36
  require(path)
20
37
  end
21
-
22
- tag_classes
23
38
  end
24
39
 
25
- private
26
-
27
40
  def tag_classes
28
41
  classes = JsDuck::Tag::Tag.descendants
29
- # exclude already loaded classes
30
- classes.reject! {|cls| @already_loaded[cls.name] }
31
- # remember these classes as loaded
32
- classes.each {|cls| @already_loaded[cls.name] = true }
33
42
  # sort by classname
43
+ # This ensures attributes in member signatures are
44
+ # always rendered in the same order.
34
45
  classes.sort {|a, b| a.name <=> b.name }
35
46
  end
36
47
 
@@ -1,13 +1,28 @@
1
1
  require "jsduck/tag_loader"
2
- require "jsduck/util/singleton"
3
2
 
4
3
  module JsDuck
5
4
 
6
5
  # Access to builtin @tags
7
6
  class TagRegistry
8
- include Util::Singleton
7
+ # Access to the singleton instance (only used internally)
8
+ def self.instance
9
+ @instance = TagRegistry.new unless @instance
10
+ @instance
11
+ end
12
+
13
+ # Reconfigures the registry with additional load paths.
14
+ # Used in Options class.
15
+ def self.reconfigure(load_paths)
16
+ @instance = TagRegistry.new(load_paths)
17
+ end
9
18
 
10
- def initialize
19
+ # Redirect calls from TagRegistry.method to TagRegistry.instance.method,
20
+ # making it behave like other Singleton classes.
21
+ def self.method_missing(meth, *args, &block)
22
+ self.instance.send(meth, *args, &block)
23
+ end
24
+
25
+ def initialize(load_paths=[])
11
26
  @patterns = {}
12
27
  @ext_define_patterns = {}
13
28
  @ext_define_defaults = {}
@@ -19,13 +34,7 @@ module JsDuck
19
34
  @member_types = []
20
35
  @css = []
21
36
 
22
- @loader = TagLoader.new
23
- load_from(File.dirname(__FILE__) + "/tag")
24
- end
25
-
26
- # Loads and instantiates tags from the given file or dir.
27
- def load_from(path)
28
- instantiate_tags(@loader.load_from(path))
37
+ instantiate_tags(TagLoader.new(load_paths).load_all)
29
38
  end
30
39
 
31
40
  # Instantiates all descendants of JsDuck::Tag::Tag
@@ -171,7 +180,7 @@ module JsDuck
171
180
  expand_merger(:member)
172
181
  expand_merger(:method_like)
173
182
  expand_merger(:property_like)
174
- @mergers_expanded
183
+ @mergers_expanded = true
175
184
  end
176
185
 
177
186
  def expand_merger(type_name)
@@ -0,0 +1,22 @@
1
+ require 'jsduck/tag_registry'
2
+ require 'jsduck/util/md5'
3
+
4
+ module JsDuck
5
+ module Web
6
+
7
+ # Writes the CSS gathered from Tag classes and --css option into given file.
8
+ # Then Renames the file so it contains an MD5 hash inside it,
9
+ # returning the resulting fingerprinted name.
10
+ class Css
11
+ def initialize(opts)
12
+ @opts = opts
13
+ end
14
+
15
+ def write(filename)
16
+ File.open(filename, 'w') {|f| f.write(TagRegistry.css + @opts.css) }
17
+ Util::MD5.rename(filename)
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,50 @@
1
+ require 'jsduck/util/json'
2
+ require 'jsduck/util/md5'
3
+ require 'jsduck/web/icons'
4
+ require 'jsduck/web/search'
5
+ require 'jsduck/tag_registry'
6
+
7
+ module JsDuck
8
+ module Web
9
+
10
+ # Creates big JS file with data for Docs app.
11
+ class Data
12
+ def initialize(relations, assets, opts)
13
+ @relations = relations
14
+ @assets = assets
15
+ @opts = opts
16
+ end
17
+
18
+ # Writes classes, guides, videos, and search data to one big .js file.
19
+ # Then Renames the file so it contains an MD5 hash inside it,
20
+ # returning the resulting fingerprinted name.
21
+ def write(filename)
22
+ js = "Docs = " + Util::Json.generate({
23
+ :data => {
24
+ :classes => Web::Icons.new.create(@relations.classes),
25
+ :guides => @assets.guides.to_array,
26
+ :videos => @assets.videos.to_array,
27
+ :examples => @assets.examples.to_array,
28
+ :search => Web::Search.new.create(@relations.classes, @assets),
29
+ :tests => @opts.tests,
30
+ :signatures => TagRegistry.signatures,
31
+ :memberTypes => TagRegistry.member_types,
32
+ :localStorageDb => @opts.local_storage_db,
33
+ :showPrintButton => @opts.seo,
34
+ :touchExamplesUi => @opts.touch_examples_ui,
35
+ :source => @opts.source,
36
+ :commentsUrl => @opts.comments_url,
37
+ :commentsDomain => @opts.comments_domain,
38
+ :message => @opts.message,
39
+ }
40
+ }) + ";\n"
41
+
42
+ File.open(filename, 'w') {|f| f.write(js) }
43
+
44
+ Util::MD5.rename(filename)
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,31 @@
1
+ module JsDuck
2
+ module Web
3
+
4
+ # Creates an array of small hashes documenting name, parent class
5
+ # and icon of a class.
6
+ class Icons
7
+ def create(classes)
8
+ classes.map do |cls|
9
+ {
10
+ :name => cls[:name],
11
+ :extends => cls[:extends],
12
+ :private => cls[:private],
13
+ :icon => Web::Icons::class_icon(cls),
14
+ }
15
+ end
16
+ end
17
+
18
+ # Returns CSS class name for an icon of class
19
+ def self.class_icon(cls)
20
+ if cls[:singleton]
21
+ "icon-singleton"
22
+ elsif cls.inherits_from?("Ext.Component")
23
+ "icon-component"
24
+ else
25
+ "icon-class"
26
+ end
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,88 @@
1
+ require 'jsduck/logger'
2
+ require 'jsduck/util/io'
3
+ require 'jsduck/tag_registry'
4
+ require 'fileutils'
5
+
6
+ module JsDuck
7
+ module Web
8
+
9
+ # Deals with creation of main HTML or PHP files.
10
+ class IndexHtml
11
+ def initialize(assets, opts, paths={})
12
+ @assets = assets
13
+ @opts = opts
14
+ @paths = paths
15
+ end
16
+
17
+ # In normal mode creates index.html.
18
+ #
19
+ # When --seo enabled, creates index.php, template.html and print-template.html.
20
+ def write
21
+ if @opts.seo
22
+ FileUtils.cp(@opts.template_dir+"/index.php", @opts.output_dir+"/index.php")
23
+ create_template_html(@opts.template_dir+"/template.html", @opts.output_dir+"/template.html")
24
+ create_print_template_html(@opts.template_dir+"/print-template.html", @opts.output_dir+"/print-template.html")
25
+ create_index_template_html(@opts.template_dir+"/index-template.html", @opts.output_dir+"/index-template.html")
26
+ else
27
+ create_template_html(@opts.template_dir+"/template.html", @opts.output_dir+"/index.html")
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def create_template_html(in_file, out_file)
34
+ write_template(in_file, out_file, {
35
+ "{title}" => @opts.title,
36
+ "{mobile_redirect}" => @opts.seo ? include_script(@opts.template_dir+"/mobile-redirect.js") : "",
37
+ "{header}" => @opts.header,
38
+ "{footer}" => "<div id='footer-content' style='display: none'>#{@opts.footer}</div>",
39
+ "{extjs_path}" => @opts.extjs_path,
40
+ "{data_path}" => File.basename(@paths[:data]),
41
+ "{css_path}" => File.basename(@paths[:css]),
42
+ "{welcome}" => @assets.welcome.to_html("display:none"),
43
+ "{categories}" => @assets.categories.to_html("display:none"),
44
+ "{guides}" => @assets.guides.to_html("display:none"),
45
+ "{head_html}" => @opts.head_html,
46
+ "{body_html}" => @opts.body_html,
47
+ })
48
+ end
49
+
50
+ def create_print_template_html(in_file, out_file)
51
+ write_template(in_file, out_file, {
52
+ "{title}" => @opts.title,
53
+ "{header}" => @opts.header,
54
+ "{css_path}" => File.basename(@paths[:css]),
55
+ })
56
+ end
57
+
58
+ def create_index_template_html(in_file, out_file)
59
+ categories = @assets.categories.to_html
60
+ guides = @assets.guides.to_html
61
+
62
+ write_template(in_file, out_file, {
63
+ "{title}" => @opts.title,
64
+ "{header}" => @opts.header,
65
+ "{categories}" => categories ? "<h1>API Documentation</h1> #{categories}" : "",
66
+ "{guides}" => guides ? "<h1>Guides</h1> #{guides}" : "",
67
+ "{css_path}" => File.basename(@paths[:css]),
68
+ })
69
+ end
70
+
71
+ def include_script(filename)
72
+ "<script type='text/javascript'>\n" + Util::IO.read(filename) + "\n</script>"
73
+ end
74
+
75
+ # Opens in_file, replaces {keys} inside it, writes to out_file
76
+ def write_template(in_file, out_file, replacements)
77
+ Logger.log("Writing", out_file)
78
+ html = Util::IO.read(in_file)
79
+ html.gsub!(/\{\w+\}/) do |key|
80
+ replacements[key] ? replacements[key] : key
81
+ end
82
+ File.open(out_file, 'w') {|f| f.write(html) }
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+ end