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.
Files changed (71) hide show
  1. data/HISTORY +67 -0
  2. data/INFO +14 -0
  3. data/LICENSE +0 -0
  4. data/README.rdoc +103 -0
  5. data/Rakefile +174 -0
  6. data/VERSION +8 -0
  7. data/bin/postview +51 -0
  8. data/lib/postview.rb +68 -0
  9. data/lib/postview/about.rb +34 -0
  10. data/lib/postview/application.rb +130 -0
  11. data/lib/postview/cli.rb +71 -0
  12. data/lib/postview/cli/create_command.rb +362 -0
  13. data/lib/postview/cli/server_command.rb +115 -0
  14. data/lib/postview/helpers.rb +21 -0
  15. data/lib/postview/patches.rb +11 -0
  16. data/lib/postview/settings.rb +107 -0
  17. data/lib/postview/site.rb +51 -0
  18. data/lib/postview/version.rb +27 -0
  19. data/tasks/documentation.rake +21 -0
  20. data/tasks/history.rake +7 -0
  21. data/tasks/homepage.rake +10 -0
  22. data/tasks/package.rake +11 -0
  23. data/tasks/version.rake +56 -0
  24. data/test/application_test.rb +122 -0
  25. data/test/extensions.rb +23 -0
  26. data/test/fixtures/application/config.ru +6 -0
  27. data/test/fixtures/application/config/settings.yml +22 -0
  28. data/test/fixtures/application/empty.yml +0 -0
  29. data/test/fixtures/application/posts/20090529-postview_blogware.ruby.sinatra.mkd +4 -0
  30. data/test/fixtures/application/posts/20090602-postview_blogware.ruby.sinatra.mkd +4 -0
  31. data/test/fixtures/application/posts/archive/20080529-postview_blogware.ruby.sinatra.mkd +4 -0
  32. data/test/fixtures/application/posts/archive/20080602-postview_blogware.ruby.sinatra.mkd +4 -0
  33. data/test/fixtures/application/posts/drafts/20090730-draft_postview_blogware.ruby.sinatra.mkd +4 -0
  34. data/test/fixtures/application/themes/gemstone/about.erb +0 -0
  35. data/test/fixtures/application/themes/gemstone/archive/index.erb +0 -0
  36. data/test/fixtures/application/themes/gemstone/archive/show.erb +17 -0
  37. data/test/fixtures/application/themes/gemstone/images/banners/banner.jpg +0 -0
  38. data/test/fixtures/application/themes/gemstone/images/favicon.ico +0 -0
  39. data/test/fixtures/application/themes/gemstone/images/trojan.com +0 -0
  40. data/test/fixtures/application/themes/gemstone/index.erb +0 -0
  41. data/test/fixtures/application/themes/gemstone/javascripts/gemstone.js +1 -0
  42. data/test/fixtures/application/themes/gemstone/layout.erb +0 -0
  43. data/test/fixtures/application/themes/gemstone/posts/index.erb +0 -0
  44. data/test/fixtures/application/themes/gemstone/posts/show.erb +0 -0
  45. data/test/fixtures/application/themes/gemstone/search.erb +0 -0
  46. data/test/fixtures/application/themes/gemstone/stylesheets/gemstone.css +1 -0
  47. data/test/fixtures/application/themes/gemstone/tags/index.erb +0 -0
  48. data/test/fixtures/application/themes/gemstone/tags/show.erb +0 -0
  49. data/test/helper.rb +9 -0
  50. data/test/settings_test.rb +72 -0
  51. data/test/site_test.rb +62 -0
  52. data/themes/default/about.erb +24 -0
  53. data/themes/default/archive/index.erb +21 -0
  54. data/themes/default/archive/show.erb +17 -0
  55. data/themes/default/error.erb +0 -0
  56. data/themes/default/images/favicon.ico +0 -0
  57. data/themes/default/images/logo.png +0 -0
  58. data/themes/default/images/navigation-bar.gif +0 -0
  59. data/themes/default/images/postview.png +0 -0
  60. data/themes/default/images/rack.png +0 -0
  61. data/themes/default/images/ruby.png +0 -0
  62. data/themes/default/images/sinatra.png +0 -0
  63. data/themes/default/index.erb +38 -0
  64. data/themes/default/layout.erb +117 -0
  65. data/themes/default/posts/index.erb +21 -0
  66. data/themes/default/posts/show.erb +17 -0
  67. data/themes/default/search.erb +40 -0
  68. data/themes/default/stylesheets/postview.css +238 -0
  69. data/themes/default/tags/index.erb +12 -0
  70. data/themes/default/tags/show.erb +40 -0
  71. 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,11 @@
1
+ class Array
2
+ # Count objects in elements.
3
+ def count(obj = nil)
4
+ if block_given?
5
+ select { |item| yield item }.size
6
+ else
7
+ select { |item| item == obj }.size
8
+ end
9
+ end
10
+ end
11
+
@@ -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
+
@@ -0,0 +1,7 @@
1
+ desc "Creates/updates history file."
2
+ task :history, [:branch] do |spec, args|
3
+ File.open(spec.name.upcase, "w+") do |history|
4
+ history << `git log #{args[:branch] || :master} --format="== %ai - %s%n%n%b"`
5
+ end
6
+ end
7
+
@@ -0,0 +1,10 @@
1
+ directory "homepage"
2
+
3
+ file "homepage/index.html" => FileList["homepage"] do |spec|
4
+ puts spec.name
5
+ end
6
+
7
+ task "homepage:index" do |spec|
8
+ puts spec.name
9
+ end
10
+
@@ -0,0 +1,11 @@
1
+ require 'rake/gempackagetask'
2
+
3
+ def gemspec
4
+ load 'postview.gemspec' unless @gemspec
5
+ @gemspec
6
+ end
7
+
8
+ Rake::GemPackageTask.new gemspec do |pkg|
9
+ pkg.need_zip = true
10
+ end
11
+
@@ -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
+