gidget 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +8 -20
- data/_stub_/pages/about.txt +3 -0
- data/_stub_/views/index.haml +2 -1
- data/_stub_/views/page.haml +2 -1
- data/_stub_/views/post_paging.haml +9 -0
- data/bin/gidget +1 -0
- data/lib/gidget/ext.rb +0 -5
- data/lib/gidget/file_mapper.rb +68 -0
- data/lib/gidget/page.rb +55 -0
- data/lib/gidget/post.rb +8 -40
- data/lib/gidget/server.rb +61 -45
- metadata +9 -7
- data/lib/gidget/post_index.rb +0 -28
- data/lib/gidget/tag_index.rb +0 -30
data/README.rdoc
CHANGED
@@ -7,29 +7,17 @@ Gidget is a minimalist blog engine designed to run on Heroku with a Git-based wo
|
|
7
7
|
== Basic Structure
|
8
8
|
|
9
9
|
* Sinatra based server
|
10
|
-
* A
|
10
|
+
* A File Mapper to help map requests to pages, posts, and tags
|
11
|
+
* A class to handle page information
|
11
12
|
* A class to handle post information
|
12
13
|
|
13
|
-
==
|
14
|
+
== Templates
|
14
15
|
|
15
|
-
|
16
|
-
* /2010/11/19 - an archive template with access to all posts from the specified year/month/day as well as what year, month, and day it is for (month and day are optional)
|
17
|
-
* /2010/11/19/first-post - a post template with access to the full array of posts and the current post index
|
18
|
-
* /page/1 - a paging template with access to posts for the specified day as well as the current page number and total number of pages
|
19
|
-
* /some-special-page - a custom template with access to the full array of posts
|
16
|
+
<This section is being rewritten>
|
20
17
|
|
21
|
-
== Post Creation
|
18
|
+
== Page/Post Creation
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
title: My great post title
|
26
|
-
date: 2010-11-19
|
27
|
-
|
28
|
-
_Hello World!_ This is my first blog post!
|
29
|
-
|
30
|
-
The second section is the body of the post and uses markdown as it's markup language. The two sections should be separated by an empty line.
|
31
|
-
|
32
|
-
File name and structure (other than the .txt extension) don't matter. Gidget will determine request paths based on the date and title metadata and sort them accordingly.
|
20
|
+
<This section is being rewritten>
|
33
21
|
|
34
22
|
== Settings
|
35
23
|
|
@@ -38,7 +26,6 @@ Gidget uses Sinatra's built-in setting support. Settings can be set in your con
|
|
38
26
|
gidget = Gidget::Server.new do
|
39
27
|
set :title, "My Awesome Blog"
|
40
28
|
set :author, "Your Name Goes Here"
|
41
|
-
set :summary_size, 100
|
42
29
|
set :page_size, 10
|
43
30
|
end
|
44
31
|
|
@@ -79,10 +66,11 @@ In order to deploy an app to Heroku you must have an account with them. Once yo
|
|
79
66
|
git push heroku master
|
80
67
|
heroku open
|
81
68
|
|
82
|
-
Congrats! You now have your own blog running on the
|
69
|
+
Congrats! You now have your own blog running on the world wide web!
|
83
70
|
|
84
71
|
== TO BE DONE
|
85
72
|
|
73
|
+
* Cleanup stub contents
|
86
74
|
* Come up with a decent base theme
|
87
75
|
|
88
76
|
== Contributing to gidget
|
data/_stub_/views/index.haml
CHANGED
data/_stub_/views/page.haml
CHANGED
data/bin/gidget
CHANGED
data/lib/gidget/ext.rb
CHANGED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'gidget/page'
|
3
|
+
require 'gidget/post'
|
4
|
+
|
5
|
+
|
6
|
+
module Gidget
|
7
|
+
class FileMapper
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
attr_reader :pages
|
11
|
+
attr_reader :posts
|
12
|
+
attr_reader :tags
|
13
|
+
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@pages = Hash.new
|
17
|
+
@posts = Array.new
|
18
|
+
@tags = Hash.new
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def load
|
23
|
+
page_paths = Dir.glob("pages/**/*.txt")
|
24
|
+
|
25
|
+
# load the page index
|
26
|
+
page_paths.each { |file_path|
|
27
|
+
page = Page.new(file_path)
|
28
|
+
@pages[page.request_path] = page
|
29
|
+
}
|
30
|
+
|
31
|
+
puts "Page Index created, size = " + @pages.keys.size.to_s
|
32
|
+
|
33
|
+
|
34
|
+
post_paths = Dir.glob("posts/**/*.txt")
|
35
|
+
|
36
|
+
# load the post index
|
37
|
+
post_paths.each { |file_path|
|
38
|
+
post = Post.new(file_path)
|
39
|
+
@posts << post
|
40
|
+
}
|
41
|
+
|
42
|
+
# sort the post index by date descending (newest will be first)
|
43
|
+
@posts.replace @posts.sort_by { |p| Time.parse(p.date.to_s).to_i }.reverse!
|
44
|
+
|
45
|
+
puts "Post Index created, size = " + @posts.size.to_s
|
46
|
+
|
47
|
+
|
48
|
+
# load the tag index
|
49
|
+
@posts.each { |post|
|
50
|
+
if (post.meta_data.has_key? :tags)
|
51
|
+
tags = post.meta_data[:tags].split(',')
|
52
|
+
|
53
|
+
tags.each { |tag|
|
54
|
+
tag.strip!
|
55
|
+
|
56
|
+
if (!@tags.has_key? tag)
|
57
|
+
@tags[tag] = []
|
58
|
+
end
|
59
|
+
|
60
|
+
@tags[tag] << post
|
61
|
+
}
|
62
|
+
end
|
63
|
+
}
|
64
|
+
|
65
|
+
puts "Tag Index created, size = " + @tags.keys.size.to_s
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/gidget/page.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rdiscount'
|
2
|
+
require 'yaml'
|
3
|
+
require 'gidget/ext'
|
4
|
+
|
5
|
+
|
6
|
+
module Gidget
|
7
|
+
class Page
|
8
|
+
attr_reader :file_path
|
9
|
+
attr_reader :meta_data
|
10
|
+
|
11
|
+
|
12
|
+
def initialize(file_path)
|
13
|
+
@file_path = file_path
|
14
|
+
|
15
|
+
begin
|
16
|
+
file = File.open(@file_path, "r")
|
17
|
+
|
18
|
+
# read the first paragraph and load it into a Hash with symbols as keys
|
19
|
+
@meta_data = YAML.load(file.gets("")).inject({}) { |h, (k,v)| h.merge(k.to_sym => v) }
|
20
|
+
ensure
|
21
|
+
file.close()
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def request_path
|
27
|
+
@meta_data[:permalink] || "/" + self.title.slugize
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def title
|
32
|
+
@meta_data[:title]
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def body
|
37
|
+
begin
|
38
|
+
file = File.open(@file_path, "r")
|
39
|
+
|
40
|
+
# ignore the first paragraph
|
41
|
+
file.gets("")
|
42
|
+
|
43
|
+
# read the rest of the file and process it's markdown
|
44
|
+
RDiscount.new(file.gets(nil)).to_html
|
45
|
+
ensure
|
46
|
+
file.close()
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def method_missing(m, *args, &block)
|
52
|
+
@meta_data[m] || super
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/gidget/post.rb
CHANGED
@@ -1,52 +1,20 @@
|
|
1
|
-
require '
|
2
|
-
require 'rdiscount'
|
3
|
-
require 'gidget/ext'
|
1
|
+
require 'gidget/page'
|
4
2
|
|
5
3
|
|
6
4
|
module Gidget
|
7
|
-
class Post
|
8
|
-
|
9
|
-
|
10
|
-
attr_reader :meta_data
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(file_path)
|
14
|
-
@file_path = file_path
|
15
|
-
|
16
|
-
begin
|
17
|
-
file = File.open(@file_path, "r")
|
18
|
-
|
19
|
-
# read the first paragraph and load it into a Hash with symbols as keys
|
20
|
-
@meta_data = YAML.load(file.gets("")).inject({}) { |h, (k,v)| h.merge(k.to_sym => v) }
|
21
|
-
ensure
|
22
|
-
file.close()
|
23
|
-
end
|
24
|
-
|
25
|
-
@request_path = @meta_data[:date].strftime("/%Y/%m/%d/") + @meta_data[:title].slugize
|
5
|
+
class Post < Page
|
6
|
+
def request_path
|
7
|
+
@meta_data[:permalink] || self.date.strftime("/%Y/%m/") + self.title.slugize
|
26
8
|
end
|
27
9
|
|
28
10
|
|
29
|
-
def
|
30
|
-
|
31
|
-
file = File.open(@file_path, "r")
|
32
|
-
|
33
|
-
# ignore the first paragraph
|
34
|
-
file.gets("")
|
35
|
-
|
36
|
-
# read the rest of the file and process it's markdown
|
37
|
-
RDiscount.new(file.gets(nil)).to_html
|
38
|
-
ensure
|
39
|
-
file.close()
|
40
|
-
end
|
11
|
+
def date
|
12
|
+
@meta_data[:date]
|
41
13
|
end
|
42
14
|
|
43
15
|
|
44
|
-
def
|
45
|
-
|
46
|
-
return @meta_data[m]
|
47
|
-
else
|
48
|
-
super
|
49
|
-
end
|
16
|
+
def tags
|
17
|
+
@meta_data[:tags] || ""
|
50
18
|
end
|
51
19
|
end
|
52
20
|
end
|
data/lib/gidget/server.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'sinatra/base'
|
2
|
+
require 'benchmark'
|
2
3
|
require 'haml'
|
3
|
-
require 'gidget/
|
4
|
+
require 'gidget/file_mapper'
|
4
5
|
|
5
6
|
|
6
7
|
module Gidget
|
@@ -14,82 +15,97 @@ module Gidget
|
|
14
15
|
super(app, &b=nil)
|
15
16
|
Server.class_exec(&block) if block_given?
|
16
17
|
|
17
|
-
|
18
|
+
# load the file mapper
|
19
|
+
puts Benchmark.measure { FileMapper.instance.load }
|
18
20
|
end
|
19
21
|
|
20
22
|
|
23
|
+
# route for root
|
21
24
|
get '/' do
|
22
|
-
|
25
|
+
haml :index, :locals => { :posts => FileMapper.instance.posts }
|
23
26
|
end
|
24
27
|
|
25
28
|
|
26
|
-
|
29
|
+
# route for a specific page
|
30
|
+
get %r{^\/[\w,\-,\/]+$} do
|
31
|
+
page = FileMapper.instance.pages[request.path]
|
32
|
+
|
33
|
+
if (page != nil)
|
34
|
+
haml :page, :locals => { :page => page }
|
35
|
+
else
|
36
|
+
pass
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
# route for a specific post
|
42
|
+
get %r{^\/[\w,\-,\/]+$} do
|
27
43
|
index = nil
|
28
|
-
|
29
|
-
|
44
|
+
|
45
|
+
FileMapper.instance.posts.each_with_index { |p, i|
|
30
46
|
if (p.request_path == request.path)
|
31
47
|
index = i
|
32
48
|
break
|
33
49
|
end
|
34
50
|
}
|
35
|
-
|
51
|
+
|
36
52
|
if (index != nil)
|
37
|
-
|
53
|
+
haml :post, :locals => { :posts => FileMapper.instance.posts, :index => index }
|
54
|
+
else
|
55
|
+
pass
|
38
56
|
end
|
39
57
|
end
|
40
|
-
|
41
|
-
|
42
|
-
get %r{^\/(\d{4})(\/(\d{2})(\/(\d{2}))?)?$} do
|
43
|
-
year = params[:captures][0]
|
44
|
-
month = params[:captures][2]
|
45
|
-
day = params[:captures][4]
|
46
|
-
|
47
|
-
posts = PostIndex.instance.select { |p|
|
48
|
-
p.request_path.starts_with? request.path
|
49
|
-
}
|
50
|
-
|
51
|
-
render_view(:archive, { :posts => posts, :year => year, :month => month, :day => day })
|
52
|
-
end
|
53
58
|
|
54
59
|
|
55
|
-
|
60
|
+
# route for an archive listing in the format /archive/yyyy/mm (year and month are optional)
|
61
|
+
get %r{^\/archive(\/(\d{4})(\/(\d{2}))?)?$} do
|
62
|
+
if (params[:captures] == nil)
|
63
|
+
posts = FileMapper.instance.posts
|
64
|
+
else
|
65
|
+
year = params[:captures][1]
|
66
|
+
month = params[:captures][3]
|
67
|
+
|
68
|
+
prefix = "#{year}#{month}"
|
69
|
+
|
70
|
+
posts = FileMapper.instance.posts.select { |p|
|
71
|
+
p.date.strftime("%Y%m").starts_with? prefix
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
haml :archive, :locals => { :posts => posts, :year => year, :month => month }
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# route for post paging
|
80
|
+
get %r{^\/page\/(\d+)$} do
|
56
81
|
current_page = params[:captures][0].to_i
|
57
|
-
total_pages = (
|
58
|
-
|
82
|
+
total_pages = (FileMapper.instance.posts.size + settings.page_size - 1) / settings.page_size
|
83
|
+
|
59
84
|
if (current_page <= total_pages)
|
60
|
-
posts =
|
61
|
-
|
62
|
-
|
85
|
+
posts = FileMapper.instance.posts[(current_page - 1) * settings.page_size, settings.page_size]
|
86
|
+
|
87
|
+
haml :post_paging, :locals => { :posts => posts, :current_page => current_page, :total_pages => total_pages }
|
63
88
|
else
|
64
89
|
pass
|
65
90
|
end
|
66
91
|
end
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
92
|
+
|
93
|
+
|
94
|
+
# route for list of posts tagged with a particular tag
|
95
|
+
get %r{^\/tag\/([\w,\-]+)$} do
|
96
|
+
posts = FileMapper.instance.tags[params[:captures][0]]
|
97
|
+
|
72
98
|
if (posts != nil)
|
73
|
-
|
99
|
+
haml :tag, :locals => { :posts => posts }
|
74
100
|
else
|
75
101
|
pass
|
76
102
|
end
|
77
103
|
end
|
78
104
|
|
79
105
|
|
80
|
-
|
81
|
-
|
82
|
-
render_view(request.path.to_sym, { :posts => PostIndex.instance })
|
83
|
-
rescue
|
84
|
-
pass
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
|
89
|
-
def render_view(view, locals)
|
106
|
+
# make all requests cached for a day
|
107
|
+
after do
|
90
108
|
expires(86400, :public)
|
91
|
-
|
92
|
-
haml view, :locals => locals
|
93
109
|
end
|
94
110
|
end
|
95
111
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gidget
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Forrest Robertson
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-02-08 00:00:00 -07:00
|
19
19
|
default_executable: gidget
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -139,19 +139,21 @@ files:
|
|
139
139
|
- _stub_/Gemfile
|
140
140
|
- _stub_/config.dev.ru
|
141
141
|
- _stub_/config.ru
|
142
|
+
- _stub_/pages/about.txt
|
142
143
|
- _stub_/posts/first-post.txt
|
143
144
|
- _stub_/views/about.haml
|
144
145
|
- _stub_/views/archive.haml
|
145
146
|
- _stub_/views/index.haml
|
146
147
|
- _stub_/views/page.haml
|
147
148
|
- _stub_/views/post.haml
|
149
|
+
- _stub_/views/post_paging.haml
|
148
150
|
- _stub_/views/tag.haml
|
149
151
|
- lib/gidget.rb
|
150
152
|
- lib/gidget/ext.rb
|
153
|
+
- lib/gidget/file_mapper.rb
|
154
|
+
- lib/gidget/page.rb
|
151
155
|
- lib/gidget/post.rb
|
152
|
-
- lib/gidget/post_index.rb
|
153
156
|
- lib/gidget/server.rb
|
154
|
-
- lib/gidget/tag_index.rb
|
155
157
|
- LICENSE.txt
|
156
158
|
- README.rdoc
|
157
159
|
- bin/gidget
|
data/lib/gidget/post_index.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'singleton'
|
2
|
-
require 'gidget/post'
|
3
|
-
require 'gidget/tag_index'
|
4
|
-
|
5
|
-
|
6
|
-
module Gidget
|
7
|
-
class PostIndex < Array
|
8
|
-
include Singleton
|
9
|
-
|
10
|
-
|
11
|
-
def load
|
12
|
-
paths = Dir.glob("posts/**/*.txt")
|
13
|
-
|
14
|
-
# add all the posts to the array
|
15
|
-
paths.each { |file_path|
|
16
|
-
self << Post.new(file_path)
|
17
|
-
}
|
18
|
-
|
19
|
-
# sort the array by the request path, descending (newest by date will be first)
|
20
|
-
self.replace self.sort_by { |p| p.request_path }.reverse!
|
21
|
-
|
22
|
-
puts "Post Index created, size = " + self.size.to_s
|
23
|
-
|
24
|
-
# load the tag index
|
25
|
-
TagIndex.instance.load self
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
data/lib/gidget/tag_index.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'singleton'
|
2
|
-
require 'gidget/post'
|
3
|
-
|
4
|
-
|
5
|
-
module Gidget
|
6
|
-
class TagIndex < Hash
|
7
|
-
include Singleton
|
8
|
-
|
9
|
-
|
10
|
-
def load posts
|
11
|
-
posts.each { |post|
|
12
|
-
tags = nil
|
13
|
-
|
14
|
-
if (post.meta_data.has_key? :tags)
|
15
|
-
tags = post.meta_data[:tags].split(',')
|
16
|
-
|
17
|
-
tags.each { |tag|
|
18
|
-
tag.strip!
|
19
|
-
|
20
|
-
if (!self.has_key? tag)
|
21
|
-
self[tag] = []
|
22
|
-
end
|
23
|
-
|
24
|
-
self[tag] << post
|
25
|
-
}
|
26
|
-
end
|
27
|
-
}
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|