postview 0.7.0
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.
- data/HISTORY +67 -0
- data/INFO +14 -0
- data/LICENSE +0 -0
- data/README.rdoc +103 -0
- data/Rakefile +174 -0
- data/VERSION +8 -0
- data/bin/postview +51 -0
- data/lib/postview.rb +68 -0
- data/lib/postview/about.rb +34 -0
- data/lib/postview/application.rb +130 -0
- data/lib/postview/cli.rb +71 -0
- data/lib/postview/cli/create_command.rb +362 -0
- data/lib/postview/cli/server_command.rb +115 -0
- data/lib/postview/helpers.rb +21 -0
- data/lib/postview/patches.rb +11 -0
- data/lib/postview/settings.rb +107 -0
- data/lib/postview/site.rb +51 -0
- data/lib/postview/version.rb +27 -0
- data/tasks/documentation.rake +21 -0
- data/tasks/history.rake +7 -0
- data/tasks/homepage.rake +10 -0
- data/tasks/package.rake +11 -0
- data/tasks/version.rake +56 -0
- data/test/application_test.rb +122 -0
- data/test/extensions.rb +23 -0
- data/test/fixtures/application/config.ru +6 -0
- data/test/fixtures/application/config/settings.yml +22 -0
- data/test/fixtures/application/empty.yml +0 -0
- data/test/fixtures/application/posts/20090529-postview_blogware.ruby.sinatra.mkd +4 -0
- data/test/fixtures/application/posts/20090602-postview_blogware.ruby.sinatra.mkd +4 -0
- data/test/fixtures/application/posts/archive/20080529-postview_blogware.ruby.sinatra.mkd +4 -0
- data/test/fixtures/application/posts/archive/20080602-postview_blogware.ruby.sinatra.mkd +4 -0
- data/test/fixtures/application/posts/drafts/20090730-draft_postview_blogware.ruby.sinatra.mkd +4 -0
- data/test/fixtures/application/themes/gemstone/about.erb +0 -0
- data/test/fixtures/application/themes/gemstone/archive/index.erb +0 -0
- data/test/fixtures/application/themes/gemstone/archive/show.erb +17 -0
- data/test/fixtures/application/themes/gemstone/images/banners/banner.jpg +0 -0
- data/test/fixtures/application/themes/gemstone/images/favicon.ico +0 -0
- data/test/fixtures/application/themes/gemstone/images/trojan.com +0 -0
- data/test/fixtures/application/themes/gemstone/index.erb +0 -0
- data/test/fixtures/application/themes/gemstone/javascripts/gemstone.js +1 -0
- data/test/fixtures/application/themes/gemstone/layout.erb +0 -0
- data/test/fixtures/application/themes/gemstone/posts/index.erb +0 -0
- data/test/fixtures/application/themes/gemstone/posts/show.erb +0 -0
- data/test/fixtures/application/themes/gemstone/search.erb +0 -0
- data/test/fixtures/application/themes/gemstone/stylesheets/gemstone.css +1 -0
- data/test/fixtures/application/themes/gemstone/tags/index.erb +0 -0
- data/test/fixtures/application/themes/gemstone/tags/show.erb +0 -0
- data/test/helper.rb +9 -0
- data/test/settings_test.rb +72 -0
- data/test/site_test.rb +62 -0
- data/themes/default/about.erb +24 -0
- data/themes/default/archive/index.erb +21 -0
- data/themes/default/archive/show.erb +17 -0
- data/themes/default/error.erb +0 -0
- data/themes/default/images/favicon.ico +0 -0
- data/themes/default/images/logo.png +0 -0
- data/themes/default/images/navigation-bar.gif +0 -0
- data/themes/default/images/postview.png +0 -0
- data/themes/default/images/rack.png +0 -0
- data/themes/default/images/ruby.png +0 -0
- data/themes/default/images/sinatra.png +0 -0
- data/themes/default/index.erb +38 -0
- data/themes/default/layout.erb +117 -0
- data/themes/default/posts/index.erb +21 -0
- data/themes/default/posts/show.erb +17 -0
- data/themes/default/search.erb +40 -0
- data/themes/default/stylesheets/postview.css +238 -0
- data/themes/default/tags/index.erb +12 -0
- data/themes/default/tags/show.erb +40 -0
- metadata +158 -0
@@ -0,0 +1,115 @@
|
|
1
|
+
module Postview
|
2
|
+
|
3
|
+
Application.class_eval do
|
4
|
+
set :environment, :production
|
5
|
+
end
|
6
|
+
|
7
|
+
module CLI
|
8
|
+
|
9
|
+
# Copying (c) 2009 Hallison Batista
|
10
|
+
class ServerCommand #:nodoc: all
|
11
|
+
|
12
|
+
include Command
|
13
|
+
|
14
|
+
def initialize(path, arguments)
|
15
|
+
@path, @arguments, @options = path, arguments, {}
|
16
|
+
@server_options = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
parse_arguments
|
21
|
+
load_server
|
22
|
+
start_server
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.run(args)
|
26
|
+
if args.first =~ /^\w.*|^\/\w.*/
|
27
|
+
new(args.shift, args.options).run
|
28
|
+
else
|
29
|
+
new(".", args.options).run
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Options for arguments.
|
36
|
+
def options_for(name)
|
37
|
+
{ :help => [ nil, "--help", nil,
|
38
|
+
"Show this message." ],
|
39
|
+
:host => [ "-h", "--host [HOST]", String,
|
40
|
+
"Listen on host (default 0.0.0.0)." ],
|
41
|
+
:port => [ "-p", "--port [PORT]", String,
|
42
|
+
"Use port (default: 9000)." ]
|
43
|
+
}[name]
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse_arguments
|
47
|
+
@arguments.summary_indent = " "
|
48
|
+
@arguments.summary_width = 24
|
49
|
+
@arguments.banner = <<-end_banner.gsub(/^[ ]{6}/, '')
|
50
|
+
#{Postview::Version}
|
51
|
+
|
52
|
+
Usage:
|
53
|
+
#{Postview.name.downcase} server <path> [options]
|
54
|
+
|
55
|
+
end_banner
|
56
|
+
|
57
|
+
@arguments.separator "Server options:"
|
58
|
+
|
59
|
+
@arguments.on(*options_for(:help)) { puts @arguments; exit 0 }
|
60
|
+
@arguments.on(*options_for(:host)) { |host| @options[:Host] = host }
|
61
|
+
@arguments.on(*options_for(:port)) { |port| @options[:Port] = port }
|
62
|
+
|
63
|
+
@arguments.separator ""
|
64
|
+
|
65
|
+
begin
|
66
|
+
@arguments.parse!
|
67
|
+
rescue => error
|
68
|
+
puts error
|
69
|
+
puts @arguments
|
70
|
+
end
|
71
|
+
puts "#{Postview::Version}\n\n"
|
72
|
+
end
|
73
|
+
|
74
|
+
def load_server
|
75
|
+
# This code extracted from Rack binary.
|
76
|
+
start "Loading server" do
|
77
|
+
step { @server ||= "mongrel" }
|
78
|
+
step { @options[:Host] ||= "0.0.0.0" }
|
79
|
+
step { @options[:Port] ||= "9000" }
|
80
|
+
step { @path = Pathname.new(@path) }
|
81
|
+
step { @config = @path.join("config.ru") }
|
82
|
+
step do
|
83
|
+
unless @config.exist?
|
84
|
+
raise "Configuration #{@config} not found"
|
85
|
+
else
|
86
|
+
true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
step { @source = @config.read }
|
90
|
+
step { @source = @source.gsub(/^require[ ]'postview'/,'') }
|
91
|
+
step { @server = Rack::Handler::WEBrick }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# TODO: Improve this method for run server using production environment.
|
96
|
+
def start_server
|
97
|
+
init "Postview starting #{@server} on #{@options[:Host]}:#{@options[:Port]}" do
|
98
|
+
ENV['RACK_ENV'] = "production"
|
99
|
+
config = @config.to_s
|
100
|
+
@postview = eval("Rack::Builder.new{(\n#{@source}\n)}.to_app", nil, config)
|
101
|
+
@application = Rack::Builder.new do |application|
|
102
|
+
use Rack::CommonLogger, STDOUT
|
103
|
+
use Rack::ShowExceptions
|
104
|
+
run application
|
105
|
+
end.to_app
|
106
|
+
end
|
107
|
+
@server.run(@postview, @options)
|
108
|
+
end
|
109
|
+
|
110
|
+
end # class ServerCommand
|
111
|
+
|
112
|
+
end # module CLI
|
113
|
+
|
114
|
+
end # module Postview
|
115
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Postview
|
2
|
+
|
3
|
+
# Copyright (c) 2009 Hallison Batista
|
4
|
+
module Helpers
|
5
|
+
|
6
|
+
attr_reader :site, :page
|
7
|
+
attr_reader :post, :posts, :archive, :tag, :tags
|
8
|
+
|
9
|
+
# ...
|
10
|
+
def count_posts_by_tag(tagname)
|
11
|
+
@count_posts_by_tag ||= @tags.inject({}) do |hash, tag|
|
12
|
+
hash[tag] = (@site.find.all_posts + @site.find_archived.all_posts).count{ |post| post.tags.include? tag }
|
13
|
+
hash
|
14
|
+
end
|
15
|
+
@count_posts_by_tag[tagname]
|
16
|
+
end
|
17
|
+
|
18
|
+
end # module Helpers
|
19
|
+
|
20
|
+
end # module Postview
|
21
|
+
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module Postview
|
2
|
+
|
3
|
+
# Copyright (c) 2009 Hallison Batista
|
4
|
+
class Settings
|
5
|
+
|
6
|
+
DEFAULTS = {
|
7
|
+
:site => {
|
8
|
+
:title => "Postview",
|
9
|
+
:subtitle => "Post your articles",
|
10
|
+
:author => "Hallison Batista",
|
11
|
+
:email => "email@example.com",
|
12
|
+
:domain => "example.com",
|
13
|
+
:directory => "/var/www/example",
|
14
|
+
:theme => "default"
|
15
|
+
},
|
16
|
+
:directories => {
|
17
|
+
:posts => "posts",
|
18
|
+
:archive => "posts/archive",
|
19
|
+
:drafts => "posts/drafts"
|
20
|
+
},
|
21
|
+
:sections => {
|
22
|
+
:root => "/",
|
23
|
+
:posts => "/posts",
|
24
|
+
:tags => "/tags",
|
25
|
+
:archive => "/archive",
|
26
|
+
:drafts => "/drafts",
|
27
|
+
:search => "/search",
|
28
|
+
:about => "/about"
|
29
|
+
}
|
30
|
+
}
|
31
|
+
FILE_NAME = "settings.yml"
|
32
|
+
FILE_DIR = "config"
|
33
|
+
FILE = Postview::PATH.join(FILE_DIR, FILE_NAME)
|
34
|
+
|
35
|
+
attr_reader :site, :theme, :directories, :sections
|
36
|
+
|
37
|
+
def initialize(attributes = {})
|
38
|
+
attributes.symbolize_keys.merge(DEFAULTS) do |key, value, default|
|
39
|
+
value || default
|
40
|
+
end.instance_variables_set_to(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_site
|
44
|
+
build_all_finders_for(Site.new(site))
|
45
|
+
end
|
46
|
+
|
47
|
+
def build_page
|
48
|
+
OpenStruct.new(:title => "", :keywords => [])
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_all_finders_for(site)
|
52
|
+
site.find = build_finder_for(:posts)
|
53
|
+
site.find_archived = build_finder_for(:archive)
|
54
|
+
site.find_drafted = build_finder_for(:drafts)
|
55
|
+
site
|
56
|
+
end
|
57
|
+
|
58
|
+
def build_finder_for(directory)
|
59
|
+
Postage::Finder.new(directory_for(directory))
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.load
|
63
|
+
load_file(FILE)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.load_file(file_name)
|
67
|
+
begin
|
68
|
+
new(YAML.load_file(file_name) || DEFAULTS)
|
69
|
+
rescue Errno::ENOENT
|
70
|
+
new(DEFAULTS)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.load_file_from(path)
|
75
|
+
file = Pathname.new(path).join(FILE_DIR, FILE_NAME)
|
76
|
+
new(YAML.load_file(file))
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.build_default_file
|
80
|
+
FILE.open "w+" do |file|
|
81
|
+
file << DEFAULTS.to_yaml
|
82
|
+
end unless FILE.exist?
|
83
|
+
end
|
84
|
+
|
85
|
+
def file
|
86
|
+
FILE
|
87
|
+
end
|
88
|
+
|
89
|
+
def file_names_for(directory, pattern = "**.*")
|
90
|
+
directory_for(directory, pattern)
|
91
|
+
end
|
92
|
+
|
93
|
+
def directory_for(name, *paths)
|
94
|
+
return Pathname.new(directories[name], *paths) if directories[name].match(%r{^/.*})
|
95
|
+
PATH.join(directories[name], *paths)
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_hash
|
99
|
+
DEFAULTS.keys.inject({}) do |hash, method|
|
100
|
+
hash[method] = send(method)
|
101
|
+
hash
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end # class Settings
|
106
|
+
|
107
|
+
end # module Postview
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Postview
|
2
|
+
|
3
|
+
# Copyright (c) 2009 Hallison Batista
|
4
|
+
class Site
|
5
|
+
|
6
|
+
# Site title.
|
7
|
+
attr_accessor :title
|
8
|
+
|
9
|
+
# Subtitle
|
10
|
+
attr_accessor :subtitle
|
11
|
+
|
12
|
+
# Author site
|
13
|
+
attr_accessor :author
|
14
|
+
|
15
|
+
# Email to contact author
|
16
|
+
attr_accessor :email
|
17
|
+
|
18
|
+
# Domain for host site
|
19
|
+
attr_accessor :domain
|
20
|
+
|
21
|
+
# Remote directory for site
|
22
|
+
attr_accessor :directory
|
23
|
+
|
24
|
+
# Theme directory name.
|
25
|
+
attr_accessor :theme
|
26
|
+
|
27
|
+
# Finder for posts
|
28
|
+
attr_accessor :find
|
29
|
+
|
30
|
+
# Finder for archived posts
|
31
|
+
attr_accessor :find_archived
|
32
|
+
|
33
|
+
# Finder for drafted posts
|
34
|
+
attr_accessor :find_drafted
|
35
|
+
|
36
|
+
def initialize(attributes = {})
|
37
|
+
attributes.instance_variables_set_to(self)
|
38
|
+
end
|
39
|
+
|
40
|
+
def find_all_tags
|
41
|
+
(find.all_tags + find_archived.all_tags).uniq.sort
|
42
|
+
end
|
43
|
+
|
44
|
+
def find_tag(tag)
|
45
|
+
find.tag(tag) || find_archived.tag(tag)
|
46
|
+
end
|
47
|
+
|
48
|
+
end # class Site
|
49
|
+
|
50
|
+
end #module Postview
|
51
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Postview
|
2
|
+
|
3
|
+
# Copyright (c) 2009 Hallison Batista
|
4
|
+
module Version #:nodoc: all
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def info
|
9
|
+
@version ||= OpenStruct.new(YAML.load_file(File.join(ROOT, "VERSION")))
|
10
|
+
end
|
11
|
+
|
12
|
+
def tag
|
13
|
+
%w{major minor patch release}.map do |tag|
|
14
|
+
info.send(tag)
|
15
|
+
end.compact.join(".")
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"#{name.sub(/::.*/,'')} v#{tag} (#{info.date.strftime('%B, %d %Y')}, #{info.cycle})"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end # module Version
|
25
|
+
|
26
|
+
end # module Postview
|
27
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
begin
|
2
|
+
require 'hanna/rdoctask'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rdoc'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
end
|
7
|
+
|
8
|
+
desc "Generate RDoc API documentation."
|
9
|
+
Rake::RDocTask.new("doc:api") do |doc|
|
10
|
+
doc.title = Postview.name
|
11
|
+
doc.main = %q{README.rdoc}
|
12
|
+
doc.options = %w{--line-numbers --show-hash}
|
13
|
+
doc.rdoc_dir = %q{doc/api}
|
14
|
+
doc.rdoc_files.include %w{
|
15
|
+
HISTORY
|
16
|
+
LICENSE
|
17
|
+
README.rdoc
|
18
|
+
lib/**/*.rb
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
data/tasks/history.rake
ADDED
data/tasks/homepage.rake
ADDED
data/tasks/package.rake
ADDED
data/tasks/version.rake
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'parsedate'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
def default_version
|
5
|
+
{ :major => 0,
|
6
|
+
:minor => 1,
|
7
|
+
:patch => 0,
|
8
|
+
:release => nil,
|
9
|
+
:date => Date.today,
|
10
|
+
:timestamp => DateTime.now,
|
11
|
+
:cycle => "Development version - Pre-alpha" }
|
12
|
+
end
|
13
|
+
|
14
|
+
def load_version(file = "VERSION")
|
15
|
+
File.exist?(file) ? YAML.load_file(file) : default_version
|
16
|
+
end
|
17
|
+
|
18
|
+
def current_version(file = "VERSION")
|
19
|
+
@current_value ||= OpenStruct.new(load_version)
|
20
|
+
end
|
21
|
+
|
22
|
+
namespace :version do
|
23
|
+
desc "Generate version for new release and tagging."
|
24
|
+
task :new, [:major, :minor, :patch, :release, :date, :cycle, :filename] do |spec, args|
|
25
|
+
version_file = args[:filename] || "VERSION"
|
26
|
+
current = current_version(version_file)
|
27
|
+
date = Date.new(*ParseDate.parsedate(args.date || current.date.to_s).compact) unless args or current
|
28
|
+
newer = {
|
29
|
+
:major => (args[:major] || current.major).to_i,
|
30
|
+
:minor => (args[:minor] || current.minor).to_i,
|
31
|
+
:patch => (args[:patch] || current.patch).to_i,
|
32
|
+
:release => args[:release].to_s.empty? ? nil : args[:release].to_i,
|
33
|
+
:date => date || Date.today,
|
34
|
+
:timestamp => current.timestamp || default_version[:timestamp],
|
35
|
+
:cycle => args[:cycle] || current.cycle
|
36
|
+
}
|
37
|
+
|
38
|
+
newer.merge(current.marshal_dump) do |key, new_value, current_value|
|
39
|
+
new_value || current_value
|
40
|
+
end
|
41
|
+
|
42
|
+
File.open(version_file, "w+") do |version|
|
43
|
+
version << newer.to_yaml
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Show the current version."
|
48
|
+
task :show do
|
49
|
+
version = [:major, :minor, :patch, :release].map do |info|
|
50
|
+
current_version.send info
|
51
|
+
end.compact.join('.')
|
52
|
+
$stdout.puts "Version #{version} released at #{current_version.date} (#{current_version.cycle})"
|
53
|
+
@version = current_version
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|