serious 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Christoph Olszowka
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = serious
2
+
3
+ TODO...
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Christoph Olszowka. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "serious"
8
+ gem.summary = %Q{Serious is a simple, file-driven blog engine inspired by toto and driven by sinatra}
9
+ gem.description = %Q{Serious is a simple, file-driven blog engine inspired by toto and driven by sinatra}
10
+ gem.email = "christoph at olszowka dot de"
11
+ gem.homepage = "http://github.com/colszowka/serious"
12
+ gem.authors = ["Christoph Olszowka"]
13
+ gem.add_dependency 'sinatra', ">= 0.9.4"
14
+ gem.add_dependency 'stupid_formatter', '>= 0.1.1'
15
+ gem.add_development_dependency "shoulda", ">= 0"
16
+ gem.add_development_dependency "hpricot", ">= 0"
17
+ gem.add_development_dependency "rack-test", ">= 0"
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
+ end
24
+
25
+ require 'rake/testtask'
26
+ Rake::TestTask.new(:test) do |test|
27
+ test.libs << 'lib' << 'test'
28
+ test.pattern = 'test/**/test_*.rb'
29
+ test.verbose = true
30
+ end
31
+
32
+ begin
33
+ require 'rcov/rcovtask'
34
+ Rcov::RcovTask.new do |test|
35
+ test.libs << 'test'
36
+ test.pattern = 'test/**/test_*.rb'
37
+ test.verbose = true
38
+ end
39
+ rescue LoadError
40
+ task :rcov do
41
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
42
+ end
43
+ end
44
+
45
+ task :test => :check_dependencies
46
+
47
+ task :default => :test
48
+
49
+ require 'rake/rdoctask'
50
+ Rake::RDocTask.new do |rdoc|
51
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
52
+
53
+ rdoc.rdoc_dir = 'rdoc'
54
+ rdoc.title = "serious #{version}"
55
+ rdoc.rdoc_files.include('README*')
56
+ rdoc.rdoc_files.include('lib/**/*.rb')
57
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/serious.rb ADDED
@@ -0,0 +1,61 @@
1
+ require 'rubygems'
2
+ gem 'sinatra', '~> 0.9.4'
3
+ require 'sinatra/base'
4
+ require 'stupid_formatter'
5
+ require 'yaml'
6
+
7
+ class Serious < Sinatra::Base
8
+
9
+ set :articles, Proc.new { File.join(root, 'articles') }
10
+ set :static, true # Required to serve static files, see http://www.sinatrarb.com/configuration.html
11
+
12
+ not_found do
13
+ erb :"404"
14
+ end
15
+
16
+ helpers do
17
+ def format(text)
18
+ StupidFormatter.result(text)
19
+ end
20
+
21
+ # Helper for rendering partial _archives
22
+ def render_archived(articles)
23
+ render :erb, :'_archives', :locals => { :articles => articles }, :layout => false
24
+ end
25
+
26
+ def render_article(article, summary_only=false)
27
+ render :erb, :'_article', :locals => { :article => article, :summary_only => summary_only }, :layout => !summary_only
28
+ end
29
+ end
30
+
31
+ # Index page
32
+ get '/' do
33
+ @recent = Article.all(:limit => 3)
34
+ @archived = Article.all(:limit => 10, :offset => 3)
35
+ erb :index
36
+ end
37
+
38
+ # Specific article route
39
+ get %r{^/(\d{4})/(\d{1,2})/(\d{1,2})/([^\\]+)} do
40
+ halt 404 unless @article = Article.first(*params[:captures])
41
+ render_article @article
42
+ end
43
+
44
+ # Archives route
45
+ get %r{^/(\d{4})[/]{0,1}(\d{0,2})[/]{0,1}(\d{0,2})[/]{0,1}$} do
46
+ @selection = params[:captures].reject {|s| s.strip.length == 0 }.map {|n| n.length == 1 ? "%02d" % n : n}
47
+ @articles = Article.find(*@selection)
48
+ erb :archives
49
+ end
50
+
51
+ get "/archives" do
52
+ @articles = Article.all
53
+ erb :archives
54
+ end
55
+ end
56
+
57
+ $:.unshift File.dirname(__FILE__)
58
+ require 'serious/article'
59
+ # Set up default stupid_formatter chain
60
+ StupidFormatter.chain = [StupidFormatter::Erb, StupidFormatter::RDiscount]
61
+ Serious.set :root, Dir.getwd
@@ -0,0 +1,111 @@
1
+ #
2
+ # Backend for file-system based articles
3
+ #
4
+ class Serious::Article
5
+ class << self
6
+ #
7
+ # Returns all articles. Can be drilled down by (optional) :limit and :offset options
8
+ #
9
+ def all(options={})
10
+ options = {:limit => 10000, :offset => 0}.merge(options)
11
+ (article_paths[options[:offset]...options[:limit]+options[:offset]] || []).map {|article_path| new(article_path) }
12
+ end
13
+
14
+ #
15
+ # Retrieves the article(s) for the given arguments. The arguments must be part of the filename.
16
+ # You can give any combination, but the arguments must appear in the same order as given in the
17
+ # arguments, so find(2009, 11) works for all articles in november 2009,
18
+ # find('foo-bar') works for all articles with permalink 'foo-bar', but find(2009, 'foo-bar')
19
+ # will not return anything.
20
+ #
21
+ def find(*args)
22
+ # Reformat arguments (one-digit months and days should be converted to two-digit format)
23
+ args = args.map {|a| a.to_s =~ /^\d{1}$/ ? "%02d" % a : a }
24
+ articles = article_paths.select {|path| File.basename(path) =~ /#{args.join('-')}/i }.map {|path| new(path) }
25
+ end
26
+
27
+ #
28
+ # Find the article for given arguments (same as find), but returns only the first one
29
+ #
30
+ def first(*args)
31
+ find(*args).first
32
+ end
33
+
34
+ private
35
+
36
+ # Returns all article files in articles path
37
+ def article_paths
38
+ @article_paths ||= Dir[File.join(Serious.articles, '*')].sort.reverse
39
+ end
40
+ end
41
+
42
+ attr_reader :path, :date, :permalink
43
+
44
+ def initialize(path)
45
+ @path = path
46
+ extract_date_and_permalink!
47
+ # TODO: Add some nice error handling!
48
+ end
49
+
50
+ # Lazy-loading title accessor
51
+ def title
52
+ @title ||= yaml["title"]
53
+ end
54
+
55
+ # Cached lazy-loading of summary
56
+ def summary
57
+ return @summary if @summary
58
+ @summary ||= content.split("~", 2).first.chomp
59
+ end
60
+
61
+ # Cached lazy-loading of body
62
+ def body
63
+ return @body if @body
64
+ @body ||= content.split("~", 2).join("").chomp
65
+ end
66
+
67
+ # Compiles the url for this article
68
+ def url
69
+ "/#{date.year}/#{"%02d" % date.month}/#{"%02d" % date.day}/#{permalink}"
70
+ end
71
+
72
+ # Equality comparison
73
+ def ==(article)
74
+ path == article.path
75
+ rescue NoMethodError
76
+ false
77
+ end
78
+
79
+ private
80
+
81
+ # Will extract the date and permalink from the filename.
82
+ def extract_date_and_permalink!
83
+ match = File.basename(path).match(/(\d{4})-(\d{1,2})-(\d{1,2})-([^\.]+)/)
84
+ @date = Date.new(match[1].to_i, match[2].to_i, match[3].to_i)
85
+ @permalink = match[4]
86
+ end
87
+
88
+ #
89
+ # Will read the actual article file and store the yaml front processed in @yaml,
90
+ # the content in @content
91
+ #
92
+ def load!
93
+ return [@yaml, @content] if @yaml and @content
94
+ yaml, @content = File.read(path).split(/\n\n/, 2)
95
+ @yaml = YAML.load(yaml)
96
+ end
97
+
98
+ # Cached lazy-loading yaml config
99
+ def yaml
100
+ return @yaml if @yaml
101
+ load!
102
+ @yaml
103
+ end
104
+
105
+ # Cached lazy-loading content
106
+ def content
107
+ return @content if @content
108
+ load!
109
+ @content
110
+ end
111
+ end
data/serious.gemspec ADDED
@@ -0,0 +1,81 @@
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{serious}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Christoph Olszowka"]
12
+ s.date = %q{2010-02-12}
13
+ s.description = %q{Serious is a simple, file-driven blog engine inspired by toto and driven by sinatra}
14
+ s.email = %q{christoph at olszowka dot de}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/serious.rb",
27
+ "lib/serious/article.rb",
28
+ "serious.gemspec",
29
+ "test/articles/2000-01-01-disco-2000.txt",
30
+ "test/articles/2009-04-01-foo-bar.txt",
31
+ "test/articles/2009-12-11-ruby-is-the-shit.txt",
32
+ "test/articles/2009-12-24-merry-christmas.txt",
33
+ "test/helper.rb",
34
+ "test/public/css/coderay.css",
35
+ "test/public/css/serious.css",
36
+ "test/test_article.rb",
37
+ "test/test_serious.rb",
38
+ "test/views/404.erb",
39
+ "test/views/_archives.erb",
40
+ "test/views/_article.erb",
41
+ "test/views/archives.erb",
42
+ "test/views/index.erb",
43
+ "test/views/layout.erb"
44
+ ]
45
+ s.homepage = %q{http://github.com/colszowka/serious}
46
+ s.rdoc_options = ["--charset=UTF-8"]
47
+ s.require_paths = ["lib"]
48
+ s.rubygems_version = %q{1.3.5}
49
+ s.summary = %q{Serious is a simple, file-driven blog engine inspired by toto and driven by sinatra}
50
+ s.test_files = [
51
+ "test/test_serious.rb",
52
+ "test/helper.rb",
53
+ "test/test_article.rb"
54
+ ]
55
+
56
+ if s.respond_to? :specification_version then
57
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
58
+ s.specification_version = 3
59
+
60
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
61
+ s.add_runtime_dependency(%q<sinatra>, [">= 0.9.4"])
62
+ s.add_runtime_dependency(%q<stupid_formatter>, [">= 0.1.1"])
63
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
64
+ s.add_development_dependency(%q<hpricot>, [">= 0"])
65
+ s.add_development_dependency(%q<rack-test>, [">= 0"])
66
+ else
67
+ s.add_dependency(%q<sinatra>, [">= 0.9.4"])
68
+ s.add_dependency(%q<stupid_formatter>, [">= 0.1.1"])
69
+ s.add_dependency(%q<shoulda>, [">= 0"])
70
+ s.add_dependency(%q<hpricot>, [">= 0"])
71
+ s.add_dependency(%q<rack-test>, [">= 0"])
72
+ end
73
+ else
74
+ s.add_dependency(%q<sinatra>, [">= 0.9.4"])
75
+ s.add_dependency(%q<stupid_formatter>, [">= 0.1.1"])
76
+ s.add_dependency(%q<shoulda>, [">= 0"])
77
+ s.add_dependency(%q<hpricot>, [">= 0"])
78
+ s.add_dependency(%q<rack-test>, [">= 0"])
79
+ end
80
+ end
81
+
@@ -0,0 +1,23 @@
1
+ title: Disco 2000
2
+
3
+ Well we were born within one hour of each other.
4
+ Our mothers said we could be sister and brother.
5
+ Your name is Deborah, Deborah.
6
+ ~
7
+ ### by Pulp
8
+
9
+ It never suited ya.
10
+ Oh they thought that when we grew up,
11
+ we'd get married, and never split up.
12
+ We never did it, although often I thought of it.
13
+ Oh Deborah, do you recall?
14
+ Your house was very small,
15
+ with wood chip on the wall.
16
+ When I came around to call,
17
+ you didn't notice me at all.
18
+ I said let's all meet up in the year 2000.
19
+ Won't it be strange when we're all fully grown.
20
+ Be there at 2 o'clock by the fountain down the road.
21
+ I never knew that you'd get married.
22
+ I would be living down here on my own on
23
+ that damp and lonely Thursday years ago.
@@ -0,0 +1,4 @@
1
+ title: Foo Bar
2
+
3
+ Baz!
4
+
@@ -0,0 +1,17 @@
1
+ title: Ruby is the shit!
2
+
3
+ Some kind of introduction and summary
4
+ ~
5
+ The number is <%= 1 + 3 %>
6
+
7
+ <% highlight do %>
8
+ #
9
+ # Will read the actual article file and store the yaml front processed in @yaml,
10
+ # the content in @content
11
+ #
12
+ def load!
13
+ return [@yaml, @content] if @yaml and @content
14
+ yaml, @content = File.read(path).split(/\n\n/, 2)
15
+ @yaml = YAML.load(yaml)
16
+ end
17
+ <% end %>
@@ -0,0 +1,5 @@
1
+ title: Merry Christmas!
2
+
3
+ Merry christmas, dear reader!
4
+ ~
5
+ Lorem ipsum dolor...
data/test/helper.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'rack/test'
5
+ require 'hpricot'
6
+
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
9
+ require 'serious'
10
+
11
+ class Test::Unit::TestCase
12
+ include Rack::Test::Methods
13
+ Serious.root = File.dirname(__FILE__)
14
+ StupidFormatter.chain = [StupidFormatter::Erb, StupidFormatter::RDiscount]
15
+
16
+ def app
17
+ Serious
18
+ end
19
+
20
+ def self.should_contain_elements(count, selector)
21
+ should "contain #{count} elements in '#{selector}'" do
22
+ doc = Hpricot.parse(last_response.body)
23
+ assert_equal count, (doc/selector).size
24
+ end
25
+ end
26
+
27
+ def self.should_respond_with(status)
28
+ should "respond with #{status}" do
29
+ assert_equal status, last_response.status
30
+ end
31
+ end
32
+
33
+ def self.should_contain_text(text, selector)
34
+ should "contain '#{text}' in '#{selector}'" do
35
+ doc = Hpricot.parse(last_response.body)
36
+ assert_match /#{text}/, (doc/selector).inner_html
37
+ end
38
+ end
39
+
40
+ def self.should_not_contain_text(text, selector)
41
+ should "not contain '#{text}' in '#{selector}'" do
42
+ doc = Hpricot.parse(last_response.body)
43
+ assert_no_match /#{text}/, (doc/selector).inner_html
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,35 @@
1
+ /* Shamelessly stolen from railscasts.com - thank you Ryan! */
2
+ .CodeRay {
3
+ background-color: #232323;
4
+ border: 1px solid black;
5
+ font-family: 'Consolas', 'Inconsolata', 'Monaco', 'Courier New', 'Terminal', monospace;
6
+ line-height: 1.4;
7
+ color: #E6E0DB;
8
+ padding: 3px 5px;
9
+ overflow: auto;
10
+ font-size: 12px;
11
+ margin: 12px 0;
12
+ }
13
+ .CodeRay pre {
14
+ margin: 0px;
15
+ padding: 0px;
16
+ }
17
+
18
+ .CodeRay .an { color:#E7BE69 } /* html attribute */
19
+ .CodeRay .c { color:#BC9358; font-style: italic; } /* comment */
20
+ .CodeRay .ch { color:#509E4F } /* escaped character */
21
+ .CodeRay .cl { color:#FFF } /* class */
22
+ .CodeRay .co { color:#FFF } /* constant */
23
+ .CodeRay .fl { color:#A4C260 } /* float */
24
+ .CodeRay .fu { color:#FFC56D } /* function */
25
+ .CodeRay .gv { color:#D0CFFE } /* global variable */
26
+ .CodeRay .i { color:#A4C260 } /* integer */
27
+ .CodeRay .il { background:#151515 } /* inline code */
28
+ .CodeRay .iv { color:#D0CFFE } /* instance variable */
29
+ .CodeRay .pp { color:#E7BE69 } /* doctype */
30
+ .CodeRay .r { color:#CB7832 } /* keyword */
31
+ .CodeRay .rx { color:#A4C260 } /* regex */
32
+ .CodeRay .s { color:#A4C260 } /* string */
33
+ .CodeRay .sy { color:#6C9CBD } /* symbol */
34
+ .CodeRay .ta { color:#E7BE69 } /* html tag */
35
+ .CodeRay .pc { color:#6C9CBD } /* boolean */
@@ -0,0 +1,77 @@
1
+ body {
2
+ margin: 0 auto;
3
+ font-family: 'Baskerville', Georgia, Times, serif;
4
+ font-size: 20px;
5
+ line-height: 30px;
6
+ width: 800px;
7
+ }
8
+
9
+ div, p {
10
+ font-family: 'Baskerville', Georgia, Times, serif;
11
+ }
12
+
13
+ h1, h2, h3, h4 {
14
+ font-family: "Helvetica", "Arial", "Verdana", sans-serif;
15
+ padding: 0;
16
+ margin: 0;
17
+ }
18
+
19
+ .date {
20
+ font-style: italic;
21
+ color: #666;
22
+ }
23
+
24
+ .right {
25
+ float: right;
26
+ }
27
+
28
+ #header {
29
+ margin: 25px 0px 50px 0px;
30
+ }
31
+
32
+ #header a {
33
+ color: black;
34
+ text-decoration: none;
35
+ }
36
+
37
+ #container a {
38
+ color: black;
39
+ text-decoration: none;
40
+ }
41
+
42
+ #container a:hover {
43
+ color: #BE2805;
44
+ text-decoration: none;
45
+ }
46
+
47
+ #container ul {
48
+ list-style: none;
49
+ padding: 0;
50
+ margin; 0;
51
+ }
52
+
53
+ #container ul li {
54
+ padding: 0;
55
+ margin; 0;
56
+ }
57
+
58
+ #container ul.archives li {
59
+ margin-left: 25px;
60
+ }
61
+
62
+ #container .article {
63
+ margin-bottom: 50px;
64
+ }
65
+
66
+
67
+ #footer {
68
+ margin-top: 50px;
69
+ color: #666;
70
+ text-align: right;
71
+ font-size: 14px;
72
+ }
73
+
74
+ #footer a {
75
+ text-decoration: none;
76
+ color: black;
77
+ }
@@ -0,0 +1,255 @@
1
+ require 'helper'
2
+
3
+ class TestArticle < Test::Unit::TestCase
4
+ # ========================================================================
5
+ # Tests for all articles and limited all articles finder
6
+ # ========================================================================
7
+ context "Serious::Article.all" do
8
+ setup do
9
+ @articles = Serious::Article.all
10
+ end
11
+
12
+ should("return 4 articles") { assert_equal 4, @articles.length }
13
+ should "have only instances of Serious::Article in the collection" do
14
+ assert @articles.all? {|a| a.instance_of?(Serious::Article) }
15
+ end
16
+
17
+ should "return an existing path for all articles" do
18
+ assert @articles.all? {|a| File.exist? a.path }
19
+ end
20
+
21
+ should "have 2009-12-24 as the first article's date" do
22
+ assert_equal Date.new(2009, 12, 24), @articles.first.date
23
+ end
24
+
25
+ should "have 2000-01-01 as the last article's date" do
26
+ assert_equal Date.new(2000, 1, 1), @articles.last.date
27
+ end
28
+
29
+ should "not have instance variable @yaml set on any article" do
30
+ @articles.each do |article|
31
+ assert_nil article.instance_variable_get(:@yaml)
32
+ end
33
+ end
34
+
35
+ should "not have instance variable @content set on any article" do
36
+ @articles.each do |article|
37
+ assert_nil article.instance_variable_get(:@content)
38
+ end
39
+ end
40
+ end
41
+
42
+ context "Serious::Article.all(:limit => 2)" do
43
+ setup do
44
+ @articles = Serious::Article.all(:limit => 2)
45
+ end
46
+
47
+ should("return 2 articles") { assert_equal 2, @articles.length }
48
+
49
+ should "have 2009-12-24 as the first article's date" do
50
+ assert_equal Date.new(2009, 12, 24), @articles.first.date
51
+ end
52
+
53
+ should "have 2009-12-11 as the last article's date" do
54
+ assert_equal Date.new(2009, 12, 11), @articles.last.date
55
+ end
56
+ end
57
+
58
+ context "Serious::Article.all(:limit => 2, :offset => 2)" do
59
+ setup do
60
+ @articles = Serious::Article.all(:limit => 2, :offset => 2)
61
+ end
62
+
63
+ should("return 2 articles") { assert_equal 2, @articles.length }
64
+
65
+ should "have 2009-04-01 as the first article's date" do
66
+ assert_equal Date.new(2009, 4, 1), @articles.first.date
67
+ end
68
+
69
+ should "have 2000-01-01 as the last article's date" do
70
+ assert_equal Date.new(2000, 1, 1), @articles.last.date
71
+ end
72
+ end
73
+
74
+ context "Serious::Article.all(:limit => 50, :offset => 5)" do
75
+ should "return an empty array" do
76
+ assert_equal [], Serious::Article.all(:limit => 50, :offset => 5)
77
+ end
78
+ end
79
+
80
+ # ========================================================================
81
+ # Tests for initializer and extracting date and permalink from path
82
+ # ========================================================================
83
+ context "Serious::Article.new('2010-01-15-foo-bar.txt')" do
84
+ setup do
85
+ @article = Serious::Article.new('2010-01-15-foo-bar.txt')
86
+ end
87
+
88
+ should "return Date 2010-01-15" do
89
+ assert_equal Date.new(2010, 1, 15), @article.date
90
+ end
91
+
92
+ should "return permalink 'foo-bar'" do
93
+ assert_equal 'foo-bar', @article.permalink
94
+ end
95
+
96
+ should "return '/2010/01/15/foo-bar' as url" do
97
+ assert_equal '/2010/01/15/foo-bar', @article.url
98
+ end
99
+ end
100
+
101
+ # Making sure one-digit month and day work as well
102
+ context "Serious::Article.new('2010-1-1-foo-bar.txt')" do
103
+ setup do
104
+ @article = Serious::Article.new('2010-1-1-foo-bar.txt')
105
+ end
106
+
107
+ should "return Date 2010-01-01" do
108
+ assert_equal Date.new(2010, 1, 1), @article.date
109
+ end
110
+
111
+ should "return permalink 'foo-bar'" do
112
+ assert_equal 'foo-bar', @article.permalink
113
+ end
114
+
115
+ should "return '/2010/01/01/foo-bar' as url" do
116
+ assert_equal '/2010/01/01/foo-bar', @article.url
117
+ end
118
+ end
119
+
120
+ context "Serious::Article.new('2010-02-16-some-text-for-permalink.txt')" do
121
+ setup do
122
+ @article = Serious::Article.new('2010-02-16-some-text-for-permalink.txt')
123
+ end
124
+
125
+ should "return Date 2010-02-16" do
126
+ assert_equal Date.new(2010, 2, 16), @article.date
127
+ end
128
+
129
+ should "return permalink 'some-text-for-permalink'" do
130
+ assert_equal 'some-text-for-permalink', @article.permalink
131
+ end
132
+
133
+ should "return '/2010/02/16/some-text-for-permalink' as url" do
134
+ assert_equal '/2010/02/16/some-text-for-permalink', @article.url
135
+ end
136
+ end
137
+
138
+ # ========================================================================
139
+ # Tests for finders
140
+ # ========================================================================
141
+ context "When calling find with (2009, 12, 24, 'merry-christmas'), the returned articles" do
142
+ setup do
143
+ @articles = Serious::Article.find(2009, 12, 24, 'merry-christmas')
144
+ end
145
+
146
+ should("have a length of 1") { assert_equal 1, @articles.length}
147
+
148
+ context "the found article" do
149
+ setup { @article = @articles.first }
150
+
151
+ should "have date 2009-12-24" do
152
+ assert_equal Date.new(2009, 12, 24), @article.date
153
+ end
154
+
155
+ should "have permalink 'merry-christmas'" do
156
+ assert_equal 'merry-christmas', @article.permalink
157
+ end
158
+
159
+ should "be the same as when calling Serious::Article.first(2009, 12, 24, 'merry-christmas')" do
160
+ assert_equal @article, Serious::Article.first(2009, 12, 24, 'merry-christmas')
161
+ end
162
+ end
163
+ end
164
+
165
+ should "find article for date '2009, 12, 24' with Serious::Article.first('merry-christmas')" do
166
+ assert_equal Date.new(2009, 12, 24), Serious::Article.first('merry-christmas').date
167
+ end
168
+
169
+ should "find article for date '2009, 12, 24' with Serious::Article.first(12, 24)" do
170
+ assert_equal Date.new(2009, 12, 24), Serious::Article.first(12, 24).date
171
+ end
172
+
173
+ should "find article for date '2009, 12, 24' with Serious::Article.first('12', '24')" do
174
+ assert_equal Date.new(2009, 12, 24), Serious::Article.first('12', '24').date
175
+ end
176
+
177
+ should "find article for date '2000, 1, 1' with Serious::Article.first(2000, 1, 1)" do
178
+ assert_equal Date.new(2000, 1, 1), Serious::Article.first(2000, 1, 1).date
179
+ end
180
+
181
+ should "find article for date '2000, 1, 1' with Serious::Article.first('2000', '1', '1')" do
182
+ assert_equal Date.new(2000, 1, 1), Serious::Article.first('2000', '1', '1').date
183
+ end
184
+
185
+ should "find article for date '2000, 1, 1' with Serious::Article.first('2000', '01', '01')" do
186
+ assert_equal Date.new(2000, 1, 1), Serious::Article.first('2000', '01', '01').date
187
+ end
188
+
189
+ context "Serious::Article.find(2009, 12)" do
190
+ setup do
191
+ @articles = Serious::Article.find(2009, 12)
192
+ end
193
+
194
+ should("have found 2 articles") { assert_equal 2, @articles.length }
195
+ should "return article with permalink 'merry-christmas' first" do
196
+ assert_equal 'merry-christmas', @articles.first.permalink
197
+ end
198
+ should "return article with permalink 'ruby-is-the-shit' last" do
199
+ assert_equal 'ruby-is-the-shit', @articles.last.permalink
200
+ end
201
+ end
202
+
203
+ # ========================================================================
204
+ # Tests for dynamic loading and processing of title, summary and body
205
+ # ========================================================================
206
+ context "The article 'merry-christmas'" do
207
+ setup do
208
+ @article = Serious::Article.first('merry-christmas')
209
+ end
210
+
211
+ should "not have instance variable @yaml set" do
212
+ assert_nil @article.instance_variable_get(:@yaml)
213
+ end
214
+
215
+ should "not have instance variable @content set" do
216
+ assert_nil @article.instance_variable_get(:@content)
217
+ end
218
+
219
+ context "after getting the article's title" do
220
+ setup { @title = @article.title }
221
+
222
+ should "have returned 'Merry Christmas!'" do
223
+ assert_equal 'Merry Christmas!', @title
224
+ end
225
+
226
+ should "have initialized the @yaml instance variable to a hash" do
227
+ assert @article.instance_variable_get(:@yaml).kind_of?(Hash)
228
+ end
229
+
230
+ should "have initialized the @content instance variable to a string" do
231
+ assert @article.instance_variable_get(:@content).kind_of?(String)
232
+ end
233
+
234
+ should "have summary set to 'Merry christmas, dear reader!'" do
235
+ assert_equal 'Merry christmas, dear reader!', @article.summary
236
+ end
237
+
238
+ should 'have body set to "Merry christmas, dear reader!\n\nLorem ipsum dolor..."' do
239
+ assert_equal "Merry christmas, dear reader!\n\nLorem ipsum dolor...", @article.body
240
+ end
241
+ end
242
+ end
243
+
244
+ context "The article 'foo-bar'" do
245
+ setup do
246
+ @article = Serious::Article.first('foo-bar')
247
+ end
248
+
249
+ should("have title 'Foo Bar'") { assert_equal 'Foo Bar', @article.title }
250
+ should('have summary "Baz!"') { assert_equal "Baz!\n", @article.summary }
251
+ should('have body "Baz!"') { assert_equal "Baz!\n", @article.body }
252
+ should('have summary equal to body') { assert_equal @article.summary, @article.body}
253
+ end
254
+
255
+ end
@@ -0,0 +1,160 @@
1
+ require 'helper'
2
+
3
+ class TestSerious < Test::Unit::TestCase
4
+
5
+ # ===================================================================
6
+ # Tests for the main page
7
+ # ===================================================================
8
+ context "GET /" do
9
+ setup { get '/' }
10
+
11
+ should_respond_with 200
12
+ should_contain_elements 3, "ul#articles li"
13
+ should_contain_text "Merry Christmas!", "ul#articles li:first"
14
+ should_contain_text "Merry christmas, dear reader!", "ul#articles li:first"
15
+ should_not_contain_text "Lorem ipsum dolor...", "ul#articles li:first"
16
+
17
+ should_contain_text "Ruby is the shit!", "ul#articles"
18
+ should_contain_text "Some kind of introduction and summary", "ul#articles li"
19
+ should_not_contain_text "The number is 4", "ul#articles li"
20
+
21
+ should_contain_text "Foo Bar", "ul#articles"
22
+
23
+ should_contain_elements 1, "ul.archives li"
24
+ should_contain_text "Disco 2000", "ul.archives li:first"
25
+ end
26
+
27
+ # ===================================================================
28
+ # Tests for the Archives
29
+ # ===================================================================
30
+ context "GET /2009" do
31
+ setup { get '/2009' }
32
+
33
+ should_respond_with 200
34
+ should_contain_text "Archives for 2009", "#container h2:first"
35
+ should_contain_elements 3, "ul.archives li"
36
+ should_contain_text "Merry Christmas!", "ul.archives li:first"
37
+ should_contain_text "Ruby is the shit!", "ul.archives"
38
+ should_contain_text "Foo Bar", "ul.archives"
39
+ end
40
+
41
+ context "GET /2009/12" do
42
+ setup { get '/2009/12' }
43
+
44
+ should_respond_with 200
45
+ should_contain_text "Archives for 2009-12", "#container h2:first"
46
+ should_contain_elements 2, "ul.archives li"
47
+ should_contain_text "Merry Christmas!", "ul.archives li:first"
48
+ should_contain_text "Ruby is the shit!", "ul.archives"
49
+ end
50
+
51
+ context "GET /2009/12/11" do
52
+ setup { get '/2009/12/11' }
53
+
54
+ should_respond_with 200
55
+ should_contain_text "Archives for 2009-12-11", "#container h2:first"
56
+ should_contain_elements 1, "ul.archives li"
57
+ should_contain_text "Ruby is the shit!", "ul.archives li:first"
58
+ end
59
+
60
+ context "GET /2000/" do
61
+ setup { get '/2000' }
62
+
63
+ should_respond_with 200
64
+ should_contain_text "Archives for 2000", "#container h2:first"
65
+ should_contain_elements 1, "ul.archives li"
66
+ should_contain_text "Disco 2000", "ul.archives li:first"
67
+ end
68
+
69
+ context "GET /2005/" do
70
+ setup { get '/2005' }
71
+
72
+ should_respond_with 200
73
+ should_contain_text "Archives for 2005", "#container h2:first"
74
+ should_contain_elements 0, "ul.archives li"
75
+ end
76
+
77
+ context "GET /2000/1" do
78
+ setup { get '/2000/1' }
79
+
80
+ should_respond_with 200
81
+ should_contain_text "Archives for 2000-01", "#container h2:first"
82
+ should_contain_elements 1, "ul.archives li"
83
+ should_contain_text "Disco 2000", "ul.archives li:first"
84
+ end
85
+
86
+ context "GET /2000/1/01" do
87
+ setup { get '/2000/1/01' }
88
+
89
+ should_respond_with 200
90
+ should_contain_text "Archives for 2000-01-01", "#container h2:first"
91
+ should_contain_elements 1, "ul.archives li"
92
+ should_contain_text "Disco 2000", "ul.archives li:first"
93
+ end
94
+
95
+ context "GET /archives" do
96
+ setup { get '/archives' }
97
+
98
+ should_respond_with 200
99
+ should_contain_text "Archives", "#container h2:first"
100
+ should_contain_elements 4, "ul.archives li"
101
+ should_contain_text "Merry Christmas!", "ul.archives li:first"
102
+ should_contain_text "Ruby is the shit!", "ul.archives"
103
+ should_contain_text "Foo Bar", "ul.archives"
104
+ should_contain_text "Disco 2000", "ul.archives li:last"
105
+ end
106
+
107
+ # ===================================================================
108
+ # Tests for the article view
109
+ # ===================================================================
110
+
111
+ context "GET /2009/12/24/merry-christmas" do
112
+ setup { get '/2009/12/24/merry-christmas' }
113
+
114
+ should_respond_with 200
115
+ should_contain_text "Merry Christmas!", "#container h2:first"
116
+ should_contain_text "Merry christmas, dear reader!", ".article .body"
117
+ should_contain_text "Lorem ipsum dolor...", ".article .body"
118
+ end
119
+
120
+ context "GET /2009/12/11/ruby-is-the-shit" do
121
+ setup { get '/2009/12/11/ruby-is-the-shit' }
122
+
123
+ should_respond_with 200
124
+ should_contain_text "Ruby is the shit!", "#container h2:first"
125
+ should_contain_text "Some kind of introduction and summary", ".article .body"
126
+ # Erb should evaluate properly
127
+ should_contain_text "The number is 4", ".article .body"
128
+ end
129
+
130
+ context "GET /2000/1/1/disco-2000" do
131
+ setup { get '/2000/1/1/disco-2000' }
132
+
133
+ should_respond_with 200
134
+ should_contain_text "Disco 2000", "#container h2:first"
135
+ should_contain_text "Well we were born within one hour of each other.", ".article .body"
136
+ # Markdown should evaluate properly
137
+ should_contain_text "by Pulp", ".article .body h3:first"
138
+ end
139
+
140
+ context "GET /2009/1/1/disco-2000" do
141
+ setup { get '/2009/1/1/disco-2000' }
142
+
143
+ should_respond_with 404
144
+ should_contain_text "The requested page could not be found!", "#container h2:first"
145
+ should_not_contain_text "Well we were born within one hour of each other.", ".article .body"
146
+ end
147
+
148
+ # ===================================================================
149
+ # Tests for the public folder
150
+ # ===================================================================
151
+ context "GET /css/serious.css" do
152
+ setup { get '/css/serious.css' }
153
+ should_respond_with 200
154
+ end
155
+
156
+ context "GET /foobar.baz" do
157
+ setup { get '/foobar.baz' }
158
+ should_respond_with 404
159
+ end
160
+ end
@@ -0,0 +1 @@
1
+ <h2>The requested page could not be found!</h2>
@@ -0,0 +1,8 @@
1
+ <ul class="archives">
2
+ <% articles.each do |article| %>
3
+ <li>
4
+ <a href="<%= article.url %>"><%= article.title %></a>
5
+ <span class="date"><%= article.date %></span>
6
+ </li>
7
+ <% end %>
8
+ </ul>
@@ -0,0 +1,7 @@
1
+ <div class="article">
2
+ <span class="date right"><%= article.date %></span>
3
+ <h2><a href="<%= article.url %>"><%= article.title %></a></h2>
4
+ <div class="body">
5
+ <%= format summary_only ? article.summary : article.body %>
6
+ </div>
7
+ </div>
@@ -0,0 +1,2 @@
1
+ <h2>Archives<%= @selection ? " for " + @selection.join("-") : "" %></h2>
2
+ <%= render_archived @articles %>
@@ -0,0 +1,9 @@
1
+ <ul id="articles">
2
+ <% @recent.each do |article| %>
3
+ <li>
4
+ <%= render_article article, true %>
5
+ </li>
6
+ <% end %>
7
+ </ul>
8
+ <h3><a href="/archives">Archives</a></h3>
9
+ <%= render_archived @archived %>
@@ -0,0 +1,22 @@
1
+ <html>
2
+ <head>
3
+ <link rel="stylesheet" type="text/css" href="/css/serious.css">
4
+ <link rel="stylesheet" type="text/css" href="/css/coderay.css">
5
+ <link rel="alternate" type="application/atom+xml" title="Serious Test Layout" href="/atom.xml" />
6
+ <title>Serious Test Layout</title>
7
+ </head>
8
+
9
+ <body>
10
+ <div id="header">
11
+ <h1><a href="/">Serious Blog</a></h1>
12
+ </div>
13
+ <div id="container">
14
+ <%= yield %>
15
+ </div>
16
+
17
+ <div id="footer">
18
+ This blog is <a href="http://github.com/colszowka/serious">serious</a>
19
+ </div>
20
+ </body>
21
+ </html>
22
+
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: serious
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Christoph Olszowka
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-12 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: sinatra
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.9.4
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: stupid_formatter
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.1
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: shoulda
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: hpricot
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: rack-test
57
+ type: :development
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ description: Serious is a simple, file-driven blog engine inspired by toto and driven by sinatra
66
+ email: christoph at olszowka dot de
67
+ executables: []
68
+
69
+ extensions: []
70
+
71
+ extra_rdoc_files:
72
+ - LICENSE
73
+ - README.rdoc
74
+ files:
75
+ - .document
76
+ - .gitignore
77
+ - LICENSE
78
+ - README.rdoc
79
+ - Rakefile
80
+ - VERSION
81
+ - lib/serious.rb
82
+ - lib/serious/article.rb
83
+ - serious.gemspec
84
+ - test/articles/2000-01-01-disco-2000.txt
85
+ - test/articles/2009-04-01-foo-bar.txt
86
+ - test/articles/2009-12-11-ruby-is-the-shit.txt
87
+ - test/articles/2009-12-24-merry-christmas.txt
88
+ - test/helper.rb
89
+ - test/public/css/coderay.css
90
+ - test/public/css/serious.css
91
+ - test/test_article.rb
92
+ - test/test_serious.rb
93
+ - test/views/404.erb
94
+ - test/views/_archives.erb
95
+ - test/views/_article.erb
96
+ - test/views/archives.erb
97
+ - test/views/index.erb
98
+ - test/views/layout.erb
99
+ has_rdoc: true
100
+ homepage: http://github.com/colszowka/serious
101
+ licenses: []
102
+
103
+ post_install_message:
104
+ rdoc_options:
105
+ - --charset=UTF-8
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: "0"
113
+ version:
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: "0"
119
+ version:
120
+ requirements: []
121
+
122
+ rubyforge_project:
123
+ rubygems_version: 1.3.5
124
+ signing_key:
125
+ specification_version: 3
126
+ summary: Serious is a simple, file-driven blog engine inspired by toto and driven by sinatra
127
+ test_files:
128
+ - test/test_serious.rb
129
+ - test/helper.rb
130
+ - test/test_article.rb