webgen 1.0.0.beta2 → 1.0.0.beta3

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 (157) hide show
  1. data/COPYING +34 -1
  2. data/Rakefile +1 -8
  3. data/data/webgen/passive_sources/default.metainfo +5 -0
  4. data/data/webgen/passive_sources/stylesheets/api.css +284 -0
  5. data/data/webgen/passive_sources/templates/api.template +151 -0
  6. data/data/webgen/passive_sources/templates/feed.template +4 -0
  7. data/lib/webgen/bundle/built-in/init.rb +12 -3
  8. data/lib/webgen/bundle_loader.rb +8 -2
  9. data/lib/webgen/cli/create_command.rb +3 -1
  10. data/lib/webgen/cli/show_tree_command.rb +4 -3
  11. data/lib/webgen/content_processor.rb +2 -2
  12. data/lib/webgen/content_processor/blocks.rb +2 -2
  13. data/lib/webgen/content_processor/haml.rb +1 -1
  14. data/lib/webgen/content_processor/html_head.rb +5 -4
  15. data/lib/webgen/content_processor/kramdown.rb +3 -1
  16. data/lib/webgen/content_processor/r_doc.rb +16 -3
  17. data/lib/webgen/content_processor/sass.rb +3 -3
  18. data/lib/webgen/content_processor/scss.rb +1 -1
  19. data/lib/webgen/content_processor/tikz.rb +2 -2
  20. data/lib/webgen/context/html_head.rb +1 -1
  21. data/lib/webgen/destination/file_system.rb +2 -1
  22. data/lib/webgen/item_tracker/node_content.rb +4 -4
  23. data/lib/webgen/item_tracker/node_meta_info.rb +6 -6
  24. data/lib/webgen/item_tracker/nodes.rb +1 -1
  25. data/lib/webgen/node.rb +5 -7
  26. data/lib/webgen/node_finder.rb +40 -17
  27. data/lib/webgen/page.rb +10 -0
  28. data/lib/webgen/path.rb +14 -14
  29. data/lib/webgen/path_handler.rb +19 -13
  30. data/lib/webgen/path_handler/api.rb +173 -0
  31. data/lib/webgen/path_handler/base.rb +33 -11
  32. data/lib/webgen/path_handler/copy.rb +2 -27
  33. data/lib/webgen/path_handler/feed.rb +4 -3
  34. data/lib/webgen/path_handler/meta_info.rb +1 -1
  35. data/lib/webgen/path_handler/page_utils.rb +4 -3
  36. data/lib/webgen/path_handler/sitemap.rb +3 -2
  37. data/lib/webgen/path_handler/virtual.rb +7 -2
  38. data/lib/webgen/tag.rb +5 -5
  39. data/lib/webgen/tag/execute_command.rb +1 -1
  40. data/lib/webgen/tag/include_file.rb +1 -1
  41. data/lib/webgen/tag/link.rb +2 -2
  42. data/lib/webgen/tag/menu.rb +1 -1
  43. data/lib/webgen/tag/meta_info.rb +1 -0
  44. data/lib/webgen/tag/relocatable.rb +1 -1
  45. data/lib/webgen/tag/tikz.rb +2 -2
  46. data/lib/webgen/task/create_website.rb +1 -1
  47. data/lib/webgen/test_helper.rb +20 -16
  48. data/lib/webgen/tree.rb +5 -1
  49. data/lib/webgen/version.rb +1 -1
  50. data/lib/webgen/website.rb +8 -8
  51. data/test/webgen/content_processor/test_kramdown.rb +7 -5
  52. data/test/webgen/content_processor/test_sass.rb +4 -0
  53. data/test/webgen/content_processor/test_scss.rb +4 -0
  54. data/test/webgen/content_processor/test_tikz.rb +6 -2
  55. data/test/webgen/destination/test_file_system.rb +3 -4
  56. data/test/webgen/item_tracker/test_missing_node.rb +3 -3
  57. data/test/webgen/item_tracker/test_node_content.rb +9 -12
  58. data/test/webgen/item_tracker/test_node_meta_info.rb +7 -11
  59. data/test/webgen/item_tracker/test_nodes.rb +11 -5
  60. data/test/webgen/path_handler/test_api.rb +111 -0
  61. data/test/webgen/path_handler/test_page_utils.rb +1 -1
  62. data/test/webgen/source/test_file_system.rb +3 -3
  63. data/test/webgen/tag/test_coderay.rb +3 -4
  64. data/test/webgen/tag/test_meta_info.rb +3 -0
  65. data/test/webgen/task/test_create_website.rb +2 -2
  66. data/test/webgen/test_item_tracker.rb +11 -16
  67. data/test/webgen/test_node.rb +2 -0
  68. data/test/webgen/test_node_finder.rb +30 -2
  69. data/test/webgen/test_page.rb +8 -0
  70. data/test/webgen/test_source.rb +11 -18
  71. data/test/webgen/test_tag.rb +1 -1
  72. data/test/webgen/test_tree.rb +8 -8
  73. metadata +8 -88
  74. data/ChangeLog +0 -23710
  75. data/data/webgen/website_bundles/default/README +0 -6
  76. data/data/webgen/website_bundles/default/src/index.page +0 -15
  77. data/data/webgen/website_bundles/style/1024px/README +0 -13
  78. data/data/webgen/website_bundles/style/1024px/src/default.css +0 -188
  79. data/data/webgen/website_bundles/style/1024px/src/default.template +0 -60
  80. data/data/webgen/website_bundles/style/1024px/src/images/background.gif +0 -0
  81. data/data/webgen/website_bundles/style/andreas00/README +0 -13
  82. data/data/webgen/website_bundles/style/andreas00/src/default.css +0 -290
  83. data/data/webgen/website_bundles/style/andreas00/src/default.template +0 -60
  84. data/data/webgen/website_bundles/style/andreas00/src/images/bg.gif +0 -0
  85. data/data/webgen/website_bundles/style/andreas00/src/images/front.jpg +0 -0
  86. data/data/webgen/website_bundles/style/andreas00/src/images/menubg.gif +0 -0
  87. data/data/webgen/website_bundles/style/andreas00/src/images/menubg2.gif +0 -0
  88. data/data/webgen/website_bundles/style/andreas01/README +0 -14
  89. data/data/webgen/website_bundles/style/andreas01/src/default.css +0 -310
  90. data/data/webgen/website_bundles/style/andreas01/src/default.template +0 -62
  91. data/data/webgen/website_bundles/style/andreas01/src/images/bg.gif +0 -0
  92. data/data/webgen/website_bundles/style/andreas01/src/images/front.jpg +0 -0
  93. data/data/webgen/website_bundles/style/andreas01/src/print.css +0 -35
  94. data/data/webgen/website_bundles/style/andreas03/README +0 -14
  95. data/data/webgen/website_bundles/style/andreas03/src/default.css +0 -223
  96. data/data/webgen/website_bundles/style/andreas03/src/default.template +0 -58
  97. data/data/webgen/website_bundles/style/andreas03/src/images/bodybg.png +0 -0
  98. data/data/webgen/website_bundles/style/andreas03/src/images/contbg.png +0 -0
  99. data/data/webgen/website_bundles/style/andreas03/src/images/footerbg.png +0 -0
  100. data/data/webgen/website_bundles/style/andreas03/src/images/gradient1.png +0 -0
  101. data/data/webgen/website_bundles/style/andreas03/src/images/gradient2.png +0 -0
  102. data/data/webgen/website_bundles/style/andreas04/README +0 -15
  103. data/data/webgen/website_bundles/style/andreas04/src/default.css +0 -290
  104. data/data/webgen/website_bundles/style/andreas04/src/default.template +0 -81
  105. data/data/webgen/website_bundles/style/andreas04/src/images/blinkarrow.gif +0 -0
  106. data/data/webgen/website_bundles/style/andreas04/src/images/bodybg.png +0 -0
  107. data/data/webgen/website_bundles/style/andreas04/src/images/contentbg.png +0 -0
  108. data/data/webgen/website_bundles/style/andreas04/src/images/entrybg.png +0 -0
  109. data/data/webgen/website_bundles/style/andreas04/src/images/flash.gif +0 -0
  110. data/data/webgen/website_bundles/style/andreas04/src/images/flash2.gif +0 -0
  111. data/data/webgen/website_bundles/style/andreas04/src/images/globe.gif +0 -0
  112. data/data/webgen/website_bundles/style/andreas04/src/images/globebottom.gif +0 -0
  113. data/data/webgen/website_bundles/style/andreas04/src/images/linkarrow.gif +0 -0
  114. data/data/webgen/website_bundles/style/andreas04/src/images/menuhover.png +0 -0
  115. data/data/webgen/website_bundles/style/andreas05/README +0 -14
  116. data/data/webgen/website_bundles/style/andreas05/src/default.css +0 -33
  117. data/data/webgen/website_bundles/style/andreas05/src/default.template +0 -40
  118. data/data/webgen/website_bundles/style/andreas05/src/images/bodybg.gif +0 -0
  119. data/data/webgen/website_bundles/style/andreas05/src/images/front.png +0 -0
  120. data/data/webgen/website_bundles/style/andreas06/README +0 -14
  121. data/data/webgen/website_bundles/style/andreas06/src/default.css +0 -356
  122. data/data/webgen/website_bundles/style/andreas06/src/default.template +0 -70
  123. data/data/webgen/website_bundles/style/andreas06/src/images/bodybg.gif +0 -0
  124. data/data/webgen/website_bundles/style/andreas06/src/images/boxbg.gif +0 -0
  125. data/data/webgen/website_bundles/style/andreas06/src/images/greypx.gif +0 -0
  126. data/data/webgen/website_bundles/style/andreas06/src/images/header.jpg +0 -0
  127. data/data/webgen/website_bundles/style/andreas06/src/images/innerbg.gif +0 -0
  128. data/data/webgen/website_bundles/style/andreas06/src/images/leaves.jpg +0 -0
  129. data/data/webgen/website_bundles/style/andreas06/src/images/tabs.gif +0 -0
  130. data/data/webgen/website_bundles/style/andreas07/README +0 -15
  131. data/data/webgen/website_bundles/style/andreas07/src/browserfix.css +0 -7
  132. data/data/webgen/website_bundles/style/andreas07/src/default.css +0 -92
  133. data/data/webgen/website_bundles/style/andreas07/src/default.template +0 -42
  134. data/data/webgen/website_bundles/style/andreas07/src/images/bodybg.gif +0 -0
  135. data/data/webgen/website_bundles/style/andreas07/src/images/sidebarbg.gif +0 -0
  136. data/data/webgen/website_bundles/style/andreas08/README +0 -14
  137. data/data/webgen/website_bundles/style/andreas08/src/default.css +0 -224
  138. data/data/webgen/website_bundles/style/andreas08/src/default.template +0 -51
  139. data/data/webgen/website_bundles/style/andreas09/README +0 -14
  140. data/data/webgen/website_bundles/style/andreas09/src/default.css +0 -308
  141. data/data/webgen/website_bundles/style/andreas09/src/default.template +0 -68
  142. data/data/webgen/website_bundles/style/andreas09/src/images/bodybg-black.jpg +0 -0
  143. data/data/webgen/website_bundles/style/andreas09/src/images/bodybg-green.jpg +0 -0
  144. data/data/webgen/website_bundles/style/andreas09/src/images/bodybg-orange.jpg +0 -0
  145. data/data/webgen/website_bundles/style/andreas09/src/images/bodybg-purple.jpg +0 -0
  146. data/data/webgen/website_bundles/style/andreas09/src/images/bodybg-red.jpg +0 -0
  147. data/data/webgen/website_bundles/style/andreas09/src/images/bodybg.jpg +0 -0
  148. data/data/webgen/website_bundles/style/andreas09/src/images/footerbg.jpg +0 -0
  149. data/data/webgen/website_bundles/style/andreas09/src/images/menuhover-black.jpg +0 -0
  150. data/data/webgen/website_bundles/style/andreas09/src/images/menuhover-green.jpg +0 -0
  151. data/data/webgen/website_bundles/style/andreas09/src/images/menuhover-orange.jpg +0 -0
  152. data/data/webgen/website_bundles/style/andreas09/src/images/menuhover-purple.jpg +0 -0
  153. data/data/webgen/website_bundles/style/andreas09/src/images/menuhover-red.jpg +0 -0
  154. data/data/webgen/website_bundles/style/andreas09/src/images/menuhover.jpg +0 -0
  155. data/data/webgen/website_bundles/style/simple/README +0 -6
  156. data/data/webgen/website_bundles/style/simple/src/default.css +0 -84
  157. data/data/webgen/website_bundles/style/simple/src/default.template +0 -36
@@ -112,6 +112,16 @@ module Webgen
112
112
  @blocks = blocks
113
113
  end
114
114
 
115
+ # Convert the Page object back into a string.
116
+ def to_s
117
+ str = ""
118
+ str << @meta_info.to_yaml
119
+ blocks.each do |name, value|
120
+ str << "--- #{name}\n" << value.gsub(/^---.*?$/) {|m| "\\#{m}" } << (value =~ /\n$/ ? "" : "\n")
121
+ end
122
+ str
123
+ end
124
+
115
125
  end
116
126
 
117
127
  end
@@ -29,7 +29,7 @@ module Webgen
29
29
  #
30
30
  # * Path.url
31
31
  # * Path.append
32
- # * Path.matches_pattern
32
+ # * Path.matches_pattern?
33
33
  # * Path.lcn
34
34
  #
35
35
  class Path
@@ -44,7 +44,7 @@ module Webgen
44
44
  # Construct an internal URL for the given +path+ which can be an acn/alcn/absolute path.
45
45
  #
46
46
  # If the parameter +make_absolute+ is +true+, then a relative URL will be made absolute by
47
- # prepending the special URL 'webgen:://webgen.localhost/'.
47
+ # prepending the special URL 'webgen://webgen.localhost/'.
48
48
  def self.url(path, make_absolute = true)
49
49
  url = URI.parse(URI::DEFAULT_PARSER.escape(path, URL_UNSAFE_PATTERN))
50
50
  url = WEBGEN_BASE_URI + url unless url.absolute? || !make_absolute
@@ -57,9 +57,9 @@ module Webgen
57
57
  # needs to have a trailing slash! The +path+ parameter doesn't need to be absolute and may
58
58
  # contain path patterns.
59
59
  def self.append(base, path)
60
- raise(ArgumentError, 'base needs to start with a slash (i.e. be an absolute path)') unless base =~ /^\//
60
+ raise(ArgumentError, 'base needs to start with a slash (i.e. be an absolute path)') unless base[0] == ?/
61
61
  url = url(base) + url(path, false)
62
- url.path + (url.fragment.nil? ? '' : '#' + url.fragment)
62
+ url.path << (url.fragment.nil? ? '' : "##{url.fragment}")
63
63
  end
64
64
 
65
65
  # Return +true+ if the given path string matches the given path pattern.
@@ -67,7 +67,7 @@ module Webgen
67
67
  # For information on which patterns are supported, have a look at the API documentation of
68
68
  # File.fnmatch.
69
69
  def self.matches_pattern?(path, pattern, options = File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
70
- pattern += '/' if path.to_s =~ /\/$/ && pattern !~ /\/$|^$/
70
+ pattern += '/' if path =~ /\/$/ && pattern !~ /\/$|^$/
71
71
  File.fnmatch(pattern, path, options)
72
72
  end
73
73
 
@@ -162,13 +162,13 @@ module Webgen
162
162
  #
163
163
  # Triggers analyzation of the path if invoked.
164
164
  def cn
165
- if meta_info['cn'].kind_of?(String)
165
+ if meta_info['cn']
166
166
  tmp_cn = custom_cn
167
167
  else
168
- tmp_cn = basename + (use_version_for_cn? ? "-#{meta_info['version']}" : '') +
169
- (ext.length > 0 ? '.' + ext : '')
168
+ tmp_cn = basename.dup << (use_version_for_cn? ? "-#{meta_info['version']}" : '') <<
169
+ (ext.length > 0 ? ".#{ext}" : '')
170
170
  end
171
- tmp_cn + (@path =~ /.\/$/ ? '/' : '')
171
+ tmp_cn << (@path =~ /.\/$/ ? '/' : '')
172
172
  end
173
173
 
174
174
  # The localized canonical name created from the +path+.
@@ -183,7 +183,7 @@ module Webgen
183
183
  # Triggers analyzation of the path if invoked.
184
184
  def acn
185
185
  if @path =~ /#/
186
- self.class.new(parent_path).acn + cn
186
+ self.class.new(parent_path).acn << cn
187
187
  else
188
188
  parent_path + cn
189
189
  end
@@ -194,7 +194,7 @@ module Webgen
194
194
  # Triggers analyzation of the path if invoked.
195
195
  def alcn
196
196
  if @path =~ /#/
197
- self.class.new(parent_path).alcn + lcn
197
+ self.class.new(parent_path).alcn << lcn
198
198
  else
199
199
  parent_path + lcn
200
200
  end
@@ -270,7 +270,7 @@ module Webgen
270
270
  end
271
271
 
272
272
  def to_s #:nodoc:
273
- @path.dup
273
+ @path
274
274
  end
275
275
  alias_method :to_str, :to_s
276
276
 
@@ -317,7 +317,7 @@ module Webgen
317
317
  @meta_info['sort_info'] ||= match_data[1].to_i unless match_data[1].nil?
318
318
  @basename = match_data[2]
319
319
  @meta_info['lang'] ||= Webgen::LanguageManager.language_for_code(match_data[3]) if match_data[3]
320
- @ext = (@meta_info['lang'].nil? && !match_data[3].nil? ? match_data[3].to_s + '.' : '') + match_data[4].to_s
320
+ @ext = (@meta_info['lang'].nil? && !match_data[3].nil? ? match_data[3] << '.' : '') << match_data[4].to_s
321
321
  end
322
322
  end
323
323
 
@@ -354,7 +354,7 @@ module Webgen
354
354
  ''
355
355
  end
356
356
  end
357
- self.meta_info['cn'].gsub(CN_SEGMENTS, &replace_segment).gsub(/\/+$/, '')
357
+ self.meta_info['cn'].to_s.gsub(CN_SEGMENTS, &replace_segment).gsub(/\/+$/, '')
358
358
  end
359
359
 
360
360
  end
@@ -146,19 +146,24 @@ module Webgen
146
146
  end
147
147
 
148
148
  used_secondary_paths = {}
149
+ written_nodes = Set.new
149
150
  @website.blackboard.add_listener(:before_secondary_nodes_created, self) do |path, source_alcn|
150
151
  (used_secondary_paths[source_alcn] ||= Set.new) << path if source_alcn
151
152
  end
152
- @website.blackboard.add_listener(:before_node_written, self) do |node|
153
+ @website.blackboard.add_listener(:before_all_nodes_written, self) do |node|
153
154
  used_secondary_paths = {}
155
+ written_nodes = Set.new
154
156
  end
155
157
  @website.blackboard.add_listener(:after_node_written, self) do |node|
156
- @secondary_nodes.select do |path, data|
157
- data[1] == node.alcn && used_secondary_paths[node.alcn] &&
158
- !used_secondary_paths[node.alcn].include?(path)
159
- end.each do |path, data|
160
- @secondary_nodes.delete(path)
161
- data[2].each {|alcn| @website.tree.delete_node(@website.tree[alcn])}
158
+ written_nodes << node.alcn
159
+ end
160
+ @website.blackboard.add_listener(:after_all_nodes_written, self) do |node|
161
+ @secondary_nodes.delete_if do |path, data|
162
+ if written_nodes.include?(data[1]) && (!used_secondary_paths[data[1]] ||
163
+ !used_secondary_paths[data[1]].include?(path))
164
+ data[2].each {|alcn| @website.tree.delete_node(@website.tree[alcn])}
165
+ true
166
+ end
162
167
  end
163
168
  end
164
169
  end
@@ -208,7 +213,7 @@ module Webgen
208
213
 
209
214
  # Return the instance of the path handler class with the given name.
210
215
  def instance(handler)
211
- @instances[handler] ||= extension(handler).new(@website)
216
+ @instances[handler.intern] ||= extension(handler).new(@website)
212
217
  end
213
218
 
214
219
 
@@ -216,7 +221,7 @@ module Webgen
216
221
  #
217
222
  # Can only be called once because the tree can only be populated once!
218
223
  def populate_tree
219
- raise Webgen::NodeCreationError.new("Can't populate tree twice", self.class.name) if @website.tree.root
224
+ raise Webgen::NodeCreationError.new("Can't populate tree twice", 'path_handler') if @website.tree.root
220
225
 
221
226
  time = Benchmark.measure do
222
227
  meta_info, rest = @website.ext.source.paths.partition {|path| path.path =~ /[\/.]metainfo$/}
@@ -268,9 +273,10 @@ module Webgen
268
273
  @website.blackboard.dispatch_msg(:after_node_written, node, content)
269
274
  rescue Webgen::Error => e
270
275
  e.path = node.alcn if e.path.to_s.empty?
276
+ e.location = "path_handler.#{node.node_info[:path_handler]}" unless e.location
271
277
  raise
272
278
  rescue Exception => e
273
- raise Webgen::RenderError.new(e, nil, node)
279
+ raise Webgen::RenderError.new(e, "path_handler.#{node.node_info[:path_handler]}", node)
274
280
  end
275
281
  end
276
282
  @website.blackboard.dispatch_msg(:after_all_nodes_written)
@@ -325,7 +331,7 @@ module Webgen
325
331
  # alcn from which these nodes are created!
326
332
  def create_secondary_nodes(path, content = '', source_alcn = nil)
327
333
  if (sn = @secondary_nodes[path]) && sn[1] != source_alcn
328
- raise Webgen::NodeCreationError.new("Duplicate secondary path name <#{path}>", self.class.name, path)
334
+ raise Webgen::NodeCreationError.new("Duplicate secondary path name <#{path}>", 'path_handler', path)
329
335
  end
330
336
  @website.blackboard.dispatch_msg(:before_secondary_nodes_created, path, source_alcn)
331
337
 
@@ -388,10 +394,10 @@ module Webgen
388
394
  end
389
395
  rescue Webgen::Error => e
390
396
  e.path = path.to_s if e.path.to_s.empty?
391
- e.location = instance(handler).class.name unless e.location
397
+ e.location = "path_handler.#{handler}" unless e.location
392
398
  raise
393
399
  rescue Exception => e
394
- raise Webgen::NodeCreationError.new(e, instance(handler).class.name, path)
400
+ raise Webgen::NodeCreationError.new(e, "path_handler.#{handler}", path)
395
401
  end
396
402
  private :create_nodes_with_path_handler
397
403
 
@@ -0,0 +1,173 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'time'
4
+ require 'shellwords'
5
+ require 'webgen/path_handler/base'
6
+ require 'webgen/path_handler/page_utils'
7
+ require 'webgen/context'
8
+ require 'webgen/path'
9
+ require 'webgen/content_processor/r_doc'
10
+
11
+ module Webgen
12
+ class PathHandler
13
+
14
+ # Path handler for Ruby API documentation via rdoc.
15
+ class Api
16
+
17
+ include Base
18
+ include PageUtils
19
+
20
+ # The mandatory meta info keys that need to be set on an api path.
21
+ MANDATORY_INFOS = %W[rdoc_options]
22
+
23
+ # Create the feed nodes.
24
+ def create_nodes(path, blocks)
25
+ if MANDATORY_INFOS.any? {|t| path.meta_info[t].nil?}
26
+ raise Webgen::NodeCreationError.new("At least one of #{MANDATORY_INFOS.join('/')} is missing",
27
+ "path_handler.api", path)
28
+ end
29
+
30
+ path['api_name'] ||= path.basename
31
+ path['dir_name'] ||= path.basename
32
+
33
+ cache_dir = @website.tmpdir(File.join('path_handler.api', path['api_name']))
34
+ rdoc = rdoc_object(path['rdoc_options'], cache_dir)
35
+ output_flag_file = rdoc.output_flag_file(cache_dir)
36
+
37
+ dir_node = create_directory(path, Webgen::Path.new(path.parent_path + path['dir_name'] + '/'), false)
38
+
39
+ rdoc.store.all_classes_and_modules.sort.each do |klass|
40
+ klass_node = create_page_node_for_class(path, dir_node, klass, output_flag_file)
41
+ klass.each_method {|method| create_fragment_node_for_method(path, klass_node, method)}
42
+ end
43
+
44
+ nil
45
+ end
46
+
47
+ # Create a directory for the path, applying needed meta information from the api path.
48
+ #
49
+ # Also creates the parent directories when necessary.
50
+ def create_directory(api_path, path, set_proxy_path = true)
51
+ if (dir = @website.tree[path.alcn])
52
+ return dir
53
+ end
54
+
55
+ parent_path = Webgen::Path.new(path.parent_path)
56
+ if !@website.tree[parent_path.alcn]
57
+ create_directory(api_path, parent_path)
58
+ end
59
+
60
+ path['modified_at'] = api_path['modified_at']
61
+ path['handler'] = 'directory'
62
+ path['proxy_path'] ||= "../#{path.basename}.html" if set_proxy_path
63
+ @website.ext.path_handler.create_secondary_nodes(path).first
64
+ end
65
+ private :create_directory
66
+
67
+ # Create the RDoc instance and use it for generating the API data.
68
+ #
69
+ # If possible, cached data available under +cache_dir+ is used.
70
+ def rdoc_object(options, cache_dir)
71
+ start_time = Time.now
72
+
73
+ rdoc = RDoc::RDoc.new
74
+ rdoc.options = rdoc_options(options)
75
+ rdoc.store = rdoc_store(rdoc.options, cache_dir)
76
+
77
+ rdoc.exclude = rdoc.options.exclude
78
+ rdoc.last_modified.replace(rdoc.setup_output_dir(cache_dir, false))
79
+
80
+ if !(rdoc.parse_files(rdoc.options.files)).empty?
81
+ rdoc.store.complete(rdoc.options.visibility)
82
+ rdoc.store.save
83
+ rdoc.update_output_dir(cache_dir, start_time, rdoc.last_modified)
84
+ end
85
+ rdoc.store.load_all
86
+
87
+ # We need a dummy generator with some methods
88
+ rdoc.generator = Object.new
89
+ def (rdoc.generator).class_dir; nil; end
90
+ def (rdoc.generator).file_dir; nil; end
91
+
92
+ rdoc
93
+ end
94
+ protected :rdoc_object
95
+
96
+ # Return a fully initialized RDoc::Options object.
97
+ #
98
+ # Some of the user specified options may not be used if they would interfere with this class'
99
+ # job.
100
+ def rdoc_options(user_options)
101
+ user_options = Shellwords.split(user_options) if user_options.kind_of?(String)
102
+ options = RDoc::Options.new
103
+ options.parse(user_options)
104
+ options.verbosity = 0
105
+ options.dry_run = false
106
+ options.update_output_dir = true
107
+ options.force_output = false
108
+ options.finish
109
+ options
110
+ end
111
+ protected :rdoc_options
112
+
113
+ # Return a fully initialized RDoc::Store object.
114
+ def rdoc_store(options, cache_dir)
115
+ store = RDoc::Store.new(cache_dir)
116
+ store.encoding = options.encoding
117
+ store.dry_run = options.dry_run
118
+ store.main = options.main_page
119
+ store.title = options.title
120
+ store.load_cache
121
+ store
122
+ end
123
+ protected :rdoc_store
124
+
125
+ # Create a page node for the given class +klass+ and return it.
126
+ #
127
+ # A link definition entry for the class is also created.
128
+ def create_page_node_for_class(api_path, dir_node, klass, output_flag_file)
129
+ klass_path_str = klass.http_url(dir_node.alcn)
130
+
131
+ create_directory(api_path, Webgen::Path.new(File.dirname(klass_path_str) + '/'))
132
+
133
+ path = Webgen::Path.new(klass_path_str, 'handler' => 'page', 'modified_at' => api_path['modified_at'],
134
+ 'title' => "#{klass.type} #{klass.full_name}", 'api_class' => klass.full_name,
135
+ 'api_name' => api_path['api_name'], 'template' => api_path['api_template'])
136
+ node = @website.ext.path_handler.create_secondary_nodes(path).first
137
+
138
+ node.node_info[:api_class_object] = klass
139
+ @website.ext.item_tracker.add(node, :file, output_flag_file)
140
+ add_link_definition(api_path, klass.full_name, node.alcn, klass.full_name)
141
+
142
+ node
143
+ end
144
+ protected :create_page_node_for_class
145
+
146
+ # Create a fragment node for the given method.
147
+ #
148
+ # A link definition entry for the method is also created.
149
+ def create_fragment_node_for_method(api_path, klass_node, method)
150
+ method_url = "#{klass_node.alcn}##{method.aref}"
151
+ path = Webgen::Path.new(method_url,
152
+ {'handler' => 'copy', 'modified_at' => api_path['modified_at'],
153
+ 'pipeline' => [], 'no_output' => true, 'title' => method.name})
154
+ @website.ext.path_handler.create_secondary_nodes(path)
155
+ add_link_definition(api_path, method.full_name, method_url, method.full_name)
156
+ end
157
+ protected :create_fragment_node_for_method
158
+
159
+ # Add a link definition for the given node.
160
+ def add_link_definition(api_path, link_name, url, title)
161
+ link = if api_path['prefix_for_link_defs']
162
+ "#{api_path['api_name']}:#{link_name}"
163
+ else
164
+ link_name
165
+ end
166
+ @website.ext.link_definitions[link] = [url, title]
167
+ end
168
+ protected :add_link_definition
169
+
170
+ end
171
+
172
+ end
173
+ end
@@ -4,6 +4,7 @@ require 'webgen/path_handler'
4
4
  require 'webgen/error'
5
5
  require 'webgen/node'
6
6
  require 'webgen/path'
7
+ require 'webgen/utils'
7
8
 
8
9
  module Webgen
9
10
  class PathHandler
@@ -27,10 +28,18 @@ module Webgen
27
28
  #
28
29
  module Base
29
30
 
30
- # This is the base Node sub class used by the Base#create_node method if a path handler class
31
- # does not specify another Node class.
31
+ # This is the Node sub class used by the Base#create_node method if a path handler class does
32
+ # not specify another Node class.
32
33
  class Node < Webgen::Node
33
34
 
35
+ # Does exactly the same as Node#route_to but also automatically adds the necessary item
36
+ # tracking information.
37
+ def route_to(node, lang = @lang)
38
+ tree.website.ext.item_tracker.add(self, :node_meta_info, node)
39
+ tree.website.ext.item_tracker.add(self, :node_meta_info, node.proxy_node(lang))
40
+ super
41
+ end
42
+
34
43
  # Return the result of the #content method on the associated path handler or +nil+ if the
35
44
  # associated path handler does not have a #content method.
36
45
  def content
@@ -60,18 +69,19 @@ module Webgen
60
69
  # Create a node from +path+, if possible, yield the fully initialized node if a block is given
61
70
  # and return it.
62
71
  #
63
- # The node class to be used for the created node can be specified via the +node_klass+
64
- # parameter.
65
- #
66
- # If no node can be created (e.g. when 'path.meta_info['draft']' is set), +nil+ is returned.
72
+ # The node class to be used for the to-be-created node can be specified via
73
+ # `path.meta_info['node_class']`. If this node processing information is not set, the
74
+ # Base::Node class is used.
67
75
  #
68
76
  # The parent node under which the new node should be created can optionally be specified via
69
- # 'path.meta_info['parent_alcn']'. This meta information has to be set to an alcn of an
70
- # existing node.
77
+ # 'path.meta_info['parent_alcn']'. This node processing information has to be set to the alcn
78
+ # of an existing node.
79
+ #
80
+ # If no node can be created (e.g. when 'path.meta_info['draft']' is set), +nil+ is returned.
71
81
  #
72
82
  # On the created node, the node information +:path+ is set to the given path and
73
83
  # +:path_handler+ to the path handler instance.
74
- def create_node(path, node_klass = Node)
84
+ def create_node(path)
75
85
  return nil if path.meta_info['draft']
76
86
  parent = parent_node(path)
77
87
  dest_path = self.dest_path(parent, path)
@@ -95,7 +105,7 @@ module Webgen
95
105
  path.meta_info['modified_at'] = Time.now
96
106
  end
97
107
 
98
- node = node_klass.new(parent, path.cn, dest_path, path.meta_info.dup)
108
+ node = node_class(path).new(parent, path.cn, dest_path, path.meta_info.dup)
99
109
  node.node_info[:path] = path
100
110
  node.node_info[:path_handler] = self
101
111
 
@@ -220,10 +230,22 @@ module Webgen
220
230
  # Check if the node alcn or the destination path, which would be created by #create_node for
221
231
  # the given paths, exists.
222
232
  def node_exists?(path, dest_path)
223
- @website.tree[path.alcn] || (!path.meta_info['no_output'] && @website.tree[dest_path, :dest_path])
233
+ @website.tree[path.alcn] || (!path.meta_info['no_output'] && @website.tree.node(dest_path, :dest_path))
224
234
  end
225
235
  protected :node_exists?
226
236
 
237
+ # Retrieve the node class that should be used for the given path.
238
+ def node_class(path)
239
+ if String === (klass = path.meta_info['node_class'])
240
+ Webgen::Utils.const_for_name(klass) rescue Node
241
+ elsif String === (klass = path.meta_info['base_node_class'])
242
+ Webgen::Utils.const_for_name(klass) rescue Node
243
+ else
244
+ Node
245
+ end
246
+ end
247
+ protected :node_class
248
+
227
249
  end
228
250
 
229
251
  end