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
@@ -10,49 +10,80 @@ module Webgen::ContentProcessor
|
|
10
10
|
BLOCK_RE = /<webgen:block\s*?((?:\s\w+=('|")[^'"]+\2)+)\s*\/>/
|
11
11
|
BLOCK_ATTR_RE = /(\w+)=('|")([^'"]+)\2/
|
12
12
|
|
13
|
-
# Replace
|
13
|
+
# Replace the webgen:block xml tags with the rendered content of the specified node.
|
14
14
|
def call(context)
|
15
|
-
chain = context[:chain]
|
16
|
-
new_chain = (chain.length > 1 ? chain[1..-1] : chain)
|
17
|
-
|
18
15
|
context.content.gsub!(BLOCK_RE) do |match|
|
19
16
|
attr = {}
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
log(:error) { "Could not resolve <#{path.strip}> in <#{context.ref_node.absolute_lcn}> in '#{match.to_s}'" } if temp_node.nil?
|
28
|
-
temp_node
|
29
|
-
end.compact
|
30
|
-
next match if used_chain.length != paths.length
|
31
|
-
dest_node = context.content_node
|
32
|
-
end
|
17
|
+
match_object = $~
|
18
|
+
attr[:line_nr_proc] = lambda { match_object.pre_match.scan("\n").size + 1 }
|
19
|
+
match.scan(BLOCK_ATTR_RE) {|name, sep, content| attr[name.to_sym] = content}
|
20
|
+
render_block(context, attr)
|
21
|
+
end
|
22
|
+
context
|
23
|
+
end
|
33
24
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
25
|
+
# Render a block of a page node and return the result.
|
26
|
+
#
|
27
|
+
# The Webgen::Context object +context+ is used as the render context and the +options+ hash
|
28
|
+
# needs to hold all relevant information, that is:
|
29
|
+
#
|
30
|
+
# [<tt>:name</tt> (mandatory)]
|
31
|
+
# The name of the block that should be used.
|
32
|
+
# [<tt>:chain</tt>]
|
33
|
+
# The node chain used for rendering. If this is not specified, the node chain from the context
|
34
|
+
# is used. It needs to be a String in the format <tt>(A)LCN;(A)LCN;...</tt> or an array of
|
35
|
+
# nodes.
|
36
|
+
# [<tt>:node</tt>]
|
37
|
+
# Defines which node in the node chain should be used. Valid values are +next+ (= default
|
38
|
+
# value; the next node in the node chain), +first+ (the first node in the node chain with a
|
39
|
+
# block called +name+) or +current+ (the currently rendered node, ignores the +chain+ option).
|
40
|
+
# [<tt>:notfound</tt>]
|
41
|
+
# If this property is set to +ignore+, a missing block will not raise an error. It is unset by
|
42
|
+
# default, so missing blocks will raise errors.
|
43
|
+
def render_block(context, options)
|
44
|
+
if options[:chain].nil?
|
45
|
+
used_chain = (context[:chain].length > 1 ? context[:chain][1..-1] : context[:chain]).dup
|
46
|
+
elsif options[:chain].kind_of?(Array)
|
47
|
+
used_chain = options[:chain]
|
48
|
+
else
|
49
|
+
paths = options[:chain].split(';')
|
50
|
+
used_chain = paths.collect do |path|
|
51
|
+
temp_node = context.ref_node.resolve(path.strip, context.dest_node.lang)
|
52
|
+
if temp_node.nil?
|
53
|
+
raise Webgen::RenderError.new("Could not resolve <#{path.strip}>",
|
54
|
+
self.class.name, context.dest_node.alcn,
|
55
|
+
context.ref_node.alcn, (options[:line_nr_proc].call if options[:line_nr_proc]))
|
48
56
|
end
|
49
|
-
|
57
|
+
temp_node
|
58
|
+
end.compact
|
59
|
+
return '' if used_chain.length != paths.length
|
60
|
+
dest_node = context.content_node
|
61
|
+
end
|
50
62
|
|
51
|
-
|
52
|
-
|
53
|
-
|
63
|
+
if options[:node] == 'first'
|
64
|
+
used_chain.shift while used_chain.length > 0 && !used_chain.first.node_info[:page].blocks.has_key?(options[:name])
|
65
|
+
elsif options[:node] == 'current'
|
66
|
+
used_chain = context[:chain].dup
|
54
67
|
end
|
55
|
-
|
68
|
+
block_node = used_chain.first
|
69
|
+
|
70
|
+
if !block_node || !block_node.node_info[:page].blocks.has_key?(options[:name])
|
71
|
+
if options[:notfound] == 'ignore'
|
72
|
+
return ''
|
73
|
+
elsif block_node
|
74
|
+
raise Webgen::RenderError.new("No block named '#{options[:name]}' found in <#{block_node.alcn}>",
|
75
|
+
self.class.name, context.dest_node.alcn,
|
76
|
+
context.ref_node.alcn, (options[:line_nr_proc].call if options[:line_nr_proc]))
|
77
|
+
else
|
78
|
+
raise Webgen::RenderError.new("No node in the render chain has a block named '#{options[:name]}'",
|
79
|
+
self.class.name, context.dest_node.alcn,
|
80
|
+
context.ref_node.alcn, (options[:line_nr_proc].call if options[:line_nr_proc]))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context.dest_node.node_info[:used_nodes] << block_node.alcn
|
85
|
+
tmp_context = block_node.node_info[:page].blocks[options[:name]].render(context.clone(:chain => used_chain, :dest_node => dest_node))
|
86
|
+
tmp_context.content
|
56
87
|
end
|
57
88
|
|
58
89
|
end
|
@@ -19,11 +19,14 @@ module Webgen::ContentProcessor
|
|
19
19
|
dest_node = deprecate('dest_node', 'context.dest_node', context.dest_node)
|
20
20
|
|
21
21
|
xml = ::Builder::XmlMarkup.new(:indent => 2)
|
22
|
-
eval(context.content, binding, context.ref_node.
|
22
|
+
eval(context.content, binding, context.ref_node.alcn)
|
23
23
|
context.content = xml.target!
|
24
24
|
context
|
25
|
+
rescue LoadError
|
26
|
+
raise Webgen::LoadError.new('builder', self.class.name, context.dest_node.alcn, 'builder')
|
25
27
|
rescue Exception => e
|
26
|
-
|
28
|
+
line = (e.is_a?(::SyntaxError) ? e.message : e.backtrace[0]).scan(/:(\d+)/).first.first.to_i rescue nil
|
29
|
+
raise Webgen::RenderError.new(e, self.class.name, context.dest_node.alcn, context.ref_node.alcn, line)
|
27
30
|
end
|
28
31
|
|
29
32
|
end
|
@@ -10,6 +10,7 @@ module Webgen::ContentProcessor
|
|
10
10
|
# Process the Ruby statements embedded in the content of +context+.
|
11
11
|
def call(context)
|
12
12
|
require 'erb'
|
13
|
+
extend(ERB::Util)
|
13
14
|
|
14
15
|
website = deprecate('website', 'context.website', context.website)
|
15
16
|
node = deprecate('node', 'context.node', context.content_node)
|
@@ -17,11 +18,12 @@ module Webgen::ContentProcessor
|
|
17
18
|
dest_node = deprecate('dest_node', 'context.dest_node', context.dest_node)
|
18
19
|
|
19
20
|
erb = ERB.new(context.content)
|
20
|
-
erb.filename = context.ref_node.
|
21
|
+
erb.filename = context.ref_node.alcn
|
21
22
|
context.content = erb.result(binding)
|
22
23
|
context
|
23
24
|
rescue Exception => e
|
24
|
-
|
25
|
+
line = (e.is_a?(::SyntaxError) ? e.message : e.backtrace[0]).scan(/:(\d+)/).first.first.to_i rescue nil
|
26
|
+
raise Webgen::RenderError.new(e, self.class.name, context.dest_node.alcn, context.ref_node.alcn, line)
|
25
27
|
end
|
26
28
|
|
27
29
|
end
|
@@ -29,11 +29,14 @@ module Webgen::ContentProcessor
|
|
29
29
|
else
|
30
30
|
::Erubis::Eruby.new(context.content, options)
|
31
31
|
end
|
32
|
-
erubis.filename = context.ref_node.
|
32
|
+
erubis.filename = context.ref_node.alcn
|
33
33
|
context.content = erubis.result(binding)
|
34
34
|
context
|
35
|
+
rescue LoadError
|
36
|
+
raise Webgen::LoadError.new('erubis', self.class.name, context.dest_node.alcn, 'erubis')
|
35
37
|
rescue Exception => e
|
36
|
-
|
38
|
+
line = (e.is_a?(::SyntaxError) ? e.message : e.backtrace[0]).scan(/:(\d+)/).first.first.to_i rescue nil
|
39
|
+
raise Webgen::RenderError.new(e, self.class.name, context.dest_node.alcn, context.ref_node.alcn, line)
|
37
40
|
end
|
38
41
|
|
39
42
|
end
|
@@ -18,11 +18,15 @@ module Webgen::ContentProcessor
|
|
18
18
|
:ref_node => deprecate('ref_node', 'context.ref_node', context.ref_node),
|
19
19
|
:dest_node => deprecate('dest_node', 'context.dest_node', context.dest_node)
|
20
20
|
}
|
21
|
-
context.content = ::Haml::Engine.new(context.content, :filename => context.ref_node.
|
21
|
+
context.content = ::Haml::Engine.new(context.content, :filename => context.ref_node.alcn).
|
22
22
|
render(Object.new, locals)
|
23
23
|
context
|
24
|
+
rescue LoadError
|
25
|
+
raise Webgen::LoadError.new('haml', self.class.name, context.dest_node.alcn, 'haml')
|
26
|
+
rescue ::Haml::Error => e
|
27
|
+
raise Webgen::RenderError.new(e, self.class.name, context.dest_node.alcn, context.ref_node.alcn, (e.line + 1 if e.line))
|
24
28
|
rescue Exception => e
|
25
|
-
raise
|
29
|
+
raise Webgen::RenderError.new(e, self.class.name, context.dest_node.alcn, context.ref_node.alcn)
|
26
30
|
end
|
27
31
|
|
28
32
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Webgen::ContentProcessor
|
4
|
+
|
5
|
+
# Inserts additional links to CSS/JS files and other HTML head meta info directly before the HTML
|
6
|
+
# head end tag.
|
7
|
+
#
|
8
|
+
# The data used by this content processor is taken from the Context object. Therefore this
|
9
|
+
# processor should be the last in the processing pipeline so that all other processors have been
|
10
|
+
# able to set the data.
|
11
|
+
#
|
12
|
+
# The key <tt>:cp_head</tt> of <tt>context.persistent</tt> is used (the normal
|
13
|
+
# <tt>context.options</tt> won't do because the data needs to be shared 'backwards' during the
|
14
|
+
# rendering) and it has to be a Hash with the following values:
|
15
|
+
#
|
16
|
+
# [:js_file] An array of already resolved relative or absolute paths to Javascript files.
|
17
|
+
# [:js_inline] An array of Javascript fragments to be inserted directly into the head section.
|
18
|
+
# [:css_file] An array of already resolved relative or absolute paths to CSS files.
|
19
|
+
# [:css_inline] An array of CSS fragments to be inserted directly into the head section.
|
20
|
+
# [:meta] A hash with key-value pairs from which <tt>meta</tt> tags are generated. The keys and
|
21
|
+
# the values will be properly escaped before insertion. The entries in the meta
|
22
|
+
# information <tt>meta</tt> of the content node are also used and take precedence over
|
23
|
+
# these entries.
|
24
|
+
#
|
25
|
+
# Duplicate values will be removed from the above mentioned arrays before generating the output.
|
26
|
+
class Head
|
27
|
+
|
28
|
+
include Webgen::Loggable
|
29
|
+
|
30
|
+
HTML_HEAD_END_RE = /<\/head\s*>/i #:nodoc:
|
31
|
+
|
32
|
+
# Insert the additional header information.
|
33
|
+
def call(context)
|
34
|
+
require 'erb'
|
35
|
+
context.content.sub!(HTML_HEAD_END_RE) do |match|
|
36
|
+
result = ''
|
37
|
+
if context.persistent[:cp_head].kind_of?(Hash)
|
38
|
+
context.persistent[:cp_head][:js_file].uniq.each do |js_file|
|
39
|
+
result += "\n<script type=\"text/javascript\" src=\"#{js_file}\"></script>"
|
40
|
+
end if context.persistent[:cp_head][:js_file].kind_of?(Array)
|
41
|
+
|
42
|
+
context.persistent[:cp_head][:js_inline].uniq.each do |content|
|
43
|
+
result += "\n<script type=\"text/javascript\">\n#{content}\n</script>"
|
44
|
+
end if context.persistent[:cp_head][:js_inline].kind_of?(Array)
|
45
|
+
|
46
|
+
context.persistent[:cp_head][:css_file].uniq.each do |css_file|
|
47
|
+
result += "\n<link rel=\"stylesheet\" href=\"#{css_file}\" type=\"text/css\"/>"
|
48
|
+
end if context.persistent[:cp_head][:css_file].kind_of?(Array)
|
49
|
+
|
50
|
+
context.persistent[:cp_head][:css_inline].uniq.each do |content|
|
51
|
+
result += "\n<style type=\"text/css\"><![CDATA[/\n#{content}\n]]></style>"
|
52
|
+
end if context.persistent[:cp_head][:css_inline].kind_of?(Array)
|
53
|
+
end
|
54
|
+
((context.persistent[:cp_head] || {})[:meta] || {}).merge(context.node['meta'] || {}).each do |name, content|
|
55
|
+
result += "\n<meta name=\"#{ERB::Util.h(name)}\" content=\"#{ERB::Util.h(content)}\" />"
|
56
|
+
end
|
57
|
+
result + match
|
58
|
+
end
|
59
|
+
context
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -11,8 +11,10 @@ module Webgen::ContentProcessor
|
|
11
11
|
$uid = 0 #fix for invalid fragment ids on second run
|
12
12
|
context.content = ::Maruku.new(context.content, :on_error => :raise).to_html
|
13
13
|
context
|
14
|
+
rescue LoadError
|
15
|
+
raise Webgen::LoadError.new('maruku', self.class.name, context.dest_node.alcn, 'maruku')
|
14
16
|
rescue Exception => e
|
15
|
-
raise
|
17
|
+
raise Webgen::RenderError.new(e, self.class.name, context.dest_node.alcn, context.ref_node.alcn)
|
16
18
|
end
|
17
19
|
|
18
20
|
end
|
@@ -10,6 +10,8 @@ module Webgen::ContentProcessor
|
|
10
10
|
require 'rdiscount'
|
11
11
|
context.content = ::RDiscount.new(context.content).to_html
|
12
12
|
context
|
13
|
+
rescue LoadError
|
14
|
+
raise Webgen::LoadError.new('rdiscount', self.class.name, context.dest_node.alcn, 'rdiscount')
|
13
15
|
end
|
14
16
|
|
15
17
|
end
|
@@ -11,6 +11,8 @@ module Webgen::ContentProcessor
|
|
11
11
|
require 'rdoc/markup/to_html'
|
12
12
|
context.content = ::RDoc::Markup::ToHtml.new.convert(context.content)
|
13
13
|
context
|
14
|
+
rescue LoadError
|
15
|
+
raise Webgen::LoadError.new('rdoc/markup/to_html', self.class.name, context.dest_node.alcn, 'rdoc')
|
14
16
|
end
|
15
17
|
|
16
18
|
end
|
@@ -12,6 +12,8 @@ module Webgen::ContentProcessor
|
|
12
12
|
doc.hard_breaks = context.website.config['contentprocessor.redcloth.hard_breaks']
|
13
13
|
context.content = doc.to_html
|
14
14
|
context
|
15
|
+
rescue LoadError
|
16
|
+
raise Webgen::LoadError.new('redcloth', self.class.name, context.dest_node.alcn, 'RedCloth')
|
15
17
|
end
|
16
18
|
|
17
19
|
end
|
@@ -9,10 +9,12 @@ module Webgen::ContentProcessor
|
|
9
9
|
def call(context)
|
10
10
|
require 'sass'
|
11
11
|
|
12
|
-
context.content = ::Sass::Engine.new(context.content, :filename => context.ref_node.
|
12
|
+
context.content = ::Sass::Engine.new(context.content, :filename => context.ref_node.alcn).render
|
13
13
|
context
|
14
|
-
rescue
|
15
|
-
raise
|
14
|
+
rescue LoadError
|
15
|
+
raise Webgen::LoadError.new('sass', self.class.name, context.dest_node.alcn, 'haml')
|
16
|
+
rescue ::Sass::SyntaxError => e
|
17
|
+
raise Webgen::RenderError.new(e, self.class.name, context.dest_node.alcn, context.ref_node.alcn, (e.sass_line if e.sass_line))
|
16
18
|
end
|
17
19
|
|
18
20
|
end
|
@@ -22,24 +22,38 @@ module Webgen::ContentProcessor
|
|
22
22
|
|
23
23
|
# Replace all webgen tags in the content of +context+ with the rendered content.
|
24
24
|
def call(context)
|
25
|
-
replace_tags(context
|
26
|
-
log(:debug) { "Replacing tag #{tag} with data '#{param_string}' and body '#{body}' in <#{context.ref_node.
|
27
|
-
|
28
|
-
result = ''
|
29
|
-
processor = processor_for_tag(tag)
|
30
|
-
if !processor.nil?
|
31
|
-
processor.set_params(processor.create_tag_params(param_string, context.ref_node))
|
32
|
-
result, process_output = processor.call(tag, body, context)
|
33
|
-
processor.set_params(nil)
|
34
|
-
|
35
|
-
result = call(context.clone(:content => result)).content if process_output
|
36
|
-
end
|
37
|
-
|
38
|
-
result
|
25
|
+
replace_tags(context) do |tag, param_string, body|
|
26
|
+
log(:debug) { "Replacing tag #{tag} with data '#{param_string}' and body '#{body}' in <#{context.ref_node.alcn}>" }
|
27
|
+
process_tag(tag, param_string, body, context)
|
39
28
|
end
|
40
29
|
context
|
41
30
|
end
|
42
31
|
|
32
|
+
# Process the +tag+ and return the result. The parameter +params+ needs to be a Hash holding all
|
33
|
+
# needed and optional parameters for the tag or a parameter String in YAML format and +body+ is
|
34
|
+
# the optional body for the tag. +context+ needs to be a valid Webgen::Context object.
|
35
|
+
def process_tag(tag, params, body, context)
|
36
|
+
result = ''
|
37
|
+
processor = processor_for_tag(tag)
|
38
|
+
if !processor.nil?
|
39
|
+
params = if params.kind_of?(String)
|
40
|
+
processor.create_tag_params(params, context.ref_node)
|
41
|
+
else
|
42
|
+
processor.create_params_hash(params, context.ref_node)
|
43
|
+
end
|
44
|
+
|
45
|
+
processor.set_params(params)
|
46
|
+
result, process_output = processor.call(tag, body, context)
|
47
|
+
processor.set_params(nil)
|
48
|
+
result = call(context.clone(:content => result)).content if process_output
|
49
|
+
else
|
50
|
+
raise Webgen::RenderError.new("No tag processor for '#{tag}' found", self.class.name,
|
51
|
+
context.dest_node.alcn, context.ref_node.alcn)
|
52
|
+
end
|
53
|
+
result
|
54
|
+
end
|
55
|
+
|
56
|
+
|
43
57
|
#######
|
44
58
|
private
|
45
59
|
#######
|
@@ -48,11 +62,11 @@ module Webgen::ContentProcessor
|
|
48
62
|
ProcessingStruct = Struct.new(:state, :tag, :simple_tag, :backslashes, :brackets, :start_pos, :end_pos,
|
49
63
|
:params_start_pos, :params_end_pos, :body_end_pos)
|
50
64
|
|
51
|
-
# Return the
|
52
|
-
# encountered by the parser, the method yields all found
|
53
|
-
# returned string for the tag.
|
54
|
-
def replace_tags(
|
55
|
-
scanner = StringScanner.new(content)
|
65
|
+
# Return the <tt>context.content</tt> provided by <tt>context.ref_node</tt> with all webgen tags
|
66
|
+
# replaced. When a webgen tag is encountered by the parser, the method yields all found
|
67
|
+
# information and substitutes the returned string for the tag.
|
68
|
+
def replace_tags(context) #:yields: tag_name, param_string, body
|
69
|
+
scanner = StringScanner.new(context.content)
|
56
70
|
data = ProcessingStruct.new(:before_tag)
|
57
71
|
while true
|
58
72
|
case data.state
|
@@ -72,8 +86,8 @@ module Webgen::ContentProcessor
|
|
72
86
|
when :in_start_tag
|
73
87
|
data.brackets += (scanner[1] == '{' ? 1 : -1) while data.brackets != 0 && scanner.skip_until(BRACKETS_RE)
|
74
88
|
if data.brackets != 0
|
75
|
-
|
76
|
-
|
89
|
+
raise Webgen::RenderError.new("Unbalanced curly brackets for tag '#{data.tag}'", self.class.name,
|
90
|
+
context.dest_node.alcn, context.ref_node.alcn)
|
77
91
|
else
|
78
92
|
data.params_end_pos = data.body_end_pos = data.end_pos = scanner.pos - 1
|
79
93
|
data.state = (data.simple_tag ? :process : :in_body)
|
@@ -106,8 +120,8 @@ module Webgen::ContentProcessor
|
|
106
120
|
data.end_pos = scanner.pos - 1
|
107
121
|
data.body_end_pos = scanner.pos - scanner.matched.length + scanner[1].length / 2
|
108
122
|
else
|
109
|
-
|
110
|
-
|
123
|
+
raise Webgen::RenderError.new("Invalid body part - no end tag found for '#{data.tag}'", self.class.name,
|
124
|
+
context.dest_node.alcn, context.ref_node.alcn)
|
111
125
|
end
|
112
126
|
|
113
127
|
when :done
|
@@ -115,6 +129,9 @@ module Webgen::ContentProcessor
|
|
115
129
|
end
|
116
130
|
end
|
117
131
|
scanner.string
|
132
|
+
rescue Webgen::RenderError => e
|
133
|
+
e.line = scanner.string[0...scanner.pos].scan("\n").size + 1 unless e.line
|
134
|
+
raise
|
118
135
|
end
|
119
136
|
|
120
137
|
# Return the tag processor for +tag+ or +nil+ if +tag+ is unknown.
|
@@ -125,7 +142,6 @@ module Webgen::ContentProcessor
|
|
125
142
|
elsif map.has_key?(:default)
|
126
143
|
map[:default]
|
127
144
|
else
|
128
|
-
log(:error) { "No tag processor for tag #{tag.inspect} found" }
|
129
145
|
nil
|
130
146
|
end
|
131
147
|
klass.nil? ? nil : website.cache.instance(klass)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module Webgen::ContentProcessor
|
5
|
+
|
6
|
+
# Uses the external +tidy+ program to format the content as valid (X)HTML.
|
7
|
+
class Tidy
|
8
|
+
|
9
|
+
include Webgen::Loggable
|
10
|
+
|
11
|
+
# Process the content of +context+ with the +tidy+ program.
|
12
|
+
def call(context)
|
13
|
+
error_file = Tempfile.new('webgen-tidy')
|
14
|
+
error_file.close
|
15
|
+
|
16
|
+
`tidy -v 2>&1`
|
17
|
+
if $?.exitstatus != 0
|
18
|
+
raise Webgen::CommandNotFoundError.new('tidy', self.class.name, context.dest_node.alcn)
|
19
|
+
end
|
20
|
+
|
21
|
+
cmd = "tidy -q -f #{error_file.path} #{context.website.config['contentprocessor.tidy.options']}"
|
22
|
+
result = IO.popen(cmd, 'r+') do |io|
|
23
|
+
io.write(context.content)
|
24
|
+
io.close_write
|
25
|
+
io.read
|
26
|
+
end
|
27
|
+
if $?.exitstatus != 0
|
28
|
+
File.readlines(error_file.path).each do |line|
|
29
|
+
log($?.exitstatus == 1 ? :warn : :error) { "Tidy reported problems for <#{context.dest_node.alcn}>: #{line}" }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
context.content = result
|
33
|
+
context
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|