edison 0.0.1
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.md +0 -0
- data/bin/edison +262 -0
- metadata +135 -0
data/README.md
ADDED
File without changes
|
data/bin/edison
ADDED
@@ -0,0 +1,262 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'listen'
|
5
|
+
require 'kramdown'
|
6
|
+
require 'hashie'
|
7
|
+
require 'mustache'
|
8
|
+
require 'pp'
|
9
|
+
require 'webrick'
|
10
|
+
require 'yaml'
|
11
|
+
|
12
|
+
module Edison
|
13
|
+
end
|
14
|
+
|
15
|
+
module Edison::YAMLFrontMatter
|
16
|
+
def self.read(fname)
|
17
|
+
contents = File.read(fname).strip
|
18
|
+
if contents =~ /\A---/
|
19
|
+
_, yaml, body = contents.split("---", 3)
|
20
|
+
yaml = YAML.load(yaml)
|
21
|
+
body ||= ""
|
22
|
+
body.strip!
|
23
|
+
if yaml.include? "body"
|
24
|
+
raise Exception, "YAML Front Matter can't contain a 'body' key. Put it after the front matter."
|
25
|
+
end
|
26
|
+
{"body" => body}.merge(yaml)
|
27
|
+
else
|
28
|
+
{"body" => contents}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Edison::ModelsLoader
|
34
|
+
def load(directory)
|
35
|
+
klasses = Dir[File.join(directory, "*")].map &File.method(:basename)
|
36
|
+
hash = Hashie::Mash.new
|
37
|
+
klasses.each do |klass|
|
38
|
+
objects = Dir[File.join(directory, klass, "*")]
|
39
|
+
objects.map! do |fname|
|
40
|
+
puts "Loading model #{File.join(klass, File.basename(fname))}..."
|
41
|
+
|
42
|
+
data = Hashie::Mash.new(case File.extname(fname)
|
43
|
+
when /(html)|(md)$/
|
44
|
+
Edison::YAMLFrontMatter.read(fname)
|
45
|
+
when /ya?ml$/
|
46
|
+
YAML.load_file(fname)
|
47
|
+
else
|
48
|
+
{}
|
49
|
+
end)
|
50
|
+
|
51
|
+
if data._ext
|
52
|
+
raise Exception, "Restricted key '_ext' appears in model!"
|
53
|
+
end
|
54
|
+
data._ext = File.extname(fname)
|
55
|
+
|
56
|
+
if data._ext == ".md"
|
57
|
+
data.body = Kramdown::Document.new(data.body).to_html
|
58
|
+
end
|
59
|
+
|
60
|
+
if data._fname
|
61
|
+
raise Exception, "Restricted key '_fname' appears in model!"
|
62
|
+
end
|
63
|
+
data._fname = File.basename(fname).sub(/#{File.extname(fname)}$/,'')
|
64
|
+
|
65
|
+
data
|
66
|
+
end
|
67
|
+
hash[klass] = objects
|
68
|
+
end
|
69
|
+
hash
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Edison::Renderer
|
74
|
+
attr_accessor :templates
|
75
|
+
def initialize(templates)
|
76
|
+
self.templates = templates
|
77
|
+
end
|
78
|
+
def render(template_name, data)
|
79
|
+
template = self.templates[template_name]
|
80
|
+
if template.nil?
|
81
|
+
raise Exception, "Called for template #{template_name}, but _templates/#{template_name} does not exist"
|
82
|
+
end
|
83
|
+
body = Mustache.render(template.body, data)
|
84
|
+
if template.layout
|
85
|
+
newdata = data.merge("yield" => body)
|
86
|
+
self.render(template.layout, newdata)
|
87
|
+
else
|
88
|
+
body
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class Edison::Router
|
94
|
+
attr_reader :urls, :static
|
95
|
+
def initialize
|
96
|
+
@urls = []
|
97
|
+
@static = []
|
98
|
+
end
|
99
|
+
def url(url, template=nil, data={}, &b)
|
100
|
+
if b and template and data
|
101
|
+
raise Exception, "Please pass data or block, not both!"
|
102
|
+
end
|
103
|
+
if b
|
104
|
+
b.call(@urls.find { |(url, _, _)| url == url}[2])
|
105
|
+
else
|
106
|
+
@urls << [url, template, Hashie::Mash.new(data)]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
def copy(url)
|
110
|
+
@static << url
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
module Edison
|
115
|
+
class <<self
|
116
|
+
attr_reader :models, :routes, :renderer
|
117
|
+
end
|
118
|
+
def self.initialize!(directory)
|
119
|
+
@directory = directory
|
120
|
+
|
121
|
+
@routes = Router.new
|
122
|
+
|
123
|
+
loader = ModelsLoader.new
|
124
|
+
@models = loader.load(File.join(directory, "_models"))
|
125
|
+
|
126
|
+
templates = Hash[Dir[File.join(directory, "_templates", "*")].map do |fname|
|
127
|
+
puts "Loading template _templates/#{File.basename(fname)}..."
|
128
|
+
name = File.basename(fname).sub(/\.[^\.]+$/,'')
|
129
|
+
data = Hashie::Mash.new Edison::YAMLFrontMatter.read(fname)
|
130
|
+
[name, data]
|
131
|
+
end]
|
132
|
+
|
133
|
+
static = Dir[File.join(directory, "**/*")]
|
134
|
+
blacklist = ["Gemfile", "Gemfile.lock", "config.rb", "gen.rb", "serve.rb"]
|
135
|
+
static.reject! do |fname|
|
136
|
+
name = fname.sub(/^#{directory}\//,'')
|
137
|
+
dirname = File.dirname(fname)
|
138
|
+
blacklist.include?(name) or name =~ /^_/ or File.directory?(fname)
|
139
|
+
end
|
140
|
+
static.each do |fname|
|
141
|
+
name = fname.sub(/^#{directory}\//,'')
|
142
|
+
if %w{.html .md}.include?(File.extname(fname))
|
143
|
+
data = Hashie::Mash.new Edison::YAMLFrontMatter.read(fname)
|
144
|
+
url = name.sub(/\.md$/,'')
|
145
|
+
templates[url] = data
|
146
|
+
@routes.url url, url, data
|
147
|
+
else
|
148
|
+
@routes.copy name
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
@renderer = Renderer.new(templates)
|
153
|
+
end
|
154
|
+
def self.config(&b)
|
155
|
+
instance_eval &b
|
156
|
+
end
|
157
|
+
def self.generate!
|
158
|
+
site = File.join(@directory, "_site")
|
159
|
+
|
160
|
+
FileUtils.rm_rf(site)
|
161
|
+
Dir.mkdir(site)
|
162
|
+
puts "Copying static files..."
|
163
|
+
routes.static.each do |name|
|
164
|
+
src = File.join(@directory, name)
|
165
|
+
dest = File.join(site, name)
|
166
|
+
FileUtils.mkdir_p File.dirname(dest)
|
167
|
+
FileUtils.copy src, dest
|
168
|
+
end
|
169
|
+
routes.urls.each do |(url, template_name, data)|
|
170
|
+
puts "Creating /#{url}..."
|
171
|
+
|
172
|
+
fname = File.join(site, url)
|
173
|
+
FileUtils.mkdir_p(File.dirname(fname))
|
174
|
+
File.open(fname, "w") do |f|
|
175
|
+
f.write @renderer.render(template_name, data)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
module Edison::Helpers
|
182
|
+
def self.date_from_filename(data)
|
183
|
+
if data.date
|
184
|
+
raise Exception, "Date will be inferred from filename, but found in data"
|
185
|
+
end
|
186
|
+
|
187
|
+
if File.basename(data._fname) =~ /^(\d{4}-\d{1,2}-\d{1,2})/
|
188
|
+
data.date = Date.parse($1)
|
189
|
+
else
|
190
|
+
raise Exception, "Expected filename to start with date (YYYY-M?M-D?D)"
|
191
|
+
end
|
192
|
+
|
193
|
+
data
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.default_layout(data)
|
197
|
+
unless data.layout
|
198
|
+
data.layout = "default"
|
199
|
+
end
|
200
|
+
|
201
|
+
data
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def build
|
206
|
+
directory = Dir.pwd
|
207
|
+
puts "Running in #{directory}..."
|
208
|
+
Edison.initialize!(directory)
|
209
|
+
load File.join(directory, "config.rb")
|
210
|
+
site = File.join(directory, "_site")
|
211
|
+
Edison.generate!
|
212
|
+
puts "Done!"
|
213
|
+
end
|
214
|
+
|
215
|
+
require 'commander/import'
|
216
|
+
|
217
|
+
program :name, "Edison"
|
218
|
+
program :version, "0.0.1"
|
219
|
+
program :description, "Static website generator"
|
220
|
+
|
221
|
+
default_command :help
|
222
|
+
|
223
|
+
command :up do |c|
|
224
|
+
c.description = "Build static files"
|
225
|
+
c.action do |args, options|
|
226
|
+
build
|
227
|
+
end
|
228
|
+
end
|
229
|
+
command :serve do |c|
|
230
|
+
c.description = "Auto-generating webserver"
|
231
|
+
c.action do |args, options|
|
232
|
+
directory = Dir.pwd
|
233
|
+
|
234
|
+
begin
|
235
|
+
build
|
236
|
+
rescue => e
|
237
|
+
pp e
|
238
|
+
end
|
239
|
+
|
240
|
+
listener = Listen.to(directory, :ignore => /^_site\//)
|
241
|
+
server = WEBrick::HTTPServer.new(
|
242
|
+
:Port => 4000,
|
243
|
+
:DocumentRoot => File.expand_path("_site", directory)
|
244
|
+
)
|
245
|
+
listener.change do |*args|
|
246
|
+
t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
|
247
|
+
puts "Regenerating at #{t}"
|
248
|
+
begin
|
249
|
+
build
|
250
|
+
rescue => e
|
251
|
+
pp e
|
252
|
+
end
|
253
|
+
end
|
254
|
+
listener.start(false)
|
255
|
+
|
256
|
+
Signal.trap("INT") do
|
257
|
+
server.shutdown
|
258
|
+
listener.stop
|
259
|
+
end
|
260
|
+
server.start
|
261
|
+
end
|
262
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: edison
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Michael Maltese
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2013-03-17 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: commander
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: listen
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: hashie
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :runtime
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: kramdown
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
type: :runtime
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: mustache
|
78
|
+
prerelease: false
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
type: :runtime
|
89
|
+
version_requirements: *id005
|
90
|
+
description: ""
|
91
|
+
email: michael.maltese@pomona.edu
|
92
|
+
executables:
|
93
|
+
- edison
|
94
|
+
extensions: []
|
95
|
+
|
96
|
+
extra_rdoc_files: []
|
97
|
+
|
98
|
+
files:
|
99
|
+
- bin/edison
|
100
|
+
- README.md
|
101
|
+
homepage: http://github.com/michaelmaltese/jefe
|
102
|
+
licenses: []
|
103
|
+
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
|
107
|
+
require_paths:
|
108
|
+
- - lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
hash: 3
|
115
|
+
segments:
|
116
|
+
- 0
|
117
|
+
version: "0"
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
hash: 3
|
124
|
+
segments:
|
125
|
+
- 0
|
126
|
+
version: "0"
|
127
|
+
requirements: []
|
128
|
+
|
129
|
+
rubyforge_project:
|
130
|
+
rubygems_version: 1.8.24
|
131
|
+
signing_key:
|
132
|
+
specification_version: 3
|
133
|
+
summary: A static (website) generator.
|
134
|
+
test_files: []
|
135
|
+
|