postmarkdown 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +3 -0
- data/Rakefile +24 -0
- data/app/controllers/application_controller.rb +2 -0
- data/app/controllers/posts_controller.rb +31 -0
- data/app/models/post.rb +149 -0
- data/app/views/layouts/postmarkdown.html.haml +16 -0
- data/app/views/posts/_feed_link.html.haml +2 -0
- data/app/views/posts/_post.html.haml +15 -0
- data/app/views/posts/feed.xml.builder +29 -0
- data/app/views/posts/index.html.haml +8 -0
- data/app/views/posts/show.html.haml +3 -0
- data/lib/generators/postmarkdown/install_generator.rb +19 -0
- data/lib/generators/postmarkdown/override_generator.rb +44 -0
- data/lib/generators/postmarkdown/post_generator.rb +33 -0
- data/lib/generators/postmarkdown/templates/example-post.markdown +67 -0
- data/lib/generators/postmarkdown/usage/install.txt +10 -0
- data/lib/generators/postmarkdown/usage/override.txt +9 -0
- data/lib/generators/postmarkdown/usage/post.txt +14 -0
- data/lib/postmarkdown.rb +5 -0
- data/lib/postmarkdown/config.rb +22 -0
- data/lib/postmarkdown/engine.rb +12 -0
- data/lib/postmarkdown/railtie.rb +18 -0
- data/lib/postmarkdown/routes.rb +29 -0
- data/lib/postmarkdown/util.rb +12 -0
- data/lib/postmarkdown/version.rb +3 -0
- data/postmarkdown.gemspec +35 -0
- data/public/stylesheets/postmarkdown/postmarkdown.css +67 -0
- data/readme.md +143 -0
- data/spec/acceptance/posts_spec.rb +167 -0
- data/spec/models/posts_spec.rb +72 -0
- data/spec/routing/posts_routing_spec.rb +80 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/data/posts/2011-04-01-first-post.markdown +3 -0
- data/spec/support/data/posts/2011-04-28-image.markdown +3 -0
- data/spec/support/data/posts/2011-04-28-summary.markdown +8 -0
- data/spec/support/data/posts/2011-05-01-full-metadata.markdown +10 -0
- data/spec/support/data/posts/2011-05-02-md-file-extension.md +1 -0
- data/spec/support/data/posts/2011-05-02-mdown-file-extension.mdown +1 -0
- data/spec/support/data/posts/2011-05-02-mkd-file-extension.mkd +1 -0
- data/spec/support/data/posts/2015-02-13-custom-title.markdown +5 -0
- data/spec/support/data/posts/missing-date-from-filename.markdown +1 -0
- data/spec/support/rails_app/.gitignore +4 -0
- data/spec/support/rails_app/README +256 -0
- data/spec/support/rails_app/Rakefile +7 -0
- data/spec/support/rails_app/app/controllers/application_controller.rb +3 -0
- data/spec/support/rails_app/app/helpers/application_helper.rb +2 -0
- data/spec/support/rails_app/app/posts/2011-04-01-first-post.markdown +3 -0
- data/spec/support/rails_app/app/posts/2011-04-28-image.markdown +3 -0
- data/spec/support/rails_app/app/posts/2011-04-28-summary.markdown +8 -0
- data/spec/support/rails_app/app/posts/2011-05-01-full-metadata.markdown +13 -0
- data/spec/support/rails_app/app/posts/2015-02-13-custom-title.markdown +5 -0
- data/spec/support/rails_app/app/views/layouts/application.html.erb +14 -0
- data/spec/support/rails_app/config.ru +4 -0
- data/spec/support/rails_app/config/application.rb +42 -0
- data/spec/support/rails_app/config/boot.rb +10 -0
- data/spec/support/rails_app/config/database.yml +22 -0
- data/spec/support/rails_app/config/environment.rb +5 -0
- data/spec/support/rails_app/config/environments/development.rb +26 -0
- data/spec/support/rails_app/config/environments/production.rb +49 -0
- data/spec/support/rails_app/config/environments/test.rb +35 -0
- data/spec/support/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/support/rails_app/config/initializers/inflections.rb +10 -0
- data/spec/support/rails_app/config/initializers/mime_types.rb +5 -0
- data/spec/support/rails_app/config/initializers/secret_token.rb +7 -0
- data/spec/support/rails_app/config/initializers/session_store.rb +8 -0
- data/spec/support/rails_app/config/locales/en.yml +5 -0
- data/spec/support/rails_app/config/routes.rb +3 -0
- data/spec/support/rails_app/db/seeds.rb +7 -0
- data/spec/support/rails_app/doc/README_FOR_APP +2 -0
- data/spec/support/rails_app/lib/tasks/.gitkeep +0 -0
- data/spec/support/rails_app/public/404.html +26 -0
- data/spec/support/rails_app/public/422.html +26 -0
- data/spec/support/rails_app/public/500.html +26 -0
- data/spec/support/rails_app/public/favicon.ico +0 -0
- data/spec/support/rails_app/public/images/rails.png +0 -0
- data/spec/support/rails_app/public/index.html +239 -0
- data/spec/support/rails_app/public/javascripts/application.js +2 -0
- data/spec/support/rails_app/public/javascripts/controls.js +965 -0
- data/spec/support/rails_app/public/javascripts/dragdrop.js +974 -0
- data/spec/support/rails_app/public/javascripts/effects.js +1123 -0
- data/spec/support/rails_app/public/javascripts/prototype.js +6001 -0
- data/spec/support/rails_app/public/javascripts/rails.js +191 -0
- data/spec/support/rails_app/public/robots.txt +5 -0
- data/spec/support/rails_app/public/stylesheets/.gitkeep +0 -0
- data/spec/support/rails_app/script/rails +6 -0
- data/spec/support/rails_app/test/performance/browsing_test.rb +9 -0
- data/spec/support/rails_app/test/test_helper.rb +13 -0
- data/spec/support/rails_app/vendor/plugins/.gitkeep +0 -0
- data/todo.txt +25 -0
- metadata +315 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
Description:
|
2
|
+
This generator will create the directory structure and routes required by Postmarkdown. As an added bonus, it will create an example post for the current date.
|
3
|
+
|
4
|
+
Example:
|
5
|
+
$ rails generate postmarkdown:install
|
6
|
+
|
7
|
+
This will:
|
8
|
+
- Create the directory `app/posts/`.
|
9
|
+
- Generate an example post using today's date: `app/posts/{{CURRENT_DATE}}-example-post.markdown`.
|
10
|
+
- Add default routes.
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Description:
|
2
|
+
This generator will override either the Post model, controller or views.
|
3
|
+
|
4
|
+
Examples:
|
5
|
+
$ rails generate postmarkdown:override --all # overrides all of the things
|
6
|
+
$ rails generate postmarkdown:override --controller # overrides file `app/controllers/posts_controller.rb`
|
7
|
+
$ rails generate postmarkdown:override --model # overrides file `app/models/post.rb`
|
8
|
+
$ rails generate postmarkdown:override --views # overrides all files in directory `app/views/posts/`
|
9
|
+
$ rails generate postmarkdown:override --theme # overrides the layout and stylesheet
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Description:
|
2
|
+
This generator will produce a new post by creating a markdown file in the `app/posts/` directory. The filename for the new file will be generated using the slug and publish date specified.
|
3
|
+
|
4
|
+
Example 1:
|
5
|
+
$ rails generate postmarkdown:post example-1
|
6
|
+
|
7
|
+
This will:
|
8
|
+
- Generate a new post using the slug specified and today's date: `app/posts/{{CURRENT_DATE}}-example-1.markdown`.
|
9
|
+
|
10
|
+
Example 2:
|
11
|
+
$ rails generate postmarkdown:post example-2 --date=2012-04-10
|
12
|
+
|
13
|
+
This will:
|
14
|
+
- Generate a new post using the slug and publish date specified: `app/posts/2012-04-10-example-2.markdown`.
|
data/lib/postmarkdown.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Postmarkdown
|
2
|
+
module Config
|
3
|
+
extend self
|
4
|
+
|
5
|
+
@options = {}
|
6
|
+
attr_accessor :options
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
Postmarkdown::Config.options[:feed_title] = nil
|
11
|
+
|
12
|
+
Postmarkdown::Config.options[:permalink_format] = :day
|
13
|
+
|
14
|
+
Postmarkdown::Config.options[:use_theme] = false
|
15
|
+
|
16
|
+
Postmarkdown::Config.options[:permalink_regex] = {}
|
17
|
+
Postmarkdown::Config.options[:permalink_regex][:day] = %r[\d{4}/\d{2}/\d{2}/[^/]+]
|
18
|
+
Postmarkdown::Config.options[:permalink_regex][:month] = %r[\d{4}/\d{2}/[^/]+]
|
19
|
+
Postmarkdown::Config.options[:permalink_regex][:year] = %r[\d{4}/[^/]+]
|
20
|
+
Postmarkdown::Config.options[:permalink_regex][:slug] = %r[[^/]+]
|
21
|
+
|
22
|
+
Postmarkdown::Config.options[:markdown_file_extensions] = %w(md mkd mdown markdown)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Postmarkdown
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
initializer :before_initialize do
|
4
|
+
require 'rack'
|
5
|
+
Rails.configuration.middleware.insert_before('Rack::Sendfile', 'Rack::Static',
|
6
|
+
:urls => ['/stylesheets/postmarkdown'],
|
7
|
+
:root => "#{postmarkdown_root}/public"
|
8
|
+
)
|
9
|
+
ActionController::Base.prepend_view_path("#{postmarkdown_root}/app/views")
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def postmarkdown_root
|
15
|
+
File.expand_path(File.dirname(__FILE__) + '/../..')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class ActionDispatch::Routing::Mapper
|
2
|
+
require 'postmarkdown/util'
|
3
|
+
|
4
|
+
def postmarkdown(options = {})
|
5
|
+
options.reverse_merge!({ :as => :posts, :permalink_format => :day })
|
6
|
+
|
7
|
+
get "/#{options[:as]}(/:year(/:month(/:day)))" => 'posts#index', :as => :posts, :constraints => { :year => /\d{4}/, :month => /\d{2}/, :day => /\d{2}/}
|
8
|
+
get "/#{options[:as]}/feed" => 'posts#feed', :as => :posts_feed, :format => :xml
|
9
|
+
get "/#{options[:as]}/*id" => 'posts#show', :as => :post, :constraints => { :id => postmarkdown_permalink_regex(options) }
|
10
|
+
|
11
|
+
postmarkdown_feed_title(options[:as])
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def postmarkdown_permalink_regex(options)
|
17
|
+
Postmarkdown::Config.options[:permalink_format] = options[:permalink_format]
|
18
|
+
Postmarkdown::Config.options[:permalink_regex].try(:[], options[:permalink_format]) or raise_postmarkdown_permalink_error
|
19
|
+
end
|
20
|
+
|
21
|
+
def postmarkdown_feed_title(path)
|
22
|
+
Postmarkdown::Config.options[:feed_title] ||= "#{Postmarkdown::Util.app_name} #{path.to_s.tr('/', '_').humanize.titleize}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def raise_postmarkdown_permalink_error
|
26
|
+
possible_options = Postmarkdown::Config.options[:permalink_regex].map { |k,v| k.inspect }.join(', ')
|
27
|
+
raise "Postmarkdown Routing Error: Invalid :permalink_format option #{Postmarkdown::Config.options[:permalink_format].inspect} - must be one of the following: #{possible_options}"
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'postmarkdown/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'postmarkdown'
|
7
|
+
s.version = Postmarkdown::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ['Jason Weathered', 'Nathanael Kane', 'Odin Dutton', 'Adrian Smith']
|
10
|
+
s.email = ['jason.weathered@ennova.com.au', 'nate.kane@ennova.com.au', 'odin.dutton@ennova.com.au', 'adrian.smith@ennova.com.au']
|
11
|
+
s.licenses = ['MIT']
|
12
|
+
|
13
|
+
s.homepage = ''
|
14
|
+
s.summary = %q{A simple Rails blog engine powered by markdown.}
|
15
|
+
s.description = s.summary
|
16
|
+
|
17
|
+
s.rubyforge_project = 'postmarkdown'
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
s.require_paths = ['lib', 'public']
|
23
|
+
|
24
|
+
s.add_dependency 'rails', '~> 3.0'
|
25
|
+
s.add_dependency 'haml', '~> 3.1'
|
26
|
+
s.add_dependency 'gravtastic'
|
27
|
+
s.add_dependency 'nokogiri'
|
28
|
+
s.add_dependency 'rdiscount'
|
29
|
+
s.add_dependency 'kaminari'
|
30
|
+
|
31
|
+
s.add_development_dependency 'rspec-rails', '~> 2.5'
|
32
|
+
s.add_development_dependency 'capybara', '~> 1.0.0.beta'
|
33
|
+
s.add_development_dependency 'sqlite3'
|
34
|
+
s.add_development_dependency 'delorean', '>= 0.2'
|
35
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
/* -- Reset ----------------------------------------------------------------- */
|
2
|
+
body,div,dl,dt,dd,ul,ol,li,h1,h2,h4,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0}
|
3
|
+
table{border-collapse:collapse;border-spacing:0}
|
4
|
+
fieldset,img{border:0}
|
5
|
+
address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit}
|
6
|
+
del,ins{text-decoration:none}
|
7
|
+
li{list-style:none}
|
8
|
+
caption,th{text-align:left}
|
9
|
+
h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:400}
|
10
|
+
q:before,q:after{content:''}
|
11
|
+
abbr,acronym{border:0;font-variant:normal}
|
12
|
+
legend{color:#000}
|
13
|
+
input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit}
|
14
|
+
input,button,textarea,select{font-size:100%}
|
15
|
+
sup,sub{vertical-align:baseline}
|
16
|
+
header, nav, section, article, footer{display:block;}
|
17
|
+
|
18
|
+
/* -- Global ---------------------------------------------------------------- */
|
19
|
+
html{background:#F3F3F3;text-shadow:0px 1px 0px #fff;}
|
20
|
+
body{width:760px;margin:40px auto;font:14px/140% 'Helvetica Neue', Arial, Helvetica, Sans-Serif;}
|
21
|
+
a{color:#222;}
|
22
|
+
|
23
|
+
h1, h2, h3, h4, h5, h6{font-weight:bold;}
|
24
|
+
h1{font-size:26px;margin-bottom:5px;}
|
25
|
+
h1 a{text-decoration:none;}
|
26
|
+
h2{font-size:24px;padding-top:10px;margin:30px 0 20px;border-top:2px solid #ccc;}
|
27
|
+
h3{font-size:20px;margin-bottom:20px;}
|
28
|
+
h4{font-size:18px;margin-bottom:10px;}
|
29
|
+
h5, h6{font-size:16px;margin-bottom:5px;}
|
30
|
+
|
31
|
+
p{margin-bottom:20px;}
|
32
|
+
em{font-style:italic;}
|
33
|
+
sup{font-size:12px;vertical-align:super;}
|
34
|
+
sub{font-size:12px;vertical-align:sub;}
|
35
|
+
del{color:#666;font-style:line-through;}
|
36
|
+
abbr{border-bottom:1px dotted #bbb;color:#666;text-transform:uppercase;}
|
37
|
+
code{background:#eee;padding:2px 5px;font-family:Monospace;}
|
38
|
+
small{color:#999;font-size:12px;}
|
39
|
+
strong{font-weight:bold;}
|
40
|
+
blockquote{color:#666;font-size:16px;margin-left:20px;font-family:Georgia, Serif;}
|
41
|
+
|
42
|
+
/* code */
|
43
|
+
pre{background:#eee;margin-bottom:20px;padding:10px;border:1px solid #ccc;border-width:1px 0;}
|
44
|
+
|
45
|
+
/* lists */
|
46
|
+
ol, ul{margin:0 0 20px 20px;}
|
47
|
+
ol li{list-style:decimal inside;}
|
48
|
+
ul li{list-style:disc inside;}
|
49
|
+
|
50
|
+
/* -- Header ---------------------------------------------------------------- */
|
51
|
+
header#header {margin-bottom:40px;}
|
52
|
+
header#header h1 {font-size:42px;margin-bottom:10px;font-family:Georgia, Serif;font-weight:normal;}
|
53
|
+
header#header p {color:#999;}
|
54
|
+
|
55
|
+
/* -- Content --------------------------------------------------------------- */
|
56
|
+
section#content{}
|
57
|
+
|
58
|
+
section#content section article p{margin-bottom:10px;}
|
59
|
+
|
60
|
+
section#content article{margin-bottom:40px;}
|
61
|
+
section#content article header{overflow:hidden;}
|
62
|
+
section#content article header h1{}
|
63
|
+
section#content article header img{display:none;}
|
64
|
+
section#content article header .meta{color:#999;font-size:12px;}
|
65
|
+
|
66
|
+
/* -- Footer ---------------------------------------------------------------- */
|
67
|
+
footer{margin-bottom:20px;}
|
data/readme.md
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# Postmarkdown
|
2
|
+
|
3
|
+
A simple Rails blog engine powered by Markdown.
|
4
|
+
|
5
|
+
Postmarkdown is compatible with Rails 3 only and the gem is (soon to be) hosted on [RubyGems.org](http://rubygems.org).
|
6
|
+
|
7
|
+
## Features
|
8
|
+
|
9
|
+
* Markdown files for blog posts
|
10
|
+
* No database
|
11
|
+
* RSS Feed
|
12
|
+
* Customizable Routes
|
13
|
+
* Built-in minimal theme (optional)
|
14
|
+
* HTML5
|
15
|
+
* Rails engine (so you can override models, views, controllers, etc)
|
16
|
+
* Easily customized
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
Simply add Postmarkdown to your Gemfile and bundle it up:
|
21
|
+
|
22
|
+
gem 'postmarkdown'
|
23
|
+
|
24
|
+
Then, run the generator to setup Postmarkdown for your application:
|
25
|
+
|
26
|
+
$ rails generate postmarkdown:install
|
27
|
+
|
28
|
+
The above command performs the following actions:
|
29
|
+
|
30
|
+
* Create the directory `app/posts/`. This directory is where your markdown files will live.
|
31
|
+
* Generate an example post using today's date, eg. `app/posts/2011-01-01-example-post.markdown`.
|
32
|
+
* Add some routes. By default the routes are setup underneath the path `/posts/*`, to customize these routes check out the Customizing Routes section below.
|
33
|
+
|
34
|
+
## Usage
|
35
|
+
|
36
|
+
### Generate a new Post
|
37
|
+
|
38
|
+
Here's an example of how to generate a new post using a slug and publish date:
|
39
|
+
|
40
|
+
$ rails generate postmarkdown:post test-post --date=2011-01-01
|
41
|
+
|
42
|
+
The above command will create the file `app/posts/2011-01-01-test-post.markdown`, which you can edit and add content to.
|
43
|
+
|
44
|
+
### View the Post
|
45
|
+
|
46
|
+
Open `http://localhost:3000/posts` in your browser and you should be able to navigate to your new post. The URL for your new post is `http://localhost:3000/posts/2011/01/01/test-post`.
|
47
|
+
|
48
|
+
## Overriding Files
|
49
|
+
|
50
|
+
The easiest way to customize the Postmarkdown functionality or appearance is by using the override generator. This generator can copy files from the Postmarkdown core and place them into your Rails app. For example:
|
51
|
+
|
52
|
+
$ rails generate postmarkdown:override --all # overrides all of the things
|
53
|
+
$ rails generate postmarkdown:override --controller # overrides `app/controllers/posts_controller.rb`
|
54
|
+
$ rails generate postmarkdown:override --model # overrides `app/models/post.rb`
|
55
|
+
$ rails generate postmarkdown:override --views # overrides all files in directory `app/views/posts/`
|
56
|
+
$ rails generate postmarkdown:override --theme # overrides the layout and stylesheet
|
57
|
+
|
58
|
+
## RSS Feed
|
59
|
+
|
60
|
+
Postmarkdown comes prepared with a fully functional RSS feed.
|
61
|
+
|
62
|
+
You can take advantage of the built-in feed by adding the feed link to your HTML head tag. For example, simply add the following to your default layout:
|
63
|
+
|
64
|
+
<head>
|
65
|
+
<!-- include your stylesheets and javascript here... -->
|
66
|
+
<%= yield :head %>
|
67
|
+
</head>
|
68
|
+
|
69
|
+
To customize the feed title, add the following to an initializer (`config/initializers/postmarkdown.rb`):
|
70
|
+
|
71
|
+
Postmarkdown::Config.options[:feed_title] = 'Custom Blog Title Goes Here'
|
72
|
+
|
73
|
+
To link to the feed in your app, simply use the route helper: `<%= link_to 'RSS Feed', posts_feed_path %>`
|
74
|
+
|
75
|
+
## Built-in Theme
|
76
|
+
|
77
|
+
Postmarkdown comes with minimal built-in theme for your convenience. To turn on the theme, add the following to an initializer (`config/initializers/postmarkdown.rb`):
|
78
|
+
|
79
|
+
Postmarkdown::Config.options[:use_theme] = true
|
80
|
+
|
81
|
+
## Customizing Routes
|
82
|
+
|
83
|
+
By default Postmarkdown will setup all routes to go through the `/posts/*` path. For example:
|
84
|
+
|
85
|
+
http://example.com/posts # lists all posts
|
86
|
+
http://example.com/posts/2011 # lists all posts from 2011
|
87
|
+
http://example.com/posts/2011/01 # lists all posts from January 2011
|
88
|
+
http://example.com/posts/2011/01/01 # lists all posts from the 1st of January 2011
|
89
|
+
http://example.com/posts/2011/01/01/test-post # show the specified post
|
90
|
+
|
91
|
+
You can change the default route path by modifying the 'postmarkdown' line in `routes.rb`. For example:
|
92
|
+
|
93
|
+
postmarkdown :as => :blog
|
94
|
+
|
95
|
+
This will produce the following routes:
|
96
|
+
|
97
|
+
http://example.com/blog # lists all posts
|
98
|
+
http://example.com/blog/2011 # lists all posts from 2011
|
99
|
+
http://example.com/blog/2011/01 # lists all posts from January 2011
|
100
|
+
http://example.com/blog/2011/01/01 # lists all posts from the 1st of January 2011
|
101
|
+
http://example.com/blog/2011/01/01/test-post # show the specified post
|
102
|
+
|
103
|
+
You can also customize the `posts#show` route via the `:permalink_format` option:
|
104
|
+
|
105
|
+
postmarkdown :as => :blog, :permalink_format => :day # URL: http://example.com/blog/2011/01/01/test-post
|
106
|
+
postmarkdown :as => :blog, :permalink_format => :month # URL: http://example.com/blog/2011/01/test-post
|
107
|
+
postmarkdown :as => :blog, :permalink_format => :year # URL: http://example.com/blog/2011/test-post
|
108
|
+
postmarkdown :as => :blog, :permalink_format => :slug # URL: http://example.com/blog/test-post
|
109
|
+
|
110
|
+
What about mapping Postmarkdown to root? We got you covered:
|
111
|
+
|
112
|
+
postmarkdown :as => ''
|
113
|
+
root :to => 'posts#index'
|
114
|
+
|
115
|
+
## Example Directory Structure
|
116
|
+
|
117
|
+
├── app
|
118
|
+
│ ├── controllers
|
119
|
+
│ ├── helpers
|
120
|
+
│ ├── mailers
|
121
|
+
│ ├── models
|
122
|
+
│ ├── posts (where your markdown files live)
|
123
|
+
│ │ ├── 2011-04-01-example-1.markdown
|
124
|
+
│ │ ├── 2011-04-02-example-2.markdown
|
125
|
+
│ │ ├── 2011-04-03-example-3.markdown
|
126
|
+
│ │ ├── 2011-04-04-example-4.markdown
|
127
|
+
│ └── views
|
128
|
+
│ └── posts (overridable)
|
129
|
+
│ ├── _feed_link.html.haml
|
130
|
+
│ ├── _post.html.haml
|
131
|
+
│ ├── feed.xml.builder
|
132
|
+
│ ├── index.html.haml
|
133
|
+
│ └── show.html.haml
|
134
|
+
|
135
|
+
## TODO
|
136
|
+
|
137
|
+
* Syntax highlighting for code blocks
|
138
|
+
* Generated routes should show example usage
|
139
|
+
* Support more file formats, eg. textile
|
140
|
+
|
141
|
+
## License
|
142
|
+
|
143
|
+
MIT License. Copyright 2011 Ennova.
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Post views', :type => :request do
|
4
|
+
before do
|
5
|
+
time_travel_to '2011-05-01'
|
6
|
+
Post.reset!
|
7
|
+
end
|
8
|
+
|
9
|
+
after { back_to_the_present }
|
10
|
+
|
11
|
+
context 'Posts#index' do
|
12
|
+
before { visit posts_path }
|
13
|
+
|
14
|
+
it 'should show published posts' do
|
15
|
+
# 2011-05-01-full-metadata (published today)
|
16
|
+
page.should have_content('Post with full metadata') # title
|
17
|
+
page.should have_content('Posted on 1 May 2011') # publish date
|
18
|
+
page.should have_content('by John Smith') # author
|
19
|
+
page.should have_content('This is another custom & test summary.') # summary
|
20
|
+
|
21
|
+
# 2011-04-28-summary
|
22
|
+
page.should have_content('A Test Post') # title
|
23
|
+
page.should have_content('Posted on 28 April 2011') # publish date
|
24
|
+
page.should have_content('This is a custom & test summary.') # summary
|
25
|
+
|
26
|
+
# 2011-04-28-image
|
27
|
+
page.should have_content('Image') # title
|
28
|
+
page.should have_content('Posted on 28 April 2011') # publish date
|
29
|
+
page.should have_content('Image description.') # summary
|
30
|
+
|
31
|
+
# 2011-04-01-first-post
|
32
|
+
page.should have_content('First Post') # title
|
33
|
+
page.should have_content('Posted on 1 April 2011') # publish date
|
34
|
+
page.should have_content('Lorem ipsum dolor sit amet') # part of summary
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should not show unpublished posts' do
|
38
|
+
# 2015-02-13-custom-title (not published yet)
|
39
|
+
page.should_not have_content('This is a custom title') # title
|
40
|
+
page.should_not have_content('Content goes here.') # summary
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should have the correct number of posts' do
|
44
|
+
all('section#posts article.post').size.should == 4
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'Posts#index with no posts' do
|
49
|
+
it 'should show a message' do
|
50
|
+
time_travel_to '2010-05-01'
|
51
|
+
visit posts_path
|
52
|
+
|
53
|
+
page.should have_content('No posts found.')
|
54
|
+
page.should_not have_content('First Post')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'Posts#index with year' do
|
59
|
+
before { visit posts_path(:year => '2011') }
|
60
|
+
|
61
|
+
it 'should show posts inside the date range' do
|
62
|
+
page.should have_content('Post with full metadata')
|
63
|
+
page.should have_content('A Test Post')
|
64
|
+
page.should have_content('Image')
|
65
|
+
page.should have_content('First Post')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'Posts#index with year and month' do
|
70
|
+
before { visit posts_path(:year => '2011', :month => '04') }
|
71
|
+
|
72
|
+
it 'should show posts inside the date range' do
|
73
|
+
page.should have_content('A Test Post')
|
74
|
+
page.should have_content('Image')
|
75
|
+
page.should have_content('First Post')
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should not show posts outside the date range' do
|
79
|
+
page.should_not have_content('Post with full metadata')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'Posts#index with year, month and day' do
|
84
|
+
before { visit posts_path(:year => '2011', :month => '04', :day => '01') }
|
85
|
+
|
86
|
+
it 'should show posts inside the date range' do
|
87
|
+
page.should have_content('First Post')
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should not show posts outside the date range' do
|
91
|
+
page.should_not have_content('A Test Post')
|
92
|
+
page.should_not have_content('Image')
|
93
|
+
page.should_not have_content('Post with full metadata')
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'Posts#show' do
|
98
|
+
before { visit post_path('2011/05/01/full-metadata') }
|
99
|
+
|
100
|
+
it 'should have content' do
|
101
|
+
page.should have_content('Post with full metadata') # title
|
102
|
+
page.should have_content('Posted on 1 May 2011') # publish date
|
103
|
+
page.should have_content('by John Smith') # author
|
104
|
+
|
105
|
+
# body
|
106
|
+
page.should have_content('First paragraph of content.')
|
107
|
+
page.should have_content('Second paragraph of content.')
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should not show the summary' do
|
111
|
+
page.should_not have_content('This is another custom & test summary.')
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should preserve whitespace on code blocks' do
|
115
|
+
page.source.should match '<pre><code>First line of code.
 Second line of code.
</code></pre>'
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'Posts#feed' do
|
120
|
+
before { visit posts_feed_path }
|
121
|
+
|
122
|
+
it 'should be xml format type' do
|
123
|
+
page.response_headers['Content-Type'].should == 'application/atom+xml; charset=utf-8'
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should be valid xml' do
|
127
|
+
lambda do
|
128
|
+
Nokogiri::XML::Reader(page.source)
|
129
|
+
end.should_not raise_error
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should contain the correct number of entries' do
|
133
|
+
Nokogiri::XML(page.source).search('entry').size.should == 4
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should contain an entry that is properly constructed' do
|
137
|
+
entry = Nokogiri::XML(page.source).search('entry').first
|
138
|
+
|
139
|
+
entry.search('title').text.should == 'Post with full metadata'
|
140
|
+
entry.search('author').first.search('name').text.should == 'John Smith'
|
141
|
+
entry.search('author').first.search('email').text.should == 'john.smith@example.com'
|
142
|
+
entry.search('published').text.should == '2011-05-01T00:00:00Z'
|
143
|
+
entry.search('content').text == "\n <p>First paragraph of content.</p>\n\n<p>Second paragraph of content.</p>\n\n "
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'Posts#show with invalid slug' do
|
148
|
+
it 'should raise an not found exception' do
|
149
|
+
lambda do
|
150
|
+
visit post_path('2011/05/01/invalid')
|
151
|
+
end.should raise_error(ActiveRecord::RecordNotFound)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'theme' do
|
156
|
+
it 'should not use the built-in layout by default' do
|
157
|
+
visit posts_path
|
158
|
+
page.should_not have_content('A postmarkdown blog')
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'should use the built-in layout when the global option is set' do
|
162
|
+
Postmarkdown::Config.options[:use_theme] = true
|
163
|
+
visit posts_path
|
164
|
+
page.should have_content('A postmarkdown blog')
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|