gettalong-webgen 0.5.8.20090507 → 0.5.9.20090620

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 (104) hide show
  1. data/Rakefile +5 -6
  2. data/data/webgen/passive_sources/images/generated_by_webgen.png +0 -0
  3. data/data/webgen/passive_sources/images/webgen_logo.png +0 -0
  4. data/data/webgen/passive_sources/templates/atom_feed.template +38 -0
  5. data/data/webgen/passive_sources/templates/rss_feed.template +28 -0
  6. data/data/webgen/resources.yaml +2 -1
  7. data/doc/contentprocessor/builder.page +1 -1
  8. data/doc/contentprocessor/erb.page +5 -2
  9. data/doc/contentprocessor/erubis.page +2 -2
  10. data/doc/extensions.page +1 -1
  11. data/doc/manual.page +56 -26
  12. data/doc/reference_configuration.page +36 -1
  13. data/doc/reference_website_styles.page +1 -1
  14. data/doc/sourcehandler/feed.page +6 -11
  15. data/doc/tag/includefile.page +1 -1
  16. data/lib/webgen/cli/apply_command.rb +1 -1
  17. data/lib/webgen/cli/utils.rb +2 -2
  18. data/lib/webgen/common.rb +0 -9
  19. data/lib/webgen/contentprocessor/blocks.rb +60 -36
  20. data/lib/webgen/contentprocessor/builder.rb +2 -2
  21. data/lib/webgen/contentprocessor/erb.rb +3 -2
  22. data/lib/webgen/contentprocessor/erubis.rb +2 -2
  23. data/lib/webgen/contentprocessor/haml.rb +2 -2
  24. data/lib/webgen/contentprocessor/maruku.rb +1 -1
  25. data/lib/webgen/contentprocessor/sass.rb +2 -2
  26. data/lib/webgen/contentprocessor/tags.rb +25 -11
  27. data/lib/webgen/context.rb +4 -1
  28. data/lib/webgen/context/render.rb +32 -0
  29. data/lib/webgen/context/tags.rb +20 -0
  30. data/lib/webgen/default_config.rb +4 -1
  31. data/lib/webgen/deprecated.rb +37 -4
  32. data/lib/webgen/node.rb +37 -38
  33. data/lib/webgen/path.rb +151 -54
  34. data/lib/webgen/source.rb +6 -6
  35. data/lib/webgen/source/stacked.rb +13 -5
  36. data/lib/webgen/sourcehandler.rb +71 -45
  37. data/lib/webgen/sourcehandler/base.rb +51 -21
  38. data/lib/webgen/sourcehandler/copy.rb +4 -4
  39. data/lib/webgen/sourcehandler/directory.rb +3 -9
  40. data/lib/webgen/sourcehandler/feed.rb +23 -49
  41. data/lib/webgen/sourcehandler/fragment.rb +10 -8
  42. data/lib/webgen/sourcehandler/memory.rb +9 -10
  43. data/lib/webgen/sourcehandler/metainfo.rb +9 -9
  44. data/lib/webgen/sourcehandler/page.rb +5 -5
  45. data/lib/webgen/sourcehandler/sitemap.rb +3 -3
  46. data/lib/webgen/sourcehandler/template.rb +6 -6
  47. data/lib/webgen/sourcehandler/virtual.rb +19 -17
  48. data/lib/webgen/tag/base.rb +34 -26
  49. data/lib/webgen/tag/breadcrumbtrail.rb +3 -3
  50. data/lib/webgen/tag/executecommand.rb +3 -3
  51. data/lib/webgen/tag/langbar.rb +2 -2
  52. data/lib/webgen/tag/link.rb +3 -3
  53. data/lib/webgen/tag/menu.rb +2 -2
  54. data/lib/webgen/tag/metainfo.rb +1 -1
  55. data/lib/webgen/tag/relocatable.rb +17 -21
  56. data/lib/webgen/tag/tikz.rb +5 -6
  57. data/lib/webgen/tree.rb +7 -7
  58. data/lib/webgen/version.rb +1 -1
  59. data/lib/webgen/website.rb +4 -2
  60. data/misc/default.css +8 -2
  61. data/misc/default.template +2 -2
  62. data/misc/logo.svg +313 -0
  63. data/misc/style.page +1 -1
  64. data/test/helper.rb +2 -2
  65. data/test/test_common_sitemap.rb +1 -1
  66. data/test/test_contentprocessor_blocks.rb +12 -4
  67. data/test/test_contentprocessor_builder.rb +2 -1
  68. data/test/test_contentprocessor_erb.rb +2 -1
  69. data/test/test_contentprocessor_erubis.rb +1 -1
  70. data/test/test_contentprocessor_fragments.rb +12 -11
  71. data/test/test_contentprocessor_haml.rb +2 -1
  72. data/test/test_contentprocessor_maruku.rb +1 -0
  73. data/test/test_contentprocessor_rdiscount.rb +1 -0
  74. data/test/test_contentprocessor_rdoc.rb +1 -0
  75. data/test/test_contentprocessor_sass.rb +1 -0
  76. data/test/test_contentprocessor_tags.rb +13 -0
  77. data/test/test_context.rb +28 -0
  78. data/test/test_node.rb +40 -20
  79. data/test/test_path.rb +106 -65
  80. data/test/test_source_filesystem.rb +1 -1
  81. data/test/test_source_stacked.rb +19 -6
  82. data/test/test_sourcehandler_base.rb +53 -47
  83. data/test/test_sourcehandler_copy.rb +6 -6
  84. data/test/test_sourcehandler_directory.rb +8 -12
  85. data/test/test_sourcehandler_feed.rb +10 -6
  86. data/test/test_sourcehandler_fragment.rb +6 -5
  87. data/test/test_sourcehandler_main.rb +39 -0
  88. data/test/test_sourcehandler_memory.rb +4 -4
  89. data/test/test_sourcehandler_metainfo.rb +10 -10
  90. data/test/test_sourcehandler_page.rb +9 -9
  91. data/test/test_sourcehandler_sitemap.rb +4 -4
  92. data/test/test_sourcehandler_template.rb +14 -14
  93. data/test/test_sourcehandler_virtual.rb +9 -5
  94. data/test/test_tag_base.rb +2 -2
  95. data/test/test_tag_executecommand.rb +1 -1
  96. data/test/test_tag_link.rb +4 -3
  97. data/test/test_tag_menu.rb +15 -15
  98. data/test/test_tag_metainfo.rb +1 -0
  99. data/test/test_tag_relocatable.rb +2 -1
  100. data/test/test_tag_tikz.rb +3 -3
  101. data/test/test_tree.rb +8 -8
  102. data/test/test_website.rb +15 -0
  103. metadata +14 -14
  104. data/test/test_common.rb +0 -18
@@ -19,11 +19,11 @@ module Webgen::ContentProcessor
19
19
  dest_node = deprecate('dest_node', 'context.dest_node', context.dest_node)
20
20
 
21
21
  xml = ::Builder::XmlMarkup.new(:indent => 2)
22
- eval(context.content, binding, context.ref_node.absolute_lcn)
22
+ eval(context.content, binding, context.ref_node.alcn)
23
23
  context.content = xml.target!
24
24
  context
25
25
  rescue Exception => e
26
- raise RuntimeError, "Error using Builder in <#{context.ref_node.absolute_lcn}> to generate XML: #{e.message}", e.backtrace
26
+ raise RuntimeError, "Error using Builder in <#{context.ref_node.alcn}> to generate XML: #{e.message}", e.backtrace
27
27
  end
28
28
 
29
29
  end
@@ -10,6 +10,7 @@ module Webgen::ContentProcessor
10
10
  # Process the Ruby statements embedded in the content of +context+.
11
11
  def call(context)
12
12
  require 'erb'
13
+ extend(ERB::Util)
13
14
 
14
15
  website = deprecate('website', 'context.website', context.website)
15
16
  node = deprecate('node', 'context.node', context.content_node)
@@ -17,11 +18,11 @@ module Webgen::ContentProcessor
17
18
  dest_node = deprecate('dest_node', 'context.dest_node', context.dest_node)
18
19
 
19
20
  erb = ERB.new(context.content)
20
- erb.filename = context.ref_node.absolute_lcn
21
+ erb.filename = context.ref_node.alcn
21
22
  context.content = erb.result(binding)
22
23
  context
23
24
  rescue Exception => e
24
- raise RuntimeError, "Erb processing failed in <#{context.ref_node.absolute_lcn}>: #{e.message}", e.backtrace
25
+ raise RuntimeError, "Erb processing failed in <#{context.ref_node.alcn}>: #{e.message}", e.backtrace
25
26
  end
26
27
 
27
28
  end
@@ -29,11 +29,11 @@ module Webgen::ContentProcessor
29
29
  else
30
30
  ::Erubis::Eruby.new(context.content, options)
31
31
  end
32
- erubis.filename = context.ref_node.absolute_lcn
32
+ erubis.filename = context.ref_node.alcn
33
33
  context.content = erubis.result(binding)
34
34
  context
35
35
  rescue Exception => e
36
- raise RuntimeError, "Erubis processing failed in <#{context.ref_node.absolute_lcn}>: #{e.message}", e.backtrace
36
+ raise RuntimeError, "Erubis processing failed in <#{context.ref_node.alcn}>: #{e.message}", e.backtrace
37
37
  end
38
38
 
39
39
  end
@@ -18,11 +18,11 @@ module Webgen::ContentProcessor
18
18
  :ref_node => deprecate('ref_node', 'context.ref_node', context.ref_node),
19
19
  :dest_node => deprecate('dest_node', 'context.dest_node', context.dest_node)
20
20
  }
21
- context.content = ::Haml::Engine.new(context.content, :filename => context.ref_node.absolute_lcn).
21
+ context.content = ::Haml::Engine.new(context.content, :filename => context.ref_node.alcn).
22
22
  render(Object.new, locals)
23
23
  context
24
24
  rescue Exception => e
25
- raise RuntimeError, "Error converting Haml markup to HTML in <#{context.ref_node.absolute_lcn}>: #{e.message}", e.backtrace
25
+ raise RuntimeError, "Error converting Haml markup to HTML in <#{context.ref_node.alcn}>: #{e.message}", e.backtrace
26
26
  end
27
27
 
28
28
  end
@@ -12,7 +12,7 @@ module Webgen::ContentProcessor
12
12
  context.content = ::Maruku.new(context.content, :on_error => :raise).to_html
13
13
  context
14
14
  rescue Exception => e
15
- raise RuntimeError, "Maruku to HTML conversion failed for <#{context.ref_node.absolute_lcn}>: #{e.message}", e.backtrace
15
+ raise RuntimeError, "Maruku to HTML conversion failed for <#{context.ref_node.alcn}>: #{e.message}", e.backtrace
16
16
  end
17
17
 
18
18
  end
@@ -9,10 +9,10 @@ module Webgen::ContentProcessor
9
9
  def call(context)
10
10
  require 'sass'
11
11
 
12
- context.content = ::Sass::Engine.new(context.content, :filename => context.ref_node.absolute_lcn).render
12
+ context.content = ::Sass::Engine.new(context.content, :filename => context.ref_node.alcn).render
13
13
  context
14
14
  rescue Exception => e
15
- raise RuntimeError, "Error converting Sass markup to CSS in <#{context.ref_node.absolute_lcn}>: #{e.message}", e.backtrace
15
+ raise RuntimeError, "Error converting Sass markup to CSS in <#{context.ref_node.alcn}>: #{e.message}", e.backtrace
16
16
  end
17
17
 
18
18
  end
@@ -23,23 +23,37 @@ module Webgen::ContentProcessor
23
23
  # Replace all webgen tags in the content of +context+ with the rendered content.
24
24
  def call(context)
25
25
  replace_tags(context.content, context.ref_node) do |tag, param_string, body|
26
- log(:debug) { "Replacing tag #{tag} with data '#{param_string}' and body '#{body}' in <#{context.ref_node.absolute_lcn}>" }
26
+ log(:debug) { "Replacing tag #{tag} with data '#{param_string}' and body '#{body}' in <#{context.ref_node.alcn}>" }
27
+ process_tag(tag, param_string, body, context)
28
+ end
29
+ context
30
+ end
27
31
 
28
- result = ''
29
- processor = processor_for_tag(tag)
30
- if !processor.nil?
31
- processor.set_params(processor.create_tag_params(param_string, context.ref_node))
32
+ # Process the +tag+ and return the result. The parameter +params+ needs to be a Hash holding all
33
+ # needed and optional parameters for the tag or a parameter String in YAML format and +body+ is
34
+ # the optional body for the tag. +context+ needs to be a valid Webgen::Context object.
35
+ def process_tag(tag, params, body, context)
36
+ result = ''
37
+ processor = processor_for_tag(tag)
38
+ if !processor.nil?
39
+ params, mandatory_missing = if params.kind_of?(String)
40
+ processor.create_tag_params(params, context.ref_node)
41
+ else
42
+ processor.create_params_hash(params, context.ref_node)
43
+ end
44
+ if mandatory_missing
45
+ context.dest_node.flag(:dirty)
46
+ else
47
+ processor.set_params(params)
32
48
  result, process_output = processor.call(tag, body, context)
33
49
  processor.set_params(nil)
34
-
35
50
  result = call(context.clone(:content => result)).content if process_output
36
51
  end
37
-
38
- result
39
52
  end
40
- context
53
+ result
41
54
  end
42
55
 
56
+
43
57
  #######
44
58
  private
45
59
  #######
@@ -72,7 +86,7 @@ module Webgen::ContentProcessor
72
86
  when :in_start_tag
73
87
  data.brackets += (scanner[1] == '{' ? 1 : -1) while data.brackets != 0 && scanner.skip_until(BRACKETS_RE)
74
88
  if data.brackets != 0
75
- log(:error) { "Unbalanced curly brackets in <#{node.absolute_lcn}>!" }
89
+ log(:error) { "Unbalanced curly brackets in <#{node.alcn}>!" }
76
90
  data.state = :done
77
91
  else
78
92
  data.params_end_pos = data.body_end_pos = data.end_pos = scanner.pos - 1
@@ -106,7 +120,7 @@ module Webgen::ContentProcessor
106
120
  data.end_pos = scanner.pos - 1
107
121
  data.body_end_pos = scanner.pos - scanner.matched.length + scanner[1].length / 2
108
122
  else
109
- log(:error) { "Invalid body part in <#{node.absolute_lcn}>!" }
123
+ log(:error) { "Invalid body part in <#{node.alcn}>!" }
110
124
  data.state = :done
111
125
  end
112
126
 
@@ -1,5 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  require 'webgen/context/nodes'
3
+ require 'webgen/context/tags'
4
+ require 'webgen/context/render'
3
5
 
4
6
  module Webgen
5
7
 
@@ -13,7 +15,8 @@ module Webgen
13
15
  # The content string that should be processed.
14
16
  #
15
17
  # [<tt>:processors</tt>]
16
- # Normally an AccessHash object providing access to all available content processors.
18
+ # Normally an ContentProcessor::AccessHash object providing access to all available content
19
+ # processors.
17
20
  #
18
21
  # [<tt>:chain</tt>]
19
22
  # The chain of nodes that is processed. There are some utiltity methods for getting
@@ -0,0 +1,32 @@
1
+ module Webgen
2
+
3
+ class Context
4
+
5
+ # Render the named block and return the result.
6
+ #
7
+ # call-seq:
8
+ # context.render_block(block_name)<br />
9
+ # context.render_block(:name => block_name, :option => value, ...)
10
+ #
11
+ # This method uses the functionality of the content processor +blocks+ for doing the actual
12
+ # work, so you may also want to look at Webgen::ContentProcessor::Blocks#render_block. You can
13
+ # call this method in two ways:
14
+ #
15
+ # [<tt>#render_block(block_name)</tt>]
16
+ # Renders the block named +block_name+ of the next node in the current node chain. This is the
17
+ # version that most want to use since it is equivalent to the use of <tt><webgen:block
18
+ # name="block_name" /></tt>. It is equivalent to <tt>#render_block(:name =>
19
+ # block_name)</tt>.
20
+ #
21
+ # [<tt>#render_block(opts_hash)</tt>]
22
+ # This version allows the same level of control over the output as the blocks content
23
+ # processor. For a list of valid options have a look at the documentation of the
24
+ # Webgen::ContentProcessor::Blocks#render_block method!
25
+ def render_block(name_or_hash)
26
+ name_or_hash = {:name => name_or_hash} if name_or_hash.kind_of?(String)
27
+ website.cache.instance('Webgen::ContentProcessor::Blocks').render_block(self, name_or_hash)
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,20 @@
1
+ module Webgen
2
+
3
+ class Context
4
+
5
+ # Returns the result of evaluating the webgen tag +name+ with the tag parameters +params+ and
6
+ # the +body+ in the current context.
7
+ #
8
+ # Have a look at Webgen::Tag::Base for more information about webgen tags!
9
+ #
10
+ # This method is useful when you want to have the functionality of webgen tags available but you
11
+ # don't want to use the content processor for them. Or, for example, if the used markup language
12
+ # uses a similar markup as webgen tags do and therefore you can't use the normal webgen tags
13
+ # content processor.
14
+ def tag(name, params = {}, body = '')
15
+ website.cache.instance('Webgen::ContentProcessor::Tags').process_tag(name, params, body, self)
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -43,6 +43,7 @@ end
43
43
 
44
44
  # All things regarding sources
45
45
  config.sources [['/', "Webgen::Source::FileSystem", 'src']], :doc => 'One or more sources from which files are read, relative to website directory'
46
+ config.passive_sources([['/', "Webgen::Source::Resource", "webgen-passive-sources"]], :doc => 'One or more sources for delayed node creation on node resolution')
46
47
 
47
48
  # All things regarding source handler
48
49
  config.sourcehandler.patterns({
@@ -70,7 +71,7 @@ config.sourcehandler.default_lang_in_output_path(false, :doc => 'Specifies wheth
70
71
  config.sourcehandler.default_meta_info({
71
72
  :all => {
72
73
  'output_path' => 'standard',
73
- 'output_path_style' => [:parent, :cnbase, ['.', :lang], :ext]
74
+ 'output_path_style' => [:parent, :basename, ['.', :lang], :ext]
74
75
  },
75
76
  'Webgen::SourceHandler::Copy' => {
76
77
  'kind' => 'asset'
@@ -114,6 +115,8 @@ website.autoload_service(:parse_html_headers, 'Webgen::SourceHandler::Fragment')
114
115
 
115
116
  # All things regarding output
116
117
  config.output ["Webgen::Output::FileSystem", 'out'], :doc => 'The class which is used to output the generated paths.'
118
+ config.output.do_deletion(false, :doc => 'Specifies whether the generated output paths should be deleted once the sources are deleted')
119
+
117
120
 
118
121
  Webgen::WebsiteAccess.website.blackboard.add_service(:output_instance, Webgen::Output.method(:instance))
119
122
 
@@ -3,18 +3,42 @@ module Webgen
3
3
  class Node
4
4
 
5
5
  def flagged(key)
6
- warn("Deprecation warning: this method will be removed in one of the next releases - use Node#flagged? instead!")
6
+ warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Node#flagged? instead!")
7
7
  flagged?(key)
8
8
  end
9
9
 
10
+ def absolute_cn
11
+ warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Node#acn instead!")
12
+ acn
13
+ end
14
+
15
+ def absolute_lcn
16
+ warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Node#alcn instead!")
17
+ alcn
18
+ end
19
+
20
+ end
21
+
22
+ class Path
23
+
24
+ def cnbase
25
+ warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Path#basename instead!")
26
+ @basename
27
+ end
28
+
29
+ def cnbase=(value)
30
+ warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Path#basename= instead!")
31
+ basename = value
32
+ end
33
+
10
34
  end
11
35
 
12
36
  def self.const_missing(const)
13
37
  if const.to_s == 'Block'
14
- warn("Deprecation warning: Webgen::Block name will be removed in one of the next releases - use Webgen::Page::Block instead!")
38
+ warn("Deprecation warning (~ #{caller.first}): Webgen::Block name will be removed in one of the next releases - use Webgen::Page::Block instead!")
15
39
  Webgen::Page::Block
16
40
  elsif const.to_s == "WebgenPageFormatError"
17
- warn("Deprecation warning: Webgen::WebgenPageFormatError name will be removed in one of the next releases - use Webgen::Page::FormatError instead!")
41
+ warn("Deprecation warning (~ #{caller.first}): Webgen::WebgenPageFormatError name will be removed in one of the next releases - use Webgen::Page::FormatError instead!")
18
42
  Webgen::Page::FormatError
19
43
  else
20
44
  super
@@ -25,7 +49,7 @@ module Webgen
25
49
 
26
50
  def self.const_missing(const)
27
51
  if const.to_s == 'Context'
28
- warn("Deprecation warning: Webgen::ContentProcessor::Context is now named Webgen::Context! This alias will be removed in one of the next releases.")
52
+ warn("Deprecation warning (~ #{caller.first}): Webgen::ContentProcessor::Context is now named Webgen::Context! This alias will be removed in one of the next releases.")
29
53
  Webgen::Context
30
54
  else
31
55
  super
@@ -50,4 +74,13 @@ module Webgen
50
74
 
51
75
  end
52
76
 
77
+ module Common
78
+
79
+ def self.absolute_path(path, base)
80
+ warn("Deprecation warning (~ #{caller.first}): this method will be removed in one of the next releases - use Webgen::Path.make_absolute(base, path) instead!")
81
+ Path.make_absolute(base, path)
82
+ end
83
+
84
+ end
85
+
53
86
  end
data/lib/webgen/node.rb CHANGED
@@ -22,10 +22,11 @@ module Webgen
22
22
  include WebsiteAccess
23
23
  include Loggable
24
24
 
25
- # The parent node.
25
+ # The parent node. This is in all but one case a Node object. The one exception is that the
26
+ # parent of the Tree#dummy_node is a Tree object.
26
27
  attr_reader :parent
27
28
 
28
- # The children of this node.
29
+ # The child nodes of this node.
29
30
  attr_reader :children
30
31
 
31
32
  # The full output path of this node.
@@ -38,13 +39,13 @@ module Webgen
38
39
  attr_reader :cn
39
40
 
40
41
  # The absolute canonical name of this node.
41
- attr_reader :absolute_cn
42
+ attr_reader :acn
42
43
 
43
44
  # The localized canonical name of this node.
44
45
  attr_reader :lcn
45
46
 
46
47
  # The absolute localized canonical name of this node.
47
- attr_reader :absolute_lcn
48
+ attr_reader :alcn
48
49
 
49
50
  # The level of the node. The level specifies how deep the node is in the hierarchy.
50
51
  attr_reader :level
@@ -76,7 +77,7 @@ module Webgen
76
77
  # found, the node is language neutral.
77
78
  def initialize(parent, path, cn, meta_info = {})
78
79
  @parent = parent
79
- @cn = cn.chomp('/').freeze
80
+ @cn = cn.freeze
80
81
  @children = []
81
82
  reinit(path, meta_info)
82
83
  init_rest
@@ -111,7 +112,7 @@ module Webgen
111
112
 
112
113
  # Return the node information hash which contains information for processing the node.
113
114
  def node_info
114
- tree.node_info[@absolute_lcn] ||= {}
115
+ tree.node_info[@alcn] ||= {}
115
116
  end
116
117
 
117
118
  # Check if the node is a directory.
@@ -161,8 +162,8 @@ module Webgen
161
162
  def changed?
162
163
  if_not_checked(:node) do
163
164
  flag(:dirty) if meta_info_changed? ||
164
- node_info[:used_nodes].any? {|n| n != @absolute_lcn && (!tree[n] || tree[n].changed?)} ||
165
- node_info[:used_meta_info_nodes].any? {|n| n != @absolute_lcn && (!tree[n] || tree[n].meta_info_changed?)}
165
+ node_info[:used_nodes].any? {|n| n != @alcn && (!tree[n] || tree[n].changed?)} ||
166
+ node_info[:used_meta_info_nodes].any? {|n| n != @alcn && (!tree[n] || tree[n].meta_info_changed?)}
166
167
  website.blackboard.dispatch_msg(:node_changed?, self) unless flagged?(:dirty)
167
168
  end
168
169
  flagged?(:dirty)
@@ -183,12 +184,12 @@ module Webgen
183
184
 
184
185
  # Return an informative representation of the node.
185
186
  def inspect
186
- "<##{self.class.name}: alcn=#{@absolute_lcn}>"
187
+ "<##{self.class.name}: alcn=#{@alcn}>"
187
188
  end
188
189
 
189
190
  # Return +true+ if the alcn matches the pattern. See File.fnmatch for useable patterns.
190
191
  def =~(pattern)
191
- File.fnmatch(pattern, @absolute_lcn, File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
192
+ File.fnmatch(pattern, @alcn, File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
192
193
  end
193
194
 
194
195
  # Sort nodes by using the meta info +sort_info+ (or +title+ if +sort_info+ is not set) of both
@@ -203,22 +204,16 @@ module Webgen
203
204
  self_so <=> other_so
204
205
  end
205
206
 
206
- # Construct the absolute (localized) canonical name by using the +parent+ node and +name+ (which
207
- # can be a cn or an lcn). The +type+ can be either <tt>:alcn</tt> or <tt>:acn</tt>.
208
- def self.absolute_name(parent, name, type)
209
- if parent.kind_of?(Tree)
210
- ''
211
- else
212
- parent = parent.parent while parent.is_fragment? # Handle fragment nodes specially in case they are nested
213
- parent_name = (type == :alcn ? parent.absolute_lcn : parent.absolute_cn)
214
- parent_name + (parent_name !~ /\/$/ && (parent.is_directory? || parent == parent.tree.dummy_root) ? '/' : '') + name
215
- end
216
- end
207
+ # This pattern is the the same as URI::UNSAFE except that the hash character (#) is also
208
+ # not escaped. This is needed sothat paths with fragments work correctly.
209
+ URL_UNSAFE_PATTERN = Regexp.new("[^#{URI::PATTERN::UNRESERVED}#{URI::PATTERN::RESERVED}#]") # :nodoc:
217
210
 
218
- # Construct an internal URL for the given +name+ which can be a acn/alcn/path.
219
- def self.url(name)
220
- url = URI::parse(name)
221
- url = URI::parse('webgen://webgen.localhost/') + url unless url.absolute?
211
+ # Construct an internal URL for the given +name+ which can be an acn/alcn/path. If the parameter
212
+ # +make_absolute+ is +true+, then a relative URL will be made absolute by prepending the special
213
+ # URL <tt>webgen:://webgen.localhost/</tt>.
214
+ def self.url(name, make_absolute = true)
215
+ url = URI::parse(URI::escape(name, URL_UNSAFE_PATTERN))
216
+ url = URI::parse('webgen://webgen.localhost/') + url unless url.absolute? || !make_absolute
222
217
  url
223
218
  end
224
219
 
@@ -235,7 +230,7 @@ module Webgen
235
230
  # exists, an unlocalized version of the node. If no such node is found either, +nil+ is
236
231
  # returned.
237
232
  def in_lang(lang)
238
- avail = @tree.node_access[:acn][@absolute_cn]
233
+ avail = @tree.node_access[:acn][@acn]
239
234
  avail.find do |n|
240
235
  n = n.parent while n.is_fragment?
241
236
  n.lang == lang
@@ -252,19 +247,23 @@ module Webgen
252
247
  # If the +path+ is an alcn and a node is found, it is returned. If the +path+ is an acn, the
253
248
  # correct localized node according to +lang+ is returned or if no such node exists but an
254
249
  # unlocalized version does, the unlocalized node is returned.
255
- def resolve(path, lang = nil)
256
- url = self.class.url(self.is_directory? ? File.join(@absolute_lcn, '/') : @absolute_lcn) + path
250
+ def resolve(path, lang = nil, use_passive_sources = true)
251
+ orig_path = path
252
+ url = self.class.url(@alcn) + self.class.url(path, false)
257
253
 
258
254
  path = url.path + (url.fragment.nil? ? '' : '#' + url.fragment)
259
- path.chomp!('/') unless path == '/'
260
255
  return nil if path =~ /^\/\.\./
261
256
 
262
257
  node = @tree[path, :alcn]
263
- if node && node.absolute_cn != path
264
- node
265
- else
266
- (node = @tree[path, :acn]) && node.in_lang(lang)
258
+ if !node || node.acn == path
259
+ (node = (@tree[path, :acn] || @tree[path + '/', :acn])) && (node = node.in_lang(lang))
260
+ end
261
+ if !node && use_passive_sources && !website.config['passive_sources'].empty?
262
+ nodes = website.blackboard.invoke(:create_nodes_from_paths, [path])
263
+ node = resolve(orig_path, lang, false)
264
+ node.node_info[:used_meta_info_nodes] += nodes.collect {|n| n.alcn} if node
267
265
  end
266
+ node
268
267
  end
269
268
 
270
269
  # Return the relative path to the given path +other+. The parameter +other+ can be a Node or a
@@ -295,7 +294,7 @@ module Webgen
295
294
  if !is_directory?
296
295
  self
297
296
  else
298
- key = [absolute_lcn, :index_node, lang]
297
+ key = [alcn, :index_node, lang]
299
298
  vcache = website.cache.volatile
300
299
  return vcache[key] if vcache.has_key?(key)
301
300
 
@@ -306,10 +305,10 @@ module Webgen
306
305
  index_node = resolve(index_path, lang)
307
306
  if index_node
308
307
  vcache[key] = index_node
309
- log(:info) { "Directory index path for <#{absolute_lcn}> => <#{index_node.absolute_lcn}>" }
308
+ log(:info) { "Directory index path for <#{alcn}> => <#{index_node.alcn}>" }
310
309
  elsif log_warning
311
310
  vcache[key] = self
312
- log(:warn) { "No directory index path found for directory <#{absolute_lcn}>" }
311
+ log(:warn) { "No directory index path found for directory <#{alcn}>" }
313
312
  end
314
313
  end
315
314
  vcache[key] || self
@@ -351,8 +350,8 @@ module Webgen
351
350
  # Do the rest of the initialization.
352
351
  def init_rest
353
352
  @lcn = Path.lcn(@cn, @lang)
354
- @absolute_cn = self.class.absolute_name(@parent, @cn, :acn)
355
- @absolute_lcn = self.class.absolute_name(@parent, @lcn, :alcn)
353
+ @acn = (@parent.kind_of?(Tree) ? '' : @parent.acn.sub(/#.*$/, '') + @cn)
354
+ @alcn = (@parent.kind_of?(Tree) ? '' : @parent.alcn.sub(/#.*$/, '') + @lcn)
356
355
 
357
356
  @level = -1
358
357
  @tree = @parent