francois-webby 0.9.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (233) hide show
  1. data/History.txt +218 -0
  2. data/README.rdoc +92 -0
  3. data/Rakefile +62 -0
  4. data/bin/webby +41 -0
  5. data/bin/webby-gen +41 -0
  6. data/examples/blog/Sitefile +7 -0
  7. data/examples/blog/tasks/blog.rake +72 -0
  8. data/examples/blog/templates/atom_feed.erb +40 -0
  9. data/examples/blog/templates/blog/month.erb +22 -0
  10. data/examples/blog/templates/blog/post.erb +16 -0
  11. data/examples/blog/templates/blog/year.erb +22 -0
  12. data/examples/presentation/Sitefile +10 -0
  13. data/examples/presentation/content/css/uv/twilight.css +137 -0
  14. data/examples/presentation/content/presentation/_sample_code.txt +10 -0
  15. data/examples/presentation/content/presentation/index.txt +63 -0
  16. data/examples/presentation/content/presentation/s5/blank.gif +0 -0
  17. data/examples/presentation/content/presentation/s5/bodybg.gif +0 -0
  18. data/examples/presentation/content/presentation/s5/framing.css +23 -0
  19. data/examples/presentation/content/presentation/s5/iepngfix.htc +42 -0
  20. data/examples/presentation/content/presentation/s5/opera.css +7 -0
  21. data/examples/presentation/content/presentation/s5/outline.css +15 -0
  22. data/examples/presentation/content/presentation/s5/pretty.css +86 -0
  23. data/examples/presentation/content/presentation/s5/print.css +25 -0
  24. data/examples/presentation/content/presentation/s5/s5-core.css +9 -0
  25. data/examples/presentation/content/presentation/s5/slides.css +3 -0
  26. data/examples/presentation/content/presentation/s5/slides.js +553 -0
  27. data/examples/presentation/layouts/presentation.txt +43 -0
  28. data/examples/presentation/templates/_code_partial.erb +13 -0
  29. data/examples/presentation/templates/presentation.erb +40 -0
  30. data/examples/tumblog/Sitefile +9 -0
  31. data/examples/tumblog/content/css/tumblog.css +308 -0
  32. data/examples/tumblog/content/images/tumblog/permalink.gif +0 -0
  33. data/examples/tumblog/content/images/tumblog/rss.gif +0 -0
  34. data/examples/tumblog/content/tumblog/200806/the-noble-chicken/index.txt +12 -0
  35. data/examples/tumblog/content/tumblog/200807/historical-perspectives-on-the-classic-chicken-joke/index.txt +12 -0
  36. data/examples/tumblog/content/tumblog/200807/mad-city-chickens/index.txt +10 -0
  37. data/examples/tumblog/content/tumblog/200807/the-wisdom-of-the-dutch/index.txt +11 -0
  38. data/examples/tumblog/content/tumblog/200807/up-a-tree/index.txt +13 -0
  39. data/examples/tumblog/content/tumblog/index.txt +37 -0
  40. data/examples/tumblog/content/tumblog/rss.txt +37 -0
  41. data/examples/tumblog/layouts/tumblog/default.txt +44 -0
  42. data/examples/tumblog/layouts/tumblog/post.txt +15 -0
  43. data/examples/tumblog/lib/tumblog_helper.rb +32 -0
  44. data/examples/tumblog/tasks/tumblog.rake +30 -0
  45. data/examples/tumblog/templates/atom_feed.erb +40 -0
  46. data/examples/tumblog/templates/tumblog/conversation.erb +12 -0
  47. data/examples/tumblog/templates/tumblog/link.erb +10 -0
  48. data/examples/tumblog/templates/tumblog/photo.erb +13 -0
  49. data/examples/tumblog/templates/tumblog/post.erb +12 -0
  50. data/examples/tumblog/templates/tumblog/quote.erb +11 -0
  51. data/examples/webby/Sitefile +19 -0
  52. data/examples/webby/content/communicate/index.txt +28 -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 +196 -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/learn/index.txt +28 -0
  61. data/examples/webby/content/reference/index.txt +204 -0
  62. data/examples/webby/content/release-notes/index.txt +21 -0
  63. data/examples/webby/content/release-notes/rel-0-9-0/index.txt +74 -0
  64. data/examples/webby/content/release-notes/rel-0-9-1/index.txt +93 -0
  65. data/examples/webby/content/release-notes/rel-0-9-2/index.txt +14 -0
  66. data/examples/webby/content/release-notes/rel-0-9-3/index.txt +47 -0
  67. data/examples/webby/content/robots.txt +6 -0
  68. data/examples/webby/content/script/jquery.corner.js +152 -0
  69. data/examples/webby/content/script/jquery.js +31 -0
  70. data/examples/webby/content/sitemap.txt +31 -0
  71. data/examples/webby/content/tips_and_tricks/index.txt +97 -0
  72. data/examples/webby/content/tutorial/index.txt +135 -0
  73. data/examples/webby/content/user-manual/index.txt +419 -0
  74. data/examples/webby/layouts/default.txt +49 -0
  75. data/examples/webby/templates/page.erb +10 -0
  76. data/examples/website/Sitefile +7 -0
  77. data/examples/website/content/css/blueprint/ie.css +26 -0
  78. data/examples/website/content/css/blueprint/plugins/buttons/icons/cross.png +0 -0
  79. data/examples/website/content/css/blueprint/plugins/buttons/icons/key.png +0 -0
  80. data/examples/website/content/css/blueprint/plugins/buttons/icons/tick.png +0 -0
  81. data/examples/website/content/css/blueprint/plugins/buttons/readme.txt +32 -0
  82. data/examples/website/content/css/blueprint/plugins/buttons/screen.css +97 -0
  83. data/examples/website/content/css/blueprint/plugins/fancy-type/readme.txt +14 -0
  84. data/examples/website/content/css/blueprint/plugins/fancy-type/screen.css +71 -0
  85. data/examples/website/content/css/blueprint/plugins/link-icons/icons/doc.png +0 -0
  86. data/examples/website/content/css/blueprint/plugins/link-icons/icons/email.png +0 -0
  87. data/examples/website/content/css/blueprint/plugins/link-icons/icons/external.png +0 -0
  88. data/examples/website/content/css/blueprint/plugins/link-icons/icons/feed.png +0 -0
  89. data/examples/website/content/css/blueprint/plugins/link-icons/icons/im.png +0 -0
  90. data/examples/website/content/css/blueprint/plugins/link-icons/icons/pdf.png +0 -0
  91. data/examples/website/content/css/blueprint/plugins/link-icons/icons/visited.png +0 -0
  92. data/examples/website/content/css/blueprint/plugins/link-icons/icons/xls.png +0 -0
  93. data/examples/website/content/css/blueprint/plugins/link-icons/readme.txt +18 -0
  94. data/examples/website/content/css/blueprint/plugins/link-icons/screen.css +40 -0
  95. data/examples/website/content/css/blueprint/plugins/rtl/readme.txt +10 -0
  96. data/examples/website/content/css/blueprint/plugins/rtl/screen.css +109 -0
  97. data/examples/website/content/css/blueprint/print.css +30 -0
  98. data/examples/website/content/css/blueprint/screen.css +251 -0
  99. data/examples/website/content/css/blueprint/src/forms.css +49 -0
  100. data/examples/website/content/css/blueprint/src/grid.css +212 -0
  101. data/examples/website/content/css/blueprint/src/grid.png +0 -0
  102. data/examples/website/content/css/blueprint/src/ie.css +59 -0
  103. data/examples/website/content/css/blueprint/src/print.css +85 -0
  104. data/examples/website/content/css/blueprint/src/reset.css +38 -0
  105. data/examples/website/content/css/blueprint/src/typography.css +105 -0
  106. data/examples/website/content/css/coderay.css +111 -0
  107. data/examples/website/content/css/site.css +67 -0
  108. data/examples/website/content/index.txt +19 -0
  109. data/examples/website/layouts/default.txt +61 -0
  110. data/examples/website/lib/breadcrumbs.rb +28 -0
  111. data/examples/website/templates/_partial.erb +10 -0
  112. data/examples/website/templates/page.erb +18 -0
  113. data/lib/webby/apps/generator.rb +276 -0
  114. data/lib/webby/apps/main.rb +258 -0
  115. data/lib/webby/apps.rb +12 -0
  116. data/lib/webby/auto_builder.rb +157 -0
  117. data/lib/webby/builder.rb +172 -0
  118. data/lib/webby/core_ext/enumerable.rb +11 -0
  119. data/lib/webby/core_ext/hash.rb +28 -0
  120. data/lib/webby/core_ext/kernel.rb +26 -0
  121. data/lib/webby/core_ext/string.rb +163 -0
  122. data/lib/webby/core_ext/time.rb +9 -0
  123. data/lib/webby/filters/basepath.rb +97 -0
  124. data/lib/webby/filters/erb.rb +9 -0
  125. data/lib/webby/filters/haml.rb +18 -0
  126. data/lib/webby/filters/markdown.rb +16 -0
  127. data/lib/webby/filters/maruku.rb +16 -0
  128. data/lib/webby/filters/outline.rb +309 -0
  129. data/lib/webby/filters/sass.rb +17 -0
  130. data/lib/webby/filters/slides.rb +56 -0
  131. data/lib/webby/filters/textile.rb +16 -0
  132. data/lib/webby/filters/tidy.rb +76 -0
  133. data/lib/webby/filters/wiki_words.rb +14 -0
  134. data/lib/webby/filters.rb +85 -0
  135. data/lib/webby/helpers/capture_helper.rb +141 -0
  136. data/lib/webby/helpers/coderay_helper.rb +69 -0
  137. data/lib/webby/helpers/graphviz_helper.rb +136 -0
  138. data/lib/webby/helpers/tag_helper.rb +65 -0
  139. data/lib/webby/helpers/tex_img_helper.rb +133 -0
  140. data/lib/webby/helpers/ultraviolet_helper.rb +63 -0
  141. data/lib/webby/helpers/url_helper.rb +241 -0
  142. data/lib/webby/helpers.rb +30 -0
  143. data/lib/webby/journal.rb +126 -0
  144. data/lib/webby/link_validator.rb +160 -0
  145. data/lib/webby/renderer.rb +389 -0
  146. data/lib/webby/resources/db.rb +251 -0
  147. data/lib/webby/resources/layout.rb +54 -0
  148. data/lib/webby/resources/meta_file.rb +211 -0
  149. data/lib/webby/resources/page.rb +81 -0
  150. data/lib/webby/resources/partial.rb +85 -0
  151. data/lib/webby/resources/resource.rb +201 -0
  152. data/lib/webby/resources/static.rb +36 -0
  153. data/lib/webby/resources.rb +137 -0
  154. data/lib/webby/stelan/mktemp.rb +135 -0
  155. data/lib/webby/stelan/paginator.rb +165 -0
  156. data/lib/webby/tasks/build.rake +27 -0
  157. data/lib/webby/tasks/create.rake +25 -0
  158. data/lib/webby/tasks/deploy.rake +22 -0
  159. data/lib/webby/tasks/growl.rake +16 -0
  160. data/lib/webby/tasks/validate.rake +19 -0
  161. data/lib/webby.rb +232 -0
  162. data/spec/core_ext/hash_spec.rb +47 -0
  163. data/spec/core_ext/string_spec.rb +110 -0
  164. data/spec/core_ext/time_spec.rb +19 -0
  165. data/spec/data/hooligans/bad_meta_data_1.txt +34 -0
  166. data/spec/data/hooligans/bad_meta_data_2.txt +34 -0
  167. data/spec/data/html/anchor.html +11 -0
  168. data/spec/data/html/external.html +10 -0
  169. data/spec/data/html/invalid-relative.html +10 -0
  170. data/spec/data/html/relative-anchor.html +10 -0
  171. data/spec/data/html/relative-invalid-anchor.html +10 -0
  172. data/spec/data/html/relative.html +10 -0
  173. data/spec/data/outline/basic.out +81 -0
  174. data/spec/data/outline/basic.txt +25 -0
  175. data/spec/data/outline/no_clobber.out +86 -0
  176. data/spec/data/outline/numbering.out +81 -0
  177. data/spec/data/outline/numbering_only.out +21 -0
  178. data/spec/data/outline/toc_range_1.out +66 -0
  179. data/spec/data/outline/toc_range_2.out +55 -0
  180. data/spec/data/outline/toc_style.out +81 -0
  181. data/spec/data/site/Sitefile +9 -0
  182. data/spec/data/site/content/_partial.txt +10 -0
  183. data/spec/data/site/content/css/coderay.css +111 -0
  184. data/spec/data/site/content/css/site.css +67 -0
  185. data/spec/data/site/content/css/tumblog.css +308 -0
  186. data/spec/data/site/content/images/tumblog/permalink.gif +0 -0
  187. data/spec/data/site/content/images/tumblog/rss.gif +0 -0
  188. data/spec/data/site/content/index.txt +19 -0
  189. data/spec/data/site/content/photos.txt +21 -0
  190. data/spec/data/site/content/tumblog/200806/the-noble-chicken/index.txt +12 -0
  191. data/spec/data/site/content/tumblog/200807/historical-perspectives-on-the-classic-chicken-joke/index.txt +12 -0
  192. data/spec/data/site/content/tumblog/200807/mad-city-chickens/index.txt +10 -0
  193. data/spec/data/site/content/tumblog/200807/the-wisdom-of-the-dutch/index.txt +11 -0
  194. data/spec/data/site/content/tumblog/200807/up-a-tree/index.txt +13 -0
  195. data/spec/data/site/content/tumblog/index.txt +37 -0
  196. data/spec/data/site/content/tumblog/rss.txt +37 -0
  197. data/spec/data/site/layouts/default.txt +58 -0
  198. data/spec/data/site/layouts/tumblog/default.txt +44 -0
  199. data/spec/data/site/layouts/tumblog/post.txt +15 -0
  200. data/spec/data/site/lib/breadcrumbs.rb +28 -0
  201. data/spec/data/site/lib/tumblog_helper.rb +32 -0
  202. data/spec/data/site/tasks/tumblog.rake +30 -0
  203. data/spec/data/site/templates/_partial.erb +10 -0
  204. data/spec/data/site/templates/atom_feed.erb +40 -0
  205. data/spec/data/site/templates/page.erb +18 -0
  206. data/spec/data/site/templates/presentation.erb +40 -0
  207. data/spec/data/site/templates/tumblog/conversation.erb +12 -0
  208. data/spec/data/site/templates/tumblog/link.erb +10 -0
  209. data/spec/data/site/templates/tumblog/photo.erb +13 -0
  210. data/spec/data/site/templates/tumblog/post.erb +12 -0
  211. data/spec/data/site/templates/tumblog/quote.erb +11 -0
  212. data/spec/spec.opts +1 -0
  213. data/spec/spec_helper.rb +58 -0
  214. data/spec/webby/apps/generator_spec.rb +117 -0
  215. data/spec/webby/apps/main_spec.rb +88 -0
  216. data/spec/webby/filters/basepath_spec.rb +167 -0
  217. data/spec/webby/filters/maruku_spec.rb +31 -0
  218. data/spec/webby/filters/outline_spec.rb +92 -0
  219. data/spec/webby/filters/textile_spec.rb +31 -0
  220. data/spec/webby/helpers/capture_helper_spec.rb +56 -0
  221. data/spec/webby/link_validator_spec.rb +154 -0
  222. data/spec/webby/renderer_spec.rb +139 -0
  223. data/spec/webby/resources/db_spec.rb +250 -0
  224. data/spec/webby/resources/layout_spec.rb +83 -0
  225. data/spec/webby/resources/meta_file_spec.rb +171 -0
  226. data/spec/webby/resources/page_spec.rb +111 -0
  227. data/spec/webby/resources/partial_spec.rb +58 -0
  228. data/spec/webby/resources/resource_spec.rb +219 -0
  229. data/spec/webby/resources/static_spec.rb +49 -0
  230. data/spec/webby/resources_spec.rb +69 -0
  231. data/tasks/mswin32.rake +38 -0
  232. data/tasks/website.rake +37 -0
  233. metadata +372 -0
data/lib/webby/apps.rb ADDED
@@ -0,0 +1,12 @@
1
+
2
+ module Webby::Apps
3
+
4
+ class << self
5
+ def author() 'Tim Pease'; end
6
+ end
7
+
8
+ end # module Webby::Apps
9
+
10
+ Webby.require_all_libs_relative_to(__FILE__)
11
+
12
+ # EOF
@@ -0,0 +1,157 @@
1
+ require 'directory_watcher'
2
+ require 'launchy'
3
+ require 'webrick'
4
+
5
+ module Webby
6
+
7
+ # The AutoBuilder class is used to monitor the content and layouts folders
8
+ # and to compile the resource files only when they are modified. If a
9
+ # layout is modified, then all resources that depend upon the layout are
10
+ # compiled.
11
+ #
12
+ class AutoBuilder
13
+
14
+ # TODO: hit Ctrl-C once to rebuild everything, and hit it twice to stop the autobuild loop
15
+
16
+ # call-seq:
17
+ # AutoBuilder.run
18
+ #
19
+ # Creates a new AutoBuilder and sets it running. This method will only
20
+ # return when the user presses Ctrl-C.
21
+ #
22
+ def self.run
23
+ self.new.run
24
+ end
25
+
26
+ attr_reader :logger
27
+
28
+ # call-seq:
29
+ # AutoBuilder.new
30
+ #
31
+ # Create a new AutoBuilder class.
32
+ #
33
+ def initialize
34
+ @logger = Logging::Logger[self]
35
+
36
+ @builder = Builder.new
37
+ ::Webby.load_files
38
+
39
+ @watcher = DirectoryWatcher.new '.', :interval => 2
40
+ @watcher.add_observer self
41
+
42
+ glob = []
43
+ glob << File.join(::Webby.site.layout_dir, '**', '*')
44
+ glob << File.join(::Webby.site.content_dir, '**', '*')
45
+ @watcher.glob = glob
46
+
47
+ @web_server = ::Webby.site.use_web_server ? WebServer.new : nil
48
+ end
49
+
50
+ # call-seq:
51
+ # update( *events )
52
+ #
53
+ # The update method is called by the DirectoryWatcher when files have been
54
+ # modified, added, or deleted. An array of events is passed to his method,
55
+ # and each event contains the event type and the path to the file.
56
+ #
57
+ def update( *events )
58
+ ary = events.find_all {|evt| evt.type != :removed}
59
+ return if ary.empty?
60
+
61
+ ary.each do |evt|
62
+ logger.debug "changed #{evt.path}"
63
+ next unless test ?f, evt.path
64
+ next if evt.path =~ ::Webby.exclude
65
+ Resources.new evt.path
66
+ end
67
+
68
+ logger.info 'running the build'
69
+ @builder.run :load_files => false, :verbose => false
70
+ rescue => err
71
+ logger.error err
72
+ end
73
+
74
+ # call-seq:
75
+ # run
76
+ #
77
+ # Starts the DirectoryWatcher running and waits till the user presses
78
+ # Ctrl-C to stop the watcher thread.
79
+ #
80
+ def run
81
+ logger.info 'starting autobuild (Ctrl-C to stop)'
82
+
83
+ Signal.trap('INT') {
84
+ @watcher.stop
85
+ @web_server.stop if @web_server
86
+ }
87
+
88
+ @watcher.start
89
+ if @web_server
90
+ @web_server.start
91
+ sleep 0.25
92
+ Launchy.open("http://localhost:#{::Webby.site.web_port}")
93
+ end
94
+
95
+ @watcher.join
96
+ @web_server.join if @web_server
97
+ end
98
+
99
+ # Wrapper class around the webrick web server.
100
+ #
101
+ class WebServer
102
+
103
+ # Create a new webrick server configured to serve pages from the output
104
+ # directory. Output will be directed to /dev/null.
105
+ #
106
+ def initialize
107
+ logger = WEBrick::Log.new(Kernel::DEV_NULL, WEBrick::Log::DEBUG)
108
+ access_log = [[ logger, WEBrick::AccessLog::COMBINED_LOG_FORMAT ]]
109
+
110
+ @thread = nil
111
+ @running = false
112
+ @server = WEBrick::HTTPServer.new(
113
+ :BindAddress => 'localhost',
114
+ :Port => ::Webby.site.web_port,
115
+ :DocumentRoot => ::Webby.site.output_dir,
116
+ :FancyIndexing => true,
117
+ :Logger => logger,
118
+ :AccessLog => access_log
119
+ )
120
+ end
121
+
122
+ # Returns +true+ if the server is running.
123
+ #
124
+ def running?
125
+ @running
126
+ end
127
+
128
+ # Start the webrick server running in a separate thread (so we don't
129
+ # block forever).
130
+ #
131
+ def start
132
+ return if running?
133
+ @running = true
134
+ @thread = Thread.new {@server.start}
135
+ end
136
+
137
+ # Stop the webrick server.
138
+ #
139
+ def stop
140
+ return if not running?
141
+ @running = false
142
+ @server.shutdown
143
+ end
144
+
145
+ # Join on the webserver thread.
146
+ #
147
+ def join
148
+ return if not running?
149
+ @thread.join
150
+ end
151
+
152
+ end # class WebServer
153
+
154
+ end # class AutoBuilder
155
+ end # module Webby
156
+
157
+ # EOF
@@ -0,0 +1,172 @@
1
+ require 'find'
2
+ require 'fileutils'
3
+ require 'erb'
4
+
5
+ module Webby
6
+
7
+ # The Builder class performs the work of scanning the content folder,
8
+ # creating Resource objects, and converting / copying the contents to the
9
+ # output folder as needed.
10
+ #
11
+ class Builder
12
+
13
+ class << self
14
+
15
+ # call-seq:
16
+ # Builder.run( :rebuild => false )
17
+ #
18
+ # Create a new instance of the Builder class and invoke the run method.
19
+ # If the <code>:rebuild</code> option is given as +true+, then all pages
20
+ # will be recreated / copied.
21
+ #
22
+ def run( opts = {} )
23
+ self.new.run opts
24
+ end
25
+
26
+ # call-seq:
27
+ # Builder.create( page, :from => template, :locals => {} )
28
+ #
29
+ # This mehod is used to create a new _page_ in the content folder based
30
+ # on the specified template. _page_ is the relative path to the new page
31
+ # from the <code>content/</code> folder. The _template_ is the name of
32
+ # the template to use from the <code>templates/</code> folder.
33
+ #
34
+ def create( page, opts = {} )
35
+ tmpl = opts[:from]
36
+ raise Error, "template not given" unless tmpl
37
+
38
+ name = ::Webby::Resources.basename(page)
39
+ ext = ::Webby::Resources.extname(page)
40
+ dir = ::File.dirname(page)
41
+ dir = '' if dir == '.'
42
+
43
+ if tmpl.pathmap('%n') =~ %r/^_/
44
+ page = ::File.join(::Webby.site.content_dir, dir, '_'+name)
45
+ page << '.' << (ext.empty? ? 'txt' : ext)
46
+ elsif ::Webby.site.create_mode == 'directory' and name != 'index'
47
+ page = ::File.join(::Webby.site.content_dir, dir, name, 'index')
48
+ page << '.' << (ext.empty? ? 'txt' : ext)
49
+ else
50
+ page = ::File.join(::Webby.site.content_dir, page)
51
+ page << '.txt' if ext.empty?
52
+ end
53
+ raise Error, "#{page} already exists" if test ?e, page
54
+
55
+ Logging::Logger[self].info "creating #{page}"
56
+ FileUtils.mkdir_p ::File.dirname(page)
57
+
58
+ context = scope
59
+ opts[:locals].each do |k,v|
60
+ Thread.current[:value] = v
61
+ definition = "#{k} = Thread.current[:value]"
62
+ eval(definition, context)
63
+ end if opts.has_key?(:locals)
64
+
65
+ str = ERB.new(::File.read(tmpl), nil, '-').result(context)
66
+ ::File.open(page, 'w') {|fd| fd.write str}
67
+
68
+ page
69
+ end
70
+
71
+ # call-seq:
72
+ # Builder.new_page_info => [page, title, directory]
73
+ #
74
+ def new_page_info
75
+ args = Webby.site.args
76
+
77
+ # TODO: maybe even get rid of this method altogether
78
+ raise "Usage: webby #{args.rake.first} 'path'" if args.raw.empty?
79
+
80
+ [args.page, args.title, args.dir]
81
+ end
82
+
83
+ private
84
+
85
+ # Returns the binding in the scope of the Builder class object.
86
+ #
87
+ def scope() binding end
88
+
89
+ end # class << self
90
+
91
+ # call-seq:
92
+ # Builder.new
93
+ #
94
+ # Creates a new Builder object for creating pages from the content and
95
+ # layout directories.
96
+ #
97
+ def initialize
98
+ @logger = Logging::Logger[self]
99
+ end
100
+
101
+ # call-seq:
102
+ # run( :rebuild => false, :load_files => true )
103
+ #
104
+ # Runs the Webby builder by loading in the layout files from the
105
+ # <code>layouts/</code> folder and the content from the
106
+ # <code>contents/</code> folder. Content is analyzed, and those that need
107
+ # to be copied or compiled (filtered using ERB, Texttile, Markdown, etc.)
108
+ # are handled. The results are placed in the <code>output/</code> folder.
109
+ #
110
+ # If the <code>:rebuild</code> flag is set to +true+, then all content is
111
+ # copied and/or compiled to the output folder.
112
+ #
113
+ # A content file can mark itself as dirty by setting the +dirty+ flag to
114
+ # +true+ in the meta-data of the file. This will cause the contenet to
115
+ # always be compiled when the builder is run. Conversely, setting the
116
+ # dirty flag to +false+ will cause the content to never be compiled or
117
+ # copied to the output folder.
118
+ #
119
+ # A content file needs to be built if the age of the file is less then the
120
+ # age of the output product -- i.e. the content file has been modified
121
+ # more recently than the output file.
122
+ #
123
+ def run( opts = {} )
124
+ opts[:load_files] = true unless opts.has_key?(:load_files)
125
+ verbose = opts.getopt(:verbose, true)
126
+
127
+ unless test(?d, output_dir)
128
+ journal.create output_dir
129
+ FileUtils.mkdir output_dir
130
+ end
131
+
132
+ ::Webby.load_files if opts[:load_files]
133
+
134
+ Resources.pages.each do |page|
135
+ unless page.dirty? or opts[:rebuild]
136
+ journal.identical(page.destination) if verbose
137
+ next
138
+ end
139
+
140
+ # copy the resource to the output directory if it is static
141
+ if page.instance_of? Resources::Static
142
+ FileUtils.mkdir_p ::File.dirname(page.destination)
143
+ journal.create_or_update(page)
144
+ FileUtils.cp page.path, page.destination
145
+ FileUtils.chmod 0644, page.destination
146
+
147
+ # otherwise, layout the resource and write the results to
148
+ # the output directory
149
+ else Renderer.write(page) end
150
+ end
151
+
152
+ # touch the cairn so we know when the website was last generated
153
+ FileUtils.touch ::Webby.cairn
154
+
155
+ nil
156
+ end
157
+
158
+ def load_files
159
+ ::Webby.deprecated "load_files", "it is being replaced by the Webby#load() method"
160
+ ::Webby.load_files
161
+ end
162
+
163
+ %w(output_dir layout_dir content_dir).each do |key|
164
+ self.class_eval <<-CODE
165
+ def #{key}( ) ::Webby.site.#{key} end
166
+ CODE
167
+ end
168
+
169
+ end # class Builder
170
+ end # module Webby
171
+
172
+ # EOF
@@ -0,0 +1,11 @@
1
+
2
+ module Enumerable
3
+
4
+ def injecting( initial )
5
+ inject(initial) do |memo, obj|
6
+ yield(memo, obj); memo
7
+ end
8
+ end
9
+ end # module Enumerable
10
+
11
+ # EOF
@@ -0,0 +1,28 @@
1
+
2
+ class Hash
3
+
4
+ def sanitize!
5
+ h = self.injecting({}) do |h, (k, v)|
6
+ h[k] = case v
7
+ when 'none', 'nil'; nil
8
+ when 'true', 'yes'; true
9
+ when 'false', 'no'; false
10
+ else v end
11
+ end
12
+ self.replace h
13
+ end
14
+
15
+ def stringify_keys
16
+ h = {}
17
+ self.each {|k,v| h[k.to_s] = v}
18
+ return h
19
+ end
20
+
21
+ def symbolize_keys
22
+ h = {}
23
+ self.each {|k,v| h[k.to_sym] = v}
24
+ return h
25
+ end
26
+ end # class Hash
27
+
28
+ # EOF
@@ -0,0 +1,26 @@
1
+
2
+ module Kernel
3
+
4
+ # :stopdoc:
5
+ WINDOWS = %r/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM
6
+ DEV_NULL = WINDOWS ? 'NUL:' : '/dev/null'
7
+ # :startdoc:
8
+
9
+ def cmd_available?( *args )
10
+ io = [STDOUT.dup, STDERR.dup]
11
+ STDOUT.reopen DEV_NULL
12
+ STDERR.reopen DEV_NULL
13
+ system(*(args.flatten))
14
+ ensure
15
+ STDOUT.reopen io.first
16
+ STDERR.reopen io.last
17
+ $stdout, $stderr = STDOUT, STDERR
18
+ end
19
+
20
+ def journal
21
+ @journal ||= ::Webby::Journal.new
22
+ end
23
+
24
+ end # module Kernel
25
+
26
+ # EOF
@@ -0,0 +1,163 @@
1
+
2
+ class String
3
+
4
+ def self.small_words
5
+ @small_words ||= %w(a an and as at but by en for if in of on or the to v[.]? via vs[.]?)
6
+ end
7
+
8
+ def /( path )
9
+ ::File.join(self, path)
10
+ end
11
+
12
+ def titlecase
13
+ swrgxp = self.class.small_words.join('|')
14
+
15
+ parts = self.split( %r/( [:.;?!][ ] | (?:[ ]|^)["“] )/x )
16
+ parts.each do |part|
17
+ part.gsub!(%r/\b[[:alpha:]][[:lower:].'’]*\b/) do |s|
18
+ s =~ %r/\w+\.\w+/ ? s : s.capitalize
19
+ end
20
+
21
+ # Lowercase the small words
22
+ part.gsub!(%r/\b(#{swrgxp})\b/i) {|w| w.downcase}
23
+
24
+ # If the first word is a small word, then capitalize it
25
+ part.gsub!(%r/\A([[:punct:]]*)(#{swrgxp})\b/) {$1 + $2.capitalize}
26
+
27
+ # If the last word is a small word, then capitalize it
28
+ part.gsub!(%r/\b(#{swrgxp})([^\w\s]*)\z/) {$1.capitalize + $2}
29
+ end
30
+
31
+ str = parts.join
32
+
33
+ # Special cases:
34
+ str.gsub!(/ V(s?)\. /, ' v\1. ') # "v." and "vs."
35
+ str.gsub!(/(['’])S\b/, '\1s') # 'S (otherwise you get "the SEC'S decision")
36
+ str.gsub!(/\b(AT&T|Q&A)\b/i) { |w| w.upcase } # "AT&T" and "Q&A", which get tripped up.
37
+
38
+ str
39
+ end
40
+
41
+ # Borrowed from the excellent StringEx library: git://github.com/rsl/stringex.git
42
+
43
+ # Create a URI-friendly representation of the string.
44
+ def to_url
45
+ remove_formatting.downcase.replace_whitespace("-").collapse("-")
46
+ end
47
+
48
+ # Performs multiple text manipulations. Essentially a shortcut for typing them all. View source
49
+ # below to see which methods are run.
50
+ def remove_formatting
51
+ strip_html_tags.convert_accented_entities.convert_misc_entities.convert_misc_characters.collapse
52
+ end
53
+
54
+ # Removes HTML tags from text. This code is simplified from Tobias Luettke's regular expression
55
+ # in Typo[http://typosphere.org].
56
+ def strip_html_tags(leave_whitespace = false)
57
+ name = /[\w:_-]+/
58
+ value = /([A-Za-z0-9]+|('[^']*?'|"[^"]*?"))/
59
+ attr = /(#{name}(\s*=\s*#{value})?)/
60
+ rx = /<[!\/?\[]?(#{name}|--)(\s+(#{attr}(\s+#{attr})*))?\s*([!\/?\]]+|--)?>/
61
+ (leave_whitespace) ? gsub(rx, "").strip : gsub(rx, "").gsub(/\s+/, " ").strip
62
+ end
63
+
64
+ # Converts HTML entities into the respective non-accented letters. Examples:
65
+ #
66
+ # "&aacute;".convert_accented_entities # => "a"
67
+ # "&ccedil;".convert_accented_entities # => "c"
68
+ # "&egrave;".convert_accented_entities # => "e"
69
+ # "&icirc;".convert_accented_entities # => "i"
70
+ # "&oslash;".convert_accented_entities # => "o"
71
+ # "&uuml;".convert_accented_entities # => "u"
72
+ #
73
+ # Note: This does not do any conversion of Unicode/Ascii accented-characters. For that
74
+ # functionality please use <tt>to_ascii</tt>.
75
+ def convert_accented_entities
76
+ gsub(/&([A-Za-z])(grave|acute|circ|tilde|uml|ring|cedil|slash);/, '\1')
77
+ end
78
+
79
+ # Converts HTML entities (taken from common Textile/RedCloth formattings) into plain text formats.
80
+ #
81
+ # Note: This isn't an attempt at complete conversion of HTML entities, just those most likely
82
+ # to be generated by Textile.
83
+ def convert_misc_entities
84
+ dummy = dup
85
+ {
86
+ "#822[01]" => "\"",
87
+ "#821[67]" => "'",
88
+ "#8230" => "...",
89
+ "#8211" => "-",
90
+ "#8212" => "--",
91
+ "#215" => "x",
92
+ "gt" => ">",
93
+ "lt" => "<",
94
+ "(#8482|trade)" => "(tm)",
95
+ "(#174|reg)" => "(r)",
96
+ "(#169|copy)" => "(c)",
97
+ "(#38|amp)" => "and",
98
+ "nbsp" => " ",
99
+ "(#162|cent)" => " cent",
100
+ "(#163|pound)" => " pound",
101
+ "(#188|frac14)" => "one fourth",
102
+ "(#189|frac12)" => "half",
103
+ "(#190|frac34)" => "three fourths",
104
+ "(#176|deg)" => " degrees"
105
+ }.each do |textiled, normal|
106
+ dummy.gsub!(/&#{textiled};/, normal)
107
+ end
108
+ dummy.gsub(/&[^;]+;/, "")
109
+ end
110
+
111
+ # Converts various common plaintext characters to a more URI-friendly representation.
112
+ # Examples:
113
+ #
114
+ # "foo & bar".convert_misc_characters # => "foo and bar"
115
+ # "Chanel #9".convert_misc_characters # => "Chanel number nine"
116
+ # "user@host".convert_misc_characters # => "user at host"
117
+ # "google.com".convert_misc_characters # => "google dot com"
118
+ # "$10".convert_misc_characters # => "10 dollars"
119
+ # "*69".convert_misc_characters # => "star 69"
120
+ # "100%".convert_misc_characters # => "100 percent"
121
+ # "windows/mac/linux".convert_misc_characters # => "windows slash mac slash linux"
122
+ #
123
+ # Note: Because this method will convert any & symbols to the string "and",
124
+ # you should run any methods which convert HTML entities (convert_html_entities and convert_misc_entities)
125
+ # before running this method.
126
+ def convert_misc_characters
127
+ dummy = dup.gsub(/\.{3,}/, " dot dot dot ") # Catch ellipses before single dot rule!
128
+ {
129
+ /\s*&\s*/ => "and",
130
+ /\s*#/ => "number",
131
+ /\s*@\s*/ => "at",
132
+ /(\S|^)\.(\S)/ => '\1 dot \2',
133
+ /(\s|^)\$(\d*)(\s|$)/ => '\2 dollars',
134
+ /\s*\*\s*/ => "star",
135
+ /\s*%\s*/ => "percent",
136
+ /\s*(\\|\/)\s*/ => "slash",
137
+ }.each do |found, replaced|
138
+ replaced = " #{replaced} " unless replaced =~ /\\1/
139
+ dummy.gsub!(found, replaced)
140
+ end
141
+ dummy = dummy.gsub(/(^|\w)'(\w|$)/, '\1\2').gsub(/[\.,:;()\[\]\/\?!\^'"_]/, " ")
142
+ end
143
+
144
+ # Replace runs of whitespace in string. Defaults to a single space but any replacement
145
+ # string may be specified as an argument. Examples:
146
+ #
147
+ # "Foo bar".replace_whitespace # => "Foo bar"
148
+ # "Foo bar".replace_whitespace("-") # => "Foo-bar"
149
+ def replace_whitespace(replace = " ")
150
+ gsub(/\s+/, replace)
151
+ end
152
+
153
+ # Removes specified character from the beginning and/or end of the string and then performs
154
+ # <tt>String#squeeze(character)</tt>, condensing runs of the character within the string.
155
+ #
156
+ # Note: This method has been superceded by ActiveSupport's squish method.
157
+ def collapse(character = " ")
158
+ sub(/^#{character}*/, "").sub(/#{character}*$/, "").squeeze(character)
159
+ end
160
+
161
+ end # class String
162
+
163
+ # EOF