webgen 0.5.2 → 0.5.3

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