webgen 0.5.8 → 0.5.9
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +4 -0
- data/ChangeLog +1037 -0
- data/Rakefile +5 -6
- data/THANKS +1 -0
- data/VERSION +1 -1
- data/bin/webgen +1 -1
- data/data/webgen/passive_sources/images/generated_by_webgen.png +0 -0
- data/data/webgen/passive_sources/images/webgen_logo.png +0 -0
- data/data/webgen/passive_sources/stylesheets/coderay-default.css +129 -0
- data/data/webgen/passive_sources/templates/atom_feed.template +38 -0
- data/data/webgen/passive_sources/templates/rss_feed.template +28 -0
- data/data/webgen/passive_sources/templates/sitemap.template +21 -0
- data/data/webgen/resources.yaml +2 -1
- data/data/webgen/website_skeleton/Rakefile +5 -1
- data/doc/contentprocessor/builder.page +2 -2
- data/doc/contentprocessor/erb.page +5 -2
- data/doc/contentprocessor/erubis.page +2 -2
- data/doc/contentprocessor/head.page +21 -0
- data/doc/contentprocessor/tidy.page +14 -0
- data/doc/extensions.page +1 -1
- data/doc/faq.page +2 -2
- data/doc/manual.page +108 -43
- data/doc/reference_configuration.page +83 -5
- data/doc/reference_metainfo.page +24 -4
- data/doc/reference_website_styles.page +2 -2
- data/doc/sourcehandler/feed.page +11 -13
- data/doc/sourcehandler/metainfo.page +10 -3
- data/doc/sourcehandler/page.page +4 -4
- data/doc/sourcehandler/sitemap.page +8 -7
- data/doc/tag/coderay.page +6 -2
- data/doc/tag/includefile.page +1 -1
- data/doc/tag/menu.page +3 -0
- data/lib/webgen/cli/apply_command.rb +1 -1
- data/lib/webgen/cli/utils.rb +2 -2
- data/lib/webgen/common.rb +0 -9
- data/lib/webgen/contentprocessor.rb +18 -3
- data/lib/webgen/contentprocessor/blocks.rb +67 -36
- data/lib/webgen/contentprocessor/builder.rb +5 -2
- data/lib/webgen/contentprocessor/erb.rb +4 -2
- data/lib/webgen/contentprocessor/erubis.rb +5 -2
- data/lib/webgen/contentprocessor/haml.rb +6 -2
- data/lib/webgen/contentprocessor/head.rb +64 -0
- data/lib/webgen/contentprocessor/maruku.rb +3 -1
- data/lib/webgen/contentprocessor/rdiscount.rb +2 -0
- data/lib/webgen/contentprocessor/rdoc.rb +2 -0
- data/lib/webgen/contentprocessor/redcloth.rb +2 -0
- data/lib/webgen/contentprocessor/sass.rb +5 -3
- data/lib/webgen/contentprocessor/tags.rb +40 -24
- data/lib/webgen/contentprocessor/tidy.rb +38 -0
- data/lib/webgen/context.rb +13 -4
- data/lib/webgen/context/render.rb +32 -0
- data/lib/webgen/context/tags.rb +20 -0
- data/lib/webgen/default_config.rb +15 -4
- data/lib/webgen/deprecated.rb +38 -4
- data/lib/webgen/error.rb +135 -0
- data/lib/webgen/node.rb +48 -40
- data/lib/webgen/output.rb +5 -3
- data/lib/webgen/output/filesystem.rb +4 -4
- data/lib/webgen/page.rb +4 -4
- data/lib/webgen/path.rb +161 -58
- data/lib/webgen/source.rb +9 -6
- data/lib/webgen/source/filesystem.rb +1 -1
- data/lib/webgen/source/stacked.rb +13 -5
- data/lib/webgen/source/tararchive.rb +6 -2
- data/lib/webgen/sourcehandler.rb +100 -54
- data/lib/webgen/sourcehandler/base.rb +58 -24
- data/lib/webgen/sourcehandler/copy.rb +6 -5
- data/lib/webgen/sourcehandler/directory.rb +3 -9
- data/lib/webgen/sourcehandler/feed.rb +25 -50
- data/lib/webgen/sourcehandler/fragment.rb +10 -8
- data/lib/webgen/sourcehandler/memory.rb +9 -10
- data/lib/webgen/sourcehandler/metainfo.rb +9 -9
- data/lib/webgen/sourcehandler/page.rb +6 -5
- data/lib/webgen/sourcehandler/sitemap.rb +22 -22
- data/lib/webgen/sourcehandler/template.rb +6 -6
- data/lib/webgen/sourcehandler/virtual.rb +19 -17
- data/lib/webgen/tag/base.rb +27 -27
- data/lib/webgen/tag/breadcrumbtrail.rb +3 -3
- data/lib/webgen/tag/coderay.rb +19 -8
- data/lib/webgen/tag/executecommand.rb +4 -3
- data/lib/webgen/tag/langbar.rb +2 -2
- data/lib/webgen/tag/link.rb +8 -7
- data/lib/webgen/tag/menu.rb +2 -2
- data/lib/webgen/tag/metainfo.rb +1 -1
- data/lib/webgen/tag/relocatable.rb +17 -21
- data/lib/webgen/tag/tikz.rb +7 -10
- data/lib/webgen/tree.rb +7 -7
- data/lib/webgen/version.rb +1 -1
- data/lib/webgen/website.rb +32 -2
- data/misc/default.css +8 -2
- data/misc/default.template +2 -2
- data/misc/logo.svg +313 -0
- data/misc/style.page +1 -1
- data/test/helper.rb +18 -2
- data/test/test_cli.rb +104 -0
- data/test/test_common_sitemap.rb +1 -1
- data/test/test_contentprocessor.rb +8 -2
- data/test/test_contentprocessor_blocks.rb +17 -8
- data/test/test_contentprocessor_builder.rb +13 -2
- data/test/test_contentprocessor_erb.rb +9 -3
- data/test/test_contentprocessor_erubis.rb +9 -3
- data/test/test_contentprocessor_fragments.rb +12 -11
- data/test/test_contentprocessor_haml.rb +11 -2
- data/test/test_contentprocessor_head.rb +44 -0
- data/test/test_contentprocessor_maruku.rb +5 -1
- data/test/test_contentprocessor_rdiscount.rb +4 -0
- data/test/test_contentprocessor_rdoc.rb +4 -0
- data/test/test_contentprocessor_redcloth.rb +5 -1
- data/test/test_contentprocessor_sass.rb +8 -2
- data/test/test_contentprocessor_tags.rb +22 -7
- data/test/test_contentprocessor_tidy.rb +34 -0
- data/test/test_context.rb +39 -0
- data/test/test_error.rb +85 -0
- data/test/test_node.rb +57 -21
- data/test/test_page.rb +23 -5
- data/test/test_path.rb +120 -64
- data/test/test_source_filesystem.rb +1 -1
- data/test/test_source_stacked.rb +19 -6
- data/test/test_sourcehandler_base.rb +63 -50
- data/test/test_sourcehandler_copy.rb +6 -6
- data/test/test_sourcehandler_directory.rb +8 -12
- data/test/test_sourcehandler_feed.rb +15 -7
- data/test/test_sourcehandler_fragment.rb +6 -5
- data/test/test_sourcehandler_main.rb +39 -0
- data/test/test_sourcehandler_memory.rb +4 -4
- data/test/test_sourcehandler_metainfo.rb +20 -11
- data/test/test_sourcehandler_page.rb +10 -10
- data/test/test_sourcehandler_sitemap.rb +24 -5
- data/test/test_sourcehandler_template.rb +18 -15
- data/test/test_sourcehandler_virtual.rb +9 -5
- data/test/test_tag_base.rb +6 -29
- data/test/test_tag_coderay.rb +16 -3
- data/test/test_tag_executecommand.rb +2 -2
- data/test/test_tag_link.rb +5 -4
- data/test/test_tag_menu.rb +15 -15
- data/test/test_tag_metainfo.rb +1 -0
- data/test/test_tag_relocatable.rb +3 -2
- data/test/test_tag_tikz.rb +5 -5
- data/test/test_tree.rb +8 -8
- data/test/test_website.rb +15 -0
- metadata +21 -14
- data/test/test_common.rb +0 -18
data/lib/webgen/output.rb
CHANGED
@@ -18,8 +18,10 @@ module Webgen
|
|
18
18
|
# Write the +data+ to the given output +path+. The parameter +data+ is either a String with the
|
19
19
|
# content or a Webgen::Path::SourceIO object. The parameter +type+ specifies the type of the to
|
20
20
|
# be written path: <tt>:file</tt> or <tt>:directory</tt>.
|
21
|
-
# [<tt>read(path)</tt>]
|
22
|
-
# Return the content of the given path if it exists or raise an error otherwise.
|
21
|
+
# [<tt>read(path, mode = 'rb')</tt>]
|
22
|
+
# Return the content of the given path if it exists or raise an error otherwise. The parameter
|
23
|
+
# +mode+ specifies the mode in which the path should be opened and defaults to reading in binary
|
24
|
+
# mode.
|
23
25
|
#
|
24
26
|
# It seems a bit odd that an output instance has to implement reading functionality. However,
|
25
27
|
# consider the case where you want webgen to render a website programmatically and *use* the
|
@@ -52,7 +54,7 @@ module Webgen
|
|
52
54
|
# @data[path] = [(io.kind_of?(String) ? io : io.data), type]
|
53
55
|
# end
|
54
56
|
#
|
55
|
-
# def read(path)
|
57
|
+
# def read(path, mode = 'rb')
|
56
58
|
# path = File.join('/', path)
|
57
59
|
# raise "No such file #{path}" unless @data[path] && @data[path].last == :file
|
58
60
|
# @data[path].first
|
@@ -50,7 +50,7 @@ module Webgen::Output
|
|
50
50
|
if data.kind_of?(String)
|
51
51
|
File.open(dest, 'wb') {|f| f.write(data) }
|
52
52
|
else
|
53
|
-
data.stream do |source|
|
53
|
+
data.stream('rb') do |source|
|
54
54
|
File.open(dest, 'wb') {|f| FileUtils.copy_stream(source, f) }
|
55
55
|
end
|
56
56
|
end
|
@@ -59,9 +59,9 @@ module Webgen::Output
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
# Return the content of the given +path+.
|
63
|
-
def read(path)
|
64
|
-
File.open(File.join(@root, path),
|
62
|
+
# Return the content of the given +path+ which is opened in +mode+.
|
63
|
+
def read(path, mode = 'rb')
|
64
|
+
File.open(File.join(@root, path), mode) {|f| f.read}
|
65
65
|
end
|
66
66
|
|
67
67
|
end
|
data/lib/webgen/page.rb
CHANGED
@@ -49,7 +49,7 @@ module Webgen
|
|
49
49
|
|
50
50
|
|
51
51
|
# Raised during parsing of data in Webgen Page Format if the data is invalid.
|
52
|
-
class FormatError <
|
52
|
+
class FormatError < StandardError; end
|
53
53
|
|
54
54
|
|
55
55
|
# :stopdoc:
|
@@ -57,7 +57,7 @@ module Webgen
|
|
57
57
|
RE_META_INFO = /\A---\s*(?:\n|\r|\r\n).*?(?:\n|\r|\r\n)(?=---.*?(?:\n|\r|\r\n)|\Z)/m
|
58
58
|
RE_BLOCKS_OPTIONS = /^--- *?(?: *((?:\w+:[^\s]* *)*))?$|^$/
|
59
59
|
RE_BLOCKS_START = /^--- .*?$|^--- *$/
|
60
|
-
RE_BLOCKS = /(?:(#{RE_BLOCKS_START})|\A)(.*?)(?:(?=#{RE_BLOCKS_START})|\
|
60
|
+
RE_BLOCKS = /(?:(#{RE_BLOCKS_START})|\A)\n?(.*?)(?:(?=#{RE_BLOCKS_START})|\z)/m
|
61
61
|
# :startdoc:
|
62
62
|
|
63
63
|
class << self
|
@@ -100,7 +100,7 @@ module Webgen
|
|
100
100
|
raise FormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
|
101
101
|
end
|
102
102
|
rescue ArgumentError => e
|
103
|
-
raise FormatError, e.message
|
103
|
+
raise FormatError, "Invalid YAML syntax in meta information block: #{e.message}"
|
104
104
|
end
|
105
105
|
meta_info
|
106
106
|
end
|
@@ -126,7 +126,7 @@ module Webgen
|
|
126
126
|
raise(FormatError, "Previously used name '#{name}' also used for block #{index+1}") if blocks.has_key?(name)
|
127
127
|
content ||= ''
|
128
128
|
content.gsub!(/^(\\+)(---.*?)$/) {|m| "\\" * ($1.length / 2) + $2}
|
129
|
-
content.
|
129
|
+
content.chomp!("\n") unless index + 1 == scanned.length
|
130
130
|
blocks[name] = blocks[index+1] = Block.new(name, content, options)
|
131
131
|
end
|
132
132
|
meta_info.delete('blocks')
|
data/lib/webgen/path.rb
CHANGED
@@ -1,11 +1,33 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
|
+
require 'pathname'
|
3
4
|
require 'webgen/languages'
|
4
5
|
|
5
6
|
module Webgen
|
6
7
|
|
7
|
-
#
|
8
|
-
#
|
8
|
+
# == General Information
|
9
|
+
#
|
10
|
+
# A Path object provides information about a path that is used to create one or more nodes as well
|
11
|
+
# as methods for accessing the path's content. So a Path object always refers to a source path. In
|
12
|
+
# contrast, output paths are always strings and just specify the location where a specific node
|
13
|
+
# should be written to.
|
14
|
+
#
|
15
|
+
# Note the +path+ and +source_path+ attributes of a Path object:
|
16
|
+
#
|
17
|
+
# * The +source_path+ specifies a path string that was directly created by a Source object. Each
|
18
|
+
# Path object must have such a valid source path sothat webgen can infer the Path the lead to
|
19
|
+
# the creation of a Node object later.
|
20
|
+
#
|
21
|
+
# * In contrast, the +path+ attribute specifies the path that is used to create the canonical name
|
22
|
+
# (and by default the output path) of a Node object. Normally it is the same as the
|
23
|
+
# +source_path+ but can differ (e.g. when fragment nodes are created for page file nodes).
|
24
|
+
#
|
25
|
+
# A Path object can represent one of three different things: a directory, a file or a fragment. If
|
26
|
+
# the +path+ ends with a slash character, then the path object represents a directory, if the path
|
27
|
+
# contains a hash character anywhere, then the path object represents a fragment and else it
|
28
|
+
# represents a file. Have a look at the webgen manual to see the exact format of a path!
|
29
|
+
#
|
30
|
+
# == Relation to Source classes
|
9
31
|
#
|
10
32
|
# A webgen source class needs to derive a specialized path class from this class and implement an
|
11
33
|
# approriate #changed? method that returns +true+ if the path's content has changed since the last
|
@@ -13,30 +35,48 @@ module Webgen
|
|
13
35
|
class Path
|
14
36
|
|
15
37
|
# Helper class for easy access to the content of a path.
|
38
|
+
#
|
39
|
+
# This class is used sothat the creation of the real IO object for #stream can be delayed till
|
40
|
+
# it is actually needed. This is done by not directly requiring the user of this class to supply
|
41
|
+
# the IO object, but by requiring a block that creates the real IO object.
|
16
42
|
class SourceIO
|
17
43
|
|
18
|
-
# Create a new SourceIO object. A block has to be specified that returns
|
44
|
+
# Create a new SourceIO object. A block has to be specified that returns the to-be-wrapped IO
|
45
|
+
# object.
|
19
46
|
def initialize(&block)
|
20
47
|
@block = block
|
21
|
-
raise ArgumentError, '
|
48
|
+
raise ArgumentError, 'You need to provide a block which returns an IO object' if @block.nil?
|
22
49
|
end
|
23
50
|
|
24
|
-
# Provide direct access to the wrapped IO object.
|
25
|
-
|
26
|
-
|
51
|
+
# Provide direct access to the wrapped IO object by yielding it. After the method block
|
52
|
+
# returns the IO object is automatically closed.
|
53
|
+
#
|
54
|
+
# The parameter +mode+ specifies the mode in which the wrapped IO object should be opened.
|
55
|
+
# This can be used, for example, to open a file in binary mode (or specify a certain input
|
56
|
+
# encoding under Ruby 1.9).
|
57
|
+
def stream(mode = 'r')
|
58
|
+
io = @block.call(mode)
|
27
59
|
yield(io)
|
28
60
|
ensure
|
29
61
|
io.close
|
30
62
|
end
|
31
63
|
|
32
|
-
# Return the content of the wrapped IO object as string.
|
33
|
-
|
34
|
-
|
64
|
+
# Return the whole content of the wrapped IO object as string. For a description of the
|
65
|
+
# parameter +mode+ see #stream.
|
66
|
+
def data(mode = 'r')
|
67
|
+
stream(mode) {|io| io.read}
|
35
68
|
end
|
36
69
|
|
37
70
|
end
|
38
71
|
|
39
72
|
|
73
|
+
# Make the given +path+ absolute by prepending the absolute directory path +base+ if necessary.
|
74
|
+
# Also resolves all '..' and '.' references in +path+.
|
75
|
+
def self.make_absolute(base, path)
|
76
|
+
raise(ArgumentError, 'base has to be an absolute path, ie. needs to start with a slash') unless base =~ /\//
|
77
|
+
Pathname.new(path =~ /^\// ? path : File.join(base, path)).cleanpath.to_s
|
78
|
+
end
|
79
|
+
|
40
80
|
# Return +true+ if the given +path+ matches the given +pattern+ (trailing slashes of directories
|
41
81
|
# are not respected). For information on which patterns are supported, have a look at the
|
42
82
|
# documentation of File.fnmatch.
|
@@ -49,66 +89,86 @@ module Webgen
|
|
49
89
|
|
50
90
|
include Comparable
|
51
91
|
|
52
|
-
# The full path.
|
53
|
-
|
92
|
+
# The full path for which this Path object was created.
|
93
|
+
attr_reader :path
|
54
94
|
|
55
|
-
#
|
56
|
-
|
95
|
+
# A string specifying the path that lead to the creation of this path.
|
96
|
+
attr_reader :source_path
|
57
97
|
|
58
|
-
# The
|
59
|
-
|
98
|
+
# The string specifying the parent path
|
99
|
+
attr_reader :parent_path
|
60
100
|
|
61
|
-
# The
|
62
|
-
attr_accessor :
|
63
|
-
|
64
|
-
# The canonical name without the extension.
|
65
|
-
attr_accessor :cnbase
|
101
|
+
# The canonical name of the path without the extension.
|
102
|
+
attr_accessor :basename
|
66
103
|
|
67
|
-
# The extension
|
104
|
+
# The extension of the +path+.
|
68
105
|
attr_accessor :ext
|
69
106
|
|
70
107
|
# Extracted meta information for the path.
|
71
108
|
attr_accessor :meta_info
|
72
109
|
|
110
|
+
# Specifies whether this path should be used during the "tree update" phase of a webgen run or
|
111
|
+
# only later during node resolution.
|
112
|
+
attr_writer :passive
|
113
|
+
|
114
|
+
# Is this path only used later during node resolution? Defaults to +false+, i.e. used during the
|
115
|
+
# "tree update" phase.
|
116
|
+
def passive?; @passive; end
|
117
|
+
|
118
|
+
|
73
119
|
# Create a new Path object for +path+. The optional +source_path+ parameter specifies the path
|
74
|
-
# that lead to the creation of this path. The optional block needs to return an IO object
|
75
|
-
# the content of the path.
|
120
|
+
# string that lead to the creation of this path. The optional block needs to return an IO object
|
121
|
+
# for getting the content of the path.
|
122
|
+
#
|
123
|
+
# The +path+ needs to be in a well defined format which can be looked up in the webgen manual.
|
76
124
|
def initialize(path, source_path = path, &ioblock)
|
77
125
|
@meta_info = {}
|
78
126
|
@io = block_given? ? SourceIO.new(&ioblock) : nil
|
79
127
|
@source_path = source_path
|
128
|
+
@passive = false
|
80
129
|
analyse(path)
|
81
130
|
end
|
82
131
|
|
83
|
-
# Mount this path at the mount point +mp
|
84
|
-
# the new path object.
|
132
|
+
# Mount this path at the mount point +mp+, optionally stripping +prefix+ from the parent path,
|
133
|
+
# and return the new path object.
|
134
|
+
#
|
135
|
+
# The parameters +mp+ and +prefix+ have to be absolute directory paths, ie. they have to start
|
136
|
+
# and end with a slash and must not contain any hash characters!
|
137
|
+
#
|
138
|
+
#--
|
139
|
+
# Can't use self.class.new(...) here because the semantics of the sub constructors is not know
|
140
|
+
#++
|
85
141
|
def mount_at(mp, prefix = nil)
|
142
|
+
raise(ArgumentError, "The mount point (#{mp}) must be a valid directory path") if mp =~ /^[^\/]|#|[^\/]$/
|
143
|
+
raise(ArgumentError, "The strip prefix (#{prefix}) must be a valid directory path") if !prefix.nil? && prefix =~ /^[^\/]|#|[^\/]$/
|
144
|
+
|
86
145
|
temp = dup
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
temp.
|
146
|
+
strip_re = /^#{Regexp.escape(prefix.to_s)}/
|
147
|
+
temp.instance_variable_set(:@path, temp.path.sub(strip_re, ''))
|
148
|
+
reanalyse = (@path == '/' || temp.path == '')
|
149
|
+
temp.instance_variable_set(:@path, File.join(mp, temp.path))
|
150
|
+
temp.instance_variable_set(:@source_path, temp.path) if @path == @source_path
|
91
151
|
if reanalyse
|
92
152
|
temp.send(:analyse, temp.path)
|
93
153
|
else
|
94
|
-
temp.
|
154
|
+
temp.instance_variable_set(:@parent_path, File.join(mp, temp.parent_path.sub(strip_re, '')))
|
95
155
|
end
|
96
156
|
temp
|
97
157
|
end
|
98
158
|
|
99
|
-
# Has the content of this path changed since the last webgen run? This default implementation
|
100
|
-
# always returns +true+, a specialized sub class needs to override this behaviour!
|
101
|
-
def changed?
|
102
|
-
true
|
103
|
-
end
|
104
|
-
|
105
159
|
# Duplicate the path object.
|
106
160
|
def dup
|
107
161
|
temp = super
|
108
|
-
temp.meta_info
|
162
|
+
temp.instance_variable_set(:@meta_info, @meta_info.dup)
|
109
163
|
temp
|
110
164
|
end
|
111
165
|
|
166
|
+
# Has the content of this path changed since the last webgen run? This default implementation
|
167
|
+
# always returns +true+, a specialized sub class needs to override this behaviour!
|
168
|
+
def changed?
|
169
|
+
true
|
170
|
+
end
|
171
|
+
|
112
172
|
# The SourceIO object associated with the path.
|
113
173
|
def io
|
114
174
|
if @io
|
@@ -118,26 +178,45 @@ module Webgen
|
|
118
178
|
end
|
119
179
|
end
|
120
180
|
|
121
|
-
# The canonical name created from the
|
181
|
+
# The canonical name created from the +path+ (namely from the parts +basename+ and +extension+).
|
122
182
|
def cn
|
123
|
-
@
|
183
|
+
@basename + (@ext.length > 0 ? '.' + @ext : '') + (@basename != '/' && @path =~ /.\/$/ ? '/' : '')
|
124
184
|
end
|
125
185
|
|
126
|
-
# Utility method for creating the lcn from +cn+ and the language +lang+.
|
186
|
+
# Utility method for creating the lcn from the +cn+ and the language +lang+.
|
127
187
|
def self.lcn(cn, lang)
|
128
188
|
if lang.nil?
|
129
189
|
cn
|
130
190
|
else
|
131
|
-
cn.split('.').insert(1, lang.to_s).join('.')
|
191
|
+
cn.split('.').insert((cn =~ /^\./ ? 2 : 1), lang.to_s).join('.')
|
132
192
|
end
|
133
193
|
end
|
134
194
|
|
135
|
-
# The localized canonical name created from the
|
195
|
+
# The localized canonical name created from the +path+.
|
136
196
|
def lcn
|
137
197
|
self.class.lcn(cn, @meta_info['lang'])
|
138
198
|
end
|
139
199
|
|
140
|
-
#
|
200
|
+
# The absolute canonical name of this path.
|
201
|
+
def acn
|
202
|
+
if @path =~ /#/
|
203
|
+
self.class.new(@parent_path).acn + cn
|
204
|
+
else
|
205
|
+
@parent_path + cn
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# The absolute localized canonical name of this path.
|
210
|
+
def alcn
|
211
|
+
if @path =~ /#/
|
212
|
+
self.class.new(@parent_path).alcn + lcn
|
213
|
+
else
|
214
|
+
@parent_path + lcn
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# Equality -- Return +true+ if +other+ is a Path object with the same #path or if +other+ is a
|
219
|
+
# String equal to the #path. Else return +false+.
|
141
220
|
def ==(other)
|
142
221
|
if other.kind_of?(Path)
|
143
222
|
other.path == @path
|
@@ -149,13 +228,12 @@ module Webgen
|
|
149
228
|
end
|
150
229
|
alias_method(:eql?, :==)
|
151
230
|
|
152
|
-
#
|
231
|
+
# Compare the #path of this object to <tt>other.path</tt>
|
153
232
|
def <=>(other)
|
154
|
-
@path <=> other.
|
233
|
+
@path <=> other.path
|
155
234
|
end
|
156
235
|
|
157
|
-
|
158
|
-
def hash
|
236
|
+
def hash #:nodoc:
|
159
237
|
@path.hash
|
160
238
|
end
|
161
239
|
|
@@ -172,21 +250,46 @@ module Webgen
|
|
172
250
|
private
|
173
251
|
#######
|
174
252
|
|
175
|
-
FILENAME_RE = /^(?:(\d+)\.)?([^.]*?)(?:\.(\w\w\w?)(?=.))?(?:\.(.*))?$/
|
176
|
-
|
177
253
|
# Analyse the +path+ and fill the object with the extracted information.
|
178
254
|
def analyse(path)
|
179
255
|
@path = path
|
180
|
-
@
|
181
|
-
|
182
|
-
|
256
|
+
if @path =~ /#/
|
257
|
+
analyse_fragment
|
258
|
+
elsif @path =~ /\/$/
|
259
|
+
analyse_directory
|
260
|
+
else
|
261
|
+
analyse_file
|
262
|
+
end
|
263
|
+
@meta_info['title'] = @basename.tr('_-', ' ').capitalize
|
264
|
+
@ext ||= ''
|
265
|
+
raise "The basename of a path may not be empty: #{@path}" if @basename.empty? || @basename == '#'
|
266
|
+
raise "The parent path must start with a slash: #{@path}" if @path !~ /^\// && @path != '/'
|
267
|
+
end
|
183
268
|
|
184
|
-
|
185
|
-
|
186
|
-
@
|
187
|
-
@
|
269
|
+
# Analyse the path assuming it is a directory.
|
270
|
+
def analyse_directory
|
271
|
+
@parent_path = (@path == '/' ? '' : File.join(File.dirname(@path), '/'))
|
272
|
+
@basename = File.basename(@path)
|
273
|
+
end
|
274
|
+
|
275
|
+
FILENAME_RE = /^(?:(\d+)\.)?(\.?[^.]*?)(?:\.(\w\w\w?)(?=\.))?(?:\.(.*))?$/
|
276
|
+
|
277
|
+
# Analyse the path assuming it is a file.
|
278
|
+
def analyse_file
|
279
|
+
@parent_path = File.join(File.dirname(@path), '/')
|
280
|
+
match_data = FILENAME_RE.match(File.basename(@path))
|
281
|
+
|
282
|
+
@meta_info['sort_info'] = (match_data[1].nil? ? nil : match_data[1].to_i)
|
283
|
+
@basename = match_data[2]
|
284
|
+
@meta_info['lang'] = Webgen::LanguageManager.language_for_code(match_data[3])
|
285
|
+
@ext = (@meta_info['lang'].nil? && !match_data[3].nil? ? match_data[3].to_s : '') + match_data[4].to_s
|
286
|
+
end
|
188
287
|
|
189
|
-
|
288
|
+
# Analyse the path assuming it is a fragment.
|
289
|
+
def analyse_fragment
|
290
|
+
@parent_path, @basename = @path.scan(/^(.*?)(#.*?)$/).first
|
291
|
+
raise "The parent path of a fragment path must be a file path and not a directory path: #{@path}" if @parent_path =~ /\/$/
|
292
|
+
raise "A fragment path must only contain one hash character: #{path}" if @path.count("#") > 1
|
190
293
|
end
|
191
294
|
|
192
295
|
end
|
data/lib/webgen/source.rb
CHANGED
@@ -10,9 +10,13 @@ module Webgen
|
|
10
10
|
#
|
11
11
|
# A source class only needs to respond to the method +paths+ which needs to return a set of paths
|
12
12
|
# for the source. The returned paths must respond to the method <tt>changed?</tt> (has to return
|
13
|
-
# +true+ if the paths has changed since the last webgen run).
|
14
|
-
#
|
15
|
-
# singleton methods on each path
|
13
|
+
# +true+ if the paths has changed since the last webgen run). If a path represents a directory, it
|
14
|
+
# needs to have a trailing slash! The default implementation in the Path class just returns
|
15
|
+
# +true+. One can either derive a specialized path class or define singleton methods on each path
|
16
|
+
# object.
|
17
|
+
#
|
18
|
+
# Also note that the returned Path objects should have the meta information <tt>modified_at</tt>
|
19
|
+
# set to the correct last modification time of the path, ie. the value has to be a Time object!
|
16
20
|
#
|
17
21
|
# == Sample Source Class
|
18
22
|
#
|
@@ -36,10 +40,9 @@ module Webgen
|
|
36
40
|
# end
|
37
41
|
#
|
38
42
|
# You can use this source class in your website (after placing the code in, for example,
|
39
|
-
# <tt>ext/init.rb</tt>) by updating the <tt>sources</tt> configuration option
|
40
|
-
# has to be placed after the definition of the +MemorySource+ class):
|
43
|
+
# <tt>ext/init.rb</tt>) by updating the <tt>sources</tt> configuration option:
|
41
44
|
#
|
42
|
-
# WebsiteAccess.website.config['sources'] << ['/', MemorySource]
|
45
|
+
# WebsiteAccess.website.config['sources'] << ['/', 'MemorySource']
|
43
46
|
#
|
44
47
|
module Source
|
45
48
|
|
@@ -14,7 +14,7 @@ module Webgen
|
|
14
14
|
|
15
15
|
# Create a new object with absolute path +path+ for the file system path +fs_path+.
|
16
16
|
def initialize(path, fs_path)
|
17
|
-
super(path) { File.open(fs_path,
|
17
|
+
super(path) {|mode| File.open(fs_path, mode) }
|
18
18
|
@fs_path = fs_path
|
19
19
|
WebsiteAccess.website.cache[[:fs_path, @fs_path]] = File.mtime(@fs_path)
|
20
20
|
@meta_info['modified_at'] = File.mtime(@fs_path)
|