gettalong-webgen 0.5.5.20081001 → 0.5.5.20081010

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 (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+.