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
@@ -44,7 +44,11 @@
44
44
  <title><%= h(context.node['title']) %></title>
45
45
  <link><%= context.node.feed_link %>"</link>
46
46
  <description><%= h(context.node['description']) %></description>
47
+ <% if context.node['created_at'].kind_of?(Time) %>
48
+ <pubdate><%= context.node['created_at'].rfc822 %></pubdate>
49
+ <% else %>
47
50
  <pubDate><%= Time.now.rfc822 %></pubDate>
51
+ <% end %>
48
52
  <lastBuildDate><%= Time.now.rfc822 %></lastBuildDate>
49
53
  <generator>webgen - Webgen::PathHandler::Feed</generator>
50
54
 
@@ -153,8 +153,8 @@ item_tracker.register('NodeContent')
153
153
 
154
154
  item_tracker.register('NodeMetaInfo')
155
155
  website.blackboard.add_listener(:after_node_created) do |node|
156
- item_tracker.add(node, :node_meta_info, node.alcn)
157
- item_tracker.add(node, :node_meta_info, node.alcn, Webgen::ItemTracker::NodeMetaInfo::CONTENT_MODIFICATION_KEY)
156
+ item_tracker.add(node, :node_meta_info, node)
157
+ item_tracker.add(node, :node_meta_info, node, Webgen::ItemTracker::NodeMetaInfo::CONTENT_MODIFICATION_KEY)
158
158
  end
159
159
 
160
160
  item_tracker.register('Nodes')
@@ -169,11 +169,18 @@ website.blackboard.add_listener(:node_resolution_failed) do |path, lang|
169
169
  end
170
170
  end
171
171
 
172
+ ########################################################################
173
+ # The link definitions extension
174
+ website.ext.link_definitions = {}
175
+
176
+
172
177
  ########################################################################
173
178
  # Everything related to the node finder extension
174
179
  require 'webgen/node_finder'
175
180
 
176
181
  website.ext.node_finder = Webgen::NodeFinder.new(website)
182
+ option('node_finder.option_sets', {},
183
+ 'Node finder option sets that can be referenced by name')
177
184
 
178
185
 
179
186
  ########################################################################
@@ -206,7 +213,6 @@ option('path_handler.default_template', 'default.template',
206
213
  website.ext.path_handler = path_handler = Webgen::PathHandler.new(website)
207
214
 
208
215
  # handlers are registered in invocation order
209
-
210
216
  path_handler.register('Directory')
211
217
  path_handler.register('MetaInfo', :patterns => ['/**/metainfo', '/**/*.metainfo'])
212
218
  path_handler.register('Template')
@@ -215,6 +221,7 @@ path_handler.register('Copy')
215
221
  path_handler.register('Feed')
216
222
  path_handler.register('Sitemap')
217
223
  path_handler.register('Virtual')
224
+ path_handler.register('Api')
218
225
 
219
226
 
220
227
  ########################################################################
@@ -260,6 +267,8 @@ option('tag.date.format', '%Y-%m-%d %H:%M:%S',
260
267
  tag.register('MetaInfo', :names => ['meta_info', :default])
261
268
  option('tag.meta_info.escape_html', true,
262
269
  'Special HTML characters in the output will be escaped if true', &true_or_false)
270
+ option('tag.meta_info.mi', nil,
271
+ 'The name of the meta information that should be output', &is_string)
263
272
 
264
273
  tag.register('Relocatable', :names => ['relocatable', 'r'], :mandatory => ['path'])
265
274
  option('tag.relocatable.path', nil,
@@ -44,11 +44,17 @@ module Webgen
44
44
 
45
45
  # Loads all bundles that are marked for auto-loading.
46
46
  def load_autoload_bundles
47
- Gem::Specification.map {|s| s.name }.uniq.each do |gem_name|
47
+ bundles = Gem::Specification.map {|s| s.name }.uniq.map do |gem_name|
48
48
  md = /^webgen-(.*)-bundle$/.match(gem_name)
49
49
  next unless md
50
+ md[1]
51
+ end.compact
50
52
 
51
- bundle_name = md[1]
53
+ bundles += $LOAD_PATH.map do |path|
54
+ Dir[File.join(path, 'webgen/bundle', '*')].map {|d| File.basename(d)}
55
+ end.flatten.compact
56
+
57
+ bundles.each do |bundle_name|
52
58
  file = resolve_init_file(bundle_name)
53
59
  next unless file
54
60
 
@@ -1,6 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  require 'webgen/cli/utils'
4
+ require 'tmpdir'
4
5
 
5
6
  module Webgen
6
7
  module CLI
@@ -48,8 +49,9 @@ DESC
48
49
  raise OptionParser::MissingArgument.new('DIR') if args.length == 0
49
50
  Webgen::Website.new(args[0], Webgen::CLI::Logger.new) do |website|
50
51
  website.logger.verbose = commandparser.verbose
52
+ website.config['website.tmpdir'] = Dir.tmpdir
51
53
  end.execute_task(:create_website, @template)
52
- puts "Created a new webgen website in <#{args[0]}>" + (@template ? "using the '#{template}' template" : '')
54
+ puts "Created a new webgen website in <#{args[0]}>" + (@template ? " using the '#{@template}' template" : '')
53
55
  rescue Webgen::Task::CreateWebsite::Error => e
54
56
  puts "An error occured while creating the website: #{e.message}"
55
57
  end
@@ -56,10 +56,11 @@ DESC
56
56
  children.sort {|a,b| a.alcn <=> b.alcn}.map do |node|
57
57
  sub = collect_data(node.children, selector)
58
58
  if sub.length > 0 ||
59
- ((selector.nil? || node.lcn.include?(selector)) &&
59
+ ((selector.nil? || node.alcn.include?(selector)) &&
60
60
  ((!node.is_fragment? || @show_fragments) &&
61
61
  (!node['passive'] || commandparser.website.ext.item_tracker.node_referenced?(node))))
62
62
  data = [@use_alcn ? node.alcn : node.lcn]
63
+ data << node.alcn
63
64
  data << (@meta_info ? node.meta_info.map {|k,v| "#{k}: #{v.inspect}"} : [])
64
65
  data << sub
65
66
  data
@@ -71,9 +72,9 @@ DESC
71
72
  private :collect_data
72
73
 
73
74
  def print_tree(data, indent = '', selector)
74
- data.each do |name, info, children|
75
+ data.each do |name, alcn, info, children|
75
76
  puts("#{indent}#{Utils.light(Utils.blue(name))}")
76
- info.each {|i| puts("#{indent} #{i}")} if info.length > 0 && (selector.nil? || name.include?(selector))
77
+ info.each {|i| puts("#{indent} #{i}")} if info.length > 0 && (selector.nil? || alcn.include?(selector))
77
78
  print_tree(children, indent + ' ', selector)
78
79
  end
79
80
  end
@@ -104,10 +104,10 @@ module Webgen
104
104
  extension(name).call(context)
105
105
  rescue Webgen::Error => e
106
106
  e.path = context.dest_node if e.path.to_s.empty?
107
+ e.location = "content_processor.#{name}" unless e.location
107
108
  raise
108
109
  rescue Exception => e
109
- ext = extension(name)
110
- raise Webgen::RenderError.new(e, (ext.respond_to?(:name) ? ext.name : nil), context.dest_node)
110
+ raise Webgen::RenderError.new(e, "content_processor.#{name}", context.dest_node)
111
111
  end
112
112
 
113
113
  # Normalize the content processor pipeline.
@@ -77,11 +77,11 @@ module Webgen
77
77
  return ''
78
78
  elsif block_node
79
79
  raise Webgen::RenderError.new("No block named '#{options[:name]}' found in <#{block_node}>",
80
- self.name, context.dest_node,
80
+ 'content_processor.blocks', context.dest_node,
81
81
  context.ref_node, (options[:line_nr_proc].call if options[:line_nr_proc]))
82
82
  else
83
83
  raise Webgen::RenderError.new("No node in the render chain has a block named '#{options[:name]}'",
84
- self.name, context.dest_node,
84
+ 'content_processor.blocks', context.dest_node,
85
85
  context.ref_node, (options[:line_nr_proc].call if options[:line_nr_proc]))
86
86
  end
87
87
  end
@@ -16,7 +16,7 @@ module Webgen
16
16
  context
17
17
  rescue ::Haml::Error => e
18
18
  line = (e.line ? e.line + 1 : Webgen::Error.error_line(e))
19
- raise Webgen::RenderError.new(e, self.class.name, context.dest_node, nil, line)
19
+ raise Webgen::RenderError.new(e, 'content_processor.haml', context.dest_node, nil, line)
20
20
  end
21
21
 
22
22
  end
@@ -14,11 +14,12 @@ module Webgen
14
14
  # processor should be the last in the processing pipeline so that all other processors have been
15
15
  # able to set the data.
16
16
  #
17
- # Use the methods defined on the special Context#html_head object to provide values.
17
+ # Use the methods defined on the special Webgen::Context::HtmlHead::Proxy object which can be
18
+ # accessed via Webgen::Context#html_head to provide values.
18
19
  #
19
20
  # == Internal details
20
21
  #
21
- # The key ':cp_html_head' of 'context.persistent' is used (the normal 'context.options' won't do
22
+ # The key +:cp_html_head+ of +context.persistent+ is used (the normal +context.options+ won't do
22
23
  # because the data needs to be shared 'backwards' during the rendering) and it has to be a Hash
23
24
  # with the following values:
24
25
  #
@@ -85,7 +86,7 @@ module Webgen
85
86
  def self.links_to_translations(context)
86
87
  context.website.tree.translations(context.dest_node).map do |node|
87
88
  next '' if node.alcn == context.dest_node.alcn
88
- context.website.ext.item_tracker.add(context.dest_node, :node_meta_info, node.alcn)
89
+ context.website.ext.item_tracker.add(context.dest_node, :node_meta_info, node)
89
90
 
90
91
  result = "\n<link type=\"text/html\" rel=\"alternate\" hreflang=\"#{node.lang}\" "
91
92
  result << "href=\"#{context.dest_node.route_to(node)}\" "
@@ -103,7 +104,7 @@ module Webgen
103
104
  next path if Webgen::Path.url(path, false).absolute?
104
105
  node = context.content_node.resolve(path, context.dest_node.lang, true)
105
106
  if node
106
- context.website.ext.item_tracker.add(context.dest_node, :node_meta_info, node.alcn)
107
+ context.website.ext.item_tracker.add(context.dest_node, :node_meta_info, node)
107
108
  context.dest_node.route_to(node)
108
109
  else
109
110
  nil
@@ -35,7 +35,9 @@ module Webgen
35
35
 
36
36
  # Convert the content in +context+ to HTML.
37
37
  def self.call(context)
38
- doc = ::Kramdown::Document.new(context.content, context.website.config['content_processor.kramdown.options'])
38
+ options = context.website.config['content_processor.kramdown.options'].dup
39
+ options[:link_defs] = context.website.ext.link_definitions.merge(options[:link_defs] || {})
40
+ doc = ::Kramdown::Document.new(context.content, options)
39
41
  context.content = CustomHtmlConverter.new(doc.root, doc.options, context).convert(doc.root)
40
42
  doc.warnings.each do |warn|
41
43
  context.website.logger.warn { "kramdown warning while parsing <#{context.ref_node}>: #{warn}" }
@@ -1,18 +1,31 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  require 'webgen/content_processor'
4
- webgen_require 'rdoc/markup/to_html', 'rdoc'
4
+
5
+ ### Hack...
6
+ # Workaround to load the correct version of rdoc. Unusable versions don't have a rdoc/store file and
7
+ # so we can use this to our advantage.
8
+ begin
9
+ # If a useable version is available, this won't fail with a LoadError (but probably a NameError)
10
+ # and will activate the correct version, even if installed via Rubygems.
11
+ require 'rdoc/store'
12
+ rescue LoadError
13
+ webgen_require('rdoc/rdoc', 'rdoc')
14
+ rescue Exception
15
+ end
16
+ require 'rdoc/rdoc'
17
+
5
18
 
6
19
  module Webgen
7
20
  class ContentProcessor
8
21
 
9
22
  # Converts content in RDoc markup (the native Ruby documentation format) to HTML. Needs the newer
10
- # RDoc implementation (version >= 2.4.x).
23
+ # RDoc implementation (version >= 4.0.0).
11
24
  module RDoc
12
25
 
13
26
  # Convert the content in RDoc markup to HTML.
14
27
  def self.call(context)
15
- context.content = ::RDoc::Markup::ToHtml.new.convert(context.content)
28
+ context.content = ::RDoc::Markup::ToHtml.new(::RDoc::Options.new).convert(context.content)
16
29
  context
17
30
  end
18
31
 
@@ -110,7 +110,7 @@ module Webgen
110
110
 
111
111
  if ref_node
112
112
  if dest_node = ref_node.resolve(path, context.dest_node.lang, true)
113
- context.website.ext.item_tracker.add(context.dest_node, :node_meta_info, dest_node.alcn)
113
+ context.website.ext.item_tracker.add(context.dest_node, :node_meta_info, dest_node)
114
114
  path = context.dest_node.route_to(dest_node)
115
115
  end
116
116
  else
@@ -127,7 +127,7 @@ module Webgen
127
127
  context.content = ::Sass::Engine.new(context.content, default_options(context)).render
128
128
  context
129
129
  rescue ::Sass::SyntaxError => e
130
- raise Webgen::RenderError.new(e, self.class.name, context.dest_node, nil, (e.sass_line if e.sass_line))
130
+ raise Webgen::RenderError.new(e, 'content_processor.sass', context.dest_node, nil, (e.sass_line if e.sass_line))
131
131
  end
132
132
 
133
133
  def self.default_options(context) # :nodoc:
@@ -136,7 +136,7 @@ module Webgen
136
136
  opts.merge({
137
137
  :filename => context.ref_node.alcn,
138
138
  :syntax => :sass,
139
- :cache_store => ::Sass::CacheStores::Filesystem.new(context.website.tmpdir('sass')),
139
+ :cache_store => ::Sass::CacheStores::Filesystem.new(context.website.tmpdir('content_processor.sass')),
140
140
  :filesystem_importer => FileSystemImporter,
141
141
  :load_paths => load_paths,
142
142
  :webgen_context => context
@@ -14,7 +14,7 @@ module Webgen
14
14
  context.content = ::Sass::Engine.new(context.content, options).render
15
15
  context
16
16
  rescue ::Sass::SyntaxError => e
17
- raise Webgen::RenderError.new(e, self.class.name, context.dest_node, nil, (e.sass_line if e.sass_line))
17
+ raise Webgen::RenderError.new(e, 'content_processor.scss', context.dest_node, nil, (e.sass_line if e.sass_line))
18
18
  end
19
19
 
20
20
  end
@@ -56,7 +56,7 @@ module Webgen
56
56
  execute("pdflatex -shell-escape -interaction=nonstopmode -halt-on-error #{file}.tex", cwd, context) do |status, stdout, stderr|
57
57
  errors = (stdout+stderr).scan(/^!(.*\n.*)/).join("\n")
58
58
  raise Webgen::RenderError.new("Error while parsing TikZ picture commands with PDFLaTeX: #{errors}",
59
- self.name, context.dest_node, context.ref_node)
59
+ 'content_processor.tikz', context.dest_node, context.ref_node)
60
60
  end
61
61
 
62
62
  execute("pdfcrop #{file}.pdf #{file}.pdf", cwd, context)
@@ -93,7 +93,7 @@ module Webgen
93
93
  yield(status, stdout, stderr)
94
94
  else
95
95
  raise Webgen::RenderError.new("Error while running a command for a TikZ picture: #{stdout + "\n" + stderr}",
96
- self.name, context.dest_node, context.ref_node)
96
+ 'content_processor.tikz', context.dest_node, context.ref_node)
97
97
  end
98
98
  end
99
99
  [status, stdout, stderr]
@@ -43,7 +43,7 @@ module Webgen
43
43
  def type_check!(type) #:nodoc:
44
44
  if ![:css, :js].include?(type)
45
45
  raise Webgen::RenderError.new("Type must either be :css or :js, not #{type}",
46
- self.class.name, @context.dest_node, @context.ref_node)
46
+ "context.html_head", @context.dest_node, @context.ref_node)
47
47
  end
48
48
  end
49
49
  private :type_check!
@@ -37,7 +37,8 @@ module Webgen
37
37
  # Write the +data+ to the given +path+.
38
38
  def write(path, data)
39
39
  dest = File.join(@root, path)
40
- FileUtils.makedirs(File.dirname(dest))
40
+ parent_dir = File.dirname(dest)
41
+ FileUtils.makedirs(parent_dir) unless File.directory?(parent_dir)
41
42
  if path[-1] == ?/
42
43
  FileUtils.makedirs(dest)
43
44
  else
@@ -8,9 +8,9 @@ module Webgen
8
8
  # This class is used to track changes to the content of a node. The content of a node is changed
9
9
  # if any of its dependencies are changed.
10
10
  #
11
- # The item for this tracker is the alcn of the node:
11
+ # The item for this tracker is the node:
12
12
  #
13
- # website.ext.item_tracker.add(some_node, :node_content, my_node.alcn)
13
+ # website.ext.item_tracker.add(some_node, :node_content, my_node)
14
14
  #
15
15
  class NodeContent
16
16
 
@@ -18,8 +18,8 @@ module Webgen
18
18
  @website = website
19
19
  end
20
20
 
21
- def item_id(alcn) #:nodoc:
22
- alcn
21
+ def item_id(node) #:nodoc:
22
+ node.alcn
23
23
  end
24
24
 
25
25
  def item_data(alcn) #:nodoc:
@@ -9,17 +9,17 @@ module Webgen
9
9
  #
10
10
  # Depending on what should be tracked, one needs to provide the following item:
11
11
  #
12
- # [node_alcn, nil]
12
+ # [node, nil]
13
13
  # Tracks changes to the whole meta information of the node, i.e. if any meta information value
14
14
  # changes, a change is detected.
15
15
  #
16
- # [node_alcn, key]
16
+ # [node, key]
17
17
  # Tracks changes to a specific meta information key of the node.
18
18
  #
19
19
  # Here are some examples:
20
20
  #
21
- # website.ext.item_tracker.add(some_node, :node_meta_info, my_node.alcn) # first case
22
- # website.ext.item_tracker.add(some_node, :node_meta_info, my_node.alcn, 'title') # second case
21
+ # website.ext.item_tracker.add(some_node, :node_meta_info, my_node) # first case
22
+ # website.ext.item_tracker.add(some_node, :node_meta_info, my_node, 'title') # second case
23
23
  #
24
24
  class NodeMetaInfo
25
25
 
@@ -29,8 +29,8 @@ module Webgen
29
29
  @website = website
30
30
  end
31
31
 
32
- def item_id(alcn, key = nil) #:nodoc:
33
- [alcn, key]
32
+ def item_id(node, key = nil) #:nodoc:
33
+ [node.alcn, key]
34
34
  end
35
35
 
36
36
  def item_data(alcn, key = nil) #:nodoc:
@@ -51,7 +51,7 @@ module Webgen
51
51
  method_name, options, type = *iid
52
52
  nodes = node_list(method_name, options)
53
53
  old_data != nodes_to_alcn(nodes) ||
54
- nodes.flatten.any? {|n| type == :content ? @website.ext.item_tracker.node_changed?(n) : @website.ext.item_tracker.item_changed?(:node_meta_info, n.alcn)}
54
+ nodes.flatten.any? {|n| type == :content ? @website.ext.item_tracker.node_changed?(n) : @website.ext.item_tracker.item_changed?(:node_meta_info, n)}
55
55
  end
56
56
 
57
57
  def referenced_nodes(iid, alcn_list) #:nodoc:
@@ -12,6 +12,8 @@ module Webgen
12
12
  # information is available through the #[] and #meta_info accessors, the internal processing
13
13
  # information through the #node_info accessor.
14
14
  #
15
+ # This class is not directly used. Instead path handlers define sub-classes that provide handler
16
+ # specific methods. See the basic sub-class Webgen::PathHandler::Base::Node.
15
17
  class Node
16
18
 
17
19
  # The parent node. This is in all but one case a Node object. The one exception is that the
@@ -167,7 +169,8 @@ module Webgen
167
169
  # If the +lang+ parameter is not used, it defaults to the language of the current node.
168
170
  def route_to(node, lang = @lang)
169
171
  my_url = Webgen::Path.url(@dest_path)
170
- other_url = Webgen::Path.url(node.proxy_node(lang).dest_path)
172
+ pnode = node.proxy_node(lang)
173
+ other_url = Webgen::Path.url(pnode['routing_path'] || pnode.dest_path)
171
174
 
172
175
  # resolve any '.' and '..' paths in the target url
173
176
  if other_url.path =~ /\/\.\.?\// && other_url.scheme == 'webgen'
@@ -185,12 +188,7 @@ module Webgen
185
188
  #
186
189
  # If the +lang+ parameter is not used, it defaults to the language of the current node.
187
190
  def proxy_node(lang = @lang)
188
- proxy_path = self['proxy_path']
189
- if proxy_path.nil?
190
- self
191
- else
192
- resolve(proxy_path, lang, true) || self
193
- end
191
+ self['proxy_path'] && resolve(self['proxy_path'], lang, true) || self
194
192
  end
195
193
 
196
194
  # Return a HTML link from this node to the given node.
@@ -61,6 +61,9 @@ module Webgen
61
61
  # the value of this meta information is used for comparison of nodes (again, if both compared
62
62
  # values are integers, a numeric comparison is done, else a string comparison).
63
63
  #
64
+ # [:reverse]
65
+ # Value: +true+ of +false+/+nil+. If this option is set to +true+, the sort order is reversed.
66
+ #
64
67
  # === Filter options
65
68
  #
66
69
  # These options are used for filtering the nodes. All nodes are used by default if no filter
@@ -71,9 +74,9 @@ module Webgen
71
74
  # used.
72
75
  #
73
76
  # [:lang]
74
- # Value: a language code/+nil+/the special value :+node+ or an array of these values. Nodes that
77
+ # Value: a language code/+nil+/the special value +node+ or an array of these values. Nodes that
75
78
  # have one of the specified language codes, are language independent (in case of the value
76
- # +nil+) or have the same language as the reference node (in case of the value :+node+) are
79
+ # +nil+) or have the same language as the reference node (in case of the value +node+) are
77
80
  # used.
78
81
  #
79
82
  # [:mi]
@@ -97,6 +100,9 @@ module Webgen
97
100
  # and end levels). All nodes whose hierarchy level in the node tree are greater than or equal to
98
101
  # the start level and lower than or equal to the end level are used.
99
102
  #
103
+ # Negative numbers, where -1 stands for the reference node, -2 for its parent node and so on,
104
+ # can also be used.
105
+ #
100
106
  # [:ancestors]
101
107
  # Value: +true+ or +false+/+nil+. If this filter option is set to +true+, only nodes that are
102
108
  # ancestors of the reference node are used. The reference node itself is used as well.
@@ -106,8 +112,17 @@ module Webgen
106
112
  # descendants of the reference node are used. The reference node itself is used as well.
107
113
  #
108
114
  # [:siblings]
109
- # Value: +true+ or +false+/+nil+. If this filter option is set to +true+, only nodes that are
110
- # siblings of the reference are node used. The reference node itself is used as well.
115
+ # Value: +true+, +false+/+nil+, or an array with two integers. If this filter option is set to
116
+ # +true+, only nodes that are sibling node of the reference node are used. The reference node
117
+ # itself is used as well. If set to +false+ or +nil+, this filter is ignored.
118
+ #
119
+ # If an array with two numbers is specified, all sibling nodes of the reference node or its
120
+ # parent nodes the hierarchy level of which lies between these numbers are used. The parent
121
+ # nodes and the reference node are used as well if their level lies between the numbers.
122
+ # Counting starts at zero (the root node).
123
+ #
124
+ # Negative numbers, where -1 stands for the reference node, -2 for its parent node and so on,
125
+ # can also be used.
111
126
  #
112
127
  # == Implementing a filter module
113
128
  #
@@ -177,14 +192,14 @@ module Webgen
177
192
  end
178
193
  opts = prepare_options_hash(opts_or_name)
179
194
 
180
- limit, offset, flatten, sort, levels = remove_non_filter_options(opts)
195
+ limit, offset, flatten, sort, levels, reverse = remove_non_filter_options(opts)
181
196
  flatten = true if limit || offset
182
197
  levels = [levels || [1, 1_000_000]].flatten.map {|i| i.to_i}
183
198
 
184
199
  nodes = filter_nodes(opts, ref_node)
185
200
 
186
201
  if flatten
187
- sort_nodes(nodes, sort)
202
+ sort_nodes(nodes, sort, reverse)
188
203
  nodes = nodes[(offset.to_s.to_i)..(limit ? offset.to_s.to_i + limit.to_s.to_i - 1 : -1)] if limit || offset
189
204
  else
190
205
  result = {}
@@ -208,7 +223,7 @@ module Webgen
208
223
  end
209
224
  end
210
225
  nodes = reducer.call(result, 1)
211
- sort_nodes(nodes, sort, false)
226
+ sort_nodes(nodes, sort, reverse, false)
212
227
  end
213
228
 
214
229
  cache_result(opts_or_name, ref_node, nodes)
@@ -237,7 +252,8 @@ module Webgen
237
252
  end
238
253
 
239
254
  def remove_non_filter_options(opts)
240
- [opts.delete(:limit), opts.delete(:offset), opts.delete(:flatten), opts.delete(:sort), opts.delete(:levels)]
255
+ [opts.delete(:limit), opts.delete(:offset), opts.delete(:flatten),
256
+ opts.delete(:sort), opts.delete(:levels), opts.delete(:reverse)]
241
257
  end
242
258
 
243
259
  def filter_nodes(opts, ref_node)
@@ -255,23 +271,23 @@ module Webgen
255
271
  nodes
256
272
  end
257
273
 
258
- def sort_nodes(nodes, sort, flat_mode = true)
274
+ def sort_nodes(nodes, sort, reverse, flat_mode = true)
259
275
  return unless sort
260
276
  if sort == true
261
277
  nodes.sort! do |(a,_),(b,_)|
262
278
  a = (a['sort_info'] && a['sort_info'].to_s) || a['title'].to_s || ''
263
279
  b = (b['sort_info'] && b['sort_info'].to_s) || b['title'].to_s || ''
264
280
  (a = a.to_i; b = b.to_i) if a !~ /\D/ && b !~ /\D/
265
- a <=> b
281
+ (reverse ? b <=> a : a <=> b)
266
282
  end
267
283
  else
268
284
  nodes.sort! do |(a,_),(b,_)|
269
285
  a, b = a[sort].to_s, b[sort].to_s
270
286
  a, b = a.to_i, b.to_i if a !~ /\D/ && b !~ /\D/
271
- a <=> b
287
+ (reverse ? b <=> a : a <=> b)
272
288
  end
273
289
  end
274
- nodes.each {|n, children| sort_nodes(children, sort, flat_mode) if children } unless flat_mode
290
+ nodes.each {|n, children| sort_nodes(children, sort, reverse, flat_mode) if children } unless flat_mode
275
291
  end
276
292
 
277
293
  # :section: Filter methods
@@ -313,12 +329,12 @@ module Webgen
313
329
  end
314
330
 
315
331
  def filter_absolute_levels(nodes, ref_node, range)
316
- range = [range].flatten.map {|i| i.to_i}
332
+ range = [range].flatten.map {|i| (i = i.to_i) < 0 ? ref_node.level + 1 + i : i}
317
333
  nodes.keep_if {|n| n.level >= range.first && n.level <= range.last}
318
334
  end
319
335
 
320
336
  def filter_lang(nodes, ref_node, langs)
321
- langs = [langs].flatten.map {|l| l == :node ? ref_node.lang : l}.uniq
337
+ langs = [langs].flatten.map {|l| l == 'node' ? ref_node.lang : l}.uniq
322
338
  nodes.keep_if {|n| langs.any? {|l| n.lang == l}}
323
339
  end
324
340
 
@@ -341,9 +357,16 @@ module Webgen
341
357
  end
342
358
  end
343
359
 
344
- def filter_siblings(nodes, ref_node, enabled)
345
- return nodes unless enabled
346
- nodes.keep_if { |n| n.parent == ref_node.parent}
360
+ def filter_siblings(nodes, ref_node, value)
361
+ return nodes unless value
362
+ if value == true
363
+ nodes.keep_if {|n| n.parent == ref_node.parent}
364
+ else
365
+ value = [value].flatten.map {|i| (i = i.to_i) < 0 ? ref_node.level + 1 + i : i}
366
+ nodes.keep_if do |n|
367
+ n.level >= value.first && n.level <= value.last && (n.parent.is_ancestor_of?(ref_node) || n.is_root?)
368
+ end
369
+ end
347
370
  end
348
371
 
349
372
  end