webgen 1.0.0.beta2 → 1.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
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