webgen 1.0.0.beta1 → 1.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/API.rdoc +64 -11
  2. data/ChangeLog +391 -0
  3. data/README.md +2 -2
  4. data/VERSION +1 -1
  5. data/data/webgen/passive_sources/templates/tag.template +1 -1
  6. data/data/webgen/passive_sources/templates/tikz.template +14 -0
  7. data/lib/webgen/bundle/built-in/init.rb +9 -7
  8. data/lib/webgen/bundle_loader.rb +1 -1
  9. data/lib/webgen/cli/show_command.rb +2 -0
  10. data/lib/webgen/cli/show_config_command.rb +0 -1
  11. data/lib/webgen/cli/show_dependencies_command.rb +6 -63
  12. data/lib/webgen/cli/show_tree_command.rb +85 -0
  13. data/lib/webgen/content_processor/erb.rb +1 -1
  14. data/lib/webgen/content_processor/{rdoc.rb → r_doc.rb} +0 -0
  15. data/lib/webgen/content_processor/{redcloth.rb → red_cloth.rb} +0 -0
  16. data/lib/webgen/content_processor/ruby.rb +3 -0
  17. data/lib/webgen/content_processor/sass.rb +10 -6
  18. data/lib/webgen/content_processor/tikz.rb +10 -20
  19. data/lib/webgen/context/html_head.rb +7 -0
  20. data/lib/webgen/item_tracker.rb +42 -15
  21. data/lib/webgen/item_tracker/file.rb +7 -3
  22. data/lib/webgen/item_tracker/missing_node.rb +17 -5
  23. data/lib/webgen/item_tracker/node_content.rb +7 -3
  24. data/lib/webgen/item_tracker/node_meta_info.rb +8 -3
  25. data/lib/webgen/item_tracker/nodes.rb +10 -3
  26. data/lib/webgen/node.rb +4 -29
  27. data/lib/webgen/node_finder.rb +25 -10
  28. data/lib/webgen/path.rb +2 -2
  29. data/lib/webgen/path_handler/base.rb +20 -9
  30. data/lib/webgen/path_handler/feed.rb +29 -22
  31. data/lib/webgen/path_handler/page.rb +1 -3
  32. data/lib/webgen/path_handler/page_utils.rb +114 -33
  33. data/lib/webgen/path_handler/sitemap.rb +13 -6
  34. data/lib/webgen/path_handler/template.rb +0 -70
  35. data/lib/webgen/path_handler/virtual.rb +10 -2
  36. data/lib/webgen/tag.rb +13 -13
  37. data/lib/webgen/tag/tikz.rb +2 -1
  38. data/lib/webgen/test_helper.rb +2 -11
  39. data/lib/webgen/version.rb +1 -1
  40. data/test/webgen/content_processor/test_erb.rb +4 -0
  41. data/test/webgen/content_processor/{test_rdoc.rb → test_r_doc.rb} +1 -1
  42. data/test/webgen/content_processor/{test_redcloth.rb → test_red_cloth.rb} +1 -1
  43. data/test/webgen/content_processor/test_sass.rb +2 -2
  44. data/test/webgen/content_processor/test_tikz.rb +10 -3
  45. data/test/webgen/item_tracker/test_file.rb +5 -5
  46. data/test/webgen/item_tracker/test_missing_node.rb +8 -9
  47. data/test/webgen/item_tracker/test_node_content.rb +5 -6
  48. data/test/webgen/item_tracker/test_node_meta_info.rb +6 -7
  49. data/test/webgen/item_tracker/test_nodes.rb +7 -9
  50. data/test/webgen/path_handler/test_base.rb +4 -5
  51. data/test/webgen/path_handler/test_page.rb +1 -1
  52. data/test/webgen/path_handler/test_page_utils.rb +39 -11
  53. data/test/webgen/path_handler/test_template.rb +5 -45
  54. data/test/webgen/path_handler/test_virtual.rb +21 -0
  55. data/test/webgen/tag/test_link.rb +1 -1
  56. data/test/webgen/tag/test_tikz.rb +2 -2
  57. data/test/webgen/test_context.rb +10 -0
  58. data/test/webgen/test_item_tracker.rb +7 -4
  59. data/test/webgen/test_node.rb +3 -16
  60. data/test/webgen/test_node_finder.rb +10 -6
  61. data/test/webgen/test_tag.rb +4 -4
  62. metadata +218 -216
data/README.md CHANGED
@@ -31,7 +31,7 @@ Apart from this basic functionality, webgen offers many features that
31
31
  makes authoring websites easier:
32
32
 
33
33
  * Multiple markup languages to choose from for writing HTML and CSS
34
- files (Markdown, Textile, RDoc, Haml, Sass ...)
34
+ files (Markdown, Textile, RDoc, Haml, Sass, ...)
35
35
 
36
36
  * Automatic generation of menus, breadcrumb trails, ... and more!
37
37
 
@@ -42,7 +42,7 @@ makes authoring websites easier:
42
42
  view the website *without a web server*)
43
43
 
44
44
  * Easily extendable (all major components can be extended with new
45
- functionality)
45
+ functionality or existing functionality can be replaced)
46
46
 
47
47
  * No need to know the Ruby language for basic websites
48
48
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0.beta1
1
+ 1.0.0.beta2
@@ -1,6 +1,6 @@
1
1
  --- name:tag.langbar pipeline:ruby ------------------------------------------------------------------
2
2
  context.content = context[:nodes].map do |node|
3
- attrs = {:link_text => node.lang}
3
+ attrs = {'link_text' => node.lang}
4
4
  attrs['class'] = 'webgen-langbar-current-lang' if context.content_node.lang == node.lang
5
5
  context.dest_node.link_to(node, node.lang, attrs)
6
6
  end.join(context[:config]['tag.langbar.separator'])
@@ -0,0 +1,14 @@
1
+ --- name:content pipeline:erb
2
+ \nonstopmode
3
+ \documentclass{standalone}
4
+ \usepackage{tikz}
5
+
6
+ <% if context['content_processor.tikz.libraries'] %>
7
+ \usetikzlibrary{<%= context['content_processor.tikz.libraries'].join(',') %>}
8
+ <% end %>
9
+
10
+ \begin{document}
11
+ \begin{tikzpicture}[<%= context['content_processor.tikz.opts'] %>]
12
+ <%= context['data'] %>
13
+ \end{tikzpicture}
14
+ \end{document}
@@ -59,6 +59,8 @@ website.ext.content_processor = content_processor = Webgen::ContentProcessor.new
59
59
  content_processor.register('Blocks')
60
60
  content_processor.register('Builder')
61
61
  content_processor.register('Erb')
62
+ option('content_processor.erb.trim_mode', '',
63
+ "Specifies the ERB trim mode, can contain any combination of '%', '<' and '<>'", &is_string)
62
64
 
63
65
  content_processor.register('Erubis')
64
66
  option('content_processor.erubis.use_pi', false,
@@ -112,6 +114,8 @@ option('content_processor.tikz.resolution', '72 72',
112
114
  end
113
115
  option('content_processor.tikz.transparent', false,
114
116
  'Specifies whether the generated image should be transparent (only if the extension is png)', &true_or_false)
117
+ option('content_processor.tikz.template', '/templates/tikz.template',
118
+ 'Specifies the template with the LaTeX framework that should be used for rendering', &is_string)
115
119
 
116
120
  content_processor.register('Xmllint')
117
121
  option('content_processor.xmllint.options', "--catalogs --noout --valid",
@@ -196,6 +200,8 @@ option('path_handler.version_in_dest_path', 'except_default',
196
200
  raise "The value has to be 'true', 'false' or 'except_default'"
197
201
  end
198
202
  end
203
+ option('path_handler.default_template', 'default.template',
204
+ 'The name of the default template file')
199
205
 
200
206
  website.ext.path_handler = path_handler = Webgen::PathHandler.new(website)
201
207
 
@@ -203,11 +209,7 @@ website.ext.path_handler = path_handler = Webgen::PathHandler.new(website)
203
209
 
204
210
  path_handler.register('Directory')
205
211
  path_handler.register('MetaInfo', :patterns => ['/**/metainfo', '/**/*.metainfo'])
206
-
207
212
  path_handler.register('Template')
208
- option('path_handler.template.default_template', 'default.template',
209
- 'The name of the default template file')
210
-
211
213
  path_handler.register('Page')
212
214
  path_handler.register('Copy')
213
215
  path_handler.register('Feed')
@@ -255,7 +257,7 @@ tag.register('Date')
255
257
  option('tag.date.format', '%Y-%m-%d %H:%M:%S',
256
258
  'The format of the date (same options as Ruby\'s Time#strftime)', &is_string)
257
259
 
258
- tag.register('MetaInfo', :names => :default)
260
+ tag.register('MetaInfo', :names => ['meta_info', :default])
259
261
  option('tag.meta_info.escape_html', true,
260
262
  'Special HTML characters in the output will be escaped if true', &true_or_false)
261
263
 
@@ -271,7 +273,7 @@ option('tag.link.path', nil,
271
273
  option('tag.link.attr', {},
272
274
  'A hash of additional HTML attributes that should be set on the link', &is_hash)
273
275
 
274
- tag.register('ExecuteCommand', :names => 'execute_cmd', :mandatory => ['command'])
276
+ tag.register('ExecuteCommand', :mandatory => ['command'])
275
277
  option('tag.execute_command.command', nil,
276
278
  'The command which should be executed', &is_string)
277
279
  option('tag.execute_command.process_output', true,
@@ -293,7 +295,7 @@ option('tag.coderay.lang', 'ruby',
293
295
  option('tag.coderay.process_body', true,
294
296
  'The tag body will be scanned for tags before highlighting if true', &true_or_false)
295
297
  option('tag.coderay.wrap', :div,
296
- 'Specifies how the code should be wrapped, either "div" or "span"') do |val|
298
+ "Specifies how the code should be wrapped, either 'div' or 'span'") do |val|
297
299
  val = val.to_s.intern
298
300
  raise "The value has to be either div or span" unless val == :div || val == :span
299
301
  val
@@ -54,7 +54,7 @@ module Webgen
54
54
 
55
55
  info_file = File.join(File.dirname(file), 'info.yaml')
56
56
  next unless File.file?(info_file)
57
- next unless YAML.load(File.read(info_file))['autoload']
57
+ next unless (begin YAML.load(File.read(info_file))['autoload']; rescue Exception; false end)
58
58
 
59
59
  load(bundle_name)
60
60
  end
@@ -4,6 +4,7 @@ require 'webgen/cli/utils'
4
4
  require 'webgen/cli/show_extensions_command'
5
5
  require 'webgen/cli/show_config_command'
6
6
  require 'webgen/cli/show_dependencies_command'
7
+ require 'webgen/cli/show_tree_command'
7
8
 
8
9
  module Webgen
9
10
  module CLI
@@ -22,6 +23,7 @@ DESC
22
23
  add_command(ShowConfigCommand.new)
23
24
  add_command(ShowExtensionsCommand.new)
24
25
  add_command(ShowDependenciesCommand.new)
26
+ add_command(ShowTreeCommand.new)
25
27
  end
26
28
 
27
29
  end
@@ -33,7 +33,6 @@ DESC
33
33
  end
34
34
  end
35
35
  @modified = false
36
- @unknown = true
37
36
  end
38
37
 
39
38
  def execute(args) # :nodoc:
@@ -24,79 +24,22 @@ DESC
24
24
  end
25
25
 
26
26
  def execute(args) # :nodoc:
27
- cache = commandparser.website.cache[:item_tracker_data]
28
- if cache.nil?
27
+ data = commandparser.website.ext.item_tracker.cached_items(commandparser.verbose)
28
+ if data.empty?
29
29
  puts "No data available, you need to generate the website first!"
30
30
  return
31
31
  end
32
32
  arg = args.shift
33
33
 
34
- data = cache[:node_dependencies]
35
- data = data.select {|alcn, _| alcn.include?(arg) } if arg
36
- data.sort.each do |alcn, deps|
37
- deps = deps.sort {|a,b| a.first <=> b.first }.map do |uid|
38
- method = "format_#{uid.first}"
39
- if respond_to?(method, true)
40
- send(method, alcn, uid, cache[:item_data][uid])
41
- else
42
- unknown_uid(uid)
43
- end
44
- end.compact
45
-
46
- if deps.length > 0 || commandparser.verbose
34
+ data.select! {|alcn, _| alcn.include?(arg) } if arg
35
+ data.sort.each do |alcn, items|
36
+ if items.length > 0 || commandparser.verbose
47
37
  puts("#{Utils.light(Utils.blue(alcn))}: ")
48
- deps.each {|d| puts(" #{[d].flatten.join("\n ")}")}
38
+ items.each {|d| puts(" #{[d].flatten.join("\n ")}")}
49
39
  end
50
40
  end
51
41
  end
52
42
 
53
- def unknown_uid(uid)
54
- uid.first.to_s
55
- end
56
- private :unknown_uid
57
-
58
- def format_node_meta_info(alcn, uid, data)
59
- dep_alcn, key = *uid.last
60
- return if alcn == dep_alcn && !commandparser.verbose
61
-
62
- if key.nil?
63
- "Any meta info from <#{dep_alcn}>"
64
- else
65
- "Meta info key '#{key}' from <#{dep_alcn}>"
66
- end
67
- end
68
- private :format_node_meta_info
69
-
70
- def format_node_content(alcn, uid, data)
71
- dep_alcn = uid.last
72
- return if alcn == dep_alcn && !commandparser.verbose
73
-
74
- "Content from node <#{dep_alcn}>"
75
- end
76
- private :format_node_content
77
-
78
- def format_file(alcn, uid, data)
79
- "Content from file '#{uid.last}'"
80
- end
81
- private :format_file
82
-
83
- def format_missing_node(alcn, uid, data)
84
- path, lang = *uid.last
85
-
86
- "Missing acn, alcn or dest path <#{path}>" << (lang.nil? ? '' : " in language '#{lang}'")
87
- end
88
- private :format_missing_node
89
-
90
- def format_nodes(alcn, uid, data)
91
- method, _, type = *uid.last
92
-
93
- res = [(type == :content ? "Content" : "Meta info") + " from these nodes"]
94
- res.first << " (result of #{[method].flatten.join('.')})" if commandparser.verbose
95
- res.first << ":"
96
- res += data.flatten
97
- end
98
- private :format_nodes
99
-
100
43
  end
101
44
 
102
45
  end
@@ -0,0 +1,85 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'webgen/cli/utils'
4
+
5
+ module Webgen
6
+ module CLI
7
+
8
+ # The CLI command for showing the node tree.
9
+ class ShowTreeCommand < CmdParse::Command
10
+
11
+ def initialize # :nodoc:
12
+ super('tree', false, false, true)
13
+ self.short_desc = 'Show the node tree'
14
+ self.description = Utils.format_command_desc(<<DESC)
15
+ Shows the internal representation of all destination paths that have been created
16
+ from the source paths. Additionally, the meta information associated with each
17
+ node can be shown as well.
18
+
19
+ This command can be used before or after the website has been generated. Note,
20
+ however, that nodes that are created during generation like fragment nodes can
21
+ only be shown if the website has been generated.
22
+
23
+ If an argument is given, only those nodes that have the argument in their LCN
24
+ are displayed.
25
+
26
+ Hint: The global verbosity option enables additional output.
27
+ DESC
28
+ self.options = CmdParse::OptionParserWrapper.new do |opts|
29
+ opts.separator "Options:"
30
+ opts.on("-a", "--alcn",
31
+ *Utils.format_option_desc("Use ALCN insted of LCN for paths")) do |v|
32
+ @use_alcn = true
33
+ end
34
+ opts.on("-f", "--[no-]fragments",
35
+ *Utils.format_option_desc("Show fragment nodes (default: no)")) do |v|
36
+ @show_fragments = v
37
+ end
38
+ opts.on("-m", "--[no-]meta-info",
39
+ *Utils.format_option_desc("Show meta information (default: no)")) do |v|
40
+ @meta_info = v
41
+ end
42
+ end
43
+ @meta_info = false
44
+ @use_alcn = false
45
+ @show_fragments = false
46
+ end
47
+
48
+ def execute(args) # :nodoc:
49
+ selector = args.shift
50
+ commandparser.website.ext.path_handler.populate_tree
51
+ data = collect_data(commandparser.website.tree.dummy_root.children, selector)
52
+ print_tree(data, selector)
53
+ end
54
+
55
+ def collect_data(children, selector)
56
+ children.sort {|a,b| a.alcn <=> b.alcn}.map do |node|
57
+ sub = collect_data(node.children, selector)
58
+ if sub.length > 0 ||
59
+ ((selector.nil? || node.lcn.include?(selector)) &&
60
+ ((!node.is_fragment? || @show_fragments) &&
61
+ (!node['passive'] || commandparser.website.ext.item_tracker.node_referenced?(node))))
62
+ data = [@use_alcn ? node.alcn : node.lcn]
63
+ data << (@meta_info ? node.meta_info.map {|k,v| "#{k}: #{v.inspect}"} : [])
64
+ data << sub
65
+ data
66
+ else
67
+ nil
68
+ end
69
+ end.compact
70
+ end
71
+ private :collect_data
72
+
73
+ def print_tree(data, indent = '', selector)
74
+ data.each do |name, info, children|
75
+ puts("#{indent}#{Utils.light(Utils.blue(name))}")
76
+ info.each {|i| puts("#{indent} #{i}")} if info.length > 0 && (selector.nil? || name.include?(selector))
77
+ print_tree(children, indent + ' ', selector)
78
+ end
79
+ end
80
+ private :print_tree
81
+
82
+ end
83
+
84
+ end
85
+ end
@@ -13,7 +13,7 @@ module Webgen
13
13
 
14
14
  # Process the Ruby statements embedded in the content of +context+.
15
15
  def self.call(context)
16
- erb = ERB.new(context.content)
16
+ erb = ERB.new(context.content, nil, context.website.config['content_processor.erb.trim_mode'])
17
17
  erb.filename = context.ref_node.alcn
18
18
  context.content = erb.result(binding)
19
19
  context
File without changes
@@ -1,6 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  require 'webgen/content_processor'
4
+ require 'erb'
4
5
 
5
6
  module Webgen
6
7
  class ContentProcessor
@@ -8,6 +9,8 @@ module Webgen
8
9
  # Processes the content that is valid Ruby to generate new content.
9
10
  module Ruby
10
11
 
12
+ extend ERB::Util
13
+
11
14
  # Process the content of +context+ which needs to be valid Ruby code.
12
15
  def self.call(context)
13
16
  eval(context.content, binding, context.ref_node.alcn)
@@ -105,14 +105,18 @@ module Webgen
105
105
  context = options[:webgen_context]
106
106
  path = path.value
107
107
 
108
- dest_node = context.website.tree[options[:filename]].resolve(path, context.dest_node.lang, true)
109
- if dest_node
110
- context.website.ext.item_tracker.add(context.dest_node, :node_meta_info, dest_node.alcn)
111
- result = context.dest_node.route_to(dest_node)
108
+ ref_node = context.website.tree[options[:filename]]
109
+ ref_node = context.website.tree.root if ref_node.nil? && path[0] == ?/
110
+
111
+ if ref_node
112
+ if dest_node = ref_node.resolve(path, context.dest_node.lang, true)
113
+ context.website.ext.item_tracker.add(context.dest_node, :node_meta_info, dest_node.alcn)
114
+ path = context.dest_node.route_to(dest_node)
115
+ end
112
116
  else
113
- result = path
117
+ context.website.logger.warn { "Couldn't determine reference node for resolving node in Sass file." }
114
118
  end
115
- ::Sass::Script::String.new("url(\"#{result}\")")
119
+ ::Sass::Script::String.new(path, :string)
116
120
  end
117
121
  declare :relocatable, [:string]
118
122
 
@@ -18,22 +18,11 @@ module Webgen
18
18
  # Uses LaTeX and the TikZ library for creating images from LaTeX code.
19
19
  module Tikz
20
20
 
21
- LATEX_TEMPLATE = <<EOF
22
- \\nonstopmode \\documentclass{article} \\usepackage{tikz} \\pagestyle{empty}
23
- <% if context['content_processor.tikz.libraries'] %>
24
- \\usetikzlibrary{<%= context['content_processor.tikz.libraries'].join(',') %>}
25
- <% end %>
26
- \\begin{document}
27
- \\begin{tikzpicture}[<%= context['content_processor.tikz.opts'] %>]
28
- <%= context.content %>
29
- \\end{tikzpicture}
30
- \\end{document}
31
- EOF
32
-
33
21
  # Process the content with LaTeX to generate a TikZ image.
34
22
  def self.call(context)
35
23
  prepare_options(context)
36
- context.content = ERB.new(LATEX_TEMPLATE).result(binding)
24
+ context.content = context.render_block(:name => 'content',
25
+ :chain => [context.website.tree[context['content_processor.tikz.template']]])
37
26
  context.content = File.binread(compile(context))
38
27
  context
39
28
  end
@@ -41,9 +30,11 @@ EOF
41
30
  # Collect the necessary options and save them in the context object.
42
31
  def self.prepare_options(context)
43
32
  %w[content_processor.tikz.resolution content_processor.tikz.transparent
44
- content_processor.tikz.libraries content_processor.tikz.opts].each do |opt|
33
+ content_processor.tikz.libraries content_processor.tikz.opts
34
+ content_processor.tikz.template].each do |opt|
45
35
  context[opt] = context.content_node[opt] || context.website.config[opt]
46
36
  end
37
+ context['data'] = context.content
47
38
  end
48
39
  private_class_method :prepare_options
49
40
 
@@ -54,17 +45,16 @@ EOF
54
45
  # Returns the path to the created image.
55
46
  def self.compile(context)
56
47
  cwd = context.website.tmpdir('content_processor.tikz')
48
+ tex_file = File.join(cwd, context.dest_node.dest_path.tr('/', '_').sub(/\..*?$/, '.tex'))
57
49
  FileUtils.mkdir_p(cwd)
58
- tempfile = Tempfile.open(['webgen-tikz', '.tex'], cwd)
59
- tempfile.write(context.content)
60
- tempfile.close
50
+ File.write(tex_file, context.content)
61
51
 
62
- file = File.basename(tempfile.path, '.tex')
52
+ file = File.basename(tex_file, '.tex')
63
53
  ext = File.extname(context.dest_node.dest_path)
64
54
  render_res, output_res = context['content_processor.tikz.resolution'].split(' ')
65
55
 
66
- execute("pdflatex --shell-escape -interaction=batchmode #{file}.tex", cwd, context) do |status, stdout, stderr|
67
- errors = stderr.scan(/^!(.*\n.*)/).join("\n")
56
+ execute("pdflatex -shell-escape -interaction=nonstopmode -halt-on-error #{file}.tex", cwd, context) do |status, stdout, stderr|
57
+ errors = (stdout+stderr).scan(/^!(.*\n.*)/).join("\n")
68
58
  raise Webgen::RenderError.new("Error while parsing TikZ picture commands with PDFLaTeX: #{errors}",
69
59
  self.name, context.dest_node, context.ref_node)
70
60
  end
@@ -16,6 +16,13 @@ module Webgen
16
16
  @context = context
17
17
  end
18
18
 
19
+ # Set the meta tag to the provided value.
20
+ #
21
+ # Note that some meta information keys may not be specified multiple times!
22
+ def meta(name, content)
23
+ (cp_hash[:meta] ||= {})[name] = content
24
+ end
25
+
19
26
  # Add a link to the given file in the HTML head section.
20
27
  #
21
28
  # The type can either be :css for CSS files or :js for javascript files. The path to the