secondplanet-toto 0.4.9

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.
@@ -0,0 +1,79 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{secondplanet-toto}
8
+ s.version = "0.4.9"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["cloudhead", "secondplanet"]
12
+ s.date = %q{2014-04-12}
13
+ s.description = %q{toto w/ org-mode instead of markdown}
14
+ s.email = %q{tco@secondplanetanimation.com}
15
+ s.files = [
16
+ ".document",
17
+ ".gitignore",
18
+ "LICENSE",
19
+ "README.md",
20
+ "Rakefile",
21
+ "TODO",
22
+ "VERSION",
23
+ "lib/ext/ext.rb",
24
+ "lib/toto.rb",
25
+ "test/articles/1900-05-17-the-wonderful-wizard-of-oz.txt",
26
+ "test/articles/2001-01-01-two-thousand-and-one.txt",
27
+ "test/articles/2009-04-01-tilt-factor.txt",
28
+ "test/articles/2009-12-04-some-random-article.txt",
29
+ "test/articles/2009-12-11-the-dichotomy-of-design.txt",
30
+ "test/autotest.rb",
31
+ "test/templates/about.rhtml",
32
+ "test/templates/archives.rhtml",
33
+ "test/templates/article.rhtml",
34
+ "test/templates/feed.builder",
35
+ "test/templates/index.builder",
36
+ "test/templates/index.rhtml",
37
+ "test/templates/layout.rhtml",
38
+ "test/templates/repo.rhtml",
39
+ "test/test_helper.rb",
40
+ "test/toto_test.rb",
41
+ "secondplanet-toto.gemspec"
42
+ ]
43
+ s.homepage = %q{http://github.com/secondplanet/toto}
44
+ s.rdoc_options = ["--charset=UTF-8"]
45
+ s.require_paths = ["lib"]
46
+ s.rubygems_version = %q{1.3.5}
47
+ s.summary = %q{toto with org mode}
48
+ s.test_files = [
49
+ "test/autotest.rb",
50
+ "test/test_helper.rb",
51
+ "test/toto_test.rb"
52
+ ]
53
+
54
+ if s.respond_to? :specification_version then
55
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
56
+ s.specification_version = 3
57
+
58
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
59
+ s.add_development_dependency(%q<riot>, [">= 0"])
60
+ s.add_runtime_dependency(%q<builder>, [">= 0"])
61
+ s.add_runtime_dependency(%q<rack>, [">= 0"])
62
+ s.add_runtime_dependency(%q<rdiscount>, [">= 0"])
63
+ s.add_runtime_dependency(%q<org-ruby>, [">= 0"])
64
+ else
65
+ s.add_dependency(%q<riot>, [">= 0"])
66
+ s.add_dependency(%q<builder>, [">= 0"])
67
+ s.add_dependency(%q<rack>, [">= 0"])
68
+ s.add_dependency(%q<rdiscount>, [">= 0"])
69
+ s.add_runtime_dependency(%q<org-ruby>, [">= 0"])
70
+ end
71
+ else
72
+ s.add_dependency(%q<riot>, [">= 0"])
73
+ s.add_dependency(%q<builder>, [">= 0"])
74
+ s.add_dependency(%q<rack>, [">= 0"])
75
+ s.add_dependency(%q<rdiscount>, [">= 0"])
76
+ s.add_runtime_dependency(%q<org-ruby>, [">= 0"])
77
+ end
78
+ end
79
+
@@ -0,0 +1,5 @@
1
+ title: The Wonderful Wizard of Oz
2
+ date: 17/05/1900
3
+
4
+ _Once upon a time_...
5
+
@@ -0,0 +1,5 @@
1
+ title: the wizard of oz
2
+ date: 12/10/1932
3
+
4
+ Once upon a time...
5
+
@@ -0,0 +1,5 @@
1
+ title: the wizard of oz
2
+ date: 12/10/1932
3
+
4
+ Once upon a time...
5
+
@@ -0,0 +1,5 @@
1
+ title: the wizard of oz
2
+ date: 12/10/1932
3
+
4
+ Once upon a time...
5
+
@@ -0,0 +1,5 @@
1
+ title: the wizard of oz
2
+ date: 12/10/1932
3
+
4
+ Once upon a time...
5
+
data/test/autotest.rb ADDED
@@ -0,0 +1,34 @@
1
+ #
2
+ # Convenience Methods
3
+ #
4
+ def run(cmd)
5
+ print "\n\n"
6
+ puts(cmd)
7
+ system(cmd)
8
+ print "\n\n"
9
+ end
10
+
11
+ def run_all_tests
12
+ # see Rakefile for the definition of the test:all task
13
+ system("rake -s test:all VERBOSE=true")
14
+ end
15
+
16
+ #
17
+ # Watchr Rules
18
+ #
19
+ watch('^test/.*?_test\.rb' ) {|m| run("ruby -rubygems %s" % m[0]) }
20
+ watch('^lib/(.*)\.rb' ) {|m| run("ruby -rubygems test/%s_test.rb" % m[1]) }
21
+ watch('^lib/toto/(.*)\.rb' ) {|m| run("ruby -rubygems test/%s_test.rb" % m[1]) }
22
+ watch('^test/test_helper\.rb') { run_all_tests }
23
+
24
+ #
25
+ # Signal Handling
26
+ #
27
+ # Ctrl-\
28
+ Signal.trap('QUIT') do
29
+ puts " --- Running all tests ---\n\n"
30
+ run_all_tests
31
+ end
32
+
33
+ # Ctrl-C
34
+ Signal.trap('INT') { abort("\n") }
@@ -0,0 +1 @@
1
+ <span id="count"><%= @articles.length %></span>
@@ -0,0 +1,5 @@
1
+ <h1><%= @path %></h1>
2
+ <% for entry in archives %>
3
+ <li class="entry"><%= entry.title %></li>
4
+ <% end %>
5
+
@@ -0,0 +1,4 @@
1
+ <h2><%= title %></h2>
2
+ <span><%= date %></h2>
3
+ <p><%= body %></p>
4
+
@@ -0,0 +1,21 @@
1
+ xml.instruct!
2
+ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
3
+ xml.title @config[:title]
4
+ xml.id @config[:url]
5
+ xml.updated articles.first[:date].iso8601 unless articles.empty?
6
+ xml.author { xml.name @config[:author] }
7
+
8
+ articles.each do |article|
9
+ xml.entry do
10
+ xml.title article.title
11
+ xml.link "rel" => "alternate", "href" => article.url
12
+ xml.id article.url
13
+ xml.published article[:date].iso8601
14
+ xml.updated article[:date].iso8601
15
+ xml.author { xml.name @config[:author] }
16
+ xml.summary article.summary, "type" => "html"
17
+ xml.content article.body, "type" => "html"
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,21 @@
1
+ xml.instruct!
2
+ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
3
+ xml.title @config[:title]
4
+ xml.id @config[:url]
5
+ xml.updated articles.first[:date].iso8601 unless articles.empty?
6
+ xml.author { xml.name @config[:author] }
7
+
8
+ articles.each do |article|
9
+ xml.entry do
10
+ xml.title article.title
11
+ xml.link "rel" => "alternate", "href" => article.url
12
+ xml.id article.url
13
+ xml.published article[:date].iso8601
14
+ xml.updated article[:date].iso8601
15
+ xml.author { xml.name @config[:author] }
16
+ xml.summary article.summary, "type" => "html"
17
+ xml.content article.body, "type" => "html"
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,13 @@
1
+ <ul id="articles">
2
+ <% for article in articles[0...3] %>
3
+ <li><%= article %></li>
4
+ <% end %>
5
+ </ul>
6
+ <div id="archives">
7
+ <%= archives[3...5] %>
8
+ </div>
9
+ <!-- testing env variable passing -->
10
+ <p>env passed: <%= env != nil %><br/></p>
11
+ <!-- testing get/post parameter passing -->
12
+ <p>request method type: <%= env['REQUEST_METHOD'] %><br/></p>
13
+ <p>request name value pair: <%= env['QUERY_STRING'] %><br/></p>
@@ -0,0 +1,4 @@
1
+ <html>
2
+ <%= yield %>
3
+ </html>
4
+
@@ -0,0 +1 @@
1
+ <%= readme %>
@@ -0,0 +1,44 @@
1
+ require 'rubygems'
2
+ require 'hpricot'
3
+ require 'riot'
4
+
5
+ $:.unshift File.dirname(__FILE__)
6
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
7
+
8
+ require 'toto'
9
+
10
+ module Toto
11
+ class IncludesHTMLMacro < Riot::AssertionMacro
12
+ register :includes_html
13
+
14
+ def evaluate(actual, expected)
15
+ doc = Hpricot.parse(actual)
16
+ expected = expected.to_a.flatten
17
+
18
+ if (doc/expected.first).empty?
19
+ fail("expected #{actual} to contain a <#{expected.first}>")
20
+ elsif !(doc/expected.first).inner_html.match(expected.last)
21
+ fail("expected <#{expected.first}> to contain #{expected.last}")
22
+ else
23
+ pass
24
+ end
25
+ end
26
+ end
27
+
28
+ class IncludesElementsMacro < Riot::AssertionMacro
29
+ register :includes_elements
30
+
31
+ def evaluate(actual, selector, count)
32
+ doc = Hpricot.parse(actual)
33
+ (doc/selector).size == count ? pass : fail("expected #{actual} to contain #{count} #{selector}(s)")
34
+ end
35
+ end
36
+
37
+ class WithinMacro < Riot::AssertionMacro
38
+ register :within
39
+
40
+ def evaluate(actual, expected)
41
+ expected.include?(actual) ? pass : fail("expected #{actual} to be within #{expected}")
42
+ end
43
+ end
44
+ end
data/test/toto_test.rb ADDED
@@ -0,0 +1,285 @@
1
+ require 'test/test_helper'
2
+ require 'date'
3
+
4
+ URL = "http://toto.oz"
5
+ AUTHOR = "toto"
6
+
7
+ context Toto do
8
+ setup do
9
+ @config = Toto::Config.new(:markdown => true, :author => AUTHOR, :url => URL)
10
+ @toto = Rack::MockRequest.new(Toto::Server.new(@config))
11
+ Toto::Paths[:articles] = "test/articles"
12
+ Toto::Paths[:pages] = "test/templates"
13
+ Toto::Paths[:templates] = "test/templates"
14
+ end
15
+
16
+ context "GET /" do
17
+ setup { @toto.get('/') }
18
+
19
+ asserts("returns a 200") { topic.status }.equals 200
20
+ asserts("body is not empty") { not topic.body.empty? }
21
+ asserts("content type is set properly") { topic.content_type }.equals "text/html"
22
+ should("include a couple of article") { topic.body }.includes_elements("#articles li", 3)
23
+ should("include an archive") { topic.body }.includes_elements("#archives li", 2)
24
+
25
+ context "with no articles" do
26
+ setup { Rack::MockRequest.new(Toto::Server.new(@config.merge(:ext => 'oxo'))).get('/') }
27
+
28
+ asserts("body is not empty") { not topic.body.empty? }
29
+ asserts("returns a 200") { topic.status }.equals 200
30
+ end
31
+
32
+ context "with a user-defined to_html" do
33
+ setup do
34
+ @config[:to_html] = lambda do |path, page, binding|
35
+ ERB.new(File.read("#{path}/#{page}.rhtml")).result(binding)
36
+ end
37
+ @toto.get('/')
38
+ end
39
+
40
+ asserts("returns a 200") { topic.status }.equals 200
41
+ asserts("body is not empty") { not topic.body.empty? }
42
+ asserts("content type is set properly") { topic.content_type }.equals "text/html"
43
+ should("include a couple of article") { topic.body }.includes_elements("#articles li", 3)
44
+ should("include an archive") { topic.body }.includes_elements("#archives li", 2)
45
+ asserts("Etag header present") { topic.headers.include? "ETag" }
46
+ asserts("Etag header has a value") { not topic.headers["ETag"].empty? }
47
+ end
48
+ end
49
+
50
+ context "GET /about" do
51
+ setup { @toto.get('/about') }
52
+ asserts("returns a 200") { topic.status }.equals 200
53
+ asserts("body is not empty") { not topic.body.empty? }
54
+ should("have access to @articles") { topic.body }.includes_html("#count" => /5/)
55
+ end
56
+
57
+ context "GET a single article" do
58
+ setup { @toto.get("/1900/05/17/the-wonderful-wizard-of-oz") }
59
+ asserts("returns a 200") { topic.status }.equals 200
60
+ asserts("content type is set properly") { topic.content_type }.equals "text/html"
61
+ should("contain the article") { topic.body }.includes_html("p" => /<em>Once upon a time<\/em>/)
62
+ end
63
+
64
+ context "GET to the archive" do
65
+ context "through a year" do
66
+ setup { @toto.get('/2009') }
67
+ asserts("returns a 200") { topic.status }.equals 200
68
+ should("includes the entries for that year") { topic.body }.includes_elements("li.entry", 3)
69
+ end
70
+
71
+ context "through a year & month" do
72
+ setup { @toto.get('/2009/12') }
73
+ asserts("returns a 200") { topic.status }.equals 200
74
+ should("includes the entries for that month") { topic.body }.includes_elements("li.entry", 2)
75
+ should("includes the year & month") { topic.body }.includes_html("h1" => /2009\/12/)
76
+ end
77
+
78
+ context "through /archive" do
79
+ setup { @toto.get('/archive') }
80
+ end
81
+ end
82
+
83
+ context "GET to an unknown route with a custom error" do
84
+ setup do
85
+ @config[:error] = lambda {|code| "error: #{code}" }
86
+ @toto.get('/unknown')
87
+ end
88
+
89
+ should("returns a 404") { topic.status }.equals 404
90
+ should("return the custom error") { topic.body }.equals "error: 404"
91
+ end
92
+
93
+ context "Request is invalid" do
94
+ setup { @toto.delete('/invalid') }
95
+ should("returns a 400") { topic.status }.equals 400
96
+ end
97
+
98
+ context "GET /index.xml (atom feed)" do
99
+ setup { @toto.get('/index.xml') }
100
+ asserts("content type is set properly") { topic.content_type }.equals "application/xml"
101
+ asserts("body should be valid xml") { topic.body }.includes_html("feed > entry" => /.+/)
102
+ asserts("summary shouldn't be empty") { topic.body }.includes_html("summary" => /.{10,}/)
103
+ end
104
+ context "GET /index?param=testparam (get parameter)" do
105
+ setup { @toto.get('/index?param=testparam') }
106
+ asserts("returns a 200") { topic.status }.equals 200
107
+ asserts("content type is set properly") { topic.content_type }.equals "text/html"
108
+ asserts("contain the env variable") { topic.body }.includes_html("p" => /env passed: true/)
109
+ asserts("access the http get parameter") { topic.body }.includes_html("p" => /request method type: GET/)
110
+ asserts("access the http parameter name value pair") { topic.body }.includes_html("p" => /request name value pair: param=testparam/)
111
+ end
112
+
113
+
114
+
115
+ context "GET to a repo name" do
116
+ setup do
117
+ class Toto::Repo
118
+ def readme() "#{self[:name]}'s README" end
119
+ end
120
+ end
121
+
122
+ context "when the repo is in the :repos array" do
123
+ setup do
124
+ @config[:github] = {:user => "cloudhead", :repos => ['the-repo']}
125
+ @toto.get('/the-repo')
126
+ end
127
+ should("return the-repo's README") { topic.body }.includes("the-repo's README")
128
+ end
129
+
130
+ context "when the repo is not in the :repos array" do
131
+ setup do
132
+ @config[:github] = {:user => "cloudhead", :repos => []}
133
+ @toto.get('/the-repo')
134
+ end
135
+ should("return a 404") { topic.status }.equals 404
136
+ end
137
+ end
138
+
139
+ context "creating an article" do
140
+ setup do
141
+ @config[:markdown] = true
142
+ @config[:date] = lambda {|t| "the time is #{t.strftime("%Y/%m/%d %H:%M")}" }
143
+ @config[:summary] = {:length => 50}
144
+ end
145
+
146
+ context "with the bare essentials" do
147
+ setup do
148
+ Toto::Article.new({
149
+ :title => "Toto & The Wizard of Oz.",
150
+ :body => "#Chapter I\nhello, *stranger*."
151
+ }, @config)
152
+ end
153
+
154
+ should("have a title") { topic.title }.equals "Toto & The Wizard of Oz."
155
+ should("parse the body as markdown") { topic.body }.equals "<h1>Chapter I</h1>\n\n<p>hello, <em>stranger</em>.</p>\n"
156
+ should("create an appropriate slug") { topic.slug }.equals "toto-and-the-wizard-of-oz"
157
+ should("set the date") { topic.date }.equals "the time is #{Date.today.strftime("%Y/%m/%d %H:%M")}"
158
+ should("create a summary") { topic.summary == topic.body }
159
+ should("have an author") { topic.author }.equals AUTHOR
160
+ should("have a path") { topic.path }.equals Date.today.strftime("/%Y/%m/%d/toto-and-the-wizard-of-oz/")
161
+ should("have a url") { topic.url }.equals Date.today.strftime("#{URL}/%Y/%m/%d/toto-and-the-wizard-of-oz/")
162
+ end
163
+
164
+ context "with a user-defined summary" do
165
+ setup do
166
+ Toto::Article.new({
167
+ :title => "Toto & The Wizard of Oz.",
168
+ :body => "Well,\nhello ~\n, *stranger*."
169
+ }, @config.merge(:markdown => false, :summary => {:max => 150, :delim => /~\n/}))
170
+ end
171
+
172
+ should("split the article at the delimiter") { topic.summary }.equals "Well,\nhello"
173
+ should("not have the delimiter in the body") { topic.body !~ /~/ }
174
+ end
175
+
176
+ context "with everything specified" do
177
+ setup do
178
+ Toto::Article.new({
179
+ :title => "The Wizard of Oz",
180
+ :body => ("a little bit of text." * 5) + "\n" + "filler" * 10,
181
+ :date => "19/10/1976",
182
+ :slug => "wizard-of-oz",
183
+ :author => "toetoe"
184
+ }, @config)
185
+ end
186
+
187
+ should("parse the date") { [topic[:date].month, topic[:date].year] }.equals [10, 1976]
188
+ should("use the slug") { topic.slug }.equals "wizard-of-oz"
189
+ should("use the author") { topic.author }.equals "toetoe"
190
+
191
+ context "and long first paragraph" do
192
+ should("create a valid summary") { topic.summary }.equals "<p>" + ("a little bit of text." * 5).chop + "&hellip;</p>\n"
193
+ end
194
+
195
+ context "and a short first paragraph" do
196
+ setup do
197
+ @config[:markdown] = false
198
+ Toto::Article.new({:body => "there ain't such thing as a free lunch\n" * 10}, @config)
199
+ end
200
+
201
+ should("create a valid summary") { topic.summary.size }.within 75..80
202
+ end
203
+ end
204
+
205
+ context "in a subdirectory" do
206
+ context "with implicit leading forward slash" do
207
+ setup do
208
+ conf = Toto::Config.new({})
209
+ conf.set(:prefix, "blog")
210
+ Toto::Article.new({
211
+ :title => "Toto & The Wizard of Oz.",
212
+ :body => "#Chapter I\nhello, *stranger*."
213
+ }, conf)
214
+ end
215
+
216
+ should("be in the directory") { topic.path }.equals Date.today.strftime("/blog/%Y/%m/%d/toto-and-the-wizard-of-oz/")
217
+ end
218
+
219
+ context "with explicit leading forward slash" do
220
+ setup do
221
+ conf = Toto::Config.new({})
222
+ conf.set(:prefix, "/blog")
223
+ Toto::Article.new({
224
+ :title => "Toto & The Wizard of Oz.",
225
+ :body => "#Chapter I\nhello, *stranger*."
226
+ }, conf)
227
+ end
228
+
229
+ should("be in the directory") { topic.path }.equals Date.today.strftime("/blog/%Y/%m/%d/toto-and-the-wizard-of-oz/")
230
+ end
231
+
232
+ context "with explicit trailing forward slash" do
233
+ setup do
234
+ conf = Toto::Config.new({})
235
+ conf.set(:prefix, "blog/")
236
+ Toto::Article.new({
237
+ :title => "Toto & The Wizard of Oz.",
238
+ :body => "#Chapter I\nhello, *stranger*."
239
+ }, conf)
240
+ end
241
+
242
+ should("be in the directory") { topic.path }.equals Date.today.strftime("/blog/%Y/%m/%d/toto-and-the-wizard-of-oz/")
243
+ end
244
+ end
245
+ end
246
+
247
+ context "using Config#set with a hash" do
248
+ setup do
249
+ conf = Toto::Config.new({})
250
+ conf.set(:summary, {:delim => /%/})
251
+ conf
252
+ end
253
+
254
+ should("set summary[:delim] to /%/") { topic[:summary][:delim].source }.equals "%"
255
+ should("leave the :max intact") { topic[:summary][:max] }.equals 150
256
+ end
257
+
258
+ context "using Config#set with a block" do
259
+ setup do
260
+ conf = Toto::Config.new({})
261
+ conf.set(:to_html) {|path, p, _| path + p }
262
+ conf
263
+ end
264
+
265
+ should("set the value to a proc") { topic[:to_html] }.respond_to :call
266
+ end
267
+
268
+ context "testing individual configuration parameters" do
269
+ context "generate error pages" do
270
+ setup do
271
+ conf = Toto::Config.new({})
272
+ conf.set(:error) {|code| "error code #{code}" }
273
+ conf
274
+ end
275
+
276
+ should("create an error page") { topic[:error].call(400) }.equals "error code 400"
277
+ end
278
+ end
279
+
280
+ context "extensions to the core Ruby library" do
281
+ should("respond to iso8601") { Date.today }.respond_to?(:iso8601)
282
+ end
283
+ end
284
+
285
+