webgen 0.5.2 → 0.5.3

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 (85) hide show
  1. data/Rakefile +15 -4
  2. data/VERSION +1 -1
  3. data/data/webgen/webgui/controller/main.rb +1 -1
  4. data/data/webgen/website_skeleton/ext/init.rb +6 -0
  5. data/data/webgen/website_styles/1024px/src/default.css +188 -188
  6. data/data/webgen/website_styles/1024px/src/default.template +51 -51
  7. data/data/webgen/website_styles/andreas00/src/default.template +1 -1
  8. data/data/webgen/website_styles/andreas01/src/default.css +8 -8
  9. data/data/webgen/website_styles/andreas01/src/default.template +1 -1
  10. data/data/webgen/website_styles/andreas03/src/default.css +3 -3
  11. data/data/webgen/website_styles/andreas03/src/default.template +2 -2
  12. data/data/webgen/website_styles/andreas04/src/default.css +1 -1
  13. data/data/webgen/website_styles/andreas05/src/default.css +3 -3
  14. data/data/webgen/website_styles/andreas05/src/default.template +26 -26
  15. data/data/webgen/website_styles/andreas06/src/default.css +6 -6
  16. data/data/webgen/website_styles/andreas06/src/default.template +1 -1
  17. data/data/webgen/website_styles/andreas07/src/default.css +6 -6
  18. data/data/webgen/website_styles/andreas08/src/default.css +7 -7
  19. data/data/webgen/website_styles/andreas08/src/default.template +2 -2
  20. data/data/webgen/website_styles/andreas09/src/default.css +3 -3
  21. data/data/webgen/website_styles/andreas09/src/default.template +1 -1
  22. data/data/webgen/website_styles/simple/src/default.css +84 -84
  23. data/data/webgen/website_styles/simple/src/default.template +1 -1
  24. data/doc/index.page +27 -12
  25. data/doc/manual.page +52 -10
  26. data/doc/reference_configuration.page +108 -52
  27. data/doc/reference_metainfo.page +77 -2
  28. data/doc/sourcehandler/feed.page +82 -0
  29. data/doc/sourcehandler/metainfo.page +3 -2
  30. data/doc/sourcehandler/sitemap.page +46 -0
  31. data/doc/tag.template +2 -3
  32. data/doc/tag/breadcrumbtrail.page +11 -3
  33. data/doc/tag/menu.page +6 -4
  34. data/doc/tag/sitemap.page +31 -0
  35. data/doc/upgrading.page +67 -0
  36. data/lib/webgen/cli/utils.rb +4 -4
  37. data/lib/webgen/cli/webgui_command.rb +2 -1
  38. data/lib/webgen/common.rb +10 -0
  39. data/lib/webgen/common/sitemap.rb +76 -0
  40. data/lib/webgen/configuration.rb +64 -1
  41. data/lib/webgen/contentprocessor.rb +1 -1
  42. data/lib/webgen/contentprocessor/builder.rb +1 -1
  43. data/lib/webgen/contentprocessor/erb.rb +1 -1
  44. data/lib/webgen/contentprocessor/haml.rb +1 -1
  45. data/lib/webgen/contentprocessor/maruku.rb +1 -1
  46. data/lib/webgen/contentprocessor/sass.rb +1 -1
  47. data/lib/webgen/coreext.rb +10 -0
  48. data/lib/webgen/default_config.rb +35 -4
  49. data/lib/webgen/node.rb +12 -6
  50. data/lib/webgen/page.rb +1 -1
  51. data/lib/webgen/path.rb +1 -1
  52. data/lib/webgen/sourcehandler.rb +11 -6
  53. data/lib/webgen/sourcehandler/base.rb +5 -2
  54. data/lib/webgen/sourcehandler/feed.rb +121 -0
  55. data/lib/webgen/sourcehandler/metainfo.rb +22 -13
  56. data/lib/webgen/sourcehandler/page.rb +5 -3
  57. data/lib/webgen/sourcehandler/sitemap.rb +60 -0
  58. data/lib/webgen/sourcehandler/template.rb +5 -1
  59. data/lib/webgen/sourcehandler/virtual.rb +1 -0
  60. data/lib/webgen/tag.rb +1 -0
  61. data/lib/webgen/tag/breadcrumbtrail.rb +42 -10
  62. data/lib/webgen/tag/langbar.rb +1 -1
  63. data/lib/webgen/tag/menu.rb +10 -14
  64. data/lib/webgen/tag/sitemap.rb +42 -0
  65. data/lib/webgen/tree.rb +1 -1
  66. data/lib/webgen/version.rb +1 -1
  67. data/lib/webgen/website.rb +5 -6
  68. data/misc/default.css +6 -2
  69. data/test/helper.rb +13 -0
  70. data/test/test_common_sitemap.rb +56 -0
  71. data/test/test_configuration.rb +24 -0
  72. data/test/test_contentprocessor_maruku.rb +4 -1
  73. data/test/test_node.rb +4 -1
  74. data/test/test_page.rb +11 -5
  75. data/test/test_path.rb +10 -10
  76. data/test/test_sourcehandler_feed.rb +74 -0
  77. data/test/test_sourcehandler_metainfo.rb +26 -12
  78. data/test/test_sourcehandler_page.rb +1 -0
  79. data/test/test_sourcehandler_sitemap.rb +47 -0
  80. data/test/test_sourcehandler_template.rb +3 -0
  81. data/test/test_sourcehandler_virtual.rb +4 -1
  82. data/test/test_tag_breadcrumbtrail.rb +33 -23
  83. data/test/test_tag_menu.rb +24 -25
  84. data/test/test_tag_sitemap.rb +44 -0
  85. metadata +37 -4
@@ -0,0 +1,121 @@
1
+ require 'webgen/websiteaccess'
2
+ require 'webgen/sourcehandler/base'
3
+
4
+ module Webgen::SourceHandler
5
+
6
+ # Source handler for creating atom and/or rss feeds.
7
+ class Feed
8
+
9
+ include Webgen::WebsiteAccess
10
+ include Base
11
+
12
+ # The mandatory keys that need to be set in a feed file.
13
+ MANDATORY_INFOS = %W[site_url author entries]
14
+
15
+ def initialize # :nodoc:
16
+ website.blackboard.add_listener(:node_changed?, method(:node_changed?))
17
+ end
18
+
19
+ # Create atom and/or rss feed files from +parent+ and +path+.
20
+ def create_node(parent, path)
21
+ page = page_from_path(path)
22
+ path.meta_info['link'] ||= parent.absolute_lcn
23
+
24
+ if MANDATORY_INFOS.any? {|t| path.meta_info[t].nil?}
25
+ raise "One of #{MANDATORY_INFOS.join('/')} information missing for feed <#{path}>"
26
+ end
27
+
28
+ create_feed_node = lambda do |type|
29
+ path.ext = type
30
+ super(parent, path) do |node|
31
+ node.node_info[:feed] = page
32
+ node.node_info[:feed_type] = type
33
+ end
34
+ end
35
+
36
+ nodes = []
37
+ nodes << create_feed_node['atom'] if path.meta_info['atom']
38
+ nodes << create_feed_node['rss'] if path.meta_info['rss']
39
+
40
+ nodes
41
+ end
42
+
43
+ # Return the rendered feed represented by +node+.
44
+ def content(node)
45
+ website.cache[[:sourcehandler_feed, node.node_info[:src]]] = feed_entries(node).map {|n| n.absolute_lcn}
46
+ block_name = node.node_info[:feed_type] + '_template'
47
+ if node.node_info[:feed].blocks.has_key?(block_name)
48
+ node.node_info[:feed].blocks[block_name].
49
+ render(Webgen::ContentProcessor::Context.new(:chain => [node])).content
50
+ else
51
+ feed = (website.cache.volatile[:sourcehandler_feed] ||= {})[node.node_info[:src]] ||= build_feed_for(node)
52
+ feed.feed_type = node.node_info[:feed_type]
53
+ feed.build_xml
54
+ end
55
+ end
56
+
57
+ # Helper method for returning the entries for the feed node +node+.
58
+ def feed_entries(node)
59
+ nr_items = (node['number_of_entries'].to_i == 0 ? 10 : node['number_of_entries'].to_i)
60
+ patterns = [node['entries']].flatten.map {|pat| Pathname.new(pat =~ /^\// ? pat : File.join(node.parent.absolute_lcn, pat)).cleanpath.to_s}
61
+
62
+ node.tree.node_access[:alcn].values.
63
+ select {|node| patterns.any? {|pat| node =~ pat} && node.node_info[:page]}.
64
+ sort {|a,b| a['modified_at'] <=> b['modified_at']}.
65
+ reverse[0, nr_items]
66
+ end
67
+
68
+ #######
69
+ private
70
+ #######
71
+
72
+ # Return the populated FeedTools::Feed object for +node+.
73
+ def build_feed_for(node)
74
+ require 'feed_tools'
75
+ require 'time'
76
+
77
+ site_url = node['site_url']
78
+
79
+ feed = FeedTools::Feed.new
80
+ feed.title = node['title']
81
+ feed.description = node['description']
82
+ feed.author = node['author']
83
+ feed.author.url = node['author_url']
84
+ feed.base_uri = site_url
85
+ feed.link = File.join(site_url, node.tree[node['link']].path)
86
+ feed.id = feed.link
87
+
88
+ feed.published = (node['created_at'].kind_of?(Time) ? node['created_at'] : Time.now)
89
+ feed.updated = Time.now
90
+ feed.generator = 'webgen - Webgen::SourceHandler::Feed'
91
+ feed.icon = File.join(site_url, node.tree[node['icon']].path) if node['icon']
92
+
93
+ node.feed_entries.each do |entry|
94
+ item = FeedTools::FeedItem.new
95
+ item.title = entry['title']
96
+ item.link = File.join(site_url, entry.path)
97
+ item.content = entry.node_info[:page].blocks['content'].render(Webgen::ContentProcessor::Context.new(:chain => [entry])).content
98
+ item.updated = entry['modified_at']
99
+ item.published = entry['created_at'] if entry['created_at'].kind_of?(Time)
100
+ if entry['author']
101
+ item.author = entry['author']
102
+ item.author.url = entry['author_url']
103
+ end
104
+ item.id = item.link
105
+ feed << item
106
+ end
107
+ feed
108
+ end
109
+
110
+ # Check if the +node+ has meta information from any meta info node and if so, if the meta info
111
+ # node in question has changed.
112
+ def node_changed?(node)
113
+ return if node.node_info[:processor] != self.class.name
114
+ entries = node.feed_entries
115
+ node.dirty = true if entries.map {|n| n.absolute_lcn } != website.cache[[:sourcehandler_feed, node.node_info[:src]]] ||
116
+ entries.any? {|n| n.changed?}
117
+ end
118
+
119
+ end
120
+
121
+ end
@@ -15,7 +15,7 @@ module Webgen::SourceHandler
15
15
 
16
16
  # Upon creation the object registers itself as listener for some node hooks.
17
17
  def initialize
18
- website.blackboard.add_listener(:node_changed?, method(:node_changed?))
18
+ website.blackboard.add_listener(:node_meta_info_changed?, method(:node_meta_info_changed?))
19
19
  website.blackboard.add_listener(:before_node_created, method(:before_node_created))
20
20
  website.blackboard.add_listener(:before_node_deleted, method(:before_node_deleted))
21
21
  website.blackboard.add_listener(:after_node_created, method(:after_node_created))
@@ -30,9 +30,14 @@ module Webgen::SourceHandler
30
30
  node.node_info[mi_key] = {}
31
31
  YAML::load(page.blocks[block_name].content).each do |key, value|
32
32
  key = Pathname.new(key =~ /^\// ? key : File.join(parent.absolute_lcn, key)).cleanpath.to_s
33
- node.node_info[mi_key][key.chomp('/')] = value
33
+ key.chomp('/') unless key == '/'
34
+ node.node_info[mi_key][key] = value
34
35
  end if page.blocks.has_key?(block_name)
35
36
  end
37
+ website.cache[[:sh_metainfo_node_mi, node.absolute_lcn]] = {
38
+ :mi_paths => node.node_info[:mi_paths],
39
+ :mi_alcn => node.node_info[:mi_alcn]
40
+ }
36
41
 
37
42
  mark_all_matched_dirty(node)
38
43
 
@@ -53,13 +58,20 @@ module Webgen::SourceHandler
53
58
  private
54
59
  #######
55
60
 
61
+ # Return +true+ if any meta information for +node+ provided by +mi_node+ has changed.
62
+ def meta_info_changed?(mi_node, node, use_cache = true)
63
+ use_cache = false if !website.cache.old_data[[:sh_metainfo_node_mi, mi_node.absolute_lcn]]
64
+ cached = website.cache[[:sh_metainfo_node_mi, mi_node.absolute_lcn]]
65
+ path = website.blackboard.invoke(:source_paths)[node.node_info[:src]]
66
+ (mi_node.node_info[:mi_paths].any? {|pattern, mi| path =~ pattern && (!use_cache || mi != cached[:mi_paths][pattern])} ||
67
+ mi_node.node_info[:mi_alcn].any? {|pattern, mi| node =~ pattern && (!use_cache || mi != cached[:mi_alcn][pattern])})
68
+ end
69
+
56
70
  # Mark all nodes that are matched by a path or an alcn specifcation in the meta info node +node+
57
71
  # as dirty.
58
- def mark_all_matched_dirty(node)
59
- source_paths = website.blackboard.invoke(:source_paths)
72
+ def mark_all_matched_dirty(node, use_cache = true)
60
73
  node.tree.node_access[:alcn].each do |path, n|
61
- n.dirty = true if node.node_info[:mi_paths].any? {|pattern, mi| source_paths[n.node_info[:src]] =~ pattern }
62
- n.dirty = true if node.node_info[:mi_alcn].any? {|pattern, mi| n =~ pattern }
74
+ n.dirty_meta_info = true if meta_info_changed?(node, n, use_cache)
63
75
  end
64
76
  end
65
77
 
@@ -83,14 +95,11 @@ module Webgen::SourceHandler
83
95
 
84
96
  # Check if the +node+ has meta information from any meta info node and if so, if the meta info
85
97
  # node in question has changed.
86
- def node_changed?(node)
98
+ def node_meta_info_changed?(node)
87
99
  return if self.nodes.include?(node)
88
- path = website.blackboard.invoke(:source_paths)[node.node_info[:src]]
89
100
  self.nodes.each do |n|
90
- if n.changed? &&
91
- (n.node_info[:mi_paths].any? {|pattern, mi| path =~ pattern} ||
92
- n.node_info[:mi_alcn].any? {|pattern, mi| node =~ pattern})
93
- node.dirty = true
101
+ if n.created && meta_info_changed?(n, node)
102
+ node.dirty_meta_info = true
94
103
  return
95
104
  end
96
105
  end
@@ -99,7 +108,7 @@ module Webgen::SourceHandler
99
108
  # Delete the meta info node +node+ from the internal array.
100
109
  def before_node_deleted(node)
101
110
  return unless node.node_info[:processor] == self.class.name
102
- mark_all_matched_dirty(node)
111
+ mark_all_matched_dirty(node, false) if !website.blackboard.invoke(:source_paths).include?(node.node_info[:src])
103
112
  self.nodes.delete(node)
104
113
  end
105
114
 
@@ -65,9 +65,11 @@ module Webgen::SourceHandler
65
65
  def meta_info_changed?(node)
66
66
  return if !node.created || node.node_info[:processor] != self.class.name
67
67
  ckey = [:sh_page_node_mi, node.absolute_lcn]
68
- if website.cache.old_data[ckey] != website.cache.new_data[ckey]
69
- node.dirty_meta_info = true
70
- end
68
+ old_mi = website.cache.old_data[ckey]
69
+ old_mi.delete('modified_at') if old_mi
70
+ new_mi = website.cache.new_data[ckey]
71
+ new_mi.delete('modified_at')
72
+ node.dirty_meta_info = true if old_mi != new_mi
71
73
  end
72
74
 
73
75
  end
@@ -0,0 +1,60 @@
1
+ require 'webgen/websiteaccess'
2
+ require 'webgen/sourcehandler/base'
3
+ require 'uri'
4
+ require 'time'
5
+
6
+ module Webgen::SourceHandler
7
+
8
+ # Source handler for creating an XML sitemap based on the specification of http://sitemaps.org.
9
+ #
10
+ # Uses Webgen::Common::Sitemap to generate the needed sitemap tree and to check if a sitemap has
11
+ # changed.
12
+ class Sitemap
13
+
14
+ include Webgen::WebsiteAccess
15
+ include Base
16
+
17
+ # Create an XML sitemap from +parent+ and +path+.
18
+ def create_node(parent, path)
19
+ page_from_path(path)
20
+ path.ext = 'xml'
21
+ raise "Needed information site_url missing for sitemap <#{path}>" if path.meta_info['site_url'].nil?
22
+ super(parent, path)
23
+ end
24
+
25
+ # Return the rendered feed represented by +node+.
26
+ def content(node)
27
+ require 'builder'
28
+ list = website.blackboard.invoke(:create_sitemap, node, node.lang, options_for_node(node)).to_lcn_list.flatten
29
+ sitemap = ::Builder::XmlMarkup.new(:indent => 2)
30
+ sitemap.instruct!(:xml, :version => '1.0', :encoding => 'UTF-8')
31
+ sitemap.urlset(:xmlns => "http://www.sitemaps.org/schemas/sitemap/0.9") do
32
+ list.each do |alcn|
33
+ item = node.tree[alcn]
34
+ sitemap.url do |url|
35
+ sitemap.loc(URI.escape(File.join(node['site_url'], item.path)))
36
+ sitemap.lastmod(item['modified_at'].iso8601)
37
+ changefreq = item['change_freq'] || node['default_change_freq']
38
+ sitemap.changefreq(changefreq) if changefreq
39
+ priority = item['priority'] || node['default_priority']
40
+ sitemap.priority(priority) if priority
41
+ end
42
+ end
43
+ end
44
+ sitemap.target!
45
+ end
46
+
47
+ #######
48
+ private
49
+ #######
50
+
51
+ # Return a hash with the sitemap-creation-options set on the +node+.
52
+ def options_for_node(node)
53
+ options = {}
54
+ node.meta_info.each {|k,v| options[k] = v if k =~ /\./}
55
+ options
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -35,7 +35,11 @@ module Webgen::SourceHandler
35
35
  template_node = cached_template[lang] = nil
36
36
  else
37
37
  log(:info) { "Using default template in language '#{lang}' for <#{node.absolute_lcn}>" }
38
- template_node = cached_template[lang] = default_template(node.parent, lang)
38
+ template_node = default_template(node.parent, lang)
39
+ if template_node == node && !node.parent.is_root?
40
+ template_node = default_template(node.parent.parent, lang)
41
+ end
42
+ cached_template[lang] = template_node
39
43
  end
40
44
 
41
45
  if template_node.nil?
@@ -23,6 +23,7 @@ module Webgen::SourceHandler
23
23
 
24
24
  temp_path = Webgen::Path.new(key)
25
25
  temp_path.meta_info.update(value || {})
26
+ temp_path.meta_info['modified_at'] = path.meta_info['modified_at']
26
27
  temp_path.meta_info['no_output'] = true
27
28
  output_path = temp_path.meta_info.delete('url') || key
28
29
  output_path = (output_path =~ /^\// ? output_path : File.join(temp_parent.absolute_lcn, output_path))
@@ -16,6 +16,7 @@ module Webgen
16
16
  autoload :ExecuteCommand, 'webgen/tag/executecommand'
17
17
  autoload :Coderay, 'webgen/tag/coderay'
18
18
  autoload :Date, 'webgen/tag/date'
19
+ autoload :Sitemap, 'webgen/tag/sitemap'
19
20
 
20
21
  end
21
22
 
@@ -1,3 +1,4 @@
1
+ require 'webgen/websiteaccess'
1
2
  require 'webgen/tag'
2
3
 
3
4
  module Webgen::Tag
@@ -6,13 +7,31 @@ module Webgen::Tag
6
7
  # hierarchies of directories.
7
8
  class BreadcrumbTrail
8
9
 
9
- include Webgen::Tag::Base
10
+ include Webgen::WebsiteAccess
11
+ include Base
12
+
13
+ def initialize #:nodoc:
14
+ website.blackboard.add_listener(:node_changed?, method(:node_changed?))
15
+ end
10
16
 
11
17
  # Create the breadcrumb trail.
12
18
  def call(tag, body, context)
13
- out = []
14
- node = context.content_node
19
+ out = breadcrumb_trail_list(context.content_node)
20
+ (context.dest_node.node_info[:tag_breadcrumb_trail] ||= {})[[@params.to_a.sort, context.content_node.absolute_lcn]] = out.map {|n| n.absolute_lcn}
21
+ out = out.map {|n| context.dest_node.link_to(n, :lang => context.content_node.lang) }.
22
+ join(param('tag.breadcrumbtrail.separator'))
23
+ log(:debug) { "Breadcrumb trail for <#{context.content_node.absolute_lcn}>: #{out}" }
24
+ out
25
+ end
26
+
27
+ #######
28
+ private
29
+ #######
15
30
 
31
+ # Return the list of nodes that make up the breadcrumb trail of +node+ according to the current
32
+ # parameters.
33
+ def breadcrumb_trail_list(node)
34
+ list = []
16
35
  omit_index_path = if node.meta_info.has_key?('omit_index_path')
17
36
  node['omit_index_path']
18
37
  else
@@ -23,15 +42,28 @@ module Webgen::Tag
23
42
  node = node.parent if omit_index_path
24
43
 
25
44
  until node == node.tree.dummy_root
26
- context.dest_node.node_info[:used_meta_info_nodes] << node.routing_node(context.dest_node.lang).absolute_lcn
27
- context.dest_node.node_info[:used_meta_info_nodes] << node.absolute_lcn
28
- out.push(context.dest_node.link_to(node.in_lang(context.content_node.lang)))
45
+ list.unshift(node)
29
46
  node = node.parent
30
47
  end
31
- out[0] = '' if param('tag.breadcrumbtrail.omit_last') && !omit_index_path
32
- out = out.reverse.join(param('tag.breadcrumbtrail.separator'))
33
- log(:debug) { "Breadcrumb trail for <#{context.dest_node.absolute_lcn}>: #{out}" }
34
- out
48
+ list[param('tag.breadcrumbtrail.start_level')..param('tag.breadcrumbtrail.end_level')].to_a
49
+ end
50
+
51
+ # Check if the breadcrumb trails for +node+ have changed.
52
+ def node_changed?(node)
53
+ return if !node.node_info[:tag_breadcrumb_trail]
54
+
55
+ node.node_info[:tag_breadcrumb_trail].each do |(params, cn_alcn), cached_list|
56
+ cn = node.tree[cn_alcn]
57
+ set_params(params.to_hash)
58
+ list = breadcrumb_trail_list(cn)
59
+ set_params({})
60
+
61
+ if (list.map {|n| n.absolute_lcn} != cached_list) ||
62
+ list.any? {|n| (r = n.routing_node(cn.lang)) && r != node && r.meta_info_changed?}
63
+ node.dirty = true
64
+ break
65
+ end
66
+ end
35
67
  end
36
68
 
37
69
  end
@@ -20,7 +20,7 @@ module Webgen::Tag
20
20
  result = lang_nodes.
21
21
  reject {|n| (context.content_node.lang == n.lang && !param('tag.langbar.show_own_lang'))}.
22
22
  sort {|a, b| a.lang <=> b.lang}.
23
- collect {|n| context.dest_node.link_to(n, :link_text => n.lang)}.
23
+ collect {|n| context.dest_node.link_to(n, :link_text => n.lang, :lang => n.lang)}.
24
24
  join(param('tag.langbar.separator'))
25
25
  (param('tag.langbar.show_single_lang') || lang_nodes.length > 1 ? result : "")
26
26
  end
@@ -58,12 +58,8 @@ module Webgen::Tag
58
58
  def call(tag, body, context)
59
59
  tree = specific_menu_tree_for(context.content_node)
60
60
 
61
- (context.dest_node.node_info[:tag_menu_menus] ||= []) << [@params, context.content_node.absolute_lcn, (tree ? tree.to_lcn_list : nil)]
62
- if tree && !tree.children.empty?
63
- "<div class=\"webgen-menu\">#{create_output(context, tree)}</div>"
64
- else
65
- ""
66
- end
61
+ (context.dest_node.node_info[:tag_menu_menus] ||= {})[[@params.to_a.sort, context.content_node.absolute_lcn]] = (tree ? tree.to_lcn_list : nil)
62
+ (tree && !tree.children.empty? ? create_output(context, tree) : '')
67
63
  end
68
64
 
69
65
  #########
@@ -75,11 +71,11 @@ module Webgen::Tag
75
71
  return if !node.node_info[:tag_menu_menus] || @inside_node_changed
76
72
 
77
73
  @inside_node_changed = true #TODO: better solution for this race condition?
78
- node.node_info[:tag_menu_menus].each do |params, cn_alcn, cached_tree|
74
+ node.node_info[:tag_menu_menus].each do |(params, cn_alcn), cached_tree|
79
75
  cn = node.tree[cn_alcn]
80
76
  menu_tree = menu_tree_for_lang(cn.lang, cn.tree.root)
81
77
 
82
- set_params(params)
78
+ set_params(params.to_hash)
83
79
  tree = build_specific_menu_tree(cn, menu_tree)
84
80
  tree_list = tree.to_lcn_list if tree
85
81
  set_params({})
@@ -134,11 +130,11 @@ module Webgen::Tag
134
130
  end
135
131
 
136
132
  # Create the HTML menu of the +tree+ using the provided +context+.
137
- def create_output(context, tree)
133
+ def create_output(context, tree, level = 1)
138
134
  out = "<ul>"
139
135
  tree.children.each do |child|
140
- menu = child.children.length > 0 ? create_output(context, child) : ''
141
- style, link = menu_item_details(context.dest_node, child.node, context.content_node.lang)
136
+ menu = child.children.length > 0 ? create_output(context, child, level + 1) : ''
137
+ style, link = menu_item_details(context.dest_node, child.node, context.content_node.lang, level)
142
138
 
143
139
  out << "<li #{style}>#{link}"
144
140
  out << menu
@@ -149,15 +145,15 @@ module Webgen::Tag
149
145
  end
150
146
 
151
147
  # Return style information (node is selected, ...) and a link from +dest_node+ to +node+.
152
- def menu_item_details(dest_node, node, lang)
153
- styles = []
148
+ def menu_item_details(dest_node, node, lang, level)
149
+ styles = ['webgen-menu-level' + level.to_s]
154
150
  styles << 'webgen-menu-submenu' if node.is_directory? || (node.is_fragment? && node.children.length > 0)
155
151
  styles << 'webgen-menu-submenu-inhierarchy' if (node.is_directory? || (node.is_fragment? && node.children.length > 0)) &&
156
152
  dest_node.in_subtree_of?(node)
157
153
  styles << 'webgen-menu-item-selected' if node == dest_node
158
154
  style = "class=\"#{styles.join(' ')}\"" if styles.length > 0
159
155
 
160
- link = dest_node.link_to(node)
156
+ link = dest_node.link_to(node, :lang => lang)
161
157
 
162
158
  [style, link]
163
159
  end