webgen 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/ChangeLog +154 -0
  2. data/Rakefile +1 -1
  3. data/TODO +7 -4
  4. data/VERSION +1 -1
  5. data/doc/plugin/extension.rb +9 -1
  6. data/doc/src/about.page +2 -2
  7. data/doc/src/default.css +2 -2
  8. data/doc/src/default.template +4 -2
  9. data/doc/src/documentation/cli.page +1 -1
  10. data/doc/src/documentation/gettingstarted.page +4 -4
  11. data/doc/src/documentation/index.page +5 -5
  12. data/doc/src/documentation/meta_info_reference.page +21 -0
  13. data/doc/src/documentation/plugins/filehandler/directory.page +12 -0
  14. data/doc/src/documentation/plugins/filehandler/index.page +21 -5
  15. data/doc/src/documentation/plugins/filehandler/pagehandler.page +31 -3
  16. data/doc/src/documentation/plugins/index.page +2 -2
  17. data/doc/src/documentation/plugins/tags/index.page +7 -2
  18. data/doc/src/documentation/plugins/tags/multilang.fr.page +1 -1
  19. data/doc/src/download.page +1 -1
  20. data/doc/src/features.page +3 -2
  21. data/doc/src/generated_by_webgen.png +0 -0
  22. data/doc/src/index.page +18 -5
  23. data/doc/src/meta.info +8 -5
  24. data/install.rb +1 -1
  25. data/lib/{util → webgen}/composite.rb +1 -1
  26. data/lib/webgen/configuration.rb +2 -2
  27. data/lib/{util → webgen}/listener.rb +1 -1
  28. data/lib/webgen/node.rb +10 -10
  29. data/lib/webgen/plugin.rb +19 -12
  30. data/lib/webgen/plugins/filehandler/backing.rb +7 -4
  31. data/lib/webgen/plugins/filehandler/directory.rb +10 -9
  32. data/lib/webgen/plugins/filehandler/filecopy.rb +5 -6
  33. data/lib/webgen/plugins/filehandler/filehandler.rb +104 -89
  34. data/lib/webgen/plugins/filehandler/page.rb +45 -16
  35. data/lib/webgen/plugins/filehandler/picturegallery.rb +4 -3
  36. data/lib/webgen/plugins/filehandler/template.rb +4 -2
  37. data/lib/webgen/plugins/tags/langbar.rb +2 -2
  38. data/lib/webgen/plugins/tags/menu.rb +48 -35
  39. data/lib/webgen/plugins/tags/relocatable.rb +18 -6
  40. data/lib/webgen/plugins/tags/sitemap.rb +10 -9
  41. data/lib/webgen/plugins/tags/wikilink.rb +3 -1
  42. data/testsite/src/projects/00.index.de.page +1 -1
  43. data/testsite/src/projects/subproj/index.page +1 -1
  44. metadata +7 -5
@@ -1,7 +1,7 @@
1
1
  #
2
2
  #--
3
3
  #
4
- # $Id: filecopy.rb 249 2005-04-13 19:23:51Z thomas $
4
+ # $Id: filecopy.rb 269 2005-05-08 16:06:40Z thomas $
5
5
  #
6
6
  # webgen: template based static website generator
7
7
  # Copyright (C) 2004 Thomas Leitner
@@ -30,15 +30,14 @@ module FileHandlers
30
30
  class FileCopyHandler < DefaultFileHandler
31
31
 
32
32
  summary "Copies files from source to destination without modification"
33
- add_param 'types', ['css', 'jpg', 'png', 'gif'], \
34
- 'The extension that will be registered by this handler. All files with ' \
35
- 'these extensions will be copied from the source to the destination folder.'
33
+ add_param 'paths', ['**/*.css', '**/*.jpg', '**/*.png', '**/*.gif'], \
34
+ 'The path patterns which should match the files that should get copied by this handler.'
36
35
  depends_on 'FileHandler'
37
36
 
38
37
  def initialize
39
38
  super
40
- get_param( 'types' ).each do |type|
41
- extension( type )
39
+ get_param( 'paths' ).each do |path|
40
+ self.class.handle_path( path )
42
41
  end
43
42
  end
44
43
 
@@ -1,7 +1,7 @@
1
1
  #
2
2
  #--
3
3
  #
4
- # $Id: filehandler.rb 256 2005-04-14 01:13:57Z thomas $
4
+ # $Id: filehandler.rb 272 2005-05-09 08:53:04Z thomas $
5
5
  #
6
6
  # webgen: template based static website generator
7
7
  # Copyright (C) 2004 Thomas Leitner
@@ -20,13 +20,11 @@
20
20
  #++
21
21
  #
22
22
 
23
- require 'util/listener'
23
+ require 'set'
24
+ require 'webgen/listener'
24
25
 
25
26
  module FileHandlers
26
27
 
27
- # Super plugin for handling files. File handler plugins can register themselves by adding a new
28
- # key:value pair to +extensions+. The key has to be the extension in lowercase and the value is
29
- # the plugin object itself.
30
28
  class FileHandler < Webgen::Plugin
31
29
 
32
30
  summary "Super plugin for handling files"
@@ -35,31 +33,50 @@ module FileHandlers
35
33
  builds the tree. When all approriate transformations on the tree have
36
34
  been performed the FileHandler is used to write the output files.
37
35
  ".gsub( /^\s+/, '' ).gsub( /\n/, ' ' )
38
-
39
- add_param 'ignored', ['.svn', 'CVS'], 'Specifies path names via regular expresssions which should be ignored.'
40
-
36
+ add_param 'ignorePaths', ['**/.svn{/**/**,/}', '**/CVS{/**/**,/}'], 'An array of path patterns which match files that should ' \
37
+ 'be excluded from the list of \'to be processed\' files.'
41
38
 
42
39
  include Listener
43
40
 
44
- attr_reader :extensions
45
-
46
41
  def initialize
47
- @extensions = Hash.new
48
-
49
- add_msg_name( :DIR_NODE_CREATED )
50
- add_msg_name( :FILE_NODE_CREATED )
51
- add_msg_name( :AFTER_DIR_READ )
42
+ add_msg_name( :AFTER_ALL_READ )
52
43
  end
53
44
 
54
-
55
- # Recursively builds the tree with all the nodes and returns it.
45
+ # Builds the tree with all the nodes and returns it.
56
46
  def build_tree
57
- root = build_entry( Webgen::Plugin['Configuration']['srcDirectory'], nil )
58
- unless root.nil?
59
- root['title'] = '/'
60
- root['dest'] = Webgen::Plugin['Configuration']['outDirectory'] + '/'
61
- root['src'] = Webgen::Plugin['Configuration']['srcDirectory'] + '/'
47
+ allFiles = get_files_for_pattern( File.join( '**', '{.[^.]**/**/**,**}' ) )
48
+ get_param( 'ignorePaths' ).each do |pattern|
49
+ allFiles.subtract( get_files_for_pattern( pattern ) )
62
50
  end
51
+
52
+ handlerFiles = sort_file_handlers( Webgen::Plugin['DefaultFileHandler'].get_file_handlers ).collect do |pattern, handler|
53
+ [get_files_for_pattern( pattern ), Webgen::Plugin.config[handler].obj]
54
+ end
55
+
56
+ rootPath = Webgen::Plugin['Configuration']['srcDirectory'] + File::SEPARATOR
57
+ rootHandler = handler_for_path( rootPath, handlerFiles )
58
+ if rootHandler.nil? || allFiles.empty?
59
+ logger.error { "No file handler for root directory <#{rootPath}> found" } if rootHandler.nil?
60
+ logger.error { "No files found in directory <#{rootPath}>" } if allFiles.empty?
61
+ return nil
62
+ end
63
+
64
+ logger.debug { "Using plugin #{rootHandler.class.name} for handling the root node" }
65
+ root = create_root_node( rootPath, rootHandler )
66
+ allFiles.subtract( [rootPath] )
67
+ handlerFiles.find {|files, handler| handler == rootHandler}[0].subtract( [rootPath] )
68
+
69
+ handlerFiles.each do |files, handler|
70
+ commonFiles = allFiles & files
71
+ allFiles.subtract( commonFiles )
72
+ diffFiles = files - commonFiles
73
+ logger.info { "Not handling files for #{handler.class.name} as they do not exist or are excluded: #{diffFiles.inspect}" } if diffFiles.length > 0
74
+ commonFiles.each {|file| build_entry( file, root, handler, handlerFiles ) }
75
+ end
76
+
77
+ dispatch_msg( :AFTER_ALL_READ, root )
78
+ logger.info { "No handlers found for files: #{allFiles.inspect}" } if allFiles.length > 0
79
+
63
80
  root
64
81
  end
65
82
 
@@ -71,7 +88,7 @@ module FileHandlers
71
88
  node['processor'].write_node( node )
72
89
 
73
90
  node.each do |child|
74
- write_tree child
91
+ write_tree( child )
75
92
  end
76
93
  end
77
94
 
@@ -87,70 +104,60 @@ module FileHandlers
87
104
  end
88
105
  end
89
106
 
90
-
91
107
  #######
92
108
  private
93
109
  #######
94
110
 
95
- def build_entry( path, parent )
96
- self.logger.info { "Processing <#{path}> ..." }
97
-
98
- if FileTest.file?( path )
99
- node = handle_file( path, parent )
100
- elsif FileTest.directory?( path )
101
- node = handle_directory( path, parent )
102
- else
103
- type = File.lstat( path ).ftype if File.exists?( path )
104
- self.logger.warn { "Path <#{path}> (type: #{type || 'non existing file/dir'}) cannot be handled as it is neither a file nor a directory" }
105
- node = nil
111
+ def get_files_for_pattern( pattern )
112
+ files = Dir[File.join( Webgen::Plugin['Configuration']['srcDirectory'], pattern )].to_set
113
+ files.collect! do |f|
114
+ f = f.sub( /([^.])\.{1,2}$/, '\1' ) # remove '.' and '..' from end of paths
115
+ f += File::SEPARATOR if File.directory?( f ) && ( f[-1] != ?/ )
116
+ f
106
117
  end
107
-
108
- return node
118
+ files
109
119
  end
110
120
 
111
-
112
- def handle_file( path, parent )
113
- extension = File.extname( path ).sub( /^./, '' )
114
-
115
- if @extensions.has_key?( extension )
116
- node = @extensions[extension].create_node( path, parent )
117
- dispatch_msg( :FILE_NODE_CREATED, node ) unless node.nil?
118
- else
119
- self.logger.warn { "No plugin for <#{path}> (extension: #{extension}) -> ignored" }
120
- end
121
-
122
- return node
121
+ def create_root_node( path, handler )
122
+ root = handler.create_node( path, nil )
123
+ root['title'] = '/'
124
+ root['dest'] = Webgen::Plugin['Configuration']['outDirectory'] + '/'
125
+ root['src'] = Webgen::Plugin['Configuration']['srcDirectory'] + '/'
126
+ root
123
127
  end
124
128
 
125
-
126
- def handle_directory( path, parent )
127
- node = nil
128
-
129
- if @extensions.has_key?( :dir )
130
- node = @extensions[:dir].create_node( path, parent )
131
-
132
- dispatch_msg( :DIR_NODE_CREATED, node )
133
-
134
- Dir[path + File::SEPARATOR + '{.*,*}'].delete_if do |name|
135
- name =~ /#{File::SEPARATOR}\.{1,2}$/ || \
136
- File.basename( name ) =~ Regexp.new( get_param( 'ignored' ).join( '|' ) )
137
- end.sort! do |a, b|
138
- if File.file?( a ) && File.directory?( b )
139
- -1
140
- elsif ( File.file?( a ) && File.file?( b ) ) || ( File.directory?( a ) && File.directory?( b ) )
141
- a <=> b
142
- else
143
- 1
144
- end
145
- end.each do |filename|
146
- child = build_entry( filename, node )
147
- node.add_child( child ) unless child.nil?
129
+ def build_entry( file, root, handler, handlerFiles )
130
+ pathname, filename = File.split( file )
131
+ pathname = pathname + '/'
132
+ treeFile = file.sub( /^#{root['src']}/, '' )
133
+ treePath = pathname.sub( /^#{root['src']}/, '' )
134
+
135
+ node = root.node_for_string?( treeFile, 'src' )
136
+ return node unless node.nil?
137
+ logger.info { "Processing <#{file}> with #{handler.class.name} ..." }
138
+
139
+ parentNode = root.node_for_string?( treePath )
140
+ if parentNode.nil?
141
+ if pathname == root['src']
142
+ parentNode = root
143
+ else
144
+ logger.debug { "Parent node for <#{file}> does not exist, create node for path <#{pathname}>" }
145
+ parentNode = build_entry( pathname, root, handler_for_path( pathname, handlerFiles ), handlerFiles )
148
146
  end
149
-
150
- dispatch_msg( :AFTER_DIR_READ, node )
151
147
  end
148
+ raise "Parent node is nil" if parentNode.nil?
149
+ logger.info { "Creating node for <#{file}>..." }
150
+ n = handler.create_node( file, parentNode )
151
+ parentNode.add_child( n ) unless n.nil?
152
+ n
153
+ end
152
154
 
153
- return node
155
+ def handler_for_path( path, handlerFiles )
156
+ handlerFiles.find {|p, handler| p.include?( path )}[1]
157
+ end
158
+
159
+ def sort_file_handlers( handlers )
160
+ handlers.sort {|a,b| a[0].count( "?*" ) <=> b[0].count( "?*" )}
154
161
  end
155
162
 
156
163
  end
@@ -158,21 +165,25 @@ module FileHandlers
158
165
  # The default handler which is the super class of all file handlers.
159
166
  class DefaultFileHandler < Webgen::Plugin
160
167
 
161
- VIRTUAL = true
162
-
163
168
  summary "Base class of all file handler plugins"
164
169
 
165
- def initialize
166
- extension( Webgen::Plugin.config[self.class].extension ) if Webgen::Plugin.config[self.class].extension
170
+ # Specify the extension which should be handled by the class.
171
+ def self.handle_path( path )
172
+ logger.info { "Registering class #{self.name} for handling the path pattern: #{path.inspect}" }
173
+ (@@config[self].path ||= []) << path
174
+ handlers = (@@config[DefaultFileHandler].file_handler ||= {})
175
+ logger.warn { "Path pattern #{path} already associated with class #{handlers[path].name}, not using class #{self.name} for it!" } if handlers[path]
176
+ handlers[path] ||= self
167
177
  end
168
178
 
169
- # Specify the extension which should be handled by the class.
170
- def self.extension( ext ); @@config[self].extension = ext; end
179
+ # Specify the files handled by the class via the extension.
180
+ def self.extension( ext )
181
+ handle_path( "**/{.[^.]**/**/*.#{ext},*.#{ext}}" )
182
+ end
171
183
 
172
- # Register the file extension specified by a subclass.
173
- def extension( ext )
174
- self.logger.info { "Registering file handler #{self.class.name} (#{self.object_id}) with extension '#{ext}'" }
175
- Webgen::Plugin['FileHandler'].extensions[ext] = self
184
+ # Return the registered file handler plugins.
185
+ def get_file_handlers
186
+ @@config[self.class].file_handler
176
187
  end
177
188
 
178
189
  # Supplies the +path+ to a file and the +parent+ node sothat the plugin can create a node for this
@@ -180,21 +191,25 @@ module FileHandlers
180
191
  #
181
192
  # Has to be overridden by the subclass!!!
182
193
  def create_node( path, parent )
183
- raise "Not implemented"
194
+ raise NotImplementedError
184
195
  end
185
196
 
186
197
  # Asks the plugin to write out the node.
187
198
  #
188
199
  # Has to be overridden by the subclass!!!
189
200
  def write_node( node )
190
- raise "Not implemented"
201
+ raise NotImplementedError
202
+ end
203
+
204
+ # Returns the node for the language +lang+ which is equal to this +node+.
205
+ def get_node_for_lang( node, lang )
206
+ node
191
207
  end
192
208
 
193
209
  # Returns a HTML link for the given +node+ relative to +refNode+. You can optionally specify the
194
210
  # title for the link. If not specified, the title of the node is used.
195
211
  def get_html_link( node, refNode, title = node['title'] )
196
- url = refNode.relpath_to_node( node )
197
- "<a href=\"#{url}\">#{title}</a>"
212
+ "<a href=\"#{refNode.relpath_to_node( node )}\">#{title}</a>"
198
213
  end
199
214
 
200
215
  end
@@ -1,7 +1,7 @@
1
1
  #
2
2
  #--
3
3
  #
4
- # $Id: page.rb 256 2005-04-14 01:13:57Z thomas $
4
+ # $Id: page.rb 277 2005-05-12 08:43:54Z thomas $
5
5
  #
6
6
  # webgen: template based static website generator
7
7
  # Copyright (C) 2004 Thomas Leitner
@@ -22,6 +22,7 @@
22
22
 
23
23
  require 'webgen/plugins/filehandler/filehandler'
24
24
  require 'yaml'
25
+ require 'erb'
25
26
 
26
27
  module FileHandlers
27
28
 
@@ -32,7 +33,9 @@ module FileHandlers
32
33
  class PageNode < Node; end;
33
34
 
34
35
  summary "Class for processing page files"
36
+ depends_on 'FileHandler', 'DefaultContentHandler'
35
37
  extension 'page'
38
+
36
39
  add_param 'defaultLangInFilename', false, \
37
40
  'If true, the output files for the default language will have the ' \
38
41
  'language in the file name like all other page files. If false, they won''t.'
@@ -41,7 +44,9 @@ module FileHandlers
41
44
  'the :name part and the file language will be used for the :lang part. If <defaultLangInFilename> is true, the :lang part or the subarray in which '\
42
45
  'the :lang part was defined, will be omitted.'
43
46
  add_param 'validator', 'xmllint', 'The validator for checking HTML files on their validness. Set to "" or nil to prevent checking.'
44
- depends_on 'FileHandler', 'DefaultContentHandler'
47
+ add_param 'useERB', true, 'Specifies if the content blocks of the page file should be processed with ERB before they are formatted.'
48
+
49
+ used_meta_info 'title', 'orderInfo', 'lang', 'blocks', 'useERB'
45
50
 
46
51
  def create_node( srcName, parent )
47
52
  create_node_internally( parse_data( File.read( srcName ), srcName ), analyse_file_name( File.basename( srcName ) ), parent )
@@ -52,12 +57,25 @@ module FileHandlers
52
57
  end
53
58
 
54
59
  def write_node( node )
55
- # do nothing if page base node
56
60
  templateNode = Webgen::Plugin['TemplateFileHandler'].get_template_for_node( node )
57
61
 
58
- outstring = templateNode['content'].dup
59
-
60
- Webgen::Plugin['Tags'].substitute_tags( outstring, node, templateNode )
62
+ useERB = node['useERB'] || ( node['useERB'].nil? && get_param( 'useERB' ) )
63
+ node['blocks'].each do |blockdata|
64
+ begin
65
+ content = ( useERB ? ERB.new( blockdata['data'] ).result( binding ) : blockdata['data'] )
66
+ rescue Exception => e
67
+ logger.error { "ERB threw an error while processing an ERB template (<#{node.recursive_value('src')}>, block #{blockdata['name']}): #{e.message}" }
68
+ content = blockdata['data']
69
+ end
70
+ node[blockdata['name']] = Webgen::Plugin['DefaultContentHandler'].get_format( blockdata['format'] ).format_content( content )
71
+ end
72
+ begin
73
+ outstring = ERB.new( templateNode['content'] ).result( binding )
74
+ rescue Exception => e
75
+ logger.error { "ERB threw an error while processing an ERB template (<#{templateNode.recursive_value('src')}>: #{e.message}" }
76
+ outstring = templateNode['content'].dup
77
+ end
78
+ outstring = Webgen::Plugin['Tags'].substitute_tags( outstring, node, templateNode )
61
79
 
62
80
  File.open( node.recursive_value( 'dest' ), File::CREAT|File::TRUNC|File::RDWR ) do |file|
63
81
  file.write( outstring )
@@ -69,17 +87,18 @@ module FileHandlers
69
87
  end
70
88
  end
71
89
 
90
+ # Returns a page node in +dirNode+ which has the name +name+.
72
91
  def get_page_node_by_name( dirNode, name )
73
- dirNode.find {|node| node['page:name'] == name}
92
+ dirNode.find {|node| node['int:pagename'] == name}
74
93
  end
75
94
 
76
- # Returns the page node for the given language. +node+ has to be a page node!
77
- def get_page_node_for_lang( node, lang )
95
+ # Returns the page node for the given language.
96
+ def get_node_for_lang( node, lang )
78
97
  dirNode = node.parent
79
- pageNode = dirNode.find {|child| child['page:name'] == node['page:name'] && child['lang'] == lang}
98
+ pageNode = dirNode.find {|child| child['int:pagename'] == node['int:pagename'] && child['lang'] == lang}
80
99
  if pageNode.nil?
81
100
  self.logger.info { "No page node in language '#{lang}' for page '#{node['title']}' found, trying default language" }
82
- pageNode = dirNode.find {|child| child['page:name'] == node['page:name'] && child['lang'] == Webgen::Plugin['Configuration']['lang']}
101
+ pageNode = dirNode.find {|child| child['int:pagename'] == node['int:pagename'] && child['lang'] == Webgen::Plugin['Configuration']['lang']}
83
102
  if pageNode.nil?
84
103
  self.logger.warn do
85
104
  "No page node in default language (#{Webgen::Plugin['Configuration']['lang']}) " + \
@@ -91,6 +110,14 @@ module FileHandlers
91
110
  pageNode
92
111
  end
93
112
 
113
+ # Get the HTML link for the page +node+.
114
+ def get_html_link( node, refNode, title = nil )
115
+ lang_node = get_node_for_lang( node, refNode['lang'] )
116
+ title ||= lang_node['title']
117
+ super( lang_node, refNode, title )
118
+ end
119
+
120
+
94
121
  #######
95
122
  private
96
123
  #######
@@ -98,7 +125,9 @@ module FileHandlers
98
125
  def create_node_internally( data, analysed, parent )
99
126
  lang = data['lang'] || analysed.lang
100
127
 
101
- if node = parent.find {|node| node['page:commonName'] == analysed.name && node['lang'] == lang }
128
+ pagename = create_output_name( analysed, data['outputNameStyle'] || get_param( 'outputNameStyle' ), true )
129
+
130
+ if node = parent.find {|node| node['int:pagename'] == pagename && node['lang'] == lang }
102
131
  logger.warn do
103
132
  "Two input files in the same language for one page, " + \
104
133
  "using <#{node.recursive_value( 'src' )}> instead of <#{analysed.srcName}>"
@@ -108,10 +137,10 @@ module FileHandlers
108
137
  node.metainfo = data
109
138
  node['lang'] ||= analysed.lang
110
139
  node['title'] ||= analysed.title
111
- node['menuOrder'] ||= analysed.menuOrder
140
+ node['orderInfo'] ||= analysed.orderInfo
112
141
  node['src'] = analysed.srcName
113
142
  node['dest'] = create_output_name( analysed, node['outputNameStyle'] || get_param( 'outputNameStyle' ) )
114
- node['page:name'] = create_output_name( analysed, node['outputNameStyle'] || get_param( 'outputNameStyle' ), true )
143
+ node['int:pagename'] = pagename
115
144
  node['processor'] = self
116
145
  end
117
146
 
@@ -137,7 +166,7 @@ module FileHandlers
137
166
  next
138
167
  end
139
168
  self.logger.debug { "Block '#{blockdata['name']}' formatted using '#{blockdata['format']}'" }
140
- options[blockdata['name']] = Webgen::Plugin['DefaultContentHandler'].get_format( blockdata['format'] ).format_content( blocks.shift || '' )
169
+ blockdata['data'] = blocks.shift || ''
141
170
  end
142
171
  end
143
172
  options
@@ -152,7 +181,7 @@ module FileHandlers
152
181
  analysed.srcName = srcName
153
182
  analysed.useLangPart = ( !get_param( 'defaultLangInFilename' ) && Webgen::Plugin['Configuration']['lang'] == analysed.lang ? false : true )
154
183
  analysed.name = matchData[2]
155
- analysed.menuOrder = matchData[1].to_i
184
+ analysed.orderInfo = matchData[1].to_i
156
185
  analysed.title = matchData[2].tr('_-', ' ').capitalize
157
186
 
158
187
  self.logger.debug { analysed.inspect }