postview 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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
+