Shazburg-webby 0.9.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 (172) hide show
  1. data/History.txt +176 -0
  2. data/Manifest.txt +171 -0
  3. data/README.txt +92 -0
  4. data/Rakefile +54 -0
  5. data/bin/webby +8 -0
  6. data/bin/webby-gen +8 -0
  7. data/examples/blog/Sitefile +7 -0
  8. data/examples/blog/tasks/blog.rake +72 -0
  9. data/examples/blog/templates/atom_feed.erb +40 -0
  10. data/examples/blog/templates/blog/month.erb +22 -0
  11. data/examples/blog/templates/blog/post.erb +16 -0
  12. data/examples/blog/templates/blog/year.erb +22 -0
  13. data/examples/presentation/Sitefile +10 -0
  14. data/examples/presentation/content/css/uv/twilight.css +137 -0
  15. data/examples/presentation/content/presentation/_sample_code.txt +10 -0
  16. data/examples/presentation/content/presentation/index.txt +63 -0
  17. data/examples/presentation/content/presentation/s5/blank.gif +0 -0
  18. data/examples/presentation/content/presentation/s5/bodybg.gif +0 -0
  19. data/examples/presentation/content/presentation/s5/framing.css +23 -0
  20. data/examples/presentation/content/presentation/s5/iepngfix.htc +42 -0
  21. data/examples/presentation/content/presentation/s5/opera.css +7 -0
  22. data/examples/presentation/content/presentation/s5/outline.css +15 -0
  23. data/examples/presentation/content/presentation/s5/pretty.css +86 -0
  24. data/examples/presentation/content/presentation/s5/print.css +1 -0
  25. data/examples/presentation/content/presentation/s5/s5-core.css +9 -0
  26. data/examples/presentation/content/presentation/s5/slides.css +3 -0
  27. data/examples/presentation/content/presentation/s5/slides.js +553 -0
  28. data/examples/presentation/layouts/presentation.txt +43 -0
  29. data/examples/presentation/templates/_code_partial.erb +13 -0
  30. data/examples/presentation/templates/presentation.erb +40 -0
  31. data/examples/tumblog/Sitefile +9 -0
  32. data/examples/tumblog/content/css/tumblog.css +308 -0
  33. data/examples/tumblog/content/images/tumblog/permalink.gif +0 -0
  34. data/examples/tumblog/content/images/tumblog/rss.gif +0 -0
  35. data/examples/tumblog/content/tumblog/200806/the-noble-chicken/index.txt +12 -0
  36. data/examples/tumblog/content/tumblog/200807/historical-perspectives-on-the-classic-chicken-joke/index.txt +12 -0
  37. data/examples/tumblog/content/tumblog/200807/mad-city-chickens/index.txt +10 -0
  38. data/examples/tumblog/content/tumblog/200807/the-wisdom-of-the-dutch/index.txt +11 -0
  39. data/examples/tumblog/content/tumblog/200807/up-a-tree/index.txt +13 -0
  40. data/examples/tumblog/content/tumblog/index.txt +37 -0
  41. data/examples/tumblog/content/tumblog/rss.txt +37 -0
  42. data/examples/tumblog/layouts/tumblog/default.txt +44 -0
  43. data/examples/tumblog/layouts/tumblog/post.txt +15 -0
  44. data/examples/tumblog/lib/tumblog_helper.rb +32 -0
  45. data/examples/tumblog/tasks/tumblog.rake +30 -0
  46. data/examples/tumblog/templates/atom_feed.erb +40 -0
  47. data/examples/tumblog/templates/tumblog/conversation.erb +12 -0
  48. data/examples/tumblog/templates/tumblog/link.erb +10 -0
  49. data/examples/tumblog/templates/tumblog/photo.erb +13 -0
  50. data/examples/tumblog/templates/tumblog/post.erb +12 -0
  51. data/examples/tumblog/templates/tumblog/quote.erb +11 -0
  52. data/examples/webby/Sitefile +19 -0
  53. data/examples/webby/content/css/background.gif +0 -0
  54. data/examples/webby/content/css/blueprint/print.css +76 -0
  55. data/examples/webby/content/css/blueprint/screen.css +696 -0
  56. data/examples/webby/content/css/coderay.css +96 -0
  57. data/examples/webby/content/css/site.css +184 -0
  58. data/examples/webby/content/css/uv/twilight.css +137 -0
  59. data/examples/webby/content/index.txt +37 -0
  60. data/examples/webby/content/manual/index.txt +430 -0
  61. data/examples/webby/content/reference/index.txt +202 -0
  62. data/examples/webby/content/release-notes/rel-0-9-0/index.txt +73 -0
  63. data/examples/webby/content/robots.txt +6 -0
  64. data/examples/webby/content/script/jquery.corner.js +152 -0
  65. data/examples/webby/content/script/jquery.js +31 -0
  66. data/examples/webby/content/sitemap.txt +31 -0
  67. data/examples/webby/content/tips_and_tricks/index.txt +96 -0
  68. data/examples/webby/content/tutorial/index.txt +131 -0
  69. data/examples/webby/layouts/default.txt +55 -0
  70. data/examples/webby/templates/page.erb +10 -0
  71. data/examples/website/Sitefile +7 -0
  72. data/examples/website/content/css/blueprint/License.txt +21 -0
  73. data/examples/website/content/css/blueprint/Readme.txt +100 -0
  74. data/examples/website/content/css/blueprint/compressed/print.css +76 -0
  75. data/examples/website/content/css/blueprint/compressed/screen.css +696 -0
  76. data/examples/website/content/css/blueprint/lib/forms.css +45 -0
  77. data/examples/website/content/css/blueprint/lib/grid.css +193 -0
  78. data/examples/website/content/css/blueprint/lib/grid.png +0 -0
  79. data/examples/website/content/css/blueprint/lib/ie.css +30 -0
  80. data/examples/website/content/css/blueprint/lib/reset.css +39 -0
  81. data/examples/website/content/css/blueprint/lib/typography.css +116 -0
  82. data/examples/website/content/css/blueprint/plugins/buttons/Readme +31 -0
  83. data/examples/website/content/css/blueprint/plugins/buttons/buttons.css +97 -0
  84. data/examples/website/content/css/blueprint/plugins/buttons/icons/cross.png +0 -0
  85. data/examples/website/content/css/blueprint/plugins/buttons/icons/key.png +0 -0
  86. data/examples/website/content/css/blueprint/plugins/buttons/icons/tick.png +0 -0
  87. data/examples/website/content/css/blueprint/plugins/css-classes/Readme +14 -0
  88. data/examples/website/content/css/blueprint/plugins/css-classes/css-classes.css +24 -0
  89. data/examples/website/content/css/blueprint/plugins/fancy-type/Readme +22 -0
  90. data/examples/website/content/css/blueprint/plugins/fancy-type/fancy-type-compressed.css +5 -0
  91. data/examples/website/content/css/blueprint/plugins/fancy-type/fancy-type.css +74 -0
  92. data/examples/website/content/css/blueprint/print.css +68 -0
  93. data/examples/website/content/css/blueprint/screen.css +22 -0
  94. data/examples/website/content/css/coderay.css +111 -0
  95. data/examples/website/content/css/site.css +67 -0
  96. data/examples/website/content/index.txt +19 -0
  97. data/examples/website/layouts/default.txt +58 -0
  98. data/examples/website/lib/breadcrumbs.rb +28 -0
  99. data/examples/website/templates/_partial.erb +10 -0
  100. data/examples/website/templates/page.erb +18 -0
  101. data/examples/website/templates/presentation.erb +40 -0
  102. data/lib/webby.rb +227 -0
  103. data/lib/webby/apps.rb +12 -0
  104. data/lib/webby/apps/generator.rb +283 -0
  105. data/lib/webby/apps/main.rb +221 -0
  106. data/lib/webby/auto_builder.rb +83 -0
  107. data/lib/webby/builder.rb +183 -0
  108. data/lib/webby/core_ext/enumerable.rb +11 -0
  109. data/lib/webby/core_ext/hash.rb +28 -0
  110. data/lib/webby/core_ext/kernel.rb +21 -0
  111. data/lib/webby/core_ext/string.rb +163 -0
  112. data/lib/webby/core_ext/time.rb +9 -0
  113. data/lib/webby/filters.rb +91 -0
  114. data/lib/webby/filters/basepath.rb +97 -0
  115. data/lib/webby/filters/erb.rb +9 -0
  116. data/lib/webby/filters/haml.rb +18 -0
  117. data/lib/webby/filters/markdown.rb +16 -0
  118. data/lib/webby/filters/outline.rb +308 -0
  119. data/lib/webby/filters/sass.rb +17 -0
  120. data/lib/webby/filters/slides.rb +56 -0
  121. data/lib/webby/filters/textile.rb +16 -0
  122. data/lib/webby/filters/tidy.rb +76 -0
  123. data/lib/webby/helpers.rb +30 -0
  124. data/lib/webby/helpers/capture_helper.rb +141 -0
  125. data/lib/webby/helpers/coderay_helper.rb +69 -0
  126. data/lib/webby/helpers/graphviz_helper.rb +136 -0
  127. data/lib/webby/helpers/tag_helper.rb +65 -0
  128. data/lib/webby/helpers/tex_img_helper.rb +133 -0
  129. data/lib/webby/helpers/ultraviolet_helper.rb +63 -0
  130. data/lib/webby/helpers/url_helper.rb +235 -0
  131. data/lib/webby/link_validator.rb +152 -0
  132. data/lib/webby/renderer.rb +379 -0
  133. data/lib/webby/resources.rb +96 -0
  134. data/lib/webby/resources/db.rb +251 -0
  135. data/lib/webby/resources/file.rb +221 -0
  136. data/lib/webby/resources/layout.rb +63 -0
  137. data/lib/webby/resources/page.rb +118 -0
  138. data/lib/webby/resources/partial.rb +79 -0
  139. data/lib/webby/resources/resource.rb +160 -0
  140. data/lib/webby/resources/static.rb +52 -0
  141. data/lib/webby/stelan/mktemp.rb +135 -0
  142. data/lib/webby/stelan/paginator.rb +150 -0
  143. data/lib/webby/stelan/spawner.rb +339 -0
  144. data/lib/webby/tasks/build.rake +27 -0
  145. data/lib/webby/tasks/create.rake +22 -0
  146. data/lib/webby/tasks/deploy.rake +22 -0
  147. data/lib/webby/tasks/growl.rake +15 -0
  148. data/lib/webby/tasks/heel.rake +28 -0
  149. data/lib/webby/tasks/validate.rake +19 -0
  150. data/spec/core_ext/hash_spec.rb +47 -0
  151. data/spec/core_ext/string_spec.rb +110 -0
  152. data/spec/core_ext/time_spec.rb +19 -0
  153. data/spec/spec.opts +1 -0
  154. data/spec/spec_helper.rb +14 -0
  155. data/spec/webby/apps/generator_spec.rb +111 -0
  156. data/spec/webby/apps/main_spec.rb +75 -0
  157. data/spec/webby/helpers/capture_helper_spec.rb +56 -0
  158. data/spec/webby/resources/file_spec.rb +104 -0
  159. data/spec/webby/resources_spec.rb +17 -0
  160. data/tasks/ann.rake +81 -0
  161. data/tasks/bones.rake +21 -0
  162. data/tasks/gem.rake +126 -0
  163. data/tasks/git.rake +41 -0
  164. data/tasks/manifest.rake +49 -0
  165. data/tasks/notes.rake +28 -0
  166. data/tasks/post_load.rake +39 -0
  167. data/tasks/rdoc.rake +51 -0
  168. data/tasks/rubyforge.rake +57 -0
  169. data/tasks/setup.rb +268 -0
  170. data/tasks/spec.rake +55 -0
  171. data/tasks/website.rake +38 -0
  172. metadata +287 -0
@@ -0,0 +1,17 @@
1
+
2
+ # Render text via the Sass library (part of Haml)
3
+ if try_require('sass', 'haml')
4
+
5
+ Webby::Filters.register :sass do |input, cursor|
6
+ opts = ::Webby.site.sass_options.merge(cursor.page.sass_options || {})
7
+ Sass::Engine.new(input, opts).render
8
+ end
9
+
10
+ # Otherwise raise an error if the user tries to use sass
11
+ else
12
+ Webby::Filters.register :sass do |input, cursor|
13
+ raise Webby::Error, "'haml' must be installed to use the sass filter"
14
+ end
15
+ end
16
+
17
+ # EOF
@@ -0,0 +1,56 @@
1
+ module Webby
2
+ module Filters
3
+
4
+ # The Slides filter is used to generate an S5 presentation from HTML input
5
+ # text. The input HTML is scanned for <h1> tags and slide divs are inserted
6
+ # before each <h1> tag found.
7
+ #
8
+ # When the HTML is rendered into the presentation layout, the result is an
9
+ # S5 presentation -- provided that the layout includes the appropriate S5
10
+ # javascript and CSS files.
11
+ #
12
+ class Slides
13
+
14
+ START_SLIDE = %{<div class="slide">#$/}
15
+ END_SLIDE = %{</div>#$/#$/}
16
+
17
+ # call-seq:
18
+ # Slides.new( html )
19
+ #
20
+ # Creates a new slides filter that will operate on the given
21
+ # _html_ string.
22
+ #
23
+ def initialize( str )
24
+ @str = str
25
+ @open = false
26
+ end
27
+
28
+ # call-seq:
29
+ # filter => html
30
+ #
31
+ # Process the original html document passed to the filter when it was
32
+ # created. The document will be scanned for H1 heading tags and slide
33
+ # divs will be inserted into the page before each H1 tag that is found.
34
+ #
35
+ def filter
36
+ result = []
37
+
38
+ @str.split(%r/\<h1\>/i).each do |slide|
39
+ next if slide.strip.empty?
40
+ result << START_SLIDE << '<h1>' << slide << END_SLIDE
41
+ end
42
+
43
+ result.join
44
+ end
45
+ end # class Slides
46
+
47
+ # Insert slide divs into the input HTML text.
48
+ #
49
+ register :slides do |input|
50
+ Slides.new(input).filter
51
+ end
52
+
53
+ end # module Filters
54
+ end # module Webby
55
+
56
+ # EOF
@@ -0,0 +1,16 @@
1
+
2
+ # If RedCloth is installed, then configure the textile filter
3
+ if try_require('redcloth', 'RedCloth')
4
+
5
+ Webby::Filters.register :textile do |input|
6
+ RedCloth.new(input, %w(no_span_caps)).to_html
7
+ end
8
+
9
+ # Otherwise raise an error if the user tries to use textile
10
+ else
11
+ Webby::Filters.register :textile do |input|
12
+ raise Webby::Error, "'RedCloth' must be installed to use the textile filter"
13
+ end
14
+ end
15
+
16
+ # EOF
@@ -0,0 +1,76 @@
1
+ require 'fileutils'
2
+ require 'tempfile'
3
+
4
+ module Webby
5
+ module Filters
6
+
7
+ # The Tidy filter is used to process HTML (or XHTML) through the _tidy_
8
+ # program and outpu nicely formatted and correct HTML (or XHTML).
9
+ #
10
+ # Options can be passed to the _tidy_ program via the
11
+ # <code>Webby.site</code> struct. Setting the +tidy_options+ to the string
12
+ # of desired options will do the trick.
13
+ #
14
+ # From a project's Rakefile, include the following line (or one that's more
15
+ # to your liking):
16
+ #
17
+ # SITE.tidy_options = "-indent -wrap 80 -utf8"
18
+ #
19
+ class Tidy
20
+
21
+ # call-seq:
22
+ # Tidy.new( html )
23
+ #
24
+ # Create a new filter that will process the given _html_ through the tidy
25
+ # program.
26
+ #
27
+ def initialize( str )
28
+ @log = ::Logging::Logger[self]
29
+ @str = str
30
+
31
+ # create a temporary file for holding any error messages
32
+ # from the tidy program
33
+ @err = Tempfile.new('tidy_err')
34
+ @err.close
35
+ end
36
+
37
+ # call-seq:
38
+ # process => formatted html
39
+ #
40
+ # Process the original HTML text string passed to the filter when it was
41
+ # created and output Tidy formatted HTML or XHTML.
42
+ #
43
+ def process
44
+ cmd = "tidy %s -q -f #{@err.path}" % ::Webby.site.tidy_options
45
+ out = IO.popen(cmd, 'r+') do |tidy|
46
+ tidy.write @str
47
+ tidy.close_write
48
+ tidy.read
49
+ end
50
+
51
+ if File.size(@err.path) != 0
52
+ @log.warn File.read(@err.path).strip
53
+ end
54
+
55
+ return out
56
+ end
57
+
58
+ end # class Tidy
59
+
60
+ # Render html into html/xhtml via the Tidy program
61
+ if cmd_available? %w[tidy -v]
62
+ register :tidy do |input|
63
+ Filters::Tidy.new(input).process
64
+ end
65
+
66
+ # Otherwise raise an error if the user tries to use tidy
67
+ else
68
+ register :tidy do |input|
69
+ raise Webby::Error, "'tidy' must be installed to use the tidy filter"
70
+ end
71
+ end
72
+
73
+ end # module Filters
74
+ end # module Webby
75
+
76
+ # EOF
@@ -0,0 +1,30 @@
1
+ require Webby.libpath(*%w[webby renderer])
2
+
3
+ module Webby
4
+
5
+ # The Helpers module is used to register helper modules that provide extra
6
+ # functionality to the Webby renderer. The most notable example is the
7
+ # UrlHelpers module that provides methods to link to another page in a
8
+ # Webby webiste.
9
+ #
10
+ # Helpers are registered with the Webby framework by calling:
11
+ #
12
+ # Webby::Helpers.register( MyHelper )
13
+ #
14
+ module Helpers
15
+
16
+ # call-seq:
17
+ # Helpers.register( module )
18
+ #
19
+ # Register the given _module_ as a helper module for the Webby framework.
20
+ #
21
+ def self.register( helper )
22
+ ::Webby::Renderer.__send__( :include, helper )
23
+ end
24
+
25
+ end # module Helper
26
+ end # module Webby
27
+
28
+ Webby.require_all_libs_relative_to(__FILE__)
29
+
30
+ # EOF
@@ -0,0 +1,141 @@
1
+
2
+ module Webby::Helpers
3
+
4
+ # Based on code from Rails and Merb.
5
+ #
6
+ module CaptureHelper
7
+
8
+ # Called in pages and partials to store up content for later use. Takes a
9
+ # string and/or a block. First, the string is evaluated, and then the
10
+ # block is captured using the capture() helper provided by the template
11
+ # languages. The two are concatenated together.
12
+ #
13
+ # Content is retrieved by calling the method without a string or a block.
14
+ #
15
+ # ==== Parameters
16
+ # obj<Object>:: The key in the conetnt_for hash.
17
+ # string<String>:: Textual content. Defaults to nil.
18
+ # &block:: A block to be evaluated and concatenated to string.
19
+ #
20
+ # ==== Returns
21
+ # Any content associated with the key (or nil).
22
+ #
23
+ # ==== Example
24
+ # content_for(:foo, "Foo")
25
+ # content_for(:foo) #=> "Foo"
26
+ # content_for(:foo, "Bar")
27
+ # content_for(:foo) #=> "FooBar"
28
+ #
29
+ def content_for( obj, string = nil, &block )
30
+ return @_content_for[obj] unless string || block_given?
31
+
32
+ cur = @_content_for[obj].to_s
33
+ new = string.to_s + (block_given? ? capture_erb(&block) : "")
34
+ @_content_for[obj] = cur + new
35
+ end
36
+
37
+ # Returns true if there is content for the given key. Otherwise returns
38
+ # false.
39
+ #
40
+ # ==== Parameters
41
+ # obj<Object>:: The key in the conetnt_for hash.
42
+ #
43
+ # ==== Example
44
+ # content_for(:foo, "Foo")
45
+ # content_for?(:foo) #=> true
46
+ # content_for?(:bar) #=> false
47
+ #
48
+ def content_for?( obj )
49
+ @_content_for.key?(obj)
50
+ end
51
+
52
+ # Deletes any content associated with the given object in the content_for
53
+ # hash.
54
+ #
55
+ # ==== Parameters
56
+ # obj<Object>:: The key in the conetnt_for hash.
57
+ #
58
+ # ==== Returns
59
+ # Any content associated with the key (or nil).
60
+ #
61
+ # ==== Example
62
+ # content_for(:foo, "Foo")
63
+ # content_for?(:foo) #=> true
64
+ # delete_content_for(:foo)
65
+ # content_for?(:foo) #=> false
66
+ #
67
+ def delete_content_for( obj )
68
+ @_content_for.delete(obj)
69
+ end
70
+
71
+ # This method is used to capture content from an ERB filter evaluation. It
72
+ # is useful to helpers that need to process chunks of data during ERB filter
73
+ # processing.
74
+ #
75
+ # ==== Parameters
76
+ # *args:: Arguments to pass to the block.
77
+ # &block:: The ERB block to call.
78
+ #
79
+ # ==== Returns
80
+ # String:: The output of the block.
81
+ #
82
+ # ==== Examples
83
+ # Capture being used in an ERB page:
84
+ #
85
+ # <% @foo = capture_erb do %>
86
+ # <p>Some Foo content!</p>
87
+ # <% end %>
88
+ #
89
+ def capture_erb( *args, &block )
90
+ # get the buffer from the block's binding
91
+ buffer = _erb_buffer(block.binding) rescue nil
92
+
93
+ # If there is no buffer, just call the block and get the contents
94
+ if buffer.nil?
95
+ block.call(*args)
96
+ # If there is a buffer, execute the block, then extract its contents
97
+ else
98
+ pos = buffer.length
99
+ block.call(*args)
100
+
101
+ # extract the block
102
+ data = buffer[pos..-1]
103
+
104
+ # replace it in the original with empty string
105
+ buffer[pos..-1] = ""
106
+
107
+ data
108
+ end
109
+ end
110
+
111
+ # This method is used to concatenate content into the ERB output buffer.
112
+ # It is usefule to helpers that need to insert transformed text back into
113
+ # the ERB output buffer.
114
+ #
115
+ # ==== Parameters
116
+ # string<String>:: The string to insert into the ERB output.
117
+ # the_binding<Binding>:: The binding to pass to the buffer.
118
+ #
119
+ def concat_erb( string, the_binding )
120
+ _erb_buffer(the_binding) << string
121
+ end
122
+
123
+ # Provides direct acccess to the ERB buffer in the conext of the binding.
124
+ #
125
+ # ==== Parameters
126
+ # the_binding<Binding>:: The binding to pass to the buffer.
127
+ #
128
+ # ==== Returns
129
+ # The current ERB output buffer.
130
+ #
131
+ def _erb_buffer( the_binding )
132
+ eval("_erbout", the_binding, __FILE__, __LINE__)
133
+ end
134
+
135
+ end # module CaptureHelper
136
+
137
+ register(CaptureHelper)
138
+
139
+ end # module Webby::Helpers
140
+
141
+ # EOF
@@ -0,0 +1,69 @@
1
+ if try_require 'coderay'
2
+ require 'enumerator'
3
+
4
+ module Webby::Helpers
5
+ module CodeRayHelper
6
+
7
+ # The +coderay+ method applies syntax highlighting to source code embedded
8
+ # in a webpage. The CodeRay highlighting engine is used for the HTML
9
+ # markup of the source code. The page sections to be highlighted are given
10
+ # as blocks of text to the +coderay+ method.
11
+ #
12
+ # Options can be passed to the CodeRay engine via attributes in the
13
+ # +coderay+ method.
14
+ #
15
+ # <% coderay( :lang => "ruby", :line_numbers => "inline" ) do -%>
16
+ # # Initializer for the class.
17
+ # def initialize( string )
18
+ # @str = stirng
19
+ # end
20
+ # <% end -%>
21
+ #
22
+ # The supported CodeRay options are the following:
23
+ #
24
+ # :lang : the language to highlight (ruby, c, html, ...)
25
+ # :line_numbers : include line numbers in 'table', 'inline',
26
+ # or 'list'
27
+ # :line_number_start : where to start with line number counting
28
+ # :bold_every : make every n-th number appear bold
29
+ # :tab_width : convert tab characters to n spaces
30
+ #
31
+ def coderay( *args, &block )
32
+ opts = args.last.instance_of?(Hash) ? args.pop : {}
33
+
34
+ text = capture_erb(&block)
35
+ return if text.empty?
36
+
37
+ defaults = ::Webby.site.coderay
38
+ lang = opts.getopt(:lang, defaults[:lang]).to_sym
39
+
40
+ cr_opts = {}
41
+ %w(line_numbers to_sym
42
+ line_number_start to_i
43
+ bold_every to_i
44
+ tab_width to_i).each_slice(2) do |key,convert|
45
+ key = key.to_sym
46
+ val = opts.getopt(key, defaults[key])
47
+ next if val.nil?
48
+ cr_opts[key] = val.send(convert)
49
+ end
50
+
51
+ #cr.swap(CodeRay.scan(text, lang).html(opts).div)
52
+ out = '<div class="CodeRay"><pre>'
53
+ out << ::CodeRay.scan(text, lang).html(cr_opts)
54
+ out << '</pre></div>'
55
+
56
+ # put some guards around the output (specifically for textile)
57
+ out = _guard(out)
58
+
59
+ concat_erb(out, block.binding)
60
+ return
61
+ end
62
+ end # module CodeRayHelper
63
+
64
+ register(CodeRayHelper)
65
+
66
+ end # module Webby::Helpers
67
+ end # try_require
68
+
69
+ # EOF
@@ -0,0 +1,136 @@
1
+ require 'fileutils'
2
+ require 'tempfile'
3
+
4
+ module Webby::Helpers
5
+ module GraphvizHelper
6
+
7
+ # call-seq:
8
+ # GraphvizHelper.error_check( file )
9
+ #
10
+ # Check the temporary error file to see if it contains any error messages
11
+ # from the graphviz program. If it is not empty, then read the contents
12
+ # and log an error message and raise an exception.
13
+ #
14
+ def self.error_check( file )
15
+ if ::File.size(file.path) != 0
16
+ msg = "\n" << ::File.read(file.path).strip
17
+ raise ::Webby::Error, msg
18
+ end
19
+ end
20
+
21
+ # The +graphviz+ method processes DOT scripts in a webpage and replaces them
22
+ # with generated image files. The page sections to be processed are given
23
+ # as blocks of text to the +graphviz+ method.
24
+ #
25
+ # Options can be passed to the Graphviz program using attributes in the
26
+ # +graphviz+ method.
27
+ #
28
+ # <% graphviz( :path => "images", :type => "gif", cmd => "dot" ) do %>
29
+ # digraph graph_1 {
30
+ # graph [URL="default.html"]
31
+ # a [URL="a.html"]
32
+ # b [URL="b.html"]
33
+ # c [URL="c.html"]
34
+ # a -> b -> c
35
+ # a -> c
36
+ # }
37
+ # <% end %>
38
+ #
39
+ # If the DOT script contains *URL* or *href* attributes on any of the nodes
40
+ # or edges, then an image map will be generated and the image will be
41
+ # "clikcable" in the webpage. If *URL* or *href* attributes do not appear in
42
+ # the DOT script, then a regular image will be inserted into the webpage.
43
+ #
44
+ # The image is inserted into the page using an HTML <img /> tag. A
45
+ # corresponding <map>...</map> element will be inserted if needed.
46
+ #
47
+ # The supported Graphviz options are the following:
48
+ #
49
+ # :path : where generated images will be stored
50
+ # [default is "/"]
51
+ # :type : the type of image to generate (png, jpeg, gif)
52
+ # [default is png]
53
+ # :cmd : the Graphviz command to use when generating images
54
+ # (dot, neato, twopi, circo, fdp) [default is dot]
55
+ #
56
+ # the following options are passed as-is to the generated <img /> tag
57
+ # :style : CSS styles to apply to the <img />
58
+ # :class : CSS class to apply to the <img />
59
+ # :id : HTML identifier
60
+ # :alt : alternate text for the <img />
61
+ #
62
+ def graphviz( *args, &block )
63
+ opts = args.last.instance_of?(Hash) ? args.pop : {}
64
+
65
+ text = capture_erb(&block)
66
+ return if text.empty?
67
+
68
+ # create a temporary file for holding any error messages
69
+ # from the graphviz program
70
+ err = Tempfile.new('graphviz_err')
71
+ err.close
72
+
73
+ defaults = ::Webby.site.graphviz
74
+ path = opts.getopt(:path, defaults[:path])
75
+ cmd = opts.getopt(:cmd, defaults[:cmd])
76
+ type = opts.getopt(:type, defaults[:type])
77
+
78
+ # pull the name of the graph|digraph out of the DOT script
79
+ name = text.match(%r/\A\s*(?:strict\s+)?(?:di)?graph\s+([A-Za-z_][A-Za-z0-9_]*)\s+\{/o)[1]
80
+
81
+ # see if the user includes any URL or href attributes
82
+ # if so, then we need to create an imagemap
83
+ usemap = text.match(%r/(?:URL|href)\s*=/o) != nil
84
+
85
+ # generate the image filename based on the path, graph name, and type
86
+ # of image to generate
87
+ image_fn = path.nil? ? name.dup : ::File.join(path, name)
88
+ image_fn = ::File.join('', image_fn) << '.' << type
89
+
90
+ # create the HTML img tag
91
+ out = "<img src=\"#{image_fn}\""
92
+
93
+ %w[class style id alt].each do |atr|
94
+ val = opts.getopt(atr)
95
+ next if val.nil?
96
+ out << " %s=\"%s\"" % [atr, val]
97
+ end
98
+
99
+ out << " usemap=\"\##{name}\"" if usemap
100
+ out << " />\n"
101
+
102
+ # generate the image map if needed
103
+ if usemap
104
+ IO.popen("#{cmd} -Tcmapx 2> #{err.path}", 'r+') do |io|
105
+ io.write text
106
+ io.close_write
107
+ out << io.read
108
+ end
109
+ GraphvizHelper.error_check(err)
110
+ end
111
+
112
+ # generate the image using graphviz -- but first ensure that the
113
+ # path exists
114
+ out_dir = ::Webby.site.output_dir
115
+ out_file = ::File.join(out_dir, image_fn)
116
+ FileUtils.mkpath(::File.join(out_dir, path)) unless path.nil?
117
+ cmd = "#{cmd} -T#{type} -o #{out_file} 2> #{err.path}"
118
+
119
+ IO.popen(cmd, 'w') {|io| io.write text}
120
+ GraphvizHelper.error_check(err)
121
+
122
+ # put some guards around the output (specifically for textile)
123
+ out = _guard(out)
124
+
125
+ concat_erb(out, block.binding)
126
+ return
127
+ end
128
+ end # module GraphvizHelper
129
+
130
+ if cmd_available? %w[dot -V]
131
+ register(GraphvizHelper)
132
+ end
133
+
134
+ end # module Webby::Helpers
135
+
136
+ # EOF