webby 0.7.4 → 0.8.0

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.
Files changed (57) hide show
  1. data/History.txt +19 -0
  2. data/Manifest.txt +19 -6
  3. data/README.txt +21 -5
  4. data/Rakefile +2 -3
  5. data/data/Rakefile +1 -1
  6. data/data/lib/breadcrumbs.rb +28 -0
  7. data/data/tasks/create.rake +0 -1
  8. data/data/tasks/deploy.rake +0 -1
  9. data/data/tasks/growl.rake +0 -1
  10. data/data/tasks/heel.rake +2 -3
  11. data/data/tasks/setup.rb +0 -1
  12. data/data/templates/_partial.erb +10 -0
  13. data/data/templates/atom_feed.erb +34 -0
  14. data/examples/webby/content/manual/index.txt +11 -13
  15. data/examples/webby/content/tutorial/index.txt +1 -1
  16. data/examples/webby/tasks/heel.rake +2 -2
  17. data/examples/webby/tasks/setup.rb +6 -1
  18. data/lib/webby.rb +50 -23
  19. data/lib/webby/auto_builder.rb +4 -2
  20. data/lib/webby/builder.rb +6 -5
  21. data/lib/webby/filters.rb +6 -7
  22. data/lib/webby/filters/outline.rb +4 -2
  23. data/lib/webby/filters/tidy.rb +4 -2
  24. data/lib/webby/helpers.rb +32 -0
  25. data/lib/webby/helpers/coderay_helper.rb +78 -0
  26. data/lib/webby/helpers/graphviz_helper.rb +158 -0
  27. data/lib/webby/helpers/tag_helper.rb +9 -4
  28. data/lib/webby/helpers/tex_img_helper.rb +181 -0
  29. data/lib/webby/helpers/url_helper.rb +12 -11
  30. data/lib/webby/renderer.rb +97 -18
  31. data/lib/webby/resources.rb +82 -0
  32. data/lib/webby/{pages_db.rb → resources/db.rb} +63 -33
  33. data/lib/webby/{file.rb → resources/file.rb} +27 -24
  34. data/lib/webby/resources/layout.rb +65 -0
  35. data/lib/webby/resources/page.rb +109 -0
  36. data/lib/webby/resources/partial.rb +81 -0
  37. data/lib/webby/resources/resource.rb +145 -0
  38. data/lib/webby/resources/static.rb +54 -0
  39. data/lib/webby/stelan/mktemp.rb +137 -0
  40. data/lib/webby/stelan/spawner.rb +5 -1
  41. data/lib/webby/utils.rb +3 -1
  42. data/lib/webby/webby_task.rb +43 -24
  43. data/spec/spec_helper.rb +12 -1
  44. data/spec/webby/{file_spec.rb → resources/file_spec.rb} +21 -22
  45. data/tasks/ann.rake +76 -0
  46. data/tasks/annotations.rake +6 -14
  47. data/tasks/bones.rake +40 -0
  48. data/tasks/doc.rake +1 -2
  49. data/tasks/gem.rake +29 -2
  50. data/tasks/manifest.rake +15 -21
  51. data/tasks/post_load.rake +22 -8
  52. data/tasks/setup.rb +53 -15
  53. data/tasks/spec.rake +13 -0
  54. metadata +22 -9
  55. data/lib/webby/filters/coderay.rb +0 -98
  56. data/lib/webby/filters/graphviz.rb +0 -189
  57. data/lib/webby/resource.rb +0 -293
@@ -0,0 +1,181 @@
1
+ # $Id: tex_img_helper.rb 181 2008-02-29 05:09:49Z tim_pease $
2
+
3
+ require Webby.libpath(*%w[webby stelan mktemp])
4
+ require 'fileutils'
5
+ require 'tempfile'
6
+
7
+ module Webby::Helpers
8
+ module TexImgHelper
9
+
10
+ # :stopdoc:
11
+ class Error < StandardError; end
12
+ # :startdoc:
13
+
14
+ # The +tex2img+ method converts a a section of mathematical TeX script
15
+ # into an image and embeds the resulting image into the page. The TeX
16
+ # engine must be installed on your system along with the ImageMagick
17
+ # +convert+ program.
18
+ #
19
+ # Options can be passed to the TeX engine via attributes in the
20
+ # +tex2img+ method.
21
+ #
22
+ # <% tex2img( "wave_eq", :path => "images", :alt => "wave equation" ) do -%>
23
+ # $\psi_{tot}(x,-t_0,r) = \frac{1}{(2\pi)^2} \int\!\!\!\int
24
+ # \tilde\Psi_{tot}\left(k_x,\frac{c}{2}\sqrt{k_x^2 + k_r^2},r=0\right)$
25
+ # <% end -%>
26
+ #
27
+ # The supported TeX options are the following:
28
+ #
29
+ # :path : where generated images will be stored
30
+ # [default is "/"]
31
+ # :type : the type of image to generate (png, jpeg, gif)
32
+ # [default is png]
33
+ # :bg : the background color of the image (color name,
34
+ # TeX color spec, or #aabbcc) [default is white]
35
+ # :fg : the foreground color of the image (color name,
36
+ # TeX color spec, or #aabbcc) [default is black]
37
+ # :resolution : the desired resolution in dpi (HxV)
38
+ # [default is 150x150]
39
+ # :antialias : if false, disables anti-aliasing in the resulting image
40
+ # [default is true]
41
+ #
42
+ # the following options are passed as-is to the generated <img /> tag
43
+ # :style : CSS styles to apply to the <img />
44
+ # :class : CSS class to apply to the <img />
45
+ # :id : HTML identifier
46
+ # :alt : alternate text for the <img />
47
+ #
48
+ def tex2img( *args, &block )
49
+ opts = args.last.instance_of?(Hash) ? args.pop : {}
50
+ name = args.first
51
+ raise 'TeX graphics must have a name' if name.nil?
52
+
53
+ buffer = eval('_erbout', block.binding)
54
+ pos = buffer.length
55
+ block.call(*args)
56
+
57
+ text = buffer[pos..-1].strip
58
+ if text.empty?
59
+ buffer[pos..-1] = ''
60
+ return
61
+ end
62
+
63
+ # create a temporary file for holding any error messages
64
+ # from the graphviz program
65
+ err = Tempfile.new('graphviz_err')
66
+ err.close
67
+
68
+ path = opts.getopt(:path)
69
+ type = opts.getopt(:type, 'png')
70
+ bg = opts.getopt(:bg, 'white')
71
+ fg = opts.getopt(:fg, 'black')
72
+ res = opts.getopt(:resolution, '150x150')
73
+ aa = opts.getopt(:antialias, true)
74
+
75
+ # fix the color escaping
76
+ fg = TexImgHelper.tex_color(fg)
77
+ bg = TexImgHelper.tex_color(bg)
78
+
79
+ # generate the image filename based on the path, graph name, and type
80
+ # of image to generate
81
+ image_fn = path.nil? ? name.dup : ::File.join(path, name)
82
+ image_fn = ::File.join('', image_fn) << '.' << type
83
+
84
+ # generate the image using convert -- but first ensure that the
85
+ # path exists
86
+ out_dir = ::Webby.site.output_dir
87
+ out_file = ::File.join('..', out_dir, image_fn)
88
+ FileUtils.mkpath(::File.join(out_dir, path)) unless path.nil?
89
+
90
+ tex = <<-TEX
91
+ \\documentclass[12pt]{article}
92
+ \\usepackage[usenames,dvipsnames]{color}
93
+ \\usepackage[dvips]{graphicx}
94
+ \\pagestyle{empty}
95
+ \\pagecolor#{bg}
96
+ \\begin{document}
97
+ {\\color#{fg}
98
+ #{text}
99
+ }\\end{document}
100
+ TEX
101
+ tex.gsub!(%r/\n\s+/, "\n").strip!
102
+
103
+ # make a temporarty directory to store all the TeX files
104
+ pwd = Dir.pwd
105
+ tmpdir = ::Webby::MkTemp.mktempdir('tex2img_XXXXXX')
106
+
107
+ begin
108
+ Dir.chdir(tmpdir)
109
+ File.open('out.tex', 'w') {|fd| fd.puts tex}
110
+ dev_null = test(?e, "/dev/null") ? "/dev/null" : "NUL:"
111
+
112
+ %x[latex -interaction=batchmode out.tex &> #{dev_null}]
113
+ %x[dvips -o out.eps -E out.dvi &> #{dev_null}]
114
+ %x[convert +adjoin #{aa ? '-antialias' : '+antialias'} -density #{res} out.eps #{out_file} &> #{dev_null}]
115
+ ensure
116
+ Dir.chdir(pwd)
117
+ FileUtils.rm_rf(tmpdir) if test(?e, tmpdir)
118
+ end
119
+
120
+ # generate the HTML img tag to insert back into the document
121
+ out = "<img src=\"#{image_fn}\""
122
+ %w[class style id alt].each do |atr|
123
+ val = opts.getopt(atr)
124
+ next if val.nil?
125
+ out << " %s=\"%s\"" % [atr, val]
126
+ end
127
+ out << " />\n"
128
+
129
+ if @_cursor.remaining_filters.include? 'textile'
130
+ out.insert 0, "<notextile>\n"
131
+ out << "\n</notextile>"
132
+ end
133
+
134
+ buffer[pos..-1] = out
135
+ return
136
+ ensure
137
+ end
138
+
139
+ # call-seq:
140
+ # TexImgHelper.tex_color( string ) => string
141
+ #
142
+ # Taken the given color _string_ and convert it to a TeX color spec. The
143
+ # input string can be either a RGB Hex value, a TeX color spec, or a color
144
+ # name.
145
+ #
146
+ # tex_color( '#666666' ) #=> [rgb]{0.4,0.4,0.4}
147
+ # tex_color( 'Tan' ) #=> {Tan}
148
+ # tex_color( '[rgb]{1,0,0}' ) #=> [rgb]{1,0,0}
149
+ #
150
+ # This is an example of an invalid Hex RGB color -- they must contain six
151
+ # hexidecimal characters to be valid.
152
+ #
153
+ # tex_color( '#333' ) #=> {#333}
154
+ #
155
+ def self.tex_color( color )
156
+ case color
157
+ when %r/^#([A-Fa-f0-9]{6})/o
158
+ hex = $1
159
+ rgb = []
160
+ hex.scan(%r/../) {|n| rgb << Float(n.to_i(16))/255.0}
161
+ "[rgb]{#{rgb.join(',')}}"
162
+ when %r/^[\{\[]/o
163
+ "{#{color}}"
164
+ else
165
+ color
166
+ end
167
+ end
168
+
169
+ end # module TexImgHelper
170
+
171
+ %x[latex --version 2>&1]
172
+ if 0 == $?.exitstatus
173
+ %x[convert --version 2>&1]
174
+ if 0 == $?.exitstatus
175
+ register(TexImgHelper)
176
+ end
177
+ end
178
+
179
+ end # module Webby::Helpers
180
+
181
+ # EOF
@@ -1,7 +1,6 @@
1
- # $Id: url_helper.rb 147 2008-02-14 20:14:04Z tim_pease $
1
+ # $Id: url_helper.rb 175 2008-02-28 15:49:11Z tim_pease $
2
2
 
3
- module Webby
4
- module Helpers #:nodoc:
3
+ module Webby::Helpers
5
4
 
6
5
  #
7
6
  #
@@ -38,9 +37,9 @@ module UrlHelper
38
37
  obj = args.first
39
38
 
40
39
  anchor = opts.delete(:anchor)
41
- escape = opts.has_key?(:escape) ? opts.delte(:escape) : true
40
+ escape = opts.has_key?(:escape) ? opts.delete(:escape) : true
42
41
 
43
- url = Webby::Resource === obj ? obj.url : obj.to_s
42
+ url = Webby::Resources::Resource === obj ? obj.url : obj.to_s
44
43
  url = escape_once(url) if escape
45
44
  url << "#" << anchor if anchor
46
45
 
@@ -55,8 +54,8 @@ module UrlHelper
55
54
  # method for final URL creation; see the url_for method for
56
55
  # documentation on those options.
57
56
  #
58
- # The PagesDB#find method is used to locate the page; see the find method
59
- # for the available options.
57
+ # The Resources::DB#find method is used to locate the page; see the find
58
+ # method for the available options.
60
59
  #
61
60
  # ==== Examples
62
61
  #
@@ -97,7 +96,7 @@ module UrlHelper
97
96
  attrs = opts.delete(:attrs)
98
97
 
99
98
  url = case url
100
- when String, Webby::Resource
99
+ when String, Webby::Resources::Resource
101
100
  self.url_for(url, opts)
102
101
  when :back
103
102
  'javascript:history.back()'
@@ -211,7 +210,7 @@ module UrlHelper
211
210
  link_opts = opts.delete(:url) || {}
212
211
  link_opts[:attrs] = opts.delete(:attrs)
213
212
 
214
- if Webby::Resource === name
213
+ if Webby::Resources::Resource === name
215
214
  p, name = name, nil
216
215
  elsif opts.empty? && name
217
216
  p = @pages.find(Webby.site.find_by.to_sym => name)
@@ -227,7 +226,9 @@ module UrlHelper
227
226
  end
228
227
 
229
228
  end # module UrlHelper
230
- end # module Helpers
231
- end # module Webby
229
+
230
+ register(UrlHelper)
231
+
232
+ end # module Webby::Helpers
232
233
 
233
234
  # EOF
@@ -1,10 +1,10 @@
1
- # $Id: renderer.rb 112 2008-01-26 05:31:48Z tim_pease $
1
+ # $Id: renderer.rb 173 2008-02-27 02:58:43Z tim_pease $
2
+
3
+ # Equivalent to a header guard in C/C++
4
+ # Used to prevent the spec helper from being loaded more than once
5
+ unless defined? ::Webby::Renderer
2
6
 
3
7
  require 'erb'
4
- try_require 'bluecloth'
5
- try_require 'redcloth'
6
- try_require 'haml'
7
- try_require 'sass'
8
8
 
9
9
  module Webby
10
10
 
@@ -22,10 +22,11 @@ module Webby
22
22
  #
23
23
  class Renderer
24
24
  include ERB::Util
25
- include Webby::Helpers::TagHelper
26
- include Webby::Helpers::UrlHelper
27
25
 
28
- class Error < StandardError; end # :nodoc:
26
+ # :stopdoc:
27
+ class Error < StandardError; end
28
+ @@stack = []
29
+ # :startdoc:
29
30
 
30
31
  # call-seq:
31
32
  # Renderer.write( page )
@@ -41,7 +42,7 @@ class Renderer
41
42
  ::File.open(page.destination, 'w') do |fd|
42
43
  fd.write renderer.layout_page
43
44
  end
44
- break unless renderer.__send__(:next_page)
45
+ break unless renderer.__send__(:_next_page)
45
46
  }
46
47
  end
47
48
 
@@ -53,14 +54,16 @@ class Renderer
53
54
  # render the filtered page into the desired layout.
54
55
  #
55
56
  def initialize( page )
56
- unless page.is_page?
57
+ unless page.instance_of? Resources::Page
57
58
  raise ArgumentError,
58
59
  "only page resources can be rendered '#{page.path}'"
59
60
  end
60
61
 
61
62
  @page = page
62
- @pages = Resource.pages
63
+ @pages = Resources.pages
64
+ @partials = Resources.partials
63
65
  @content = nil
66
+ @config = ::Webby.site
64
67
 
65
68
  @log = Logging::Logger[self]
66
69
  end
@@ -74,20 +77,29 @@ class Renderer
74
77
  # page's meta-data.
75
78
  #
76
79
  def layout_page
77
- layouts = Resource.layouts
80
+ layouts = Resources.layouts
78
81
  obj = @page
79
82
  str = @page.render(self)
80
83
 
84
+ @@stack << @page.path
81
85
  loop do
82
86
  lyt = layouts.find :filename => obj.layout
83
87
  break if lyt.nil?
84
88
 
85
- @content, str = str, ::Webby::File.read(lyt.path)
86
- str = Filters.process(self, lyt, str)
89
+ @content, str = str, ::Webby::Resources::File.read(lyt.path)
90
+ str = _track_rendering(lyt.path) {
91
+ Filters.process(self, lyt, str)
92
+ }
87
93
  @content, obj = nil, lyt
88
94
  end
89
95
 
96
+ @@stack.pop if @page.path == @@stack.last
97
+ raise Error, "rendering stack corrupted" unless @@stack.empty?
98
+
90
99
  str
100
+ rescue => err
101
+ @log.error "while rendering page '#{@page.path}'"
102
+ @log.error err
91
103
  end
92
104
 
93
105
  # call-seq:
@@ -97,7 +109,42 @@ class Renderer
97
109
  # determined from the page's meta-data.
98
110
  #
99
111
  def render_page
100
- Filters.process(self, @page, ::Webby::File.read(@page.path))
112
+ _track_rendering(@page.path) {
113
+ Filters.process(self, @page, ::Webby::Resources::File.read(@page.path))
114
+ }
115
+ end
116
+
117
+ # call-seq:
118
+ # render_partial( partial ) => string
119
+ #
120
+ # Render the given _partial_ into the current page. The _partial_ can
121
+ # either be the name of the partial to render or a Partial object.
122
+ #
123
+ # In the former case, the partial is found by first looking in the
124
+ # directory of the current for a partial of the same name. Failing that,
125
+ # the search is expanded to include all directories in the site. The first
126
+ # partial with a matching name is returned.
127
+ #
128
+ # In the latter case, Partial objects can be found by using the +find+
129
+ # method of the <tt>@partials</tt> database hash. Please refer to
130
+ # Webby::Resources::DB#find method for more information.
131
+ #
132
+ def render_partial( part, opts = {} )
133
+ part = case part
134
+ when String
135
+ fn = '_' + part
136
+ p = Resources.partials.find(
137
+ :filename => fn, :in_directory => @page.dir ) rescue nil
138
+ p ||= Resources.partials.find(:filename => fn)
139
+ raise Error, "could not find partial '#{part}'" if p.nil?
140
+ p
141
+ when ::Webby::Resources::Partial
142
+ part
143
+ else raise Error, "expecting a partial or a partial name" end
144
+
145
+ _track_rendering(part.path) {
146
+ Filters.process(self, part, ::Webby::Resources::File.read(part.path))
147
+ }
101
148
  end
102
149
 
103
150
  # call-seq:
@@ -119,7 +166,7 @@ class Renderer
119
166
  items[offset,per_page]
120
167
  end.first
121
168
 
122
- @pager.each &block
169
+ @pager.each(&block)
123
170
  end
124
171
 
125
172
  # call-seq:
@@ -135,13 +182,13 @@ class Renderer
135
182
  private
136
183
 
137
184
  # call-seq:
138
- # next_page => true or false
185
+ # _next_page => true or false
139
186
  #
140
187
  # Returns +true+ if there is a next page to render. Returns +false+ if
141
188
  # there is no next page or if pagination has not been configured for the
142
189
  # current page.
143
190
  #
144
- def next_page
191
+ def _next_page
145
192
  return false unless defined? @pager and @pager
146
193
 
147
194
  # go to the next page; break out if there is no next page
@@ -155,7 +202,39 @@ class Renderer
155
202
  true
156
203
  end
157
204
 
205
+ # call-seq:
206
+ # _track_rendering( path ) {block}
207
+ #
208
+ # Keep track of the page rendering for the given _path_. The _block_ is
209
+ # where the the page will be rendered.
210
+ #
211
+ # This method keeps a stack of the current pages being rendeered. It looks
212
+ # for duplicates in the stack -- an indication of a rendering loop. When a
213
+ # rendering loop is detected, an error is raised.
214
+ #
215
+ # This method returns whatever is returned from the _block_.
216
+ #
217
+ def _track_rendering( path )
218
+ loop_error = @@stack.include? path
219
+ @@stack << path
220
+
221
+ if loop_error
222
+ msg = "rendering loop detected for '#{path}'\n"
223
+ msg << " current rendering stack\n\t"
224
+ msg << @@stack.join("\n\t")
225
+ raise Error, msg
226
+ end
227
+
228
+ yield
229
+ ensure
230
+ @@stack.pop if path == @@stack.last
231
+ end
232
+
158
233
  end # class Renderer
159
234
  end # module Webby
160
235
 
236
+ Webby.require_all_libs_relative_to(__FILE__, 'stelan')
237
+
238
+ end # unless defined?
239
+
161
240
  # EOF
@@ -0,0 +1,82 @@
1
+ # $Id: resources.rb 167 2008-02-24 00:59:54Z tim_pease $
2
+
3
+ module Webby::Resources
4
+
5
+ class << self
6
+ # Returns the pages hash object.
7
+ #
8
+ def pages
9
+ @pages ||= ::Webby::Resources::DB.new
10
+ end
11
+
12
+ # Returns the layouts hash object.
13
+ #
14
+ def layouts
15
+ @layouts ||= ::Webby::Resources::DB.new
16
+ end
17
+
18
+ # Returns the partials hash object.
19
+ #
20
+ def partials
21
+ @partials ||= ::Webby::Resources::DB.new
22
+ end
23
+
24
+ # Clear the contents of the +layouts+, +pages+ and +partials+ hash
25
+ # objects.
26
+ #
27
+ def clear
28
+ self.pages.clear
29
+ self.layouts.clear
30
+ self.partials.clear
31
+ end
32
+
33
+ # call-seq:
34
+ # Resources.new( filename )
35
+ #
36
+ #
37
+ def new( fn )
38
+ # normalize the path
39
+ fn = self.path(fn)
40
+
41
+ # see if we are dealing with a layout
42
+ if %r/\A#{::Webby.site.layout_dir}\//o =~ fn
43
+ r = ::Webby::Resources::Layout.new(fn)
44
+ self.layouts << r
45
+ return r
46
+ end
47
+
48
+ # see if we are dealing with a partial
49
+ filename = ::Webby::Resources::File.basename(fn)
50
+ if %r/\A_/o =~ filename
51
+ r = ::Webby::Resources::Partial.new(fn)
52
+ self.partials << r
53
+ return r
54
+ end
55
+
56
+ # see if we are dealing with a static resource
57
+ meta = ::Webby::Resources::File.meta_data(fn)
58
+ if meta.nil?
59
+ r = ::Webby::Resources::Static.new(fn)
60
+ self.pages << r
61
+ return r
62
+ end
63
+
64
+ # this is a renderable page
65
+ r = ::Webby::Resources::Page.new(fn)
66
+ self.pages << r
67
+ return r
68
+ end
69
+
70
+ # Returns a normalized path for the given filename.
71
+ #
72
+ def path( filename )
73
+ filename.sub(%r/\A(?:\.\/|\/)/o, '').freeze
74
+ end
75
+
76
+ end # class << self
77
+
78
+ end # module Webby::Resources
79
+
80
+ Webby.require_all_libs_relative_to(__FILE__)
81
+
82
+ # EOF