zenweb 2.18.1 → 3.0.0.b1

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 (110) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.autotest +18 -0
  3. data/.gemtest +0 -0
  4. data/History.txt +6 -0
  5. data/Manifest.txt +52 -50
  6. data/README.txt +27 -22
  7. data/Rakefile +8 -9
  8. data/example-site/.isolate.rb +8 -0
  9. data/example-site/Rakefile +32 -0
  10. data/example-site/_config.yml +3 -0
  11. data/example-site/_includes/analytics.html.erb +11 -0
  12. data/example-site/_includes/header.html.erb +3 -0
  13. data/example-site/_includes/page_list_item.html +5 -0
  14. data/example-site/_includes/post_list_item.html +5 -0
  15. data/example-site/_layouts/post.erb +13 -0
  16. data/example-site/_layouts/project.erb +39 -0
  17. data/example-site/_layouts/site.erb +62 -0
  18. data/example-site/about/index.html.md +8 -0
  19. data/example-site/atom.xml.erb +43 -0
  20. data/example-site/blog/2012-01-02-page1.html.md +5 -0
  21. data/example-site/blog/2012-01-03-page2.html.md +5 -0
  22. data/example-site/blog/2012-01-04-page3.html.md +5 -0
  23. data/example-site/blog/_config.yml +1 -0
  24. data/example-site/blog/index.html.erb +19 -0
  25. data/example-site/config.ru +33 -0
  26. data/example-site/css/colors.css.less +71 -0
  27. data/example-site/css/styles.css +223 -0
  28. data/example-site/css/syntax.css +171 -0
  29. data/example-site/img/bg.png +0 -0
  30. data/example-site/index.html.erb +27 -0
  31. data/example-site/js/jquery.js +154 -0
  32. data/example-site/js/site.js +37 -0
  33. data/example-site/pages/index.html.erb +17 -0
  34. data/example-site/pages/nonblogpage.html.md +8 -0
  35. data/example-site/projects/index.html.erb +18 -0
  36. data/example-site/projects/zenweb.html.erb +9 -0
  37. data/example-site/sitemap.xml.erb +24 -0
  38. data/lib/zenweb.rb +12 -0
  39. data/lib/zenweb/config.rb +126 -0
  40. data/lib/zenweb/extensions.rb +51 -0
  41. data/lib/zenweb/page.rb +409 -0
  42. data/lib/zenweb/plugins/disqus.rb +18 -0
  43. data/lib/zenweb/plugins/erb.rb +43 -0
  44. data/lib/zenweb/plugins/google.rb +20 -0
  45. data/lib/zenweb/plugins/less.rb +10 -0
  46. data/lib/zenweb/plugins/markdown.rb +121 -0
  47. data/lib/zenweb/site.rb +237 -0
  48. data/lib/zenweb/tasks.rake +165 -0
  49. data/test/helper.rb +53 -0
  50. data/test/test_zenweb_config.rb +90 -0
  51. data/test/test_zenweb_extensions.rb +33 -0
  52. data/test/test_zenweb_page.rb +381 -0
  53. data/test/test_zenweb_plugins_disqus.rb +41 -0
  54. data/test/test_zenweb_plugins_erb.rb +60 -0
  55. data/test/test_zenweb_plugins_google.rb +38 -0
  56. data/test/test_zenweb_plugins_less.rb +33 -0
  57. data/test/test_zenweb_plugins_markdown.rb +227 -0
  58. data/test/test_zenweb_site.rb +294 -0
  59. metadata +230 -86
  60. metadata.gz.sig +0 -0
  61. data/bin/zenweb +0 -27
  62. data/bin/zenwebpage +0 -66
  63. data/bin/zenwebsite +0 -39
  64. data/design/REQUIREMENTS.txt +0 -52
  65. data/design/ZENWEB_2.txt +0 -69
  66. data/design/heirarchy.png +0 -0
  67. data/design/heirarchy.tgif +0 -311
  68. data/docs/Customizing +0 -76
  69. data/docs/FAQ +0 -12
  70. data/docs/Features +0 -128
  71. data/docs/Presentation +0 -88
  72. data/docs/QuickStart +0 -32
  73. data/docs/Renderers +0 -85
  74. data/docs/SiteMap +0 -13
  75. data/docs/YourOwnWebsite +0 -32
  76. data/docs/index +0 -14
  77. data/docs/metadata.txt +0 -10
  78. data/lib/ZenWeb.rb +0 -850
  79. data/lib/ZenWeb/CalendarRenderer.rb +0 -162
  80. data/lib/ZenWeb/CompactRenderer.rb +0 -45
  81. data/lib/ZenWeb/CompositeRenderer.rb +0 -63
  82. data/lib/ZenWeb/FileAttachmentRenderer.rb +0 -57
  83. data/lib/ZenWeb/FooterRenderer.rb +0 -38
  84. data/lib/ZenWeb/GenericRenderer.rb +0 -143
  85. data/lib/ZenWeb/HeaderRenderer.rb +0 -52
  86. data/lib/ZenWeb/HtmlRenderer.rb +0 -81
  87. data/lib/ZenWeb/HtmlTableRenderer.rb +0 -94
  88. data/lib/ZenWeb/HtmlTemplateRenderer.rb +0 -173
  89. data/lib/ZenWeb/MetadataRenderer.rb +0 -83
  90. data/lib/ZenWeb/RelativeRenderer.rb +0 -97
  91. data/lib/ZenWeb/RubyCodeRenderer.rb +0 -56
  92. data/lib/ZenWeb/SitemapRenderer.rb +0 -56
  93. data/lib/ZenWeb/StandardRenderer.rb +0 -40
  94. data/lib/ZenWeb/StupidRenderer.rb +0 -91
  95. data/lib/ZenWeb/SubpageRenderer.rb +0 -45
  96. data/lib/ZenWeb/TextToHtmlRenderer.rb +0 -219
  97. data/lib/ZenWeb/TocRenderer.rb +0 -60
  98. data/lib/ZenWeb/XXXRenderer.rb +0 -32
  99. data/test/SiteMap +0 -14
  100. data/test/Something +0 -4
  101. data/test/include.txt +0 -3
  102. data/test/index +0 -8
  103. data/test/metadata.txt +0 -10
  104. data/test/ryand/SiteMap +0 -10
  105. data/test/ryand/blah +0 -4
  106. data/test/ryand/blah-blah +0 -4
  107. data/test/ryand/index +0 -52
  108. data/test/ryand/metadata.txt +0 -2
  109. data/test/ryand/stuff/index +0 -4
  110. data/test/test_zenweb.rb +0 -1619
@@ -0,0 +1,51 @@
1
+ ##
2
+ # Walk each parent directory of dir looking for file. Yield each file
3
+ # found to caller.
4
+
5
+ def File.each_parent dir, file
6
+ until dir == "." do
7
+ dir = File.dirname dir
8
+ yield File.join(dir, file).sub(/^\.\//, "")
9
+ end
10
+ end
11
+
12
+ class File # :nodoc:
13
+ RUBY19 = "<3".respond_to? :encoding # :nodoc:
14
+
15
+ class << self
16
+ alias :binread :read unless RUBY19
17
+ end
18
+ end
19
+
20
+ class String # :nodoc:
21
+ def valid_encoding? # :nodoc:
22
+ true
23
+ end unless File::RUBY19
24
+ end
25
+
26
+ class Time # :nodoc:
27
+ ##
28
+ # Format as YYYY-MM-DD
29
+
30
+ def date
31
+ strftime "%Y-%m-%d"
32
+ end
33
+
34
+ def ym
35
+ strftime "%Y-%m"
36
+ end
37
+
38
+ ##
39
+ # Format as YYYY-MM-DD @ HH:MM
40
+
41
+ def datetime
42
+ strftime "%Y-%m-%d @ %H:%M"
43
+ end
44
+
45
+ ##
46
+ # Format as HH:MM
47
+
48
+ def time
49
+ strftime "%H:%M"
50
+ end
51
+ end
@@ -0,0 +1,409 @@
1
+ require "rubygems"
2
+
3
+ gem "rake"
4
+ require "rake"
5
+
6
+ module Zenweb
7
+
8
+ ##
9
+ # Page represents pretty much any type of file that goes on your
10
+ # website or is needed by other pages to build your website. Each
11
+ # page can have a YAML header that contains configuration data or
12
+ # variables used in the page.
13
+
14
+ class Page
15
+ include Rake::DSL
16
+
17
+ ##
18
+ # The shared site instance.
19
+
20
+ attr_reader :site
21
+
22
+ ##
23
+ # The path to this source file.
24
+
25
+ attr_reader :path
26
+
27
+ ##
28
+ # The pages directly below this page. Can be empty.
29
+
30
+ attr_reader :subpages
31
+
32
+ ##
33
+ # The parent page of this page. Can be nil.
34
+
35
+ attr_accessor :parent
36
+
37
+ ##
38
+ # Returns a regexp that will match file extensions for all known
39
+ # renderer types.
40
+
41
+ def self.renderers_re
42
+ @renderers_re ||=
43
+ begin
44
+ ext = instance_methods.grep(/^render_/).map { |s|
45
+ s.to_s.sub(/render_/, '')
46
+ }
47
+ /(?:\.(#{ext.join "|"}))+$/
48
+ end
49
+ end
50
+
51
+ def initialize site, path, config = nil # :nodoc:
52
+ # TODO: make sure that creating page /a.html strips leading / from path
53
+ @site, @path = site, path
54
+ @config = config if config
55
+ @subpages = []
56
+ end
57
+
58
+ ##
59
+ # Helper method to access the config value named +k+.
60
+
61
+ def [] k
62
+ config[k] or warn("#{self.inspect} does not define #{k.inspect}")
63
+ end
64
+
65
+ ##
66
+ # All pages below this page, recursively.
67
+
68
+ def all_subpages
69
+ subpages.map { |p| [p, p.all_subpages] }.flatten
70
+ end
71
+
72
+ ##
73
+ # Returns the actual content of the file minus the optional YAML header.
74
+
75
+ def body
76
+ # TODO: add a test for something with --- without a yaml header.
77
+ @body ||= begin
78
+ _, body = Zenweb::Config.split path
79
+ body.strip
80
+ end
81
+ end
82
+
83
+ ##
84
+ # Returns the parent url of a particular url (or self).
85
+
86
+ def parent_url url = self.url
87
+ url = File.dirname url if File.basename(url) == "index.html"
88
+ File.join File.dirname(url), "index.html"
89
+ end
90
+
91
+ ##
92
+ # Returns an array of all parent pages of this page, including self.
93
+
94
+ def breadcrumbs
95
+ pages = [self]
96
+ loop do
97
+ parent = pages.first.parent
98
+ break unless parent and parent != pages.first
99
+ pages.unshift parent
100
+ end
101
+ pages.pop # take self back off
102
+ pages
103
+ end
104
+
105
+ ##
106
+ # Return the url as users normally enter them (ie, no index.html).
107
+
108
+ def clean_url
109
+ url.sub(/\/index.html$/, '/')
110
+ end
111
+
112
+ ##
113
+ # Returns the closest Config instance for this file. That could be
114
+ # the YAML prefix in the file or it could be a _config.yml file in
115
+ # the file's directory or above.
116
+
117
+ def config
118
+ unless defined? @config then
119
+ @config = Config.new site, path
120
+ @config = @config.parent unless content.start_with? "---"
121
+ end
122
+ @config
123
+ end
124
+
125
+ ##
126
+ # Returns the entire (raw) content of the file.
127
+
128
+ def content
129
+ # TODO: this has the same drawbacks as Config.split
130
+ @content ||= File.read path
131
+ end
132
+
133
+ ##
134
+ # Returns either:
135
+ #
136
+ # + The value of the +date+ config value
137
+ # + The date embedded in the filename itself (eg: 2012-01-02-blah.html).
138
+ # + The last modified timestamp of the file itself.
139
+
140
+ def date
141
+ config['date'] || date_from_path || File.stat(path).mtime
142
+ end
143
+
144
+ def date_from_path # :nodoc:
145
+ date = path[/\d\d\d\d-\d\d-\d\d/]
146
+ Time.local(*date.split(/-/).map(&:to_i)) if date
147
+ end
148
+
149
+ ##
150
+ # Returns true if this page has a date (via config or within the path).
151
+
152
+ def dated?
153
+ config['date'] || date_from_path
154
+ end
155
+
156
+ ##
157
+ # Is this a dated page? (ie, does it have YYYY-MM-DD in the path?)
158
+
159
+ def dated_path?
160
+ path[/\d\d\d\d-\d\d-\d\d/]
161
+ end
162
+
163
+ ##
164
+ # Returns true if this is an html page.
165
+
166
+ def html?
167
+ path =~ /\.html/
168
+ end
169
+
170
+ ##
171
+ # Wires up additional dependencies for this Page. +from_deps+ may
172
+ # be a Hash (eg site.pages), an Array (eg. site.categories.blog),
173
+ # or a single page.
174
+
175
+ def depends_on deps
176
+ if String === deps then
177
+ file self.path => deps
178
+ else
179
+ deps = deps.values if Hash === deps
180
+ deps = Array(deps)
181
+
182
+ file self.url_path => deps.map(&:url_path) - [self.url_path]
183
+ end
184
+ end
185
+
186
+ ##
187
+ # Returns the extension (without the '.') of +name+, defaulting to
188
+ # +self.path+.
189
+
190
+ def filetype name = self.path
191
+ File.extname(name)[1..-1]
192
+ end
193
+
194
+ ##
195
+ # Returns an array of extensions (in reverse order) of this page
196
+ # that match known renderers. For example:
197
+ #
198
+ # Given renderer methods +render_erb+ and +render_md+, the file
199
+ # "index.html.md.erb" would return %w[erb md], but the file
200
+ # "index.html" would return [].
201
+ #
202
+ # Additional renderers can be added via Site.load_plugins.
203
+
204
+ def filetypes
205
+ @filetypes ||= path[self.class.renderers_re].split(/\./)[1..-1].reverse
206
+ rescue
207
+ []
208
+ end
209
+
210
+ ##
211
+ # Format a date string +s+ using the config value +date_fmt+ or YYYY/MM/DD.
212
+
213
+ def format_date s
214
+ fmt = self.config["date_fmt"] || "%Y/%m/%d"
215
+ Time.local(*s.split(/-/).map(&:to_i)).strftime(fmt)
216
+ end
217
+
218
+ ##
219
+ # Render and write the result to #url_path.
220
+
221
+ def generate
222
+ warn "Rendering #{url_path}"
223
+
224
+ content = self.render
225
+
226
+ open url_path, "w" do |f|
227
+ f.puts content
228
+ end
229
+ end
230
+
231
+ ##
232
+ # Render a named file from +_includes+.
233
+ #
234
+ # category: XXX
235
+
236
+ def include name, page
237
+ incl = Page.new(site, File.join("_includes", name))
238
+ incl.subrender page
239
+ end
240
+
241
+ ##
242
+ # Returns true if this page is an index page.
243
+
244
+ def index?
245
+ url.end_with? "index.html"
246
+ end
247
+
248
+ def inspect # :nodoc:
249
+ "Page[#{path.inspect}]"
250
+ end
251
+
252
+ alias :to_s :inspect # :nodoc:
253
+
254
+ ##
255
+ # Return a layout Page named in the config key +layout+.
256
+ #
257
+ # TODO: expand
258
+
259
+ def layout
260
+ unless defined? @layout then
261
+ @layout = site.layout self.config["layout"]
262
+ end
263
+ @layout
264
+ end
265
+
266
+ ##
267
+ # Convenience function to create an html link for this page.
268
+
269
+ def link_html title = self.title
270
+ %(<a href="#{clean_url}">#{title}</a>)
271
+ end
272
+
273
+ ##
274
+ # Stupid helper method to make declaring header meta lines cleaner
275
+
276
+ def meta key, name=key, label="name"
277
+ val = self.config[key]
278
+ %(<meta #{label}="#{name}" content="#{val}">) if val
279
+ end
280
+
281
+ ##
282
+ # Access a config variable and only warn if it isn't accessible.
283
+ # If +msg+ starts with render, go ahead and pass that up to the
284
+ # default method_missing.
285
+
286
+ def method_missing msg, *args # :nodoc:
287
+ case msg.to_s
288
+ when /=|^render_|^to_a(?:ry)?$/ then # to_a/ry for 1.9 only. :(
289
+ super
290
+ else
291
+ self[msg]
292
+ end
293
+ end
294
+
295
+ ##
296
+ # Render this page as a whole. This includes rendering the page's
297
+ # content into a layout if one has been specified via config.
298
+
299
+ def render page = self, content = nil
300
+ content = subrender page, content
301
+
302
+ layout = self.layout # TODO: make nullpage to avoid 'if layout' tests
303
+ content = layout.render page, content if layout
304
+
305
+ content
306
+ end
307
+
308
+ ##
309
+ # Render a Page instance based on its filetypes. For example,
310
+ # index.html.md.erb will essentially call:
311
+ #
312
+ # render_md(render_erb(content))
313
+
314
+ def subrender page = self, content = nil
315
+ self.filetypes.inject(content) { |cont, type|
316
+ send "render_#{type}", page, cont
317
+ } || self.body
318
+ end
319
+
320
+ # TODO: move this and others to plugins/html_toys.rb (or something)
321
+
322
+ def run_js_script url
323
+ <<-"EOM".gsub(/^ {6}/, '')
324
+ <script type="text/javascript">
325
+ (function() {
326
+ var s = document.createElement('script');
327
+ s.type = 'text/javascript';
328
+ s.async = true;
329
+ s.src = '#{url}';
330
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(s);
331
+ })();
332
+ </script>
333
+ EOM
334
+ end
335
+
336
+ ##
337
+ # Return the url for this page. The url is based entirely on its
338
+ # location in the file-system.
339
+ #
340
+ # TODO: expand
341
+
342
+ def url
343
+ @url ||= self.path.
344
+ sub(/^/, '/').
345
+ sub(/(\d\d\d\d)-(\d\d)-(\d\d)-/) { |s| "#{format_date s}/" }.
346
+ gsub(self.class.renderers_re, '')
347
+ end
348
+
349
+ ##
350
+ # The directory portion of the url.
351
+
352
+ def url_dir
353
+ File.dirname url_path
354
+ end
355
+
356
+ ##
357
+ # The real file path for the generated file.
358
+
359
+ def url_path
360
+ @url_path ||= File.join(".site", self.url)
361
+ end
362
+
363
+ ##
364
+ # Wire up this page to the rest of the rake dependencies. If you
365
+ # have extra dependencies for this file (ie, an index page that
366
+ # links to many other pages) you can add them by creating a rake
367
+ # task named +:extra_wirings+ and using #depends_on. Eg:
368
+ #
369
+ # task :extra_wirings do |x|
370
+ # site = $website
371
+ # page = site.pages
372
+ #
373
+ # page["sitemap.xml.erb"]. depends_on site.html_pages
374
+ # page["atom.xml.erb"]. depends_on site.pages_by_date.first(30)
375
+ # page["blog/index.html.erb"].depends_on site.categories.blog
376
+ # end
377
+
378
+ def wire
379
+ @wired ||= false # HACK
380
+ return if @wired
381
+ @wired = true
382
+
383
+ file self.path
384
+
385
+ conf = self.config
386
+ conf = conf.parent if self.path == conf.path
387
+
388
+ file self.path => conf.path if conf.path
389
+ conf.wire
390
+
391
+ if self.layout then
392
+ file self.path => self.layout.path
393
+ self.layout.wire
394
+ end
395
+
396
+ file url_path => all_subpages.map(&:url_path) if url =~ /index.html/
397
+
398
+ unless url_dir =~ %r%/_% then
399
+ directory url_dir
400
+ file url_path => url_dir
401
+ file url_path => path do
402
+ self.generate
403
+ end
404
+
405
+ task :site => url_path
406
+ end
407
+ end
408
+ end # class Page
409
+ end