webgen 0.5.8 → 0.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|