webgen 1.0.0.beta3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/COPYING +23 -1
- data/Rakefile +16 -77
- data/VERSION +1 -1
- data/bin/webgen +0 -0
- data/data/webgen/basic_website_template/ext/init.rb +3 -1
- data/data/webgen/basic_website_template/src/.gitignore +0 -0
- data/data/webgen/basic_website_template/webgen.config +1 -1
- data/data/webgen/bundle_template_files/info.yaml.erb +14 -2
- data/data/webgen/passive_sources/default.metainfo +10 -0
- data/data/webgen/passive_sources/templates/api.template +16 -2
- data/data/webgen/passive_sources/templates/feed.template +5 -5
- data/data/webgen/passive_sources/templates/sitemap.template +1 -1
- data/data/webgen/passive_sources/templates/tag.template +8 -4
- data/lib/webgen/blackboard.rb +21 -5
- data/lib/webgen/bundle/built-in-show-changes/info.yaml +17 -0
- data/lib/webgen/bundle/built-in-show-changes/init.rb +4 -5
- data/lib/webgen/bundle/built-in/info.yaml +1064 -0
- data/lib/webgen/bundle/built-in/init.rb +103 -136
- data/lib/webgen/bundle_loader.rb +82 -9
- data/lib/webgen/cli.rb +12 -8
- data/lib/webgen/cli/commands/create.rb +27 -0
- data/lib/webgen/cli/{create_bundle_command.rb → commands/create_bundle.rb} +2 -2
- data/lib/webgen/cli/{create_command.rb → commands/create_website.rb} +2 -2
- data/lib/webgen/cli/commands/generate.rb +66 -0
- data/lib/webgen/cli/{install_bundle_command.rb → commands/install.rb} +1 -1
- data/lib/webgen/cli/{show_command.rb → commands/show.rb} +6 -4
- data/lib/webgen/cli/{list_bundle_command.rb → commands/show_bundles.rb} +12 -15
- data/lib/webgen/cli/{show_config_command.rb → commands/show_config.rb} +34 -6
- data/lib/webgen/cli/{show_dependencies_command.rb → commands/show_dependencies.rb} +0 -0
- data/lib/webgen/cli/{show_extensions_command.rb → commands/show_extensions.rb} +1 -13
- data/lib/webgen/cli/{show_tree_command.rb → commands/show_tree.rb} +3 -0
- data/lib/webgen/cli/utils.rb +1 -1
- data/lib/webgen/configuration.rb +9 -11
- data/lib/webgen/content_processor/html_head.rb +3 -4
- data/lib/webgen/content_processor/rainpress.rb +21 -0
- data/lib/webgen/content_processor/sass.rb +8 -8
- data/lib/webgen/content_processor/tikz.rb +59 -16
- data/lib/webgen/item_tracker.rb +33 -12
- data/lib/webgen/item_tracker/missing_node.rb +5 -5
- data/lib/webgen/item_tracker/template_chain.rb +52 -0
- data/lib/webgen/misc/dummy_index.rb +78 -0
- data/lib/webgen/node.rb +1 -1
- data/lib/webgen/node_finder.rb +86 -141
- data/lib/webgen/page.rb +5 -5
- data/lib/webgen/path.rb +4 -1
- data/lib/webgen/path_handler.rb +25 -21
- data/lib/webgen/path_handler/api.rb +36 -3
- data/lib/webgen/path_handler/base.rb +20 -4
- data/lib/webgen/path_handler/feed.rb +6 -2
- data/lib/webgen/path_handler/meta_info.rb +4 -2
- data/lib/webgen/path_handler/page.rb +5 -7
- data/lib/webgen/path_handler/sitemap.rb +6 -1
- data/lib/webgen/path_handler/virtual.rb +6 -8
- data/lib/webgen/source/file_system.rb +2 -2
- data/lib/webgen/tag.rb +22 -18
- data/lib/webgen/tag/menu.rb +5 -5
- data/lib/webgen/test_helper.rb +18 -18
- data/lib/webgen/utils/external_command.rb +1 -1
- data/lib/webgen/utils/tag_parser.rb +1 -1
- data/lib/webgen/vendor/rainpress.rb +168 -0
- data/lib/webgen/version.rb +1 -1
- data/lib/webgen/website.rb +10 -10
- data/man/man1/webgen.1 +54 -23
- data/test/test_documentation.rb +27 -4
- data/test/webgen/cli/test_logger.rb +1 -1
- data/test/webgen/content_processor/test_blocks.rb +1 -1
- data/test/webgen/content_processor/test_builder.rb +3 -2
- data/test/webgen/content_processor/test_erb.rb +1 -1
- data/test/webgen/content_processor/test_erubis.rb +2 -2
- data/test/webgen/content_processor/test_fragments.rb +1 -1
- data/test/webgen/content_processor/test_haml.rb +2 -2
- data/test/webgen/content_processor/test_html_head.rb +5 -1
- data/test/webgen/content_processor/test_kramdown.rb +2 -2
- data/test/webgen/content_processor/test_maruku.rb +2 -2
- data/test/webgen/content_processor/test_r_discount.rb +2 -2
- data/test/webgen/content_processor/test_r_doc.rb +1 -1
- data/test/webgen/content_processor/test_rainpress.rb +19 -0
- data/test/webgen/content_processor/test_red_cloth.rb +2 -2
- data/test/webgen/content_processor/test_ruby.rb +1 -1
- data/test/webgen/content_processor/test_sass.rb +8 -6
- data/test/webgen/content_processor/test_scss.rb +3 -3
- data/test/webgen/content_processor/test_tags.rb +1 -1
- data/test/webgen/content_processor/test_tidy.rb +9 -1
- data/test/webgen/content_processor/test_tikz.rb +6 -3
- data/test/webgen/content_processor/test_xmllint.rb +9 -2
- data/test/webgen/destination/test_file_system.rb +4 -4
- data/test/webgen/item_tracker/test_file.rb +1 -1
- data/test/webgen/item_tracker/test_missing_node.rb +1 -1
- data/test/webgen/item_tracker/test_node_content.rb +1 -1
- data/test/webgen/item_tracker/test_node_meta_info.rb +1 -1
- data/test/webgen/item_tracker/test_nodes.rb +2 -4
- data/test/webgen/item_tracker/test_template_chain.rb +36 -0
- data/test/webgen/misc/test_dummy_index.rb +83 -0
- data/test/webgen/path_handler/test_api.rb +6 -46
- data/test/webgen/path_handler/test_base.rb +3 -2
- data/test/webgen/path_handler/test_copy.rb +1 -1
- data/test/webgen/path_handler/test_feed.rb +3 -4
- data/test/webgen/path_handler/test_meta_info.rb +1 -1
- data/test/webgen/path_handler/test_page.rb +1 -1
- data/test/webgen/path_handler/test_page_utils.rb +1 -1
- data/test/webgen/path_handler/test_sitemap.rb +3 -5
- data/test/webgen/path_handler/test_template.rb +1 -1
- data/test/webgen/path_handler/test_virtual.rb +1 -3
- data/test/webgen/source/test_file_system.rb +9 -4
- data/test/webgen/source/test_stacked.rb +1 -1
- data/test/webgen/source/test_tar_archive.rb +2 -2
- data/test/webgen/tag/test_breadcrumb_trail.rb +1 -1
- data/test/webgen/tag/test_coderay.rb +3 -2
- data/test/webgen/tag/test_date.rb +1 -1
- data/test/webgen/tag/test_execute_command.rb +1 -1
- data/test/webgen/tag/test_include_file.rb +1 -1
- data/test/webgen/tag/test_langbar.rb +1 -1
- data/test/webgen/tag/test_link.rb +1 -1
- data/test/webgen/tag/test_menu.rb +12 -30
- data/test/webgen/tag/test_meta_info.rb +1 -1
- data/test/webgen/tag/test_relocatable.rb +1 -1
- data/test/webgen/tag/test_tikz.rb +3 -2
- data/test/webgen/task/test_create_website.rb +2 -2
- data/test/webgen/test_blackboard.rb +11 -3
- data/test/webgen/test_bundle_loader.rb +26 -9
- data/test/webgen/test_cache.rb +1 -1
- data/test/webgen/test_cli.rb +2 -2
- data/test/webgen/test_configuration.rb +8 -9
- data/test/webgen/test_content_processor.rb +1 -1
- data/test/webgen/test_context.rb +1 -1
- data/test/webgen/test_core_ext.rb +1 -1
- data/test/webgen/test_destination.rb +1 -1
- data/test/webgen/test_error.rb +5 -5
- data/test/webgen/test_extension_manager.rb +1 -1
- data/test/webgen/test_item_tracker.rb +26 -5
- data/test/webgen/test_languages.rb +1 -1
- data/test/webgen/test_logger.rb +1 -1
- data/test/webgen/test_node.rb +1 -1
- data/test/webgen/test_node_finder.rb +2 -2
- data/test/webgen/test_page.rb +5 -5
- data/test/webgen/test_path.rb +8 -8
- data/test/webgen/test_rake_task.rb +1 -1
- data/test/webgen/test_source.rb +1 -1
- data/test/webgen/test_tag.rb +16 -24
- data/test/webgen/test_task.rb +1 -1
- data/test/webgen/test_tree.rb +1 -1
- data/test/webgen/test_utils.rb +1 -1
- data/test/webgen/test_website.rb +1 -1
- data/test/webgen/utils/test_tag_parser.rb +1 -1
- metadata +85 -105
- data/lib/webgen/cli/bundle_command.rb +0 -30
- data/lib/webgen/cli/generate_command.rb +0 -25
data/lib/webgen/node.rb
CHANGED
@@ -216,7 +216,7 @@ module Webgen
|
|
216
216
|
# Return all versions of this node.
|
217
217
|
def versions
|
218
218
|
tree.node_access[:alcn].select {|alcn, n| n.node_info[:path] == node_info[:path]}.
|
219
|
-
each_with_object({}) {|(
|
219
|
+
each_with_object({}) {|(_, v), h| h[v['version']] = v}
|
220
220
|
end
|
221
221
|
|
222
222
|
end
|
data/lib/webgen/node_finder.rb
CHANGED
@@ -21,116 +21,22 @@ module Webgen
|
|
21
21
|
#
|
22
22
|
# == Finder options
|
23
23
|
#
|
24
|
-
#
|
25
|
-
# filters available if you are using extension
|
26
|
-
#
|
27
|
-
# === Non-filter options
|
28
|
-
#
|
29
|
-
# These options are not used for filtering out nodes but provide additional functionality.
|
30
|
-
#
|
31
|
-
# [:limit]
|
32
|
-
# Value: an integer. Specifies the maximum number of nodes that should be returned. Implies
|
33
|
-
# 'flatten = true'.
|
34
|
-
#
|
35
|
-
# Note that fewer nodes may be returned if fewer nodes match the filter criterias.
|
36
|
-
#
|
37
|
-
# [:offset]
|
38
|
-
# Value: an integer. Specifies how many nodes from the front of the list should *not* be
|
39
|
-
# returned. Implies 'flatten = true'.
|
40
|
-
#
|
41
|
-
# [:levels]
|
42
|
-
# Value: one integer (is used as start and end level) or an array with two integers (the start
|
43
|
-
# and end levels). All nodes whose hierarchy level in the returned node hierarchy is greater
|
44
|
-
# than or equal to the start level and lower than or equal to the end level are used.
|
45
|
-
#
|
46
|
-
# Only used when the node hierarchy is not flattened.
|
47
|
-
#
|
48
|
-
# [:flatten]
|
49
|
-
# Value: anything except +nil+ or +false+. A flat list of nodes is returned if this option is
|
50
|
-
# set, otherwise the nodes are returned in their correct hierarchical order using nested lists.
|
51
|
-
#
|
52
|
-
# Note that any missing nodes in the hierarchy are automatically added so that traversing the
|
53
|
-
# hierarchy is always possible. For example, if we have the tree '/a/b/c' and only nodes +a+ and
|
54
|
-
# +c+ are found, node +b+ is automatically added.
|
55
|
-
#
|
56
|
-
# [:sort]
|
57
|
-
# Value: +nil+/+false+, +true+ or a meta information key. If +nil+ or +false+ is specified, no
|
58
|
-
# sorting is performed. If +true+ is specified, the meta information +sort_info+ (or if absent,
|
59
|
-
# the meta information +title+) is used for sorting. If the compared values are both integers, a
|
60
|
-
# numeric comparison is done, else a string comparison. If a meta information key is specified,
|
61
|
-
# the value of this meta information is used for comparison of nodes (again, if both compared
|
62
|
-
# values are integers, a numeric comparison is done, else a string comparison).
|
63
|
-
#
|
64
|
-
# [:reverse]
|
65
|
-
# Value: +true+ of +false+/+nil+. If this option is set to +true+, the sort order is reversed.
|
66
|
-
#
|
67
|
-
# === Filter options
|
68
|
-
#
|
69
|
-
# These options are used for filtering the nodes. All nodes are used by default if no filter
|
70
|
-
# options are specified.
|
71
|
-
#
|
72
|
-
# [:alcn]
|
73
|
-
# Value: an alcn pattern or an array of alcn patterns. Nodes that match any of the patterns are
|
74
|
-
# used.
|
75
|
-
#
|
76
|
-
# [:lang]
|
77
|
-
# Value: a language code/+nil+/the special value +node+ or an array of these values. Nodes that
|
78
|
-
# have one of the specified language codes, are language independent (in case of the value
|
79
|
-
# +nil+) or have the same language as the reference node (in case of the value +node+) are
|
80
|
-
# used.
|
81
|
-
#
|
82
|
-
# [:mi]
|
83
|
-
# Value: a hash with meta information key to value mappings. Only nodes that have the same
|
84
|
-
# values for all meta information keys are used.
|
85
|
-
#
|
86
|
-
# [:or]
|
87
|
-
# Value: a finder option set or an array of finder options sets (specifying option set names is
|
88
|
-
# also possible). Nodes that appear in any specified option set are additionally used.
|
89
|
-
#
|
90
|
-
# [:and]
|
91
|
-
# Value: a finder option set or an array of finder options sets (specifying option set names is
|
92
|
-
# also possible). Only nodes that appear in all specified option sets are used.
|
93
|
-
#
|
94
|
-
# [:not]
|
95
|
-
# Value: a finder option set or an array of finder options sets (specifying option set names is
|
96
|
-
# also possible). Only nodes that do not appear in any specified option set are used.
|
97
|
-
#
|
98
|
-
# [:absolute_levels]
|
99
|
-
# Value: one integer (is used as start and end level) or an array with two integers (the start
|
100
|
-
# and end levels). All nodes whose hierarchy level in the node tree are greater than or equal to
|
101
|
-
# the start level and lower than or equal to the end level are used.
|
102
|
-
#
|
103
|
-
# Negative numbers, where -1 stands for the reference node, -2 for its parent node and so on,
|
104
|
-
# can also be used.
|
105
|
-
#
|
106
|
-
# [:ancestors]
|
107
|
-
# Value: +true+ or +false+/+nil+. If this filter option is set to +true+, only nodes that are
|
108
|
-
# ancestors of the reference node are used. The reference node itself is used as well.
|
109
|
-
#
|
110
|
-
# [:descendants]
|
111
|
-
# Value: +true+ or +false+/+nil+. If this filter option is set to +true+, only nodes that are
|
112
|
-
# descendants of the reference node are used. The reference node itself is used as well.
|
113
|
-
#
|
114
|
-
# [:siblings]
|
115
|
-
# Value: +true+, +false+/+nil+, or an array with two integers. If this filter option is set to
|
116
|
-
# +true+, only nodes that are sibling node of the reference node are used. The reference node
|
117
|
-
# itself is used as well. If set to +false+ or +nil+, this filter is ignored.
|
118
|
-
#
|
119
|
-
# If an array with two numbers is specified, all sibling nodes of the reference node or its
|
120
|
-
# parent nodes the hierarchy level of which lies between these numbers are used. The parent
|
121
|
-
# nodes and the reference node are used as well if their level lies between the numbers.
|
122
|
-
# Counting starts at zero (the root node).
|
123
|
-
#
|
124
|
-
# Negative numbers, where -1 stands for the reference node, -2 for its parent node and so on,
|
125
|
-
# can also be used.
|
24
|
+
# A complete list of the supported finder options can be found in the user documentation! Note
|
25
|
+
# that there may also be other 3rd party node filters available if you are using extension
|
26
|
+
# bundles!
|
126
27
|
#
|
127
28
|
# == Implementing a filter module
|
128
29
|
#
|
129
30
|
# Implementing a filter module is very easy. Just create a module that contains your filter
|
130
31
|
# methods and tell the NodeFinder object about it using the #add_filter_module method. A filter
|
131
|
-
# method needs to take three arguments:
|
32
|
+
# method needs to take three arguments: the Result stucture, the reference node and the filter
|
132
33
|
# value.
|
133
34
|
#
|
35
|
+
# The +result.nodes+ accessor contains the array of nodes that should be manipulated in-place.
|
36
|
+
#
|
37
|
+
# If a filter uses the reference node in any way, it has to set +result.ref_node_used+ to +true+
|
38
|
+
# to allow proper caching!
|
39
|
+
#
|
134
40
|
# Here is a sample filter module which provides the ability to filter nodes based on the meta
|
135
41
|
# information key +category+. The +category+ key contains an array with one or more categories.
|
136
42
|
# The value for this category filter is one or more strings and the filter returns those nodes
|
@@ -138,9 +44,9 @@ module Webgen
|
|
138
44
|
#
|
139
45
|
# module CategoryFilter
|
140
46
|
#
|
141
|
-
# def filter_on_category(
|
47
|
+
# def filter_on_category(result, ref_node, categories)
|
142
48
|
# categories = [categories].flatten # needed in case categories is a string
|
143
|
-
# nodes.select {|n| categories.any? {|c| n['category'].include?(c)}}
|
49
|
+
# result.nodes.select! {|n| categories.any? {|c| n['category'].include?(c)}}
|
144
50
|
# end
|
145
51
|
#
|
146
52
|
# end
|
@@ -149,6 +55,11 @@ module Webgen
|
|
149
55
|
#
|
150
56
|
class NodeFinder
|
151
57
|
|
58
|
+
# Result class used when filtering the nodes.
|
59
|
+
#
|
60
|
+
# The attribute +ref_node_used+ must not be set to +false+ once it is +true+!
|
61
|
+
Result = Struct.new(:nodes, :ref_node_used)
|
62
|
+
|
152
63
|
# Create a new NodeFinder object for the given website.
|
153
64
|
def initialize(website)
|
154
65
|
@website = website
|
@@ -196,7 +107,7 @@ module Webgen
|
|
196
107
|
flatten = true if limit || offset
|
197
108
|
levels = [levels || [1, 1_000_000]].flatten.map {|i| i.to_i}
|
198
109
|
|
199
|
-
nodes = filter_nodes(opts, ref_node)
|
110
|
+
nodes, ref_node_used = filter_nodes(opts, ref_node)
|
200
111
|
|
201
112
|
if flatten
|
202
113
|
sort_nodes(nodes, sort, reverse)
|
@@ -226,7 +137,7 @@ module Webgen
|
|
226
137
|
sort_nodes(nodes, sort, reverse, false)
|
227
138
|
end
|
228
139
|
|
229
|
-
cache_result(opts_or_name, ref_node, nodes)
|
140
|
+
cache_result(opts_or_name, ref_node, nodes, ref_node_used)
|
230
141
|
end
|
231
142
|
|
232
143
|
#######
|
@@ -234,11 +145,19 @@ module Webgen
|
|
234
145
|
#######
|
235
146
|
|
236
147
|
def cached_result(opts, ref_node)
|
237
|
-
|
148
|
+
result_cache[opts] || result_cache[[opts, ref_node.alcn]]
|
238
149
|
end
|
239
150
|
|
240
|
-
def cache_result(opts, ref_node, result)
|
241
|
-
|
151
|
+
def cache_result(opts, ref_node, result, ref_node_used)
|
152
|
+
if ref_node_used
|
153
|
+
result_cache[[opts, ref_node.alcn]] = result
|
154
|
+
else
|
155
|
+
result_cache[opts] = result
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def result_cache
|
160
|
+
@website.cache.volatile[:node_finder] ||= {}
|
242
161
|
end
|
243
162
|
|
244
163
|
def prepare_options_hash(opts_or_name)
|
@@ -260,15 +179,17 @@ module Webgen
|
|
260
179
|
nodes = @website.tree.node_access[:alcn].values
|
261
180
|
nodes.delete(@website.tree.dummy_root)
|
262
181
|
|
182
|
+
result = Result.new(nodes, false)
|
183
|
+
|
263
184
|
opts.each do |filter, value|
|
264
185
|
if @mapping.has_key?(filter)
|
265
|
-
|
186
|
+
send(@mapping[filter], result, ref_node, value)
|
266
187
|
else
|
267
188
|
@website.logger.warn { "Ignoring unknown node finder filter '#{filter}'" }
|
268
189
|
end
|
269
190
|
end
|
270
191
|
|
271
|
-
nodes
|
192
|
+
[result.nodes, result.ref_node_used]
|
272
193
|
end
|
273
194
|
|
274
195
|
def sort_nodes(nodes, sort, reverse, flat_mode = true)
|
@@ -292,78 +213,102 @@ module Webgen
|
|
292
213
|
|
293
214
|
# :section: Filter methods
|
294
215
|
|
295
|
-
def filter_and(
|
216
|
+
def filter_and(result, ref_node, opts)
|
296
217
|
[opts].flatten.each do |cur_opts|
|
297
218
|
cur_opts = prepare_options_hash(cur_opts)
|
298
219
|
remove_non_filter_options(cur_opts)
|
299
|
-
nodes
|
220
|
+
nodes, ref_node_used = filter_nodes(cur_opts, ref_node)
|
221
|
+
result.nodes &= nodes
|
222
|
+
result.ref_node_used |= ref_node_used
|
300
223
|
end
|
301
|
-
nodes
|
302
224
|
end
|
303
225
|
|
304
|
-
def filter_or(
|
226
|
+
def filter_or(result, ref_node, opts)
|
305
227
|
[opts].flatten.each do |cur_opts|
|
306
228
|
cur_opts = prepare_options_hash(cur_opts)
|
307
229
|
remove_non_filter_options(cur_opts)
|
308
|
-
nodes
|
230
|
+
nodes, ref_node_used = filter_nodes(cur_opts, ref_node)
|
231
|
+
result.nodes |= nodes
|
232
|
+
result.ref_node_used |= ref_node_used
|
309
233
|
end
|
310
|
-
nodes
|
311
234
|
end
|
312
235
|
|
313
|
-
def filter_not(
|
236
|
+
def filter_not(result, ref_node, opts)
|
314
237
|
[opts].flatten.each do |cur_opts|
|
315
238
|
cur_opts = prepare_options_hash(cur_opts)
|
316
239
|
remove_non_filter_options(cur_opts)
|
317
|
-
nodes
|
240
|
+
nodes, ref_node_used = filter_nodes(cur_opts, ref_node)
|
241
|
+
result.nodes -= nodes
|
242
|
+
result.ref_node_used |= ref_node_used
|
318
243
|
end
|
319
|
-
nodes
|
320
244
|
end
|
321
245
|
|
322
|
-
def filter_meta_info(
|
323
|
-
nodes.keep_if {|n| mi.all? {|key, val| n[key] == val}}
|
246
|
+
def filter_meta_info(result, ref_node, mi)
|
247
|
+
result.nodes.keep_if {|n| mi.all? {|key, val| n[key] == val}}
|
324
248
|
end
|
325
249
|
|
326
|
-
def filter_alcn(
|
250
|
+
def filter_alcn(result, ref_node, alcn)
|
251
|
+
result.ref_node_used = true
|
327
252
|
alcn = [alcn].flatten.map {|a| Webgen::Path.append(ref_node.alcn, a.to_s)}
|
328
|
-
nodes.keep_if {|n| alcn.any? {|a| n =~ a}}
|
253
|
+
result.nodes.keep_if {|n| alcn.any? {|a| n =~ a}}
|
329
254
|
end
|
330
255
|
|
331
|
-
def filter_absolute_levels(
|
332
|
-
range = [range].flatten.map
|
333
|
-
|
256
|
+
def filter_absolute_levels(result, ref_node, range)
|
257
|
+
range = [range].flatten.map do |i|
|
258
|
+
if (i = i.to_i) < 0
|
259
|
+
result.ref_node_used = true
|
260
|
+
ref_node.level + 1 + i
|
261
|
+
else
|
262
|
+
i
|
263
|
+
end
|
264
|
+
end
|
265
|
+
result.nodes.keep_if {|n| n.level >= range.first && n.level <= range.last}
|
334
266
|
end
|
335
267
|
|
336
|
-
def filter_lang(
|
337
|
-
langs = [langs].flatten.map
|
338
|
-
|
268
|
+
def filter_lang(result, ref_node, langs)
|
269
|
+
langs = [langs].flatten.map do |l|
|
270
|
+
if l == 'node'
|
271
|
+
result.ref_node_used = true
|
272
|
+
ref_node.lang
|
273
|
+
else
|
274
|
+
l
|
275
|
+
end
|
276
|
+
end.uniq
|
277
|
+
result.nodes.keep_if {|n| langs.any? {|l| n.lang == l}}
|
339
278
|
end
|
340
279
|
|
341
|
-
def filter_ancestors(
|
342
|
-
return
|
280
|
+
def filter_ancestors(result, ref_node, enabled)
|
281
|
+
return unless enabled
|
282
|
+
result.ref_node_used = true
|
283
|
+
|
343
284
|
nodes = []
|
344
285
|
node = ref_node
|
345
286
|
until node == node.tree.dummy_root
|
346
287
|
nodes.unshift(node)
|
347
288
|
node = node.parent
|
348
289
|
end
|
349
|
-
nodes
|
290
|
+
result.nodes = nodes
|
350
291
|
end
|
351
292
|
|
352
|
-
def filter_descendants(
|
353
|
-
return
|
354
|
-
|
293
|
+
def filter_descendants(result, ref_node, enabled)
|
294
|
+
return unless enabled
|
295
|
+
result.ref_node_used = true
|
296
|
+
|
297
|
+
result.nodes.keep_if do |n|
|
355
298
|
n = n.parent while n != n.tree.dummy_root && n != ref_node
|
356
299
|
n == ref_node
|
357
300
|
end
|
358
301
|
end
|
359
302
|
|
360
|
-
def filter_siblings(
|
361
|
-
return
|
303
|
+
def filter_siblings(result, ref_node, value)
|
304
|
+
return unless value
|
305
|
+
result.ref_node_used = true
|
306
|
+
|
362
307
|
if value == true
|
363
|
-
nodes.keep_if {|n| n.parent == ref_node.parent}
|
308
|
+
result.nodes.keep_if {|n| n.parent == ref_node.parent}
|
364
309
|
else
|
365
310
|
value = [value].flatten.map {|i| (i = i.to_i) < 0 ? ref_node.level + 1 + i : i}
|
366
|
-
nodes.keep_if do |n|
|
311
|
+
result.nodes.keep_if do |n|
|
367
312
|
n.level >= value.first && n.level <= value.last && (n.parent.is_ancestor_of?(ref_node) || n.is_root?)
|
368
313
|
end
|
369
314
|
end
|
data/lib/webgen/page.rb
CHANGED
@@ -18,11 +18,11 @@ module Webgen
|
|
18
18
|
|
19
19
|
# :stopdoc:
|
20
20
|
RE_NEWLINE = /\r?\n/
|
21
|
-
RE_META_INFO_START = /\A
|
21
|
+
RE_META_INFO_START = /\A---[ \t]*#{RE_NEWLINE}/
|
22
22
|
RE_META_INFO = /#{RE_META_INFO_START}.*?#{RE_NEWLINE}(?=---.*?#{RE_NEWLINE}|\Z)/m
|
23
|
-
RE_BLOCKS_START_SIMPLE = /^--- (\w+)(
|
24
|
-
RE_BLOCKS_START_COMPLEX = /^---
|
25
|
-
RE_BLOCKS_START = /^---(?:
|
23
|
+
RE_BLOCKS_START_SIMPLE = /^---[ \t]*$|^---[ \t]+(\w+)[ \t]*(?:[ \t]+-+[ \t]*)?$|^$/
|
24
|
+
RE_BLOCKS_START_COMPLEX = /^---[ \t]+?(?:[ \t]*((?:\w+:\S*[ \t]*)*))?(?:[ \t]+-+[ \t]*)?$/
|
25
|
+
RE_BLOCKS_START = /^---(?:[ \t]+.*?|)(?=#{RE_NEWLINE})/
|
26
26
|
RE_BLOCKS = /(?:(#{RE_BLOCKS_START})|\A)#{RE_NEWLINE}?(.*?)(?:(?=#{RE_BLOCKS_START})|\z)/m
|
27
27
|
RE_PAGE = /(#{RE_META_INFO})?(.*)/m
|
28
28
|
# :startdoc:
|
@@ -53,7 +53,7 @@ module Webgen
|
|
53
53
|
unless meta_info.kind_of?(Hash)
|
54
54
|
raise FormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
|
55
55
|
end
|
56
|
-
rescue ArgumentError, SyntaxError => e
|
56
|
+
rescue ArgumentError, SyntaxError, YAML::SyntaxError => e
|
57
57
|
raise FormatError, "Invalid YAML syntax in meta information block: #{e.message}"
|
58
58
|
end
|
59
59
|
meta_info
|
data/lib/webgen/path.rb
CHANGED
@@ -64,11 +64,14 @@ module Webgen
|
|
64
64
|
|
65
65
|
# Return +true+ if the given path string matches the given path pattern.
|
66
66
|
#
|
67
|
+
# If a fragment path (i.e. one which has a hash character somewhere) should be matched, the
|
68
|
+
# pattern needs to have a hash character as well.
|
69
|
+
#
|
67
70
|
# For information on which patterns are supported, have a look at the API documentation of
|
68
71
|
# File.fnmatch.
|
69
72
|
def self.matches_pattern?(path, pattern, options = File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
|
70
73
|
pattern += '/' if path =~ /\/$/ && pattern !~ /\/$|^$/
|
71
|
-
File.fnmatch(pattern, path, options)
|
74
|
+
(path.to_s.include?('#') ? pattern.include?('#') : true) && File.fnmatch(pattern, path, options)
|
72
75
|
end
|
73
76
|
|
74
77
|
# Construct a localized canonical name from a given canonical name and a language.
|
data/lib/webgen/path_handler.rb
CHANGED
@@ -17,14 +17,10 @@ module Webgen
|
|
17
17
|
# source to the destination, or a complex things, like generating a whole set of nodes from one
|
18
18
|
# input path (e.g. generating a whole image gallery)!
|
19
19
|
#
|
20
|
-
# The paths that are handled by a path handler are specified via path patterns
|
21
|
-
# #create_nodes method of a path handler is called for each source path that
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
# Also note that any method invoked on a Node object that is not defined in the Node class itself
|
26
|
-
# is forwarded to the associated path handler, adding the node as first parameter to the parameter
|
27
|
-
# list.
|
20
|
+
# The paths that are handled by a path handler are generally specified via path patterns. The
|
21
|
+
# #create_nodes method of a path handler is called for each source path that should be handled.
|
22
|
+
# And when it is time to write out a node, the #content method on the path handler associated with
|
23
|
+
# the node is called to retrieve the rendered content of the node.
|
28
24
|
#
|
29
25
|
# === Tree creation
|
30
26
|
#
|
@@ -40,10 +36,11 @@ module Webgen
|
|
40
36
|
# created before their file nodes.
|
41
37
|
#
|
42
38
|
# 2. When a path handler is used for creating nodes, all source paths (retrieved by using
|
43
|
-
# Webgen::Source#paths method) that match one of the associated patterns
|
39
|
+
# Webgen::Source#paths method) that match one of the associated patterns and/or all path with
|
40
|
+
# the 'handler' meta information set to the path handler are used.
|
44
41
|
#
|
45
|
-
# 3. The meta information of a used source path is then updated with the meta information
|
46
|
-
#
|
42
|
+
# 3. The meta information of a used source path is then updated with the meta information applied
|
43
|
+
# by methods registered for the :apply_meta_info_to_path blackboard message.
|
47
44
|
#
|
48
45
|
# After that the source path is given to the #parse_meta_info! method of the path handler so
|
49
46
|
# that meta information of the path can be updated with meta information stored in the content
|
@@ -53,7 +50,7 @@ module Webgen
|
|
53
50
|
# should be used for creating nodes and each path version is then given to the #create_nodes
|
54
51
|
# method of the path handler so that it can create one or more nodes.
|
55
52
|
#
|
56
|
-
# 4. Nodes returned by
|
53
|
+
# 4. Nodes returned by #creates_nodes of a path handler are assumed to have the Node#node_info
|
57
54
|
# keys :path and :path_handler and the meta info key 'modified_at' correctly set (this is
|
58
55
|
# automatically done if the Webgen::PathHandler::Base#create_node method is used).
|
59
56
|
#
|
@@ -61,7 +58,8 @@ module Webgen
|
|
61
58
|
#
|
62
59
|
# Path patterns define which paths are handled by a specific path handler. These patterns are
|
63
60
|
# specified when a path handler is registered using #register method. The patterns need to have a
|
64
|
-
# format that Dir.glob can handle.
|
61
|
+
# format that Dir.glob can handle. Note that a user can always associate any path with a path
|
62
|
+
# handler through a meta information path and the 'handler' meta information key.
|
65
63
|
#
|
66
64
|
# In addition to specifying the patterns a path handler uses, one can also specify the place in
|
67
65
|
# the invocation list which the path handler should use. The invocation list is used from the
|
@@ -141,23 +139,23 @@ module Webgen
|
|
141
139
|
@instances = {}
|
142
140
|
@secondary_nodes = {}
|
143
141
|
|
144
|
-
@website.blackboard.add_listener(:website_generated,
|
142
|
+
@website.blackboard.add_listener(:website_generated, 'path_handler') do
|
145
143
|
@website.cache[:path_handler_secondary_nodes] = @secondary_nodes
|
146
144
|
end
|
147
145
|
|
148
146
|
used_secondary_paths = {}
|
149
147
|
written_nodes = Set.new
|
150
|
-
@website.blackboard.add_listener(:before_secondary_nodes_created,
|
148
|
+
@website.blackboard.add_listener(:before_secondary_nodes_created, 'path_handler') do |path, source_alcn|
|
151
149
|
(used_secondary_paths[source_alcn] ||= Set.new) << path if source_alcn
|
152
150
|
end
|
153
|
-
@website.blackboard.add_listener(:before_all_nodes_written,
|
151
|
+
@website.blackboard.add_listener(:before_all_nodes_written, 'path_handler') do |node|
|
154
152
|
used_secondary_paths = {}
|
155
153
|
written_nodes = Set.new
|
156
154
|
end
|
157
|
-
@website.blackboard.add_listener(:after_node_written,
|
155
|
+
@website.blackboard.add_listener(:after_node_written, 'path_handler') do |node|
|
158
156
|
written_nodes << node.alcn
|
159
157
|
end
|
160
|
-
@website.blackboard.add_listener(:after_all_nodes_written,
|
158
|
+
@website.blackboard.add_listener(:after_all_nodes_written, 'path_handler') do
|
161
159
|
@secondary_nodes.delete_if do |path, data|
|
162
160
|
if written_nodes.include?(data[1]) && (!used_secondary_paths[data[1]] ||
|
163
161
|
!used_secondary_paths[data[1]].include?(path))
|
@@ -225,10 +223,16 @@ module Webgen
|
|
225
223
|
|
226
224
|
time = Benchmark.measure do
|
227
225
|
meta_info, rest = @website.ext.source.paths.partition {|path| path.path =~ /[\/.]metainfo$/}
|
226
|
+
|
227
|
+
used_paths = []
|
228
|
+
|
229
|
+
@website.blackboard.add_listener(:before_node_created, 'path_handler (temp_populate_tree)') do |path|
|
230
|
+
used_paths << path
|
231
|
+
end
|
228
232
|
create_nodes(meta_info, [:meta_info])
|
229
233
|
create_nodes(rest)
|
234
|
+
@website.blackboard.remove_listener(:before_node_created, 'path_handler (temp_populate_tree)')
|
230
235
|
|
231
|
-
used_paths = @website.tree.node_access[:alcn].values.map {|n| n.node_info[:path]}
|
232
236
|
unused_paths = rest - used_paths
|
233
237
|
@website.logger.vinfo do
|
234
238
|
"The following source paths have not been used: #{unused_paths.join(', ')}"
|
@@ -258,11 +262,11 @@ module Webgen
|
|
258
262
|
at_least_one_node_written = false
|
259
263
|
@website.cache.reset_volatile_cache
|
260
264
|
@website.blackboard.dispatch_msg(:before_all_nodes_written)
|
261
|
-
@website.tree.node_access[:alcn].
|
265
|
+
@website.tree.node_access[:alcn].sort_by {|a, n| [n['write_order'].to_s, a]}.each do |name, node|
|
262
266
|
begin
|
263
267
|
next if node == @website.tree.dummy_root ||
|
264
268
|
(node['passive'] && !node['no_output'] && !@website.ext.item_tracker.node_referenced?(node)) ||
|
265
|
-
((@website.config['website.dry_run'] || @website.ext.destination.exists?(node.dest_path)) &&
|
269
|
+
((@website.config['website.dry_run'] || node['no_output'] || @website.ext.destination.exists?(node.dest_path)) &&
|
266
270
|
!@website.ext.item_tracker.node_changed?(node))
|
267
271
|
|
268
272
|
@website.blackboard.dispatch_msg(:before_node_written, node)
|