gettalong-webgen 0.5.5.20081001 → 0.5.5.20081010

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/doc/extensions.page +1 -1
  2. data/doc/reference_configuration.page +85 -0
  3. data/doc/tag/tikz.page +158 -0
  4. data/lib/webgen/common/sitemap.rb +2 -3
  5. data/lib/webgen/contentprocessor/blocks.rb +0 -2
  6. data/lib/webgen/contentprocessor/context.rb +0 -3
  7. data/lib/webgen/contentprocessor/erubis.rb +0 -2
  8. data/lib/webgen/default_config.rb +8 -1
  9. data/lib/webgen/node.rb +49 -24
  10. data/lib/webgen/page.rb +25 -15
  11. data/lib/webgen/path.rb +20 -10
  12. data/lib/webgen/sourcehandler/base.rb +36 -14
  13. data/lib/webgen/sourcehandler/copy.rb +2 -2
  14. data/lib/webgen/sourcehandler/directory.rb +16 -13
  15. data/lib/webgen/sourcehandler/feed.rb +3 -6
  16. data/lib/webgen/sourcehandler/fragment.rb +6 -11
  17. data/lib/webgen/sourcehandler/memory.rb +41 -0
  18. data/lib/webgen/sourcehandler/metainfo.rb +21 -21
  19. data/lib/webgen/sourcehandler/page.rb +8 -12
  20. data/lib/webgen/sourcehandler/sitemap.rb +0 -2
  21. data/lib/webgen/sourcehandler/template.rb +0 -4
  22. data/lib/webgen/sourcehandler/virtual.rb +18 -18
  23. data/lib/webgen/sourcehandler.rb +83 -70
  24. data/lib/webgen/tag/breadcrumbtrail.rb +1 -4
  25. data/lib/webgen/tag/coderay.rb +0 -3
  26. data/lib/webgen/tag/date.rb +0 -2
  27. data/lib/webgen/tag/executecommand.rb +1 -2
  28. data/lib/webgen/tag/includefile.rb +1 -3
  29. data/lib/webgen/tag/langbar.rb +1 -4
  30. data/lib/webgen/tag/menu.rb +1 -4
  31. data/lib/webgen/tag/metainfo.rb +0 -2
  32. data/lib/webgen/tag/relocatable.rb +2 -3
  33. data/lib/webgen/tag/sitemap.rb +0 -3
  34. data/lib/webgen/tag/tikz.rb +117 -0
  35. data/lib/webgen/tag.rb +1 -0
  36. data/lib/webgen/tree.rb +9 -5
  37. data/test/test_common_sitemap.rb +4 -4
  38. data/test/test_contentprocessor_context.rb +1 -1
  39. data/test/test_contentprocessor_redcloth.rb +1 -0
  40. data/test/test_contentprocessor_tags.rb +1 -1
  41. data/test/test_node.rb +33 -13
  42. data/test/test_output_filesystem.rb +1 -1
  43. data/test/test_page.rb +13 -4
  44. data/test/test_path.rb +37 -5
  45. data/test/test_source_filesystem.rb +1 -1
  46. data/test/test_source_stacked.rb +1 -1
  47. data/test/test_sourcehandler_base.rb +30 -1
  48. data/test/test_sourcehandler_copy.rb +1 -1
  49. data/test/test_sourcehandler_directory.rb +16 -1
  50. data/test/test_sourcehandler_feed.rb +6 -7
  51. data/test/test_sourcehandler_fragment.rb +1 -1
  52. data/test/test_sourcehandler_memory.rb +42 -0
  53. data/test/test_sourcehandler_metainfo.rb +23 -21
  54. data/test/test_sourcehandler_page.rb +5 -7
  55. data/test/test_sourcehandler_template.rb +1 -1
  56. data/test/test_sourcehandler_virtual.rb +2 -2
  57. data/test/test_tag_base.rb +0 -1
  58. data/test/test_tag_breadcrumbtrail.rb +4 -4
  59. data/test/test_tag_includefile.rb +3 -3
  60. data/test/test_tag_langbar.rb +5 -6
  61. data/test/test_tag_menu.rb +7 -7
  62. data/test/test_tag_metainfo.rb +1 -1
  63. data/test/test_tag_relocatable.rb +1 -1
  64. data/test/test_tag_tikz.rb +66 -0
  65. data/test/test_tree.rb +2 -7
  66. metadata +7 -2
data/doc/extensions.page CHANGED
@@ -6,7 +6,7 @@ title: Extensions
6
6
  Following is a listing of all available extensions:
7
7
 
8
8
  <%
9
- pattern = /#{File.join(node.parent.absolute_lcn, '/')}(contentprocessor|output|source|sourcehandler|tag|)\//
9
+ pattern = /#{File.join(node.parent.absolute_lcn, '/')}(contentprocessor|output|source|sourcehandler|tag|)\/.*html$/
10
10
  context.content_node.tree.node_access[:alcn].select {|alcn, n| alcn =~ pattern}.sort.each do |alcn, n|
11
11
  next if n.is_fragment?
12
12
  %>
@@ -659,6 +659,91 @@ files in Webgen Page Format.
659
659
  <a href="\{relocatable: ../features.html}">Some Path</a>
660
660
 
661
661
 
662
+ * ### tag.tikz.path
663
+
664
+ The default mandatory configuration option for Tag::TikZ that specifies the (naturally
665
+ non-existing) source path that should be used for creating the TikZ image. The output path is
666
+ derived from this path the usual way. You shouldn't use a path that does already exist!
667
+
668
+ * Syntax: `PATH` where `PATH` is a relative or absolute source path.
669
+
670
+ * Examples:
671
+
672
+ \{tikz:: images/tikz.png}\tikz \draw (0,0) -- (0,2);{tikz}
673
+
674
+
675
+ * ### tag.tikz.libraries
676
+
677
+ Specifies the names of additional TikZ library names that should be used when creating the
678
+ image.
679
+
680
+ * Syntax: `[NAME, ...]` where `NAME` is the name of a TikZ library.
681
+
682
+ * Examples:
683
+
684
+ \{tikz:: {path: images/tikz.png, libraries: [mindmap, arrows]}}
685
+ \tikz \draw (0,0) -- (0,2) -- (2,2);
686
+ {tikz}
687
+
688
+
689
+ * ### tag.tikz.opts
690
+
691
+ Specifies additional global options for the `tikzpicture` environment.
692
+
693
+ * Syntax: `OPTS` where `OPTS` is the string with the global options.
694
+
695
+ * Examples:
696
+
697
+ \{tikz:: {path: images/tikz.png, opts: 'scale=3, line cap=round'}}
698
+ \tikz \draw (0,0) -- (0,2) -- (2,2);
699
+ {tikz}
700
+
701
+
702
+ * ### tag.tikz.resolution
703
+
704
+ Specifies the render and output resolutions that should be used to convert the TikZ image in PDF
705
+ format to the chosen image format. The first number specifies the render resolution and the
706
+ second one the output resolution. If the render resolution is higher than the output resolution,
707
+ the final image quality is better but the image needs to scaled down to the output resolution.
708
+
709
+ * Syntax: `RENDER_RES OUTPUT_RES` where `RENDER_RES` is the integer specifying the render
710
+ resolution and `OUTPUT_RES` is the integer specifying the output resolution.
711
+
712
+ * Examples:
713
+
714
+ \{tikz:: {path: images/tikz.png, resolution: 300 72}}
715
+ \tikz \draw (0,0) -- (0,2) -- (2,2);
716
+ {tikz}
717
+
718
+
719
+ * ### tag.tikz.transparent
720
+
721
+ Specifies whether the generated image should be transparent. This only works when the path
722
+ specified by `tag.tikz.path` option has the extension `.png`! You should probably also set the
723
+ background of the generated image tag to transparent.
724
+
725
+ * Syntax: `BOOLEAN` where `BOOLEAN` is either `true` or `false`.
726
+
727
+ * Examples:
728
+
729
+ \{tikz:: {path: images/tikz.png, transparent: true}}
730
+ \tikz \draw (0,0) -- (0,2) -- (2,2);
731
+ {tikz}
732
+
733
+
734
+ * ### tag.tikz.img\_attr
735
+
736
+ Specifies additional HTML attributes that should be set on the generated `img` tag.
737
+
738
+ * Syntax: `\{KEY:VALUE, ...}` where `KEY` is a valid HTML `img` tag attribute name and `VALUE`
739
+ the to-be-set value.
740
+
741
+ * Examples:
742
+
743
+ \{tikz:: {path: images/tikz.png, img_attr: {alt: Some TikZ picture}}}
744
+ \tikz \draw (0,0) -- (0,2) -- (2,2);
745
+ {tikz}
746
+
662
747
  ---
663
748
 
664
749
  ## Miscelleanous Configuration Options
data/doc/tag/tikz.page ADDED
@@ -0,0 +1,158 @@
1
+ ---
2
+ title: Webgen::Tag::TikZ
3
+ used_options:
4
+ - tag.tikz.path
5
+ - tag.tikz.libraries
6
+ - tag.tikz.opts
7
+ - tag.tikz.resolution
8
+ - tag.tikz.transparent
9
+ - tag.tikz.img_attr
10
+ ---
11
+ ## Description
12
+
13
+ This tag provides support for automatically generating graphics with the fantastic PGF/TikZ library
14
+ for LaTeX. You will need to have a current LaTeX distribution with the PGF/TikZ library installed
15
+ and ImageMagick for this to work. You will also need Ghostscript if you want support for transparent
16
+ PNG images. More exactly, you will need to have the programs `pdflatex` (usually included in the
17
+ LaTeX distribution - for generating a PDF from the LaTeX document that describes the PGF/TikZ
18
+ graphic), `pdfcrop` (usually included in the LaTeX distribution - to crop the generated PDF and
19
+ throw away useless borders), `convert` (provided by ImageMagick - to convert the generated PDF
20
+ document to an image file format and to optionally resize them) and `gs` (provided by the
21
+ Ghostscript package - to generate transparent PNG images).
22
+
23
+ When using this tag, you need to set at least the default mandatory parameter `tag.tikz.path`. This
24
+ path specifies the source path that should be used for generating the image and should not
25
+ exist. The output path is dervied from this path the usual way. The extension used for this
26
+ parameter specifies the final image format that is used (a good choice is PNG). All other parameters
27
+ are optional. The commands for creating the PGF/TikZ picture are specified in the body of the
28
+ tag. Have a look at some of the examples below to set the power of PGF/TikZ.
29
+
30
+ If you want to generate transparent images, you will need to set `tag.tikz.transparent` to `true`
31
+ and specify a `tag.tikz.path` with a `.png` extension.
32
+
33
+ ## Examples
34
+
35
+ These examples are taken (sometimes a little bit altered) from the great PGF Manual included in the
36
+ PGF/TikZ distribution.
37
+
38
+ <table class="examples">
39
+ <tr>
40
+ <th>Usage</th><th>Output</th>
41
+ </tr>
42
+
43
+ <tr>
44
+ <td>
45
+ <pre>
46
+ \{tikz:: house.png}
47
+ \tikz \draw[thick,rounded corners=8pt]
48
+ (0,0) -- (0,2) -- (1,3.25) -- (2,2) -- (2,0) -- (0,2) -- (2,2) -- (0,0) -- (2,0);
49
+ {tikz}
50
+ </pre>
51
+ </td>
52
+ <td>
53
+ {tikz:: house.png}
54
+ \tikz \draw[thick,rounded corners=8pt]
55
+ (0,0) -- (0,2) -- (1,3.25) -- (2,2) -- (2,0) -- (0,2) -- (2,2) -- (0,0) -- (2,0);
56
+ {tikz}
57
+ </td>
58
+ </tr>
59
+
60
+ <tr>
61
+ <td>
62
+ <pre>
63
+ \{tikz:: {path: chain.png, libraries: [arrows,automata,shadows,positioning],
64
+ opts: "->,>=stealth,shorten >=1pt,auto,node distance=2.8cm,on grid,semithick,
65
+ every state/.style={fill=red,draw=none,circular drop shadow,text=white}",
66
+ resolution: 300 72}}
67
+ \node[initial,state] (A) {$q_a$};
68
+ \node[state] (B) [above right=of A] {$q_b$};
69
+ \node[state] (D) [below right=of A] {$q_d$};
70
+ \node[state] (C) [below right=of B] {$q_c$};
71
+ \node[state] (E) [below=of D] {$q_e$};
72
+ \path (A) edge node {0,1,L} (B)
73
+ edge node {1,1,R} (C)
74
+ (B) edge [loop above] node {1,1,L} (B)
75
+ edge node {0,1,L} (C)
76
+ (C) edge node {0,1,L} (D)
77
+ edge [bend left] node {1,0,R} (E)
78
+ (D) edge [loop below] node {1,1,R} (D)
79
+ edge node {0,1,R} (A)
80
+ (E) edge [bend left] node {1,0,R} (A);
81
+ {tikz}
82
+ </pre>
83
+ </td>
84
+ <td>
85
+ {tikz:: {path: chain.png, libraries: [arrows,automata,shadows,positioning],
86
+ opts: "->,>=stealth,shorten >=1pt,auto,node distance=2.8cm,on grid,semithick,
87
+ every state/.style={fill=red,draw=none,circular drop shadow,text=white}"}}
88
+ \node[initial,state] (A) {$q_a$};
89
+ \node[state] (B) [above right=of A] {$q_b$};
90
+ \node[state] (D) [below right=of A] {$q_d$};
91
+ \node[state] (C) [below right=of B] {$q_c$};
92
+ \node[state] (E) [below=of D] {$q_e$};
93
+ \path (A) edge node {0,1,L} (B)
94
+ edge node {1,1,R} (C)
95
+ (B) edge [loop above] node {1,1,L} (B)
96
+ edge node {0,1,L} (C)
97
+ (C) edge node {0,1,L} (D)
98
+ edge [bend left] node {1,0,R} (E)
99
+ (D) edge [loop below] node {1,1,R} (D)
100
+ edge node {0,1,R} (A)
101
+ (E) edge [bend left] node {1,0,R} (A);
102
+ {tikz}
103
+ </td>
104
+ </tr>
105
+
106
+ <tr>
107
+ <td>
108
+ Not transparent and standard res
109
+ <pre>
110
+ \{tikz:: {path: mindmap.png, libraries: [mindmap]}}
111
+ \path[mindmap,concept color=black,text=white]
112
+ node[concept] {Computer Science}
113
+ [clockwise from=0]
114
+ child[concept color=red] { node[concept] {technical} }
115
+ child[concept color=orange] { node[concept] {theoretical} };
116
+ {tikz}
117
+ </pre>
118
+ </td>
119
+ <td>
120
+ {tikz:: {path: mindmap.png, libraries: [mindmap]}}
121
+ \path[mindmap,concept color=black,text=white]
122
+ node[concept] {Computer Science}
123
+ [clockwise from=0]
124
+ child[concept color=red] { node[concept] {technical} }
125
+ child[concept color=orange] { node[concept] {theoretical} };
126
+ {tikz}
127
+ </td>
128
+ </tr>
129
+
130
+ <tr>
131
+ <td>
132
+ Transparent and high res
133
+ <pre>
134
+ \{tikz:: {path: mindmap-low.png, libraries: [mindmap],
135
+ img_attr: {style: 'background:transparent'},
136
+ transparent: true, resolution: 300 72}}
137
+ \path[mindmap,concept color=black,text=white]
138
+ node[concept] {Computer Science}
139
+ [clockwise from=0]
140
+ child[concept color=red] { node[concept] {technical} }
141
+ child[concept color=orange] { node[concept] {theoretical} };
142
+ {tikz}
143
+ </pre>
144
+ </td>
145
+ <td>
146
+ {tikz:: {path: mindmap-high.png, libraries: [mindmap],
147
+ img_attr: {style: 'background:transparent'},
148
+ transparent: true, resolution: 300 72}}
149
+ \path[mindmap,concept color=black,text=white]
150
+ node[concept] {Computer Science}
151
+ [clockwise from=0]
152
+ child[concept color=red] { node[concept] {technical} }
153
+ child[concept color=orange] { node[concept] {theoretical} };
154
+ {tikz}
155
+ </td>
156
+ </tr>
157
+
158
+ </table>
@@ -1,4 +1,4 @@
1
- require 'webgen/tag/menu'
1
+ require 'webgen/tag'
2
2
  require 'webgen/websiteaccess'
3
3
 
4
4
  module Webgen::Common
@@ -64,13 +64,12 @@ module Webgen::Common
64
64
  (tree.flatten.any? do |alcn|
65
65
  (n = node.tree[alcn]) && (r = n.routing_node(lang)) && r.meta_info_changed?
66
66
  end)
67
- node.dirty = true
67
+ node.flag(:dirty)
68
68
  break
69
69
  end
70
70
  end
71
71
  end
72
72
 
73
-
74
73
  end
75
74
 
76
75
  end
@@ -1,5 +1,3 @@
1
- require 'webgen/loggable'
2
-
3
1
  module Webgen::ContentProcessor
4
2
 
5
3
  # Replaces special xml tags with the rendered content of a node.
@@ -1,6 +1,3 @@
1
- require 'webgen/contentprocessor'
2
- require 'webgen/websiteaccess'
3
-
4
1
  module Webgen::ContentProcessor
5
2
 
6
3
  # The context object that is passed to the +call+ method of a content processor.
@@ -1,5 +1,3 @@
1
- require 'webgen/websiteaccess'
2
-
3
1
  module Webgen::ContentProcessor
4
2
 
5
3
  # Processes embedded Ruby statements with the +erubis+ library.
@@ -54,7 +54,7 @@ config.sourcehandler.patterns({
54
54
  'Webgen::SourceHandler::Sitemap' => ['**/*.sitemap']
55
55
  }, :doc => 'Source handler to path pattern map')
56
56
  config.sourcehandler.invoke({
57
- 1 => ['Webgen::SourceHandler::Directory', 'Webgen::SourceHandler::Metainfo', 'Webgen::SourceHandler::Directory'],
57
+ 1 => ['Webgen::SourceHandler::Directory', 'Webgen::SourceHandler::Metainfo'],
58
58
  5 => ['Webgen::SourceHandler::Copy', 'Webgen::SourceHandler::Template',
59
59
  'Webgen::SourceHandler::Page', 'Webgen::SourceHandler::Feed',
60
60
  'Webgen::SourceHandler::Sitemap'],
@@ -148,6 +148,7 @@ config.contentprocessor.tags.map({
148
148
  'coderay' => 'Webgen::Tag::Coderay',
149
149
  'date' => 'Webgen::Tag::Date',
150
150
  'sitemap' => 'Webgen::Tag::Sitemap',
151
+ 'tikz' => 'Webgen::Tag::TikZ',
151
152
  :default => 'Webgen::Tag::Metainfo'
152
153
  }, :doc => 'Tag processor name to class map')
153
154
 
@@ -190,6 +191,12 @@ config.tag.coderay.tab_width(8, :doc => 'Number of spaces used for a tabulator')
190
191
 
191
192
  config.tag.date.format('%Y-%m-%d %H:%M:%S', :doc => 'The format of the date (same options as Ruby\'s Time#strftime)')
192
193
 
194
+ config.tag.tikz.path(nil, :doc => 'The source path of the created image', :mandatory => 'default')
195
+ config.tag.tikz.libraries(nil, :doc => 'An array of additional TikZ library names')
196
+ config.tag.tikz.opts(nil, :doc => 'A string with global options for the tikzpicture environment')
197
+ config.tag.tikz.resolution('72 72', :doc => 'A string specifying the render and output resolutions')
198
+ config.tag.tikz.transparent(false, :doc => 'Specifies whether the generated image should be transparent (only png)')
199
+ config.tag.tikz.img_attr({}, :doc => 'A hash of additional HTML attributes for the created img tag')
193
200
 
194
201
  # All things regarding common functionality
195
202
  website.autoload_service(:create_sitemap, 'Webgen::Common::Sitemap')
data/lib/webgen/node.rb CHANGED
@@ -46,17 +46,6 @@ module Webgen
46
46
  # Meta information associated with the node.
47
47
  attr_reader :meta_info
48
48
 
49
- # Set by other objects to +true+ if they think the object has changed since the last run. Must
50
- # not be set to +false+ once it is +true+!
51
- attr_accessor :dirty
52
-
53
- # Set by other objects to +true+ if the meta information of the node has changed since the last
54
- # run. Must not be set to +false+ once it is +true+!
55
- attr_accessor :dirty_meta_info
56
-
57
- # Has the node been created or has it been read from the cache?
58
- attr_accessor :created
59
-
60
49
  # Create a new Node instance.
61
50
  #
62
51
  # +parent+ (immutable)::
@@ -78,15 +67,27 @@ module Webgen
78
67
  # found, the node is language neutral.
79
68
  def initialize(parent, path, cn, meta_info = {})
80
69
  @parent = parent
81
- @path = path.freeze
82
70
  @cn = cn.chomp('/').freeze
71
+ @children = []
72
+ reinit(path, meta_info)
73
+ init_rest
74
+ end
75
+
76
+ # Re-initializes an already initialized node and resets it to its pristine state.
77
+ def reinit(path, meta_info = {})
78
+ old_path = @path
79
+ @path = path.freeze
83
80
  @lang = meta_info.delete('lang').freeze
84
81
  @lang = nil unless is_file?
85
82
  @meta_info = meta_info
86
- @children = []
87
- @dirty = true
88
- @created = true
89
- init_rest
83
+ @flags = Set.new([:dirty, :created])
84
+ if @tree
85
+ @tree.node_access[:path].delete(old_path) if old_path
86
+ @tree.register_path(self)
87
+ self.node_info.clear
88
+ self.node_info[:used_nodes] = Set.new
89
+ self.node_info[:used_meta_info_nodes] = Set.new
90
+ end
90
91
  end
91
92
 
92
93
  # Return the meta information item for +key+.
@@ -116,26 +117,50 @@ module Webgen
116
117
  # Check if the node is the root node.
117
118
  def is_root?; self == tree.root; end
118
119
 
120
+ # Check if the node is flagged with one of the following:
121
+ #
122
+ # :created:: Has the node been created or has it been read from the cache?
123
+ # :reinit:: Does the node need to be reinitialized?
124
+ # :dirty:: Set by other objects to +true+ if they think the object has changed since the last
125
+ # run. Must not be set to +false+ once it is +true+!
126
+ # :dirty_meta_info:: Set by other objects to +true+ if the meta information of the node has
127
+ # changed since the last run. Must not be set to +false+ once it is +true+!
128
+ def flagged(key)
129
+ @flags.include?(key)
130
+ end
131
+
132
+ # Flag the node with the +keys+. See #flagged for valid keys.
133
+ def flag(*keys)
134
+ @flags += keys
135
+ website.blackboard.dispatch_msg(:node_flagged, self, keys)
136
+ end
137
+
138
+ # Remove the flags +keys+ from the node.
139
+ def unflag(*keys)
140
+ @flags.subtract(keys)
141
+ website.blackboard.dispatch_msg(:node_unflagged, self, keys)
142
+ end
143
+
119
144
  # Return +true+ if the node has changed since the last webgen run. If it has changed, +dirty+ is
120
145
  # set to +true+.
121
146
  def changed?
122
147
  if_not_checked(:node) do
123
- @dirty = @dirty || meta_info_changed?
124
- @dirty = node_info[:used_nodes].any? {|n| n != @absolute_lcn && (!tree[n] || tree[n].changed?)} unless @dirty
125
- website.blackboard.dispatch_msg(:node_changed?, self) unless @dirty
148
+ flag(:dirty) if meta_info_changed? ||
149
+ node_info[:used_nodes].any? {|n| n != @absolute_lcn && (!tree[n] || tree[n].changed?)}
150
+ website.blackboard.dispatch_msg(:node_changed?, self) unless flagged(:dirty)
126
151
  end
127
- @dirty
152
+ flagged(:dirty)
128
153
  end
129
154
 
130
155
  # Return +true+ if the meta information of the node has changed.
131
156
  def meta_info_changed?
132
157
  if_not_checked(:meta_info) do
133
- @dirty_meta_info = node_info[:used_meta_info_nodes].any? do |n|
158
+ flag(:dirty_meta_info) if node_info[:used_meta_info_nodes].any? do |n|
134
159
  n != @absolute_lcn && (!tree[n] || tree[n].meta_info_changed?)
135
- end unless @dirty_meta_info
136
- website.blackboard.dispatch_msg(:node_meta_info_changed?, self) unless @dirty_meta_info
160
+ end
161
+ website.blackboard.dispatch_msg(:node_meta_info_changed?, self) unless flagged(:dirty_meta_info)
137
162
  end
138
- @dirty_meta_info
163
+ flagged(:dirty_meta_info)
139
164
  end
140
165
 
141
166
  # Return an informative representation of the node.
data/lib/webgen/page.rb CHANGED
@@ -55,14 +55,17 @@ module Webgen
55
55
  # the information. The +meta_info+ parameter can be used to provide default meta information.
56
56
  def from_data(data, meta_info = {})
57
57
  md = /(#{RE_META_INFO})?(.*)/m.match(normalize_eol(data))
58
- if md[1].nil? && data =~ RE_META_INFO_START
59
- raise WebgenPageFormatError, 'Found start line for meta information block but no valid meta information block'
60
- end
61
- meta_info = meta_info.merge(md[1].nil? ? {} : parse_meta_info(md[1]))
58
+ meta_info = meta_info.merge(parse_meta_info(md[1], data))
62
59
  blocks = parse_blocks(md[2] || '', meta_info)
63
60
  new(meta_info, blocks)
64
61
  end
65
62
 
63
+ # Parse the given string +data+ in Webgen Page Format and return the found meta information.
64
+ def meta_info_from_data(data)
65
+ md = /(#{RE_META_INFO})?/m.match(normalize_eol(data))
66
+ parse_meta_info(md[1], data)
67
+ end
68
+
66
69
  #######
67
70
  private
68
71
  #######
@@ -72,17 +75,24 @@ module Webgen
72
75
  data.gsub(/\r\n?/, "\n")
73
76
  end
74
77
 
75
- # Parse the meta info string +data+ and return the hash with the meta information.
76
- def parse_meta_info(data)
77
- begin
78
- meta_info = YAML::load(data)
79
- unless meta_info.kind_of?(Hash)
80
- raise WebgenPageFormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
78
+ # Parse the meta info string in +mi_data+ and return the hash with the meta information. The
79
+ # original +data+ is used for checking the validness of the meta information block.
80
+ def parse_meta_info(mi_data, data)
81
+ if mi_data.nil? && data =~ RE_META_INFO_START
82
+ raise WebgenPageFormatError, 'Found start line for meta information block but no valid meta information block'
83
+ elsif mi_data.nil?
84
+ {}
85
+ else
86
+ begin
87
+ meta_info = YAML::load(mi_data.to_s)
88
+ unless meta_info.kind_of?(Hash)
89
+ raise WebgenPageFormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
90
+ end
91
+ rescue ArgumentError => e
92
+ raise WebgenPageFormatError, e.message
81
93
  end
82
- rescue ArgumentError => e
83
- raise WebgenPageFormatError, e.message
94
+ meta_info
84
95
  end
85
- meta_info
86
96
  end
87
97
 
88
98
  # Parse all blocks in +data+ and return them. Meta information can be provided in +meta_info+
@@ -118,12 +128,12 @@ module Webgen
118
128
  # The contents of the meta information block.
119
129
  attr_reader :meta_info
120
130
 
121
- # The array of blocks for the page.
131
+ # The hash of blocks for the page.
122
132
  attr_reader :blocks
123
133
 
124
134
  # Create a new Page object with the meta information provided in +meta_info+ and the given
125
135
  # +blocks+.
126
- def initialize(meta_info = {}, blocks = nil)
136
+ def initialize(meta_info = {}, blocks = {})
127
137
  @meta_info = meta_info
128
138
  @blocks = blocks
129
139
  end
data/lib/webgen/path.rb CHANGED
@@ -35,11 +35,24 @@ module Webgen
35
35
  end
36
36
 
37
37
 
38
+ # Return +true+ if the given +path+ matches the given +pattern+ (trailing slashes of directories
39
+ # are not respected). For information on which patterns are supported, have a look at the
40
+ # documentation of File.fnmatch.
41
+ def self.match(path, pattern)
42
+ path = path.to_s.chomp('/') unless path == '/'
43
+ pattern = pattern.to_s.chomp('/') unless pattern == '/'
44
+ File.fnmatch(pattern, path, File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
45
+ end
46
+
47
+
38
48
  include Comparable
39
49
 
40
- # The full source path.
50
+ # The full path.
41
51
  attr_accessor :path
42
52
 
53
+ # The source path that lead to the creation of this path.
54
+ attr_accessor :source_path
55
+
43
56
  # The basename part of the path.
44
57
  attr_accessor :basename
45
58
 
@@ -55,11 +68,13 @@ module Webgen
55
68
  # Extracted meta information for the path.
56
69
  attr_accessor :meta_info
57
70
 
58
- # Create a new Path object for +path+. The optional block needs to return an IO object for the
59
- # content of the path.
60
- def initialize(path, &ioblock)
71
+ # Create a new Path object for +path+. The optional +source_path+ parameter specifies the path
72
+ # that lead to the creation of this path. The optional block needs to return an IO object for
73
+ # the content of the path.
74
+ def initialize(path, source_path = path, &ioblock)
61
75
  @meta_info = {}
62
76
  @io = SourceIO.new(&ioblock) if block_given?
77
+ @source_path = source_path
63
78
  analyse(path)
64
79
  end
65
80
 
@@ -70,6 +85,7 @@ module Webgen
70
85
  temp.path = temp.path.sub(/^#{Regexp.escape(prefix.chomp("/"))}/, '') if prefix #"
71
86
  reanalyse = (@path == '/' || temp.path == '/')
72
87
  temp.path = File.join(mp, temp.path)
88
+ temp.source_path = temp.path if @path == @source_path
73
89
  if reanalyse
74
90
  temp.send(:analyse, temp.path)
75
91
  else
@@ -131,12 +147,6 @@ module Webgen
131
147
  end
132
148
  alias_method(:eql?, :==)
133
149
 
134
- # Return +true+ if the localized path matches the given +pattern+. For information on which
135
- # patterns are supported, have a look at the documentation of File.fnmatch.
136
- def =~(pattern)
137
- File.fnmatch(pattern, File.join(@directory, lcn), File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
138
- end
139
-
140
150
  # Implemented sothat a Path looks like a String when used as key in a hash.
141
151
  def <=>(other)
142
152
  @path <=> other.to_str
@@ -42,9 +42,18 @@ module Webgen::SourceHandler
42
42
  # <tt>node_info[:processor]</tt>:: Has to be set to the class name of the source handler. This is
43
43
  # used by the Node class: all unknown method calls are forwarded
44
44
  # to the node processor.
45
- # <tt>node_info[:src]</tt>:: Has to be set to the string version of the source path.
45
+ # <tt>node_info[:src]</tt>:: Has to be set to the string version of the path that lead to the
46
+ # creation of the node.
47
+ # <tt>node_info[:creation_path]</tt>:: Has to be set to the string version of the path that is
48
+ # used to create the path.
46
49
  # <tt>meta_info['no_output']</tt>:: Has to be set to +true+ on nodes that are used during a
47
50
  # webgen run but do not produce an output file.
51
+ # <tt>meta_info['modified_at']</tt>:: Is automatically set to the current time if not already set
52
+ # correctly (ie. if not a Time object).
53
+ #
54
+ # Note: The difference between +:src+ and +:creation_path+ is that a creation path need not have
55
+ # an existing source path representation. For example, fragments created from a page source path
56
+ # have a different +:creation_path+ which includes the fragment part.
48
57
  #
49
58
  # Additional information that is used only for processing purposes should be stored in the
50
59
  # #node_info hash of a node as the #meta_info hash is reserved for real node meta information and
@@ -55,7 +64,8 @@ module Webgen::SourceHandler
55
64
  # Path patterns define which paths are handled by a specific source handler. These patterns are
56
65
  # specified in the <tt>sourcehandler.patterns</tt> configuration hash as a mapping from the source
57
66
  # handler class name to an array of path patterns. The patterns need to have a format that
58
- # <tt>Dir.glob</tt> can handle.
67
+ # <tt>Dir.glob</tt> can handle. You can use the configuration helper +patterns+ to set this (is
68
+ # shown in the example below).
59
69
  #
60
70
  # Specifying a path pattern does not mean that webgen uses the source handler. One also needs to
61
71
  # provide an entry in the configuration value <tt>sourcehandler.invoke</tt>. This is a hash that
@@ -97,7 +107,7 @@ module Webgen::SourceHandler
97
107
  #
98
108
  # end
99
109
  #
100
- # WebsiteAccess.website.config.sourcehandler.patterns['SimpleCopy'] = ['**/*.jpg', '**/*.png']
110
+ # WebsiteAccess.website.config.patterns('SimpleCopy' => ['**/*.jpg', '**/*.png'])
101
111
  # WebsiteAccess.website.config.sourcehandler.invoke[5] << 'SimpleCopy'
102
112
  #
103
113
  module Base
@@ -156,7 +166,9 @@ module Webgen::SourceHandler
156
166
  if OutputPathHelpers.public_instance_methods(false).include?(method)
157
167
  name = send(method, parent, path, use_lang_part)
158
168
  name += '/' if path.path =~ /\/$/ && name !~ /\/$/
159
- if node_exists?(parent, path, name)
169
+ if (node = node_exists?(parent, path, name)) && node.lang == path.meta_info['lang']
170
+ name = node.path
171
+ elsif node
160
172
  name = send(method, parent, path, (path.meta_info['lang'].nil? ? false : true))
161
173
  name += '/' if path.path =~ /\/$/ && name !~ /\/$/
162
174
  end
@@ -172,21 +184,31 @@ module Webgen::SourceHandler
172
184
  parent.tree[Webgen::Node.absolute_name(parent, path.lcn, :alcn)] || (!path.meta_info['no_output'] && parent.tree[output_path, :path])
173
185
  end
174
186
 
175
- # Create and return a node under +parent+ from +path+ if it does not already exists. Some
187
+ # Create a node under +parent+ from +path+ if it does not already exists or needs to be
188
+ # re-initialized. The found node or the newly created node is returned afterwards. +nil+ is
189
+ # returned if no node can be created (e.g. when <tt>path.meta_info['draft']</tt> is set). Some
176
190
  # additional node information like <tt>:src</tt> and <tt>:processor</tt> is set and the meta
177
- # information is checked for validness. The created node is yielded if a block is given.
191
+ # information is checked for validness. The created/re-initialized node is yielded if a block is
192
+ # given.
178
193
  def create_node(parent, path, output_path = self.output_path(parent, path))
179
- return if path.meta_info['draft']
180
- if !node_exists?(parent, path, output_path)
194
+ return nil if path.meta_info['draft']
195
+ node = node_exists?(parent, path, output_path)
196
+ if node && (node.node_info[:src] != path.source_path || node.node_info[:processor] != self.class.name)
197
+ log(:warn) { "Node already exists: source = #{path.source_path} | path = #{node.path} | alcn = #{node.absolute_lcn}"}
198
+ return node
199
+ elsif !node
181
200
  node = Webgen::Node.new(parent, output_path, path.cn, path.meta_info)
182
- node['modified_at'] = Time.now unless node['modified_at'].kind_of?(Time)
183
- node.node_info[:src] = path.path
184
- node.node_info[:processor] = self.class.name
185
- yield(node) if block_given?
186
- node
201
+ elsif node.flagged(:reinit)
202
+ node.reinit(output_path, path.meta_info)
187
203
  else
188
- log(:warn) { "Node already exists: output path = #{output_path} | alcn = #{Webgen::Node.absolute_name(parent, path.lcn, :alcn)}"}
204
+ return node
189
205
  end
206
+ node['modified_at'] = Time.now unless node['modified_at'].kind_of?(Time)
207
+ node.node_info[:src] = path.source_path
208
+ node.node_info[:creation_path] = path.path
209
+ node.node_info[:processor] = self.class.name
210
+ yield(node) if block_given?
211
+ node
190
212
  end
191
213
 
192
214
  # Return the content of the given +node+. This default +content+ method just returns +nil+.