gidget 0.2.1 → 0.3.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/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
|