gumdrop 0.2.4 → 0.2.7
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog.md +12 -0
- data/Notes.md +5 -1
- data/examples/simple/Gemfile +4 -1
- data/examples/simple/data/config.yml +8 -0
- data/examples/simple/data/posts.yamldb +28 -0
- data/examples/simple/lib/site.rb +24 -0
- data/examples/simple/source/.htaccess +16 -0
- data/examples/simple/source/_pager_control.html.erb +14 -0
- data/examples/simple/source/_sidebar.html.haml +2 -0
- data/examples/simple/source/feed.xml.builder +23 -0
- data/examples/simple/source/index.html.erb +4 -1
- data/examples/simple/source/posts.generator.rb +11 -0
- data/examples/simple/source/posts/index.html.erb +6 -0
- data/examples/simple/source/theme/templates/post.template.haml +3 -0
- data/examples/simple/source/theme/templates/post_page.template.haml +6 -0
- data/examples/simple/source/theme/templates/site.template.haml +1 -1
- data/examples/simple/source/theme/templates/test.template.erb +1 -0
- data/lib/gumdrop.rb +32 -10
- data/lib/gumdrop/content.rb +8 -6
- data/lib/gumdrop/context.rb +45 -70
- data/lib/gumdrop/deferred_loader.rb +97 -0
- data/lib/gumdrop/generator.rb +75 -0
- data/lib/gumdrop/pager.rb +49 -0
- data/lib/gumdrop/server.rb +28 -13
- data/lib/gumdrop/template/Gemfile +7 -2
- data/lib/gumdrop/template/Rakefile +0 -5
- data/lib/gumdrop/template/config.ru +1 -0
- data/lib/gumdrop/template/data/config.yml +2 -0
- data/lib/gumdrop/template/lib/site.rb +14 -0
- data/lib/gumdrop/template/source/feed.xml.builder.txt +23 -0
- data/lib/gumdrop/template/source/theme/scripts/app.js.coffee +4 -0
- data/lib/gumdrop/version.rb +1 -1
- data/lib/gumdrop/view_helpers.rb +9 -4
- metadata +28 -13
data/ChangeLog.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
# v0.2.7
|
2
|
+
- Added support for `yield` in templates
|
3
|
+
- Added support for content_for -- only tested in SLIM
|
4
|
+
|
5
|
+
# v0.2.6
|
6
|
+
- Update pager_for to accept a symbol or an array
|
7
|
+
|
8
|
+
# v0.2.5
|
9
|
+
- New feature: Generators, from source tree or centreally in lib/site.rb
|
10
|
+
- Server can reload the entire site for each request, by default this feature is off
|
11
|
+
- Added Pager class for creating tumblr-like pagesets
|
12
|
+
|
1
13
|
# v0.2.4
|
2
14
|
- Modernized Sinatra usage. Added an example site (just boilerplate at this point).
|
3
15
|
|
data/Notes.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
# Future Features/Changes
|
2
|
-
-
|
2
|
+
- Add support for `data.pager_for(key, opts={})`
|
3
|
+
- Add support for Sprockets
|
4
|
+
- Add support for js and css compression
|
3
5
|
- Add options to config for `source/` and `output/` folder names. `data/` too?
|
6
|
+
- Page generation from lib/site.rb
|
7
|
+
- HTML Manifest generation??
|
4
8
|
- Some kind of admin? What would that even do?
|
data/examples/simple/Gemfile
CHANGED
@@ -2,9 +2,9 @@ source "http://rubygems.org"
|
|
2
2
|
|
3
3
|
here= File.dirname(__FILE__)
|
4
4
|
|
5
|
+
gem "i18n"
|
5
6
|
gem "sinatra"
|
6
7
|
gem "active_support"
|
7
|
-
gem "i18n"
|
8
8
|
gem "rake"
|
9
9
|
gem "gumdrop", :path=>"#{here}/../../"
|
10
10
|
|
@@ -16,4 +16,7 @@ gem "coffee-script"
|
|
16
16
|
# gem "rdiscount"
|
17
17
|
# gem "less"
|
18
18
|
# gem "haml"
|
19
|
+
gem "slim"
|
19
20
|
|
21
|
+
gem 'maruku'
|
22
|
+
gem 'builder'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
---
|
2
|
+
__proto__: true
|
3
|
+
title: String
|
4
|
+
slug: String
|
5
|
+
date: Date
|
6
|
+
filter: String
|
7
|
+
content: Text
|
8
|
+
tags: String
|
9
|
+
|
10
|
+
---
|
11
|
+
title: Testing
|
12
|
+
slug: testing
|
13
|
+
date: 2011-09-09
|
14
|
+
filter: markdown
|
15
|
+
content: |
|
16
|
+
This is just a *test*.
|
17
|
+
|
18
|
+
Enjoy!
|
19
|
+
|
20
|
+
---
|
21
|
+
title: The Second
|
22
|
+
slug: the-second
|
23
|
+
date: 2011-09-10
|
24
|
+
filter: markdown
|
25
|
+
content: |
|
26
|
+
This is just another *test*.
|
27
|
+
|
28
|
+
Enjoy! ReallY!
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Any specialized code for your site goes here...
|
2
|
+
|
3
|
+
puts "Building: #{Gumdrop.data.config.title}"
|
4
|
+
|
5
|
+
new_posts= Gumdrop.data.posts.map do |post|
|
6
|
+
mdt= Tilt['markdown'].new { post.content }
|
7
|
+
post.body = mdt.render
|
8
|
+
post
|
9
|
+
end
|
10
|
+
|
11
|
+
Gumdrop.data.set :blog, new_posts, :persist=>true
|
12
|
+
|
13
|
+
|
14
|
+
generate do
|
15
|
+
|
16
|
+
page "my-root-page.html", :template=>'test', :info=>"FROM SITE.RB"
|
17
|
+
|
18
|
+
pager= Gumdrop.data.pager_for :blog, :base_path=>'posts/page', :page_size=>1
|
19
|
+
|
20
|
+
pager.each do |pageset|
|
21
|
+
page "#{pageset.uri}.html", :template=>'post_page', :posts=>pageset.items, :pager=>pager, :current_page=>pager.current_page
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# For clean urls
|
2
|
+
DirectoryIndex index.html
|
3
|
+
|
4
|
+
<IfModule mod_rewrite.c>
|
5
|
+
RewriteEngine On
|
6
|
+
RewriteBase /
|
7
|
+
|
8
|
+
# Do not do anything for already existing files and folders
|
9
|
+
RewriteCond %{REQUEST_FILENAME} -f [OR]
|
10
|
+
RewriteCond %{REQUEST_FILENAME} -d
|
11
|
+
RewriteRule .+ - [L]
|
12
|
+
|
13
|
+
# add .html file extension (if such file does exist)
|
14
|
+
RewriteCond %{DOCUMENT_ROOT}/$1\.html -f
|
15
|
+
RewriteRule ^(.+[^/])/?$ $1.html [L,QSA]
|
16
|
+
</IfModule>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<%
|
2
|
+
previous_page = [(current_page - 1), 1].max
|
3
|
+
next_page = [(current_page + 1), pager.length].min
|
4
|
+
%>
|
5
|
+
<div class="page">
|
6
|
+
<a href="<%= uri pager[previous_page - 1].uri %>">←</a>
|
7
|
+
<%
|
8
|
+
pager.each do |pager_page|
|
9
|
+
class_name= pager_page.page == current_page ? 'current' : ''
|
10
|
+
%>
|
11
|
+
<a href="<%= uri pager_page.uri %>" class="<%= class_name %>"><%= pager_page.page %></a>
|
12
|
+
<% end %>
|
13
|
+
<a href="<%= uri pager[next_page - 1].uri %>">→</a>
|
14
|
+
</div>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
xml.instruct!
|
2
|
+
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
|
3
|
+
xml.title data.config.title
|
4
|
+
xml.subtitle data.config.tagline
|
5
|
+
xml.id data.config.url
|
6
|
+
xml.link "href" => data.config.url
|
7
|
+
xml.link "href" => "#{data.config.url}/feed.xml", "rel" => "self"
|
8
|
+
xml.updated data.blog.first.date.to_time.iso8601
|
9
|
+
xml.author { xml.name data.config.author }
|
10
|
+
|
11
|
+
data.blog.each do |post|
|
12
|
+
xml.entry do
|
13
|
+
url= "#{data.config.url}/posts/#{post.slug}"
|
14
|
+
xml.title post.title
|
15
|
+
xml.link "rel" => "alternate", "href" => url
|
16
|
+
xml.id url
|
17
|
+
xml.published post.date.to_time.iso8601
|
18
|
+
xml.updated post.date.to_time.iso8601
|
19
|
+
xml.author { xml.name data.config.author }
|
20
|
+
xml.content post.body, "type" => "html"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<p>A Message: <%= info %></p>
|
data/lib/gumdrop.rb
CHANGED
@@ -6,6 +6,7 @@ DEFAULT_OPTIONS= {
|
|
6
6
|
:cache_data => false,
|
7
7
|
:relative_paths => true,
|
8
8
|
:auto_run => false,
|
9
|
+
:force_reload => false,
|
9
10
|
:root => "."
|
10
11
|
}
|
11
12
|
|
@@ -13,8 +14,12 @@ module Gumdrop
|
|
13
14
|
|
14
15
|
autoload :Context, "gumdrop/context"
|
15
16
|
autoload :Content, "gumdrop/content"
|
17
|
+
autoload :DeferredLoader, "gumdrop/deferred_loader"
|
16
18
|
autoload :Generator, "gumdrop/generator"
|
19
|
+
autoload :GeneratedrContent, "gumdrop/generator"
|
20
|
+
autoload :GenerationDSL, "gumdrop/generator"
|
17
21
|
autoload :HashObject, "gumdrop/hash_object"
|
22
|
+
autoload :Pager, "gumdrop/pager"
|
18
23
|
autoload :Server, "gumdrop/server"
|
19
24
|
autoload :Utils, "gumdrop/utils"
|
20
25
|
autoload :VERSION, "gumdrop/version"
|
@@ -22,7 +27,7 @@ module Gumdrop
|
|
22
27
|
|
23
28
|
class << self
|
24
29
|
|
25
|
-
attr_accessor :root_path, :source_path, :site, :layouts, :generators, :partials, :config
|
30
|
+
attr_accessor :root_path, :source_path, :site, :layouts, :generators, :partials, :config, :data
|
26
31
|
|
27
32
|
def run(opts={})
|
28
33
|
# Opts
|
@@ -30,8 +35,8 @@ module Gumdrop
|
|
30
35
|
|
31
36
|
root= File.expand_path Gumdrop.config.root
|
32
37
|
src= File.join root, 'source'
|
38
|
+
$: << "#{root}/lib"
|
33
39
|
if File.exists? "#{root}/lib/view_helpers.rb"
|
34
|
-
$: << "#{root}/lib"
|
35
40
|
require 'view_helpers'
|
36
41
|
end
|
37
42
|
|
@@ -41,6 +46,17 @@ module Gumdrop
|
|
41
46
|
@partials = Hash.new {|h,k| h[k]= nil }
|
42
47
|
@root_path = root.split '/'
|
43
48
|
@source_path = src.split '/'
|
49
|
+
@data = Gumdrop::DeferredLoader.new()
|
50
|
+
|
51
|
+
if File.exists? "#{root}/lib/site.rb"
|
52
|
+
# In server mode, we want to reload it every time... right?
|
53
|
+
source= IO.readlines("#{root}/lib/site.rb").join('')
|
54
|
+
|
55
|
+
GenerationDSL.class_eval source
|
56
|
+
|
57
|
+
#load "#{root}/lib/site.rb"
|
58
|
+
# require 'site'
|
59
|
+
end
|
44
60
|
|
45
61
|
# Scan
|
46
62
|
#puts "Running in: #{root}"
|
@@ -58,7 +74,7 @@ module Gumdrop
|
|
58
74
|
@layouts[File.basename(path)]= @site.delete(path)
|
59
75
|
|
60
76
|
elsif File.extname(path) == ".generator"
|
61
|
-
@generators[File.basename(path)]= @site.delete(path)
|
77
|
+
@generators[File.basename(path)]= Generator.new( @site.delete(path) )
|
62
78
|
|
63
79
|
elsif File.basename(path).starts_with?("_")
|
64
80
|
partial_name= File.basename(path)[1..-1].gsub(File.extname(File.basename(path)), '')
|
@@ -67,16 +83,22 @@ module Gumdrop
|
|
67
83
|
end
|
68
84
|
end
|
69
85
|
|
70
|
-
|
71
|
-
|
72
|
-
node= site[path]
|
73
|
-
output_path= "output/#{node.to_s}"
|
74
|
-
FileUtils.mkdir_p File.dirname(output_path)
|
75
|
-
node.renderTo output_path
|
86
|
+
@generators.each_pair do |path, generator|
|
87
|
+
generator.execute()
|
76
88
|
end
|
77
89
|
|
78
|
-
|
90
|
+
# Render
|
91
|
+
unless opts[:dry_run]
|
92
|
+
site.keys.sort.each do |path|
|
93
|
+
node= site[path]
|
94
|
+
output_path= "output/#{node.to_s}"
|
95
|
+
FileUtils.mkdir_p File.dirname(output_path)
|
96
|
+
node.renderTo output_path
|
97
|
+
end
|
98
|
+
puts "Done."
|
99
|
+
end
|
79
100
|
end
|
101
|
+
|
80
102
|
end
|
81
103
|
|
82
104
|
Gumdrop.config= Gumdrop::HashObject.new(DEFAULT_OPTIONS)
|
data/lib/gumdrop/content.rb
CHANGED
@@ -3,9 +3,10 @@ module Gumdrop
|
|
3
3
|
|
4
4
|
class Content
|
5
5
|
|
6
|
-
attr_accessor :path, :level, :filename, :source_filename, :type, :ext, :uri, :slug, :template
|
6
|
+
attr_accessor :path, :level, :filename, :source_filename, :type, :ext, :uri, :slug, :template, :params
|
7
7
|
|
8
|
-
def initialize(path)
|
8
|
+
def initialize(path, params={})
|
9
|
+
@params= HashObject.new params
|
9
10
|
@path= path
|
10
11
|
@level= (@path.split('/').length - 2)
|
11
12
|
@source_filename= File.basename path
|
@@ -26,16 +27,17 @@ module Gumdrop
|
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
29
|
-
def render(ignore_layout=false, reset_context=true)
|
30
|
+
def render(ignore_layout=false, reset_context=true, locals={})
|
30
31
|
if reset_context
|
31
32
|
default_layout= (@ext == '.css' or @ext == '.js' or @ext == '.xml') ? nil : 'site'
|
32
|
-
Context.reset_data 'current_depth'=>@level, 'current_slug'=>@slug, 'page'=>self, 'layout'=>default_layout
|
33
|
+
Context.reset_data 'current_depth'=>@level, 'current_slug'=>@slug, 'page'=>self, 'layout'=>default_layout, 'params'=>self.params
|
33
34
|
end
|
34
|
-
|
35
|
+
Context.set_content self, locals
|
36
|
+
content= @template.render(Context)
|
35
37
|
return content if ignore_layout
|
36
38
|
layout= Context.get_template()
|
37
39
|
while !layout.nil?
|
38
|
-
content = layout.template.render(Context, :content=>content)
|
40
|
+
content = layout.template.render(Context, :content=>content) { content }
|
39
41
|
layout= Context.get_template()
|
40
42
|
end
|
41
43
|
content
|
data/lib/gumdrop/context.rb
CHANGED
@@ -1,85 +1,27 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'ostruct'
|
3
|
-
|
4
|
-
def hashes2ostruct(object)
|
5
|
-
return case object
|
6
|
-
when Hash
|
7
|
-
object = object.clone
|
8
|
-
object.each do |key, value|
|
9
|
-
object[key] = hashes2ostruct(value)
|
10
|
-
end
|
11
|
-
OpenStruct.new(object)
|
12
|
-
when Array
|
13
|
-
object = object.clone
|
14
|
-
object.map! { |i| hashes2ostruct(i) }
|
15
|
-
else
|
16
|
-
object
|
17
|
-
end
|
18
|
-
end
|
19
1
|
|
20
2
|
module Gumdrop
|
21
3
|
|
22
|
-
class DeferredLoader
|
23
|
-
attr_reader :cache
|
24
|
-
|
25
|
-
# def initialize
|
26
|
-
# puts "@!@"
|
27
|
-
# end
|
28
|
-
|
29
|
-
def method_missing(key, value=nil)
|
30
|
-
@cache= Hash.new {|h,k| h[k]= load_data(k) } if @cache.nil?
|
31
|
-
@cache[key]
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def load_data(key)
|
37
|
-
path=get_filename(key)
|
38
|
-
if File.extname(path) == ".yamldb"
|
39
|
-
docs=[]
|
40
|
-
File.open(path, 'r') do |f|
|
41
|
-
YAML.load_documents(f) do |doc|
|
42
|
-
docs << hashes2ostruct( doc )
|
43
|
-
end
|
44
|
-
end
|
45
|
-
docs
|
46
|
-
else
|
47
|
-
hashes2ostruct( YAML.load_file(path) )
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# TODO: Support './data/collection_name/*.(yaml|json)' data loading?
|
52
|
-
|
53
|
-
def get_filename(path)
|
54
|
-
if File.exists? "data/#{path}.json"
|
55
|
-
"data/#{path}.json"
|
56
|
-
elsif File.exists? "data/#{path}.yml"
|
57
|
-
"data/#{path}.yml"
|
58
|
-
elsif File.exists? "data/#{path}.yaml"
|
59
|
-
"data/#{path}.yaml"
|
60
|
-
elsif File.exists? "data/#{path}.yamldb"
|
61
|
-
"data/#{path}.yamldb"
|
62
|
-
else
|
63
|
-
raise "No data found for #{path}"
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
4
|
module Context
|
69
5
|
class << self
|
70
6
|
|
71
7
|
include ::Gumdrop::ViewHelpers
|
72
8
|
|
73
9
|
attr_accessor :state
|
74
|
-
attr_reader :data
|
10
|
+
#attr_reader :data
|
75
11
|
|
76
12
|
def uri(path)
|
13
|
+
path= path[1..-1] if path.starts_with?('/')
|
77
14
|
if Gumdrop.config.relative_paths
|
78
15
|
"#{'../'*@state['current_depth']}#{path}"
|
79
16
|
else
|
80
17
|
"/#{path}"
|
81
18
|
end
|
82
19
|
end
|
20
|
+
|
21
|
+
def url(path)
|
22
|
+
path= path[1..-1] if path.starts_with?('/')
|
23
|
+
"#{data.config.url}/#{path}"
|
24
|
+
end
|
83
25
|
|
84
26
|
def slug
|
85
27
|
@state['current_slug']
|
@@ -99,34 +41,67 @@ module Gumdrop
|
|
99
41
|
@state['layout']= name
|
100
42
|
end
|
101
43
|
|
102
|
-
def render(path)
|
44
|
+
def render(path, opts={})
|
103
45
|
page= get_page path
|
104
46
|
unless page.nil?
|
105
47
|
#TODO: nested state for an inline rendered page?
|
106
48
|
old_layout= @state['layout']
|
107
|
-
content= page.render(true, false)
|
49
|
+
content= page.render(true, false, opts)
|
108
50
|
old_layout= @state['layout']
|
109
51
|
content
|
110
52
|
else
|
111
53
|
""
|
112
54
|
end
|
113
55
|
end
|
56
|
+
|
57
|
+
def data
|
58
|
+
Gumdrop.data
|
59
|
+
end
|
114
60
|
|
115
61
|
def reset_data(preset={})
|
116
62
|
# TODO: Add a setting for reloading data on every request/page
|
117
|
-
|
63
|
+
#@data= DeferredLoader.new if @data.nil? or !Gumdrop.config.cache_data
|
64
|
+
Gumdrop.data.reset if !Gumdrop.config.cache_data
|
118
65
|
@state = preset
|
119
66
|
end
|
120
67
|
|
121
68
|
def method_missing(name, value=nil)
|
122
69
|
@state= Hash.new {|h,k| h[k]= nil } if @state.nil?
|
70
|
+
# puts "Looking for >> #{name} in #{@state.keys}"
|
123
71
|
unless value.nil?
|
124
|
-
@state[name]= value
|
72
|
+
@state[name.to_s]= value
|
73
|
+
else
|
74
|
+
@state[name.to_s]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def params
|
79
|
+
@content.params
|
80
|
+
end
|
81
|
+
|
82
|
+
def set_content(content, locals)
|
83
|
+
@content= content
|
84
|
+
@state= @state.reverse_merge(content.params).merge(locals)
|
85
|
+
end
|
86
|
+
|
87
|
+
def content_for(key, &block)
|
88
|
+
keyname= "_content_#{key}"
|
89
|
+
if block_given?
|
90
|
+
@state[keyname]= block
|
125
91
|
else
|
126
|
-
@state
|
92
|
+
if @state.has_key?(keyname)
|
93
|
+
@state[keyname].call
|
94
|
+
else
|
95
|
+
nil
|
96
|
+
end
|
127
97
|
end
|
128
98
|
end
|
129
99
|
|
100
|
+
def content_for?(key)
|
101
|
+
keyname= "_content_#{key}"
|
102
|
+
@state.has_key?(keyname)
|
103
|
+
end
|
104
|
+
|
130
105
|
protected
|
131
106
|
|
132
107
|
def get_page(path)
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
def hashes2ostruct(object)
|
5
|
+
return case object
|
6
|
+
when Hash
|
7
|
+
object = object.clone
|
8
|
+
object.each do |key, value|
|
9
|
+
object[key] = hashes2ostruct(value)
|
10
|
+
end
|
11
|
+
OpenStruct.new(object)
|
12
|
+
when Array
|
13
|
+
object = object.clone
|
14
|
+
object.map! { |i| hashes2ostruct(i) }
|
15
|
+
else
|
16
|
+
object
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Gumdrop
|
21
|
+
|
22
|
+
class DeferredLoader
|
23
|
+
attr_reader :cache
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
#puts "@!@"
|
27
|
+
@cache= {}
|
28
|
+
@persisted= {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def method_missing(key, value=nil)
|
32
|
+
cache_or_load_data(key)
|
33
|
+
@cache[key]
|
34
|
+
end
|
35
|
+
|
36
|
+
def set(key, value, opts={})
|
37
|
+
@cache[key]= value
|
38
|
+
@persisted[key]= value if opts[:persist]
|
39
|
+
end
|
40
|
+
|
41
|
+
def reset
|
42
|
+
@cache= @persisted.clone #Hash.new(@persisted) #{|h,k| h[k]= load_data(k) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def pager_for(key, opts={})
|
46
|
+
base_path= opts.fetch(:base_path, 'page')
|
47
|
+
page_size= opts.fetch(:page_size, 5)
|
48
|
+
data= if key.is_a? Symbol
|
49
|
+
cache_or_load_data(key)
|
50
|
+
@cache[key]
|
51
|
+
else
|
52
|
+
key
|
53
|
+
end
|
54
|
+
Pager.new( data, base_path, page_size )
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def cache_or_load_data(key)
|
61
|
+
@cache[key]= load_data(key) unless @cache.has_key? key
|
62
|
+
end
|
63
|
+
|
64
|
+
def load_data(key)
|
65
|
+
path=get_filename(key)
|
66
|
+
return nil if path.nil?
|
67
|
+
if File.extname(path) == ".yamldb"
|
68
|
+
docs=[]
|
69
|
+
File.open(path, 'r') do |f|
|
70
|
+
YAML.load_documents(f) do |doc|
|
71
|
+
docs << hashes2ostruct( doc ) unless doc.has_key?("__proto__")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
docs
|
75
|
+
else
|
76
|
+
hashes2ostruct( YAML.load_file(path) )
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# TODO: Support './data/collection_name/*.(yaml|json)' data loading?
|
81
|
+
|
82
|
+
def get_filename(path)
|
83
|
+
if File.exists? "data/#{path}.json"
|
84
|
+
"data/#{path}.json"
|
85
|
+
elsif File.exists? "data/#{path}.yml"
|
86
|
+
"data/#{path}.yml"
|
87
|
+
elsif File.exists? "data/#{path}.yaml"
|
88
|
+
"data/#{path}.yaml"
|
89
|
+
elsif File.exists? "data/#{path}.yamldb"
|
90
|
+
"data/#{path}.yamldb"
|
91
|
+
else
|
92
|
+
raise "No data found for #{path}"
|
93
|
+
#nil #TODO: Should it die if it can't find data?
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/gumdrop/generator.rb
CHANGED
@@ -1,6 +1,81 @@
|
|
1
1
|
module Gumdrop
|
2
2
|
|
3
3
|
class Generator
|
4
|
+
attr_reader :filename, :base_path, :params, :pages
|
5
|
+
|
6
|
+
def initialize(content, opts={})
|
7
|
+
@content= content
|
8
|
+
if @content.is_a? Proc
|
9
|
+
@filename= ""
|
10
|
+
@base_path= ""
|
11
|
+
else
|
12
|
+
@filename= content.filename || ""
|
13
|
+
@base_path= content.slug || ""
|
14
|
+
end
|
15
|
+
@params= HashObject.new
|
16
|
+
@pages= []
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute
|
20
|
+
if @content.is_a? Proc
|
21
|
+
run_dsl_from_proc @content
|
22
|
+
else
|
23
|
+
run_dsl_from_source IO.readlines(@content.path).join('')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def data
|
28
|
+
Gumdrop.data
|
29
|
+
end
|
30
|
+
|
31
|
+
def set(var_name, value)
|
32
|
+
params[var_name]= value
|
33
|
+
end
|
34
|
+
|
35
|
+
def page(name, opts={}, &block)
|
36
|
+
opts= params.reverse_merge(opts)
|
37
|
+
filepath= if @base_path.empty?
|
38
|
+
"/#{name}"
|
39
|
+
else
|
40
|
+
"/#{@base_path}/#{name}"
|
41
|
+
end
|
42
|
+
content= GeneratedContent.new(filepath, opts)
|
43
|
+
content.template = if Gumdrop.layouts.has_key?( opts[:template] )
|
44
|
+
Gumdrop.layouts[ opts[:template] ]
|
45
|
+
else
|
46
|
+
Gumdrop.layouts[ "#{opts[:template]}.template" ]
|
47
|
+
end.template
|
48
|
+
|
49
|
+
Gumdrop.site[content.uri]= content
|
50
|
+
end
|
51
|
+
|
52
|
+
def run_dsl_from_source(source)
|
53
|
+
# puts source
|
54
|
+
instance_eval source
|
55
|
+
end
|
56
|
+
|
57
|
+
def run_dsl_from_proc(proc)
|
58
|
+
# puts source
|
59
|
+
instance_eval &proc
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
class GeneratedContent < Content
|
65
|
+
# Nothing special, per se...
|
66
|
+
end
|
67
|
+
|
68
|
+
module GenerationDSL
|
69
|
+
|
70
|
+
# attr_accessor :generators
|
71
|
+
# @generators=[]
|
72
|
+
|
73
|
+
def self.generate(&block)
|
74
|
+
|
75
|
+
# Auto-generated, numerical, key for a site-level generator
|
76
|
+
Gumdrop.generators[Gumdrop.generators.keys.length] = Generator.new(block)
|
77
|
+
end
|
78
|
+
|
4
79
|
end
|
5
80
|
|
6
81
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Gumdrop
|
2
|
+
class Pager
|
3
|
+
attr_reader :all, :pages, :base_url, :current_page, :page_sets
|
4
|
+
|
5
|
+
def initialize(articles, base_path="/page", page_size=5)
|
6
|
+
@all= articles
|
7
|
+
@page_size= page_size
|
8
|
+
@base_path= base_path
|
9
|
+
@page_sets= @all.in_groups_of(page_size, false)
|
10
|
+
@pages= []
|
11
|
+
@current_page=1
|
12
|
+
@page_sets.each do |art_ary|
|
13
|
+
@pages << HashObject.new({
|
14
|
+
'items' => art_ary,
|
15
|
+
'page' => @current_page,
|
16
|
+
'uri' => "#{base_path}/#{current_page}",
|
17
|
+
'pager' => self
|
18
|
+
})
|
19
|
+
@current_page += 1
|
20
|
+
end
|
21
|
+
@current_page= nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def length
|
25
|
+
@pages.length
|
26
|
+
end
|
27
|
+
|
28
|
+
def first
|
29
|
+
@pages.first
|
30
|
+
end
|
31
|
+
|
32
|
+
def last
|
33
|
+
@pages.last
|
34
|
+
end
|
35
|
+
|
36
|
+
def each
|
37
|
+
@current_page=1
|
38
|
+
@pages.each do |page_set|
|
39
|
+
yield page_set
|
40
|
+
@current_page += 1
|
41
|
+
end
|
42
|
+
@current_page= nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def [](key)
|
46
|
+
@pages[key]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/gumdrop/server.rb
CHANGED
@@ -8,26 +8,25 @@ module Gumdrop
|
|
8
8
|
|
9
9
|
set :port, Gumdrop.config.port if Gumdrop.config.port
|
10
10
|
|
11
|
-
get '/' do
|
12
|
-
|
13
|
-
end
|
14
|
-
|
11
|
+
# get '/' do
|
12
|
+
# redirect '/index.html'
|
13
|
+
# end
|
14
|
+
|
15
15
|
get '/*' do
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
content= Content.new matches[0]
|
16
|
+
|
17
|
+
Gumdrop.run :dry_run=>true if Gumdrop.config.force_reload
|
18
|
+
|
19
|
+
file_path= get_content_path params[:splat].join('/')
|
20
|
+
|
21
|
+
if Gumdrop.site.has_key? file_path
|
22
|
+
content= Gumdrop.site[file_path]
|
24
23
|
if content.useLayout?
|
25
24
|
content_type :css if content.ext == '.css' # Meh?
|
26
25
|
content_type :js if content.ext == '.js' # Meh?
|
27
26
|
content_type :xml if content.ext == '.xml' # Meh?
|
28
27
|
content.render
|
29
28
|
else
|
30
|
-
send_file
|
29
|
+
send_file "source/#{file_path}"
|
31
30
|
end
|
32
31
|
else
|
33
32
|
puts "NOT FOUND: #{file_path}"
|
@@ -35,7 +34,22 @@ module Gumdrop
|
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
37
|
+
|
38
|
+
def get_content_path(file_path)
|
39
|
+
keys= [
|
40
|
+
file_path,
|
41
|
+
"#{file_path}.html",
|
42
|
+
"#{file_path}/index.html"
|
43
|
+
]
|
44
|
+
if file_path == ""
|
45
|
+
"index.html"
|
46
|
+
else
|
47
|
+
keys.detect {|k| Gumdrop.site.has_key?(k) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
38
51
|
if Gumdrop.config.auto_run
|
52
|
+
Gumdrop.run :dry_run=>true
|
39
53
|
run!
|
40
54
|
end
|
41
55
|
|
@@ -43,6 +57,7 @@ module Gumdrop
|
|
43
57
|
# Options
|
44
58
|
opts.reverse_merge! :auto_run => true, :cache_data => false
|
45
59
|
Gumdrop.config.merge! opts
|
60
|
+
Gumdrop.run :dry_run=>true
|
46
61
|
::Gumdrop::Server
|
47
62
|
end
|
48
63
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
+
gem "i18n"
|
3
4
|
gem "sinatra"
|
4
5
|
gem "active_support"
|
5
|
-
gem "i18n"
|
6
6
|
gem "rake"
|
7
7
|
gem "gumdrop"
|
8
8
|
|
@@ -11,7 +11,12 @@ gem "gumdrop"
|
|
11
11
|
gem "sass"
|
12
12
|
gem "coffee-script"
|
13
13
|
|
14
|
+
# For markdown support, a couple of options:
|
14
15
|
# gem "rdiscount"
|
16
|
+
# gem 'maruku'
|
17
|
+
|
18
|
+
# For template support:
|
15
19
|
# gem "less"
|
16
20
|
# gem "haml"
|
17
|
-
|
21
|
+
# gem "slim"
|
22
|
+
# gem 'builder'
|
@@ -8,16 +8,11 @@ SERVER='server.com'
|
|
8
8
|
FOLDER="~/#{SERVER}"
|
9
9
|
|
10
10
|
|
11
|
-
task :default do
|
12
|
-
sh 'rake -T'
|
13
|
-
end
|
14
|
-
|
15
11
|
desc "Build source files into output"
|
16
12
|
task :build do
|
17
13
|
Gumdrop.run()
|
18
14
|
end
|
19
15
|
|
20
|
-
|
21
16
|
desc "Run development server"
|
22
17
|
task :serve do
|
23
18
|
Gumdrop.config.auto_run= true
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Any specialized code for your site goes here...
|
2
|
+
|
3
|
+
# Example site-level generator
|
4
|
+
# generate do
|
5
|
+
#
|
6
|
+
# page "about.html", :template=>'about', :passthru=>'Available in the template' # requires a about.template.XX file
|
7
|
+
#
|
8
|
+
# # Maybe for a tumblr-like pager
|
9
|
+
# pager= Gumdrop.data.pager_for :posts, :base_path=>'posts/page', :page_size=>5
|
10
|
+
# pager.each do |page|
|
11
|
+
# page "#{page.uri}.html", :template=>'post_page', :posts=>page.items, :pager=>pager, :current_page=>pager.current_page
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
xml.instruct!
|
2
|
+
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
|
3
|
+
xml.title data.config.title
|
4
|
+
xml.subtitle data.config.tagline
|
5
|
+
xml.id data.config.url
|
6
|
+
xml.link "href" => data.config.url
|
7
|
+
xml.link "href" => "#{data.config.url}/feed.xml", "rel" => "self"
|
8
|
+
xml.updated data.blog.first.date.to_time.iso8601
|
9
|
+
xml.author { xml.name data.config.author }
|
10
|
+
|
11
|
+
data.blog.each do |post|
|
12
|
+
xml.entry do
|
13
|
+
url= "#{data.config.url}/posts/#{post.slug}"
|
14
|
+
xml.title post.title
|
15
|
+
xml.link "rel" => "alternate", "href" => url
|
16
|
+
xml.id url
|
17
|
+
xml.published post.date.to_time.iso8601
|
18
|
+
xml.updated post.date.to_time.iso8601
|
19
|
+
xml.author { xml.name data.config.author }
|
20
|
+
xml.content post.body, "type" => "html"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/gumdrop/version.rb
CHANGED
data/lib/gumdrop/view_helpers.rb
CHANGED
@@ -2,10 +2,15 @@ module Gumdrop
|
|
2
2
|
|
3
3
|
module ViewHelpers
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def hidden(&block)
|
6
|
+
#no-op
|
7
|
+
end
|
8
|
+
|
9
|
+
def markdown(source)
|
10
|
+
m= Tilt['markdown'].new { source }
|
11
|
+
m.render
|
12
|
+
end
|
13
|
+
|
9
14
|
|
10
15
|
def gumdrop_version
|
11
16
|
::Gumdrop::VERSION
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gumdrop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2011-07-22 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sinatra
|
16
|
-
requirement: &
|
16
|
+
requirement: &70267787964340 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70267787964340
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: tilt
|
27
|
-
requirement: &
|
27
|
+
requirement: &70267787963900 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70267787963900
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: active_support
|
38
|
-
requirement: &
|
38
|
+
requirement: &70267787963400 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70267787963400
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: trollop
|
49
|
-
requirement: &
|
49
|
+
requirement: &70267787962920 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70267787962920
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: haml
|
60
|
-
requirement: &
|
60
|
+
requirement: &70267787962460 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70267787962460
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: sass
|
71
|
-
requirement: &
|
71
|
+
requirement: &70267787962000 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70267787962000
|
80
80
|
description: A simple cms/prototyping tool.
|
81
81
|
email: matt@elucidata.net
|
82
82
|
executables:
|
@@ -96,28 +96,43 @@ files:
|
|
96
96
|
- examples/simple/Rakefile
|
97
97
|
- examples/simple/config.ru
|
98
98
|
- examples/simple/data/config.yml
|
99
|
+
- examples/simple/data/posts.yamldb
|
100
|
+
- examples/simple/lib/site.rb
|
99
101
|
- examples/simple/lib/view_helpers.rb
|
102
|
+
- examples/simple/source/.htaccess
|
103
|
+
- examples/simple/source/_pager_control.html.erb
|
104
|
+
- examples/simple/source/_sidebar.html.haml
|
100
105
|
- examples/simple/source/favicon.ico
|
106
|
+
- examples/simple/source/feed.xml.builder
|
101
107
|
- examples/simple/source/index.html.erb
|
108
|
+
- examples/simple/source/posts.generator.rb
|
109
|
+
- examples/simple/source/posts/index.html.erb
|
102
110
|
- examples/simple/source/theme/screen.css.scss
|
103
111
|
- examples/simple/source/theme/scripts/app.js.coffee
|
104
112
|
- examples/simple/source/theme/styles/_tools.scss
|
113
|
+
- examples/simple/source/theme/templates/post.template.haml
|
114
|
+
- examples/simple/source/theme/templates/post_page.template.haml
|
105
115
|
- examples/simple/source/theme/templates/site.template.haml
|
116
|
+
- examples/simple/source/theme/templates/test.template.erb
|
106
117
|
- gumdrop.gemspec
|
107
118
|
- lib/gumdrop.rb
|
108
119
|
- lib/gumdrop/cli.rb
|
109
120
|
- lib/gumdrop/content.rb
|
110
121
|
- lib/gumdrop/context.rb
|
122
|
+
- lib/gumdrop/deferred_loader.rb
|
111
123
|
- lib/gumdrop/generator.rb
|
112
124
|
- lib/gumdrop/hash_object.rb
|
125
|
+
- lib/gumdrop/pager.rb
|
113
126
|
- lib/gumdrop/server.rb
|
114
127
|
- lib/gumdrop/template/.htaccess
|
115
128
|
- lib/gumdrop/template/Gemfile
|
116
129
|
- lib/gumdrop/template/Rakefile
|
117
130
|
- lib/gumdrop/template/config.ru
|
118
131
|
- lib/gumdrop/template/data/config.yml
|
132
|
+
- lib/gumdrop/template/lib/site.rb
|
119
133
|
- lib/gumdrop/template/lib/view_helpers.rb
|
120
134
|
- lib/gumdrop/template/source/favicon.ico
|
135
|
+
- lib/gumdrop/template/source/feed.xml.builder.txt
|
121
136
|
- lib/gumdrop/template/source/index.html.erb
|
122
137
|
- lib/gumdrop/template/source/theme/screen.css.scss
|
123
138
|
- lib/gumdrop/template/source/theme/scripts/app.js.coffee
|