gumdrop 0.2.4 → 0.2.7
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/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
|