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,18 @@
1
+ class Zenweb::Page
2
+
3
+ ##
4
+ # Returns a javascript blob to add a disqus comments block to the page.
5
+
6
+ def disqus shortname
7
+ '<div id="disqus_thread"></div>' +
8
+ run_js_script("http://#{shortname}.disqus.com/embed.js")
9
+ end
10
+
11
+ ##
12
+ # Returns a javascript blob to convert properly formatted links to
13
+ # disqus comment counts.
14
+
15
+ def disqus_counts shortname
16
+ run_js_script "http://#{shortname}.disqus.com/count.js"
17
+ end
18
+ end
@@ -0,0 +1,43 @@
1
+ class Zenweb::Page
2
+ ##
3
+ # Render a page's erb and return the result
4
+
5
+ def render_erb page, content
6
+ erb body, self, binding
7
+ end
8
+
9
+ ##
10
+ # Render erb in +content+ for +source+ with +binding.
11
+ #
12
+ # Personally, I find erb's delimiters a bit annoying, so for now,
13
+ # I've added additional gsub's to the content to make it a bit more
14
+ # palatable.
15
+ #
16
+ # {{ ... }} becomes <%= ... %>
17
+ # {% ... %} becomes <% ... %>
18
+ #
19
+ # Unfortunately, those are the delimiters from liquid, so if someone
20
+ # goes and makes a liquid plugin it could clash. But why you'd have
21
+ # liquid and erb on the same file is beyond me... so it prolly won't
22
+ # become a legitimate issue.
23
+
24
+ def erb content, source, binding = TOPLEVEL_BINDING
25
+ require 'erb'
26
+ extend ERB::Util
27
+
28
+ unless defined? @erb then
29
+ content = content.
30
+ gsub(/\{\{/, "<%=").
31
+ gsub(/\}\}/, "%>").
32
+ gsub(/\{%/, "<%").
33
+ gsub(/%\}/, "%>").
34
+ gsub(/\\([{}%])/, '\1')
35
+
36
+ @erb = ERB.new(content, nil, "-")
37
+ end
38
+
39
+ @erb.filename = source.inspect
40
+ @erb.result binding
41
+ end
42
+ end # erb
43
+
@@ -0,0 +1,20 @@
1
+ class Zenweb::Page
2
+ ##
3
+ # Returns a javascript blob to add a google ad to the page. You need
4
+ # to provide the configuration param "google_ad_client" to your site
5
+ # config for this to work.
6
+
7
+ def google_ad slot, width = 468, height = 60
8
+ <<-"EOM".gsub(/^ {6}/, '')
9
+ <script><!--
10
+ google_ad_client = "#{self["google_ad_client"]}";
11
+ google_ad_slot = "#{slot}";
12
+ google_ad_width = #{width};
13
+ google_ad_height = #{height};
14
+ //-->
15
+ </script>
16
+ <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
17
+ </script>
18
+ EOM
19
+ end
20
+ end # google
@@ -0,0 +1,10 @@
1
+ class Zenweb::Page
2
+ ##
3
+ # Render less source to css.
4
+
5
+ def render_less page, content
6
+ require "less"
7
+
8
+ Less::Engine.new(content || body).to_css
9
+ end
10
+ end
@@ -0,0 +1,121 @@
1
+ class Zenweb::Page
2
+ KRAMDOWN_CONFIG = { # :nodoc:
3
+ :toc_levels => '2..4',
4
+
5
+ :coderay_wrap => :div,
6
+ :coderay_line_numbers => :table,
7
+ :coderay_tab_width => 4,
8
+ :coderay_css => :class,
9
+ # TODO: turn off smart quotes
10
+ }
11
+
12
+ ##
13
+ # Render markdown page content using kramdown.
14
+
15
+ def render_md page, content
16
+ markdown(content || self.body) # HACK
17
+ end
18
+
19
+ ##
20
+ # Render markdown content.
21
+ #
22
+ # I cheated and added some additional gsubs. I prefer "``` lang" so
23
+ # that works now.
24
+
25
+ def markdown content
26
+ require "kramdown"
27
+
28
+ content = content.
29
+ gsub(/^``` *(\w+)/) { "{:lang=\"#$1\"}\n~~~" }.
30
+ gsub(/^```/, '~~~')
31
+
32
+ Kramdown::Document.new(content, KRAMDOWN_CONFIG).to_html
33
+ end
34
+
35
+ ############################################################
36
+ # Helper Methods:
37
+
38
+ ##
39
+ # Returns a markdown formatted sitemap for the given pages or the
40
+ # current page's subpages. This intelligently composes a sitemap
41
+ # whether the pages are ordered (dated) or not or a combination of
42
+ # the two.
43
+
44
+ def sitemap pages = nil, indent = 0
45
+ pages ||= self.subpages
46
+ dated, regular = pages.partition(&:dated?)
47
+
48
+ bonus = 0
49
+ prev = nil
50
+ regular = regular
51
+ subpages =
52
+ regular.sort_by { |p| p.url } +
53
+ dated.sort_by { |p| [-p.date.to_i, p.url] }
54
+
55
+ subpages.map { |page|
56
+ x = []
57
+
58
+ if page.dated? then
59
+ bonus = 1
60
+ fmt ||= page.config["date_fmt"] || "%Y-%m" # REFACTOR: yuck
61
+ curr = page.date.strftime fmt
62
+ if prev != curr then
63
+ x << "#{" " * (indent)}* #{curr}:"
64
+ prev = curr
65
+ end
66
+ end
67
+
68
+ x << "#{" " * (indent+bonus)}* [#{page.title}](#{page.clean_url})"
69
+ x += [page.sitemap(nil, indent+bonus+1)] unless page.subpages.empty?
70
+ x
71
+ }.flatten.join "\n"
72
+ end
73
+
74
+ ##
75
+ # Convenience function to return a markdown TOC.
76
+
77
+ def toc
78
+ "* \n{:toc}\n"
79
+ end
80
+
81
+ ##
82
+ # Return a kramdown block-tag to add attributes to the following (or
83
+ # preceding... kramdown is a bit crazy) block. Attributes can either
84
+ # be a simple name or a hash of key/value pairs.
85
+
86
+ def attr h_or_name
87
+ h_or_name = h_or_name.map { |k,v| "#{k}=\"#{v}\"" }.join " " if
88
+ Hash === h_or_name
89
+
90
+ "{:#{h_or_name}}"
91
+ end
92
+
93
+ ##
94
+ # Return a kramdown block-tag for a CSS class.
95
+
96
+ def css_class name
97
+ attr ".#{name}"
98
+ end
99
+
100
+ ##
101
+ # Return a kramdown block-tag for a CSS ID.
102
+
103
+ def css_id name
104
+ attr "##{name}"
105
+ end
106
+
107
+ ##
108
+ # Return a markdown-formatted link for a given url and title.
109
+
110
+ def link(url, title) # :nodoc:
111
+ "[#{title}](#{url})"
112
+ end
113
+
114
+ ##
115
+ # Return a markdown-formatted image for a given url and an optional alt.
116
+
117
+ def image url, alt=url
118
+ "![#{alt}](#{url})"
119
+ end
120
+ end # markdown
121
+
@@ -0,0 +1,237 @@
1
+ require "rubygems"
2
+ gem "rake"
3
+ require "rake"
4
+ require "make/rake/work/well"
5
+
6
+ require "zenweb/page"
7
+ require "zenweb/config"
8
+ require "zenweb/extensions"
9
+
10
+ module Zenweb
11
+
12
+ ##
13
+ # Holder for the entire website. Everything gets driven from here.
14
+ #
15
+ # TODO: describe expected filesystem layout and dependency mgmt.
16
+
17
+ class Site
18
+ include Rake::DSL
19
+
20
+ ##
21
+ # Returns all pages found via #scan
22
+
23
+ attr_reader :pages
24
+
25
+ ##
26
+ # Returns all configs found via #scan
27
+
28
+ attr_reader :configs
29
+
30
+ ##
31
+ # Returns all known layouts found via #scan
32
+
33
+ attr_reader :layouts
34
+
35
+ ##
36
+ # Loads all files matching "zenweb/plugins/*.rb".
37
+
38
+ def self.load_plugins
39
+ Gem.find_files("zenweb/plugins/*.rb").each do |path|
40
+ require path
41
+ end
42
+ end
43
+
44
+ self.load_plugins
45
+
46
+ def initialize # :nodoc:
47
+ @layouts = {}
48
+ @pages = {}
49
+ @configs = Hash.new { |h,k| h[k] = Config.new self, k }
50
+ end
51
+
52
+ ##
53
+ # Returns a magic hash that groups up all the pages by category
54
+ # (directory). The hash has extra accessor methods on it to make
55
+ # grabbing what you want a bit cleaner. eg:
56
+ #
57
+ # site.categories.blog # => [Page[blog/...], ...]
58
+
59
+ def categories
60
+ @categories ||=
61
+ begin
62
+ h = Hash.new { |h2,k| h2[k] = [] }
63
+
64
+ def h.method_missing msg, *args
65
+ if self.has_key? msg.to_s then
66
+ self[msg.to_s]
67
+ else
68
+ super
69
+ end
70
+ end
71
+
72
+ pages.each do |url, page|
73
+ dir = url.split(/\//).first
74
+ next unless File.directory? dir and dir !~ /^_/
75
+ next if url =~ /index.html/ or url !~ /html/
76
+ h[dir] << page
77
+ end
78
+
79
+ h.keys.each do |dir|
80
+ h[dir] = h[dir].sort_by { |p| [-p.date.to_i, p.title ] }
81
+ end
82
+
83
+ h
84
+ end
85
+ end
86
+
87
+ ##
88
+ # Return the top level config.
89
+
90
+ def config
91
+ configs["_config.yml"]
92
+ end
93
+
94
+ ##
95
+ # Generates the website by invoking the 'site' task.
96
+
97
+ def generate
98
+ task(:site).invoke
99
+ end
100
+
101
+ ##
102
+ # Returns a list of all known html pages.
103
+
104
+ def html_pages
105
+ self.pages.values.select { |p| p.url_path =~ /\.html/ }
106
+ end
107
+
108
+ def inspect # :nodoc:
109
+ "Site[#{pages.size} pages, #{configs.size} configs]"
110
+ end
111
+
112
+ ##
113
+ # Returns a layout named +name+.
114
+
115
+ def layout name
116
+ @layouts[name]
117
+ end
118
+
119
+ ##
120
+ # Proxy object for the config. Returns a config item at +msg+.
121
+
122
+ def method_missing msg, *args
123
+ config[msg.to_s] || warn("#{self.inspect} does not define #{msg}")
124
+ end
125
+
126
+ ##
127
+ # Returns all pages (with titles) sorted by date.
128
+
129
+ def pages_by_date
130
+ # page.config["title"] avoids the warning
131
+ html_pages.select {|page| page.config["title"] }.
132
+ sort_by { |page| [-page.date.to_i, page.title] }
133
+ end
134
+
135
+ ##
136
+ # Returns a hash mapping page url to page.
137
+
138
+ def pages_by_url
139
+ unless defined? @pages_by_url then
140
+ h = {}
141
+ pages.each do |_,p|
142
+ h[p.url] = p
143
+ end
144
+ @pages_by_url = h
145
+ end
146
+ @pages_by_url
147
+ end
148
+
149
+ ##
150
+ # Scans the directory tree and finds all relevant pages, configs,
151
+ # layouts, etc.
152
+ #
153
+ # TODO: talk about expected directory structure and extra
154
+ # naming enhancements.
155
+
156
+ def scan
157
+ excludes = %w[~ Rakefile] + Array(config["exclude"])
158
+
159
+ top = Dir["*"] - excludes
160
+ files = top.select { |path| File.file? path }
161
+ files += Dir["{#{top.join(",")}}/**/*"].reject { |f| not File.file? f }
162
+
163
+ renderers_re = Page.renderers_re
164
+
165
+ files.each do |path|
166
+ case path
167
+ when /(?:#{excludes.join '|'})$/
168
+ # ignore
169
+ when /^_layout/ then
170
+ name = File.basename(path).sub(/\..+$/, '')
171
+ @layouts[name] = Page.new self, path
172
+ when /^_/ then
173
+ next
174
+ when /\.yml$/ then
175
+ @configs[path] = Config.new self, path
176
+ when /\.(?:png|jpg|gif|eot|svg|ttf|woff|ico|pdf|m4a|t?gz)$/ then # HACK
177
+ @pages[path] = Page.new self, path, self.config
178
+ when /\.(?:txt|html|css|js)$/, renderers_re then # HACK
179
+ @pages[path] = Page.new self, path
180
+ else
181
+ warn "unknown file type: #{path}" if Rake.application.options.trace
182
+ end
183
+ end
184
+
185
+ t = Time.now
186
+ @pages.reject! { |path, page| page.date && page.date > t } unless
187
+ ENV["ALL"]
188
+
189
+ fix_subpages
190
+ end
191
+
192
+ def fix_subpages # :nodoc:
193
+ parents = {}
194
+ @pages.values.select(&:index?).each do |p|
195
+ parents[File.dirname p.path] = p
196
+ end
197
+
198
+ @pages.values.each do |p|
199
+ path = File.dirname p.path
200
+ path = File.dirname path if p.index?
201
+
202
+ parent = parents[path]
203
+ next unless parent and parent != p and p.url =~ /html$/
204
+ p.parent = parent
205
+ parent.subpages << p
206
+ end
207
+
208
+ @pages.values.each do |p|
209
+ unless p.subpages.empty? then
210
+ sorted = p.subpages.sort_by(&:clean_url)
211
+ sorted = sorted.reverse if p.subpages.first.dated_path?
212
+ p.subpages.replace sorted
213
+ end
214
+ end
215
+ end
216
+
217
+ ##
218
+ # Wire up all the configs and pages. Invokes :extra_wirings to
219
+ # allow you to add extra manual dependencies.
220
+
221
+ def wire
222
+ directory ".site"
223
+ task :site => ".site"
224
+
225
+ configs.each do |path, config|
226
+ config.wire
227
+ end
228
+
229
+ pages.each do |path, page|
230
+ page.wire
231
+ end
232
+
233
+ $website = self # HACK
234
+ task(:extra_wirings).invoke
235
+ end
236
+ end # class Site
237
+ end