plate 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -0
- data/LICENSE +21 -0
- data/README.md +92 -0
- data/Rakefile +27 -0
- data/bin/plate +4 -0
- data/lib/plate.rb +56 -0
- data/lib/plate/asset.rb +47 -0
- data/lib/plate/builder.rb +375 -0
- data/lib/plate/callbacks.rb +39 -0
- data/lib/plate/cli.rb +203 -0
- data/lib/plate/dynamic_page.rb +27 -0
- data/lib/plate/engine.rb +25 -0
- data/lib/plate/errors.rb +10 -0
- data/lib/plate/haml_template.rb +18 -0
- data/lib/plate/helpers/blogging_helper.rb +102 -0
- data/lib/plate/helpers/meta_helper.rb +71 -0
- data/lib/plate/helpers/url_helper.rb +11 -0
- data/lib/plate/layout.rb +169 -0
- data/lib/plate/markdown_template.rb +22 -0
- data/lib/plate/page.rb +280 -0
- data/lib/plate/post.rb +134 -0
- data/lib/plate/post_collection.rb +116 -0
- data/lib/plate/sass_template.rb +40 -0
- data/lib/plate/scss_template.rb +9 -0
- data/lib/plate/site.rb +249 -0
- data/lib/plate/static_page.rb +37 -0
- data/lib/plate/version.rb +3 -0
- data/lib/plate/view.rb +48 -0
- data/lib/templates/config.yml +1 -0
- data/lib/templates/index.md +6 -0
- data/lib/templates/layout.erb +12 -0
- metadata +143 -0
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2012 John D. Tornow
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# Plate
|
2
|
+
|
3
|
+
Plate is a super simple static site generator and blog engine. It takes a folder full of Markdown files and turns it into a site that you can host anywhere. The output is a plain old static HTML site. In addition to basic formatting with Markdown, Plate also supports generating asset files with CoffeeScript, Sass and others.
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
* Ruby 1.8.7, 1.9.2 or 1.9.3
|
8
|
+
* Bundler
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
gem install plate
|
13
|
+
|
14
|
+
Or, create a `Gemfile` and add:
|
15
|
+
|
16
|
+
gem 'plate'
|
17
|
+
|
18
|
+
## Set up
|
19
|
+
|
20
|
+
To generate a new site with plate, run the following command:
|
21
|
+
|
22
|
+
plate new site-name/
|
23
|
+
|
24
|
+
## Building a site
|
25
|
+
|
26
|
+
To build your site, run:
|
27
|
+
|
28
|
+
plate build
|
29
|
+
|
30
|
+
Or, just run:
|
31
|
+
|
32
|
+
plate
|
33
|
+
|
34
|
+
## Directory Structure
|
35
|
+
|
36
|
+
Plate observes the following folder structure in your site:
|
37
|
+
|
38
|
+
* config/ - Put your global configuration settings here.
|
39
|
+
* content/ - All custom content for the site, besides blog posts. Everything in this folder will be copied over to the published site.
|
40
|
+
* layouts/ - Global layouts available for use on all content pages and posts.
|
41
|
+
* lib/ - Extend the basic functionality of Plate with plugins in this directory. All `.rb` files will be loaded automatically.
|
42
|
+
* posts/ - All blog post content for the site. Posts can be organized into sub-directories if you like.
|
43
|
+
* public/ - This will be generated if it does not exist, contains the produced site. Set this as the web server root to your site for development mode.
|
44
|
+
|
45
|
+
## Extending Plate
|
46
|
+
|
47
|
+
Plate is meant to be extended easily. You might want to extend the basic functionality of Plate to add additional functionality for your site. To get started, create a directory named `lib` in the root of your site. Any Ruby files (ending in `.rb`) will be automatically loaded into the stack when Plate is run.
|
48
|
+
|
49
|
+
### Callbacks
|
50
|
+
|
51
|
+
Callbacks are used to call certain blocks of code when an event happens in the lifecycle of building a site.
|
52
|
+
|
53
|
+
The callbacks currently available are:
|
54
|
+
|
55
|
+
* Site - `before_render`, `after_render`
|
56
|
+
* Page/Post - `before_render`, `after_render`
|
57
|
+
|
58
|
+
Example of a callback to be run when a site completes the build:
|
59
|
+
|
60
|
+
Plate::Site.register_callback :after_render do |site|
|
61
|
+
puts "the site finished rendering!"
|
62
|
+
end
|
63
|
+
|
64
|
+
### Helpers
|
65
|
+
|
66
|
+
Helpers are modules that are automatically loaded into views. Any methods in the module will be available when you render a page.
|
67
|
+
|
68
|
+
An example of a helper file located in `lib/sample_helper.rb`
|
69
|
+
|
70
|
+
module SampleHelper
|
71
|
+
def sample_helper_method
|
72
|
+
"yes"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
Then, in your `.erb` view you can call `sample_helper_method`.
|
77
|
+
|
78
|
+
## Issues
|
79
|
+
|
80
|
+
If you have any issues or find bugs running Plate, please [report them on Github](https://github.com/jdtornow/plate/issues). While most functions should be stable, Plate is still in its infancy and certain issues may be present.
|
81
|
+
|
82
|
+
## Testing
|
83
|
+
|
84
|
+
Plate is fully tested using Test Unit, Shoulda and Mocha. To run the test suite, `bundle install` then run:
|
85
|
+
|
86
|
+
rake test
|
87
|
+
|
88
|
+
## License
|
89
|
+
|
90
|
+
Challah is released under the [MIT license](http://www.opensource.org/licenses/MIT)
|
91
|
+
|
92
|
+
Contributions and pull-requests are more than welcome.
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'yard'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), *%w(lib)))
|
6
|
+
|
7
|
+
task :default => [ :test ]
|
8
|
+
|
9
|
+
require 'rake/testtask'
|
10
|
+
|
11
|
+
Rake::TestTask.new(:test) do |test|
|
12
|
+
test.libs << 'lib' << 'test'
|
13
|
+
test.pattern = 'test/**/test_*.rb'
|
14
|
+
test.verbose = true
|
15
|
+
end
|
16
|
+
|
17
|
+
namespace :test do
|
18
|
+
desc "Build the sample site and leave its contents in test/sample/public"
|
19
|
+
task :sample do
|
20
|
+
sh %q(ruby -I"lib:test" test/test_builder.rb -n /sample/)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
YARD::Rake::YardocTask.new do |t|
|
25
|
+
end
|
26
|
+
|
27
|
+
task :doc => :yard
|
data/bin/plate
ADDED
data/lib/plate.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pathname'
|
4
|
+
require 'active_support/core_ext/hash'
|
5
|
+
require 'directory_watcher'
|
6
|
+
require 'tilt'
|
7
|
+
|
8
|
+
require 'plate/version'
|
9
|
+
require 'plate/errors'
|
10
|
+
|
11
|
+
module Plate
|
12
|
+
autoload :CLI, 'plate/cli'
|
13
|
+
|
14
|
+
autoload :Builder, 'plate/builder'
|
15
|
+
autoload :Callbacks, 'plate/callbacks'
|
16
|
+
autoload :Layout, 'plate/layout'
|
17
|
+
autoload :Site, 'plate/site'
|
18
|
+
|
19
|
+
autoload :BloggingHelper, 'plate/helpers/blogging_helper'
|
20
|
+
autoload :MetaHelper, 'plate/helpers/meta_helper'
|
21
|
+
autoload :URLHelper, 'plate/helpers/url_helper'
|
22
|
+
|
23
|
+
autoload :View, 'plate/view'
|
24
|
+
|
25
|
+
autoload :PostCollection, 'plate/post_collection'
|
26
|
+
|
27
|
+
autoload :Asset, 'plate/asset'
|
28
|
+
autoload :DynamicPage, 'plate/dynamic_page'
|
29
|
+
autoload :Page, 'plate/page'
|
30
|
+
autoload :Post, 'plate/post'
|
31
|
+
autoload :StaticPage, 'plate/static_page'
|
32
|
+
|
33
|
+
autoload :Engine, 'plate/engine'
|
34
|
+
autoload :HamlTemplate, 'plate/haml_template'
|
35
|
+
autoload :MarkdownTemplate, 'plate/markdown_template'
|
36
|
+
autoload :SassTemplate, 'plate/sass_template'
|
37
|
+
autoload :ScssTemplate, 'plate/scss_template'
|
38
|
+
|
39
|
+
extend Engine
|
40
|
+
@engines ||= {}
|
41
|
+
|
42
|
+
# Set up the basic engines that are supported by Plate. Add your own this same way.
|
43
|
+
# Thanks to sprockets for the inspiration.
|
44
|
+
# https://github.com/sstephenson/sprockets
|
45
|
+
|
46
|
+
# Assets
|
47
|
+
register_asset_engine :coffee, Tilt::CoffeeScriptTemplate
|
48
|
+
register_asset_engine :sass, SassTemplate
|
49
|
+
register_asset_engine :scss, ScssTemplate
|
50
|
+
|
51
|
+
# Layouts & Markup
|
52
|
+
register_template_engine :erb, Tilt::ERBTemplate
|
53
|
+
register_template_engine :haml, HamlTemplate
|
54
|
+
register_template_engine :md, MarkdownTemplate
|
55
|
+
register_template_engine :markdown, MarkdownTemplate
|
56
|
+
end
|
data/lib/plate/asset.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module Plate
|
2
|
+
# An asset is a CoffeeScript or Sass file that needs to be compiled before writing
|
3
|
+
# to the destination.
|
4
|
+
class Asset < Page
|
5
|
+
def engines
|
6
|
+
@engines ||= self.extensions.reverse.collect { |e| self.site.registered_asset_engines[e.gsub(/\./, '').to_sym] }.reject { |e| !e }
|
7
|
+
end
|
8
|
+
|
9
|
+
def extensions
|
10
|
+
@extensions ||= self.basename.scan(/\.[^.]+/)
|
11
|
+
end
|
12
|
+
|
13
|
+
def format_extension
|
14
|
+
self.extensions.reverse.detect { |e| !self.site.asset_engine_extensions.include?(e) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def file_path
|
18
|
+
"#{directory}/#{file_name}"
|
19
|
+
end
|
20
|
+
|
21
|
+
# Same as page, but no layout applied
|
22
|
+
def rendered_content
|
23
|
+
return @rendered_content if @rendered_content
|
24
|
+
|
25
|
+
result = File.read(file)
|
26
|
+
|
27
|
+
self.engines.each do |engine|
|
28
|
+
template = engine.new() { result }
|
29
|
+
result = template.render(self, :site => self.site)
|
30
|
+
end
|
31
|
+
|
32
|
+
@rendered_content = result
|
33
|
+
end
|
34
|
+
|
35
|
+
# Write this page to the destination. For static files this just results
|
36
|
+
# in copying the file over to the destination
|
37
|
+
def write!
|
38
|
+
path = File.join(site.build_destination, file_path)
|
39
|
+
|
40
|
+
FileUtils.mkdir_p(File.dirname(path))
|
41
|
+
|
42
|
+
File.open(path, 'w') do |f|
|
43
|
+
f.write(self.rendered_content)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,375 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'digest'
|
3
|
+
|
4
|
+
module Plate
|
5
|
+
# Used by the command line tool to generate a site in the given directory.
|
6
|
+
class Builder
|
7
|
+
attr_accessor :source, :destination, :options, :site, :enable_logging, :helpers
|
8
|
+
|
9
|
+
def initialize(source, destination, options = {})
|
10
|
+
@source = source
|
11
|
+
@destination = destination
|
12
|
+
@options = Hash === options ? options.clone : {}
|
13
|
+
@options.symbolize_keys!
|
14
|
+
end
|
15
|
+
|
16
|
+
def cache_location
|
17
|
+
return @cache_location if @cache_location
|
18
|
+
|
19
|
+
if self.options.has_key?(:cache_location)
|
20
|
+
@cache_location ||= File.expand_path(self.options[:cache_location])
|
21
|
+
else
|
22
|
+
@cache_location ||= File.expand_path("~/.plate/#{self.id}")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Remove any caches from this site build, also resets any variables for the caching and
|
27
|
+
# temporary build folders so they can be reset
|
28
|
+
def clear_cache!
|
29
|
+
FileUtils.rm_rf(cache_location)
|
30
|
+
|
31
|
+
@cache_location = nil
|
32
|
+
@tmp_destination = nil
|
33
|
+
@loaded = false
|
34
|
+
end
|
35
|
+
|
36
|
+
# A unique id for this site, based off of the source directory
|
37
|
+
def id
|
38
|
+
check_source!
|
39
|
+
|
40
|
+
@id ||= [ File.basename(source), Digest::MD5.hexdigest(source) ].collect { |s| s.to_s.downcase.parameterize }.join('-')
|
41
|
+
end
|
42
|
+
|
43
|
+
def items?
|
44
|
+
self.total_items > 0
|
45
|
+
end
|
46
|
+
|
47
|
+
def load!
|
48
|
+
unless @loaded
|
49
|
+
log('Site builder initialized.')
|
50
|
+
|
51
|
+
self.require_plugins!
|
52
|
+
self.load_config_file!
|
53
|
+
self.setup_site!
|
54
|
+
self.setup_tmp_directory!
|
55
|
+
|
56
|
+
@loaded = true
|
57
|
+
end
|
58
|
+
|
59
|
+
@loaded
|
60
|
+
end
|
61
|
+
|
62
|
+
def relative_path(file_or_directory)
|
63
|
+
file_or_directory.gsub(/^#{Regexp.quote(source)}(.*)$/, '\1')
|
64
|
+
end
|
65
|
+
|
66
|
+
def rebuild!
|
67
|
+
log('Re-rendering site...')
|
68
|
+
|
69
|
+
clear_cache!
|
70
|
+
|
71
|
+
self.site.reload!
|
72
|
+
self.render_site!
|
73
|
+
self.copy_to_destination!
|
74
|
+
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
# When watching a directory for changes, allow reloading of site content based on modifications
|
79
|
+
# only in the content, layouts and posts folder. Changes to config or lib files will need to
|
80
|
+
# be reloaded manually.
|
81
|
+
def reloadable?(relative_file)
|
82
|
+
relative_file =~ /^\/?(content|layouts|posts)\/(.*?)/
|
83
|
+
end
|
84
|
+
|
85
|
+
# Called to start the rendering of the site based on the provided, source, destination and config options.
|
86
|
+
def render!
|
87
|
+
@start_time = Time.now
|
88
|
+
|
89
|
+
log("Building full site...")
|
90
|
+
|
91
|
+
self.load!
|
92
|
+
self.render_site!
|
93
|
+
self.copy_to_destination!
|
94
|
+
|
95
|
+
@end_time = Time.now
|
96
|
+
|
97
|
+
log("Site build completed in #{timer} seconds")
|
98
|
+
|
99
|
+
true
|
100
|
+
end
|
101
|
+
|
102
|
+
def render_file!(relative_file_path)
|
103
|
+
self.load!
|
104
|
+
|
105
|
+
page = self.site.find(relative_file_path)
|
106
|
+
|
107
|
+
if page and page.file?
|
108
|
+
# if the file is a layout, rebuild all pages using it
|
109
|
+
if Layout === page
|
110
|
+
page.reload!
|
111
|
+
|
112
|
+
log("Building layout [#{page.relative_file}]")
|
113
|
+
|
114
|
+
self.site.find_by_layout(page.relative_file).each do |layout_page|
|
115
|
+
self.render_file!(layout_page.relative_file)
|
116
|
+
end
|
117
|
+
else
|
118
|
+
log("Building file [#{page.relative_file}]")
|
119
|
+
|
120
|
+
# Remove tmp file
|
121
|
+
existing_tmp = File.join(tmp_destination, page.file_path)
|
122
|
+
|
123
|
+
if File.exists?(existing_tmp)
|
124
|
+
FileUtils.rm_rf(existing_tmp)
|
125
|
+
end
|
126
|
+
|
127
|
+
page.reload!
|
128
|
+
page.write!
|
129
|
+
|
130
|
+
# File should exist again, even though we just removed it since we re-wrote it.
|
131
|
+
if File.exists?(existing_tmp)
|
132
|
+
existing = File.join(destination, page.file_path)
|
133
|
+
|
134
|
+
if File.exists?(existing)
|
135
|
+
log("Removing existing file [#{existing}]", :indent)
|
136
|
+
FileUtils.rm_rf(existing)
|
137
|
+
end
|
138
|
+
|
139
|
+
FileUtils.mkdir_p(File.dirname(existing))
|
140
|
+
FileUtils.cp(existing_tmp, existing)
|
141
|
+
|
142
|
+
log("File build complete.", :indent)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
else
|
146
|
+
log("Cannot render file, it doesn't exist. [#{relative_file_path}]")
|
147
|
+
end
|
148
|
+
|
149
|
+
true
|
150
|
+
end
|
151
|
+
|
152
|
+
# Total number of all assets, posts and pages.
|
153
|
+
def total_items
|
154
|
+
return 0 unless self.site
|
155
|
+
@total_items ||= self.site.all_files.size
|
156
|
+
end
|
157
|
+
|
158
|
+
# Returns the time it took to run render! (in milliseconds)
|
159
|
+
def timer
|
160
|
+
return 0 unless @end_time and @start_time
|
161
|
+
((@end_time - @start_time)).round(2)
|
162
|
+
end
|
163
|
+
|
164
|
+
# The directory path of where to put the files while the site is being built.
|
165
|
+
#
|
166
|
+
# If this value is nil, no temporary directory is used and files are built
|
167
|
+
# directly in the normal destination folder.
|
168
|
+
def tmp_destination
|
169
|
+
return @tmp_destination if @tmp_destination
|
170
|
+
|
171
|
+
result = ""
|
172
|
+
|
173
|
+
if self.options.has_key?(:tmp_destination)
|
174
|
+
if self.options[:tmp_destination]
|
175
|
+
result = File.expand_path(self.options[:tmp_destination])
|
176
|
+
end
|
177
|
+
else
|
178
|
+
result = File.join(cache_location, 'build-cache')
|
179
|
+
end
|
180
|
+
|
181
|
+
@tmp_destination = result
|
182
|
+
end
|
183
|
+
|
184
|
+
def tmp_destination?
|
185
|
+
self.tmp_destination.to_s.size > 0
|
186
|
+
end
|
187
|
+
|
188
|
+
protected
|
189
|
+
# Allows process to continue if the source directory exists. If the source directory does not
|
190
|
+
# exist, raise a source does not exist error.
|
191
|
+
def check_source!
|
192
|
+
raise SourceNotFound unless directory_exists?(source)
|
193
|
+
end
|
194
|
+
|
195
|
+
# Copy all files from within the tmp/ build directory into the actual destination.
|
196
|
+
#
|
197
|
+
# Warning: This will overwrite any files already in the destination.
|
198
|
+
def copy_to_destination!
|
199
|
+
if items?
|
200
|
+
self.setup_destination!
|
201
|
+
|
202
|
+
if tmp_destination?
|
203
|
+
log("Copying content to destination directory")
|
204
|
+
FileUtils.cp_r(Dir.glob("#{tmp_destination}**/*"), destination)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# Utility method for switching between ruby 1.8* and 1.9+
|
210
|
+
def directory_exists?(dir)
|
211
|
+
Dir.respond_to?(:exists?) ? Dir.exists?(dir) : File.directory?(dir)
|
212
|
+
end
|
213
|
+
|
214
|
+
# Loads the configuration options to use for rendering this site. By default, this information
|
215
|
+
# is loaded from a file located in config/plate.yml. If this file does not exist, no config
|
216
|
+
# data is loaded by default.
|
217
|
+
#
|
218
|
+
# You can specific additional options by passing them into the options block of this class:
|
219
|
+
#
|
220
|
+
# ## Custom Config File
|
221
|
+
#
|
222
|
+
# To load a different file, pass in the relative path of that file to the source root into the :config
|
223
|
+
# option:
|
224
|
+
#
|
225
|
+
# Builder.new(source, destination, :config => 'config/other-file.yml')
|
226
|
+
def load_config_file!
|
227
|
+
config_file = 'config/plate.yml'
|
228
|
+
|
229
|
+
# Check for provided config options
|
230
|
+
if options.has_key?(:config)
|
231
|
+
# If config is false, just return without loading anything.
|
232
|
+
if options[:config] == false
|
233
|
+
log("Skipping config file load.")
|
234
|
+
config_file = false
|
235
|
+
# If something is provided for config set the config_file
|
236
|
+
else
|
237
|
+
config_file = options[:config]
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
if config_file
|
242
|
+
config_file_path = File.join(self.source, config_file)
|
243
|
+
|
244
|
+
log("Checking for config file... [#{config_file_path}]")
|
245
|
+
|
246
|
+
# If the file doesn't exist, just ignore it. If the file exists, load and parse it.
|
247
|
+
if File.exists?(config_file_path)
|
248
|
+
yml = YAML.load_file(config_file_path)
|
249
|
+
|
250
|
+
if yml
|
251
|
+
yml.symbolize_keys!
|
252
|
+
@options = @options.reverse_merge(yml)
|
253
|
+
log("Options loaded from file", :indent)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
# Make sure that the defaults are available.
|
259
|
+
@options.reverse_merge!({
|
260
|
+
:permalink => '/:category/:year/:month/:slug'
|
261
|
+
})
|
262
|
+
end
|
263
|
+
|
264
|
+
# Write to the log if enable_logging is enabled
|
265
|
+
def log(message, style = :arrow)
|
266
|
+
prefix = {
|
267
|
+
:arrow => ' -> ',
|
268
|
+
:indent => ' '
|
269
|
+
}[style] || style
|
270
|
+
|
271
|
+
puts "#{prefix}#{message}" if !!enable_logging
|
272
|
+
end
|
273
|
+
|
274
|
+
# Build out the site and store it in the destination directory
|
275
|
+
def render_site!
|
276
|
+
if items?
|
277
|
+
log("Rendering site...")
|
278
|
+
|
279
|
+
paths = []
|
280
|
+
|
281
|
+
self.site.run_callback(:before_render)
|
282
|
+
|
283
|
+
paths += self.site.assets.collect(&:write!)
|
284
|
+
paths += self.site.pages.collect(&:write!)
|
285
|
+
paths += self.site.posts.collect(&:write!)
|
286
|
+
|
287
|
+
@build_paths = paths
|
288
|
+
|
289
|
+
self.site.run_callback(:after_render)
|
290
|
+
|
291
|
+
log("Site rendered!", :indent)
|
292
|
+
else
|
293
|
+
log("No assets, posts or pages found. :(")
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
# Load any plugins and helpers in the ./lib folder. Any modules named with the
|
298
|
+
# format SomethingHelper will automatically be loaded into all views.
|
299
|
+
def require_plugins!
|
300
|
+
self.helpers = []
|
301
|
+
|
302
|
+
matcher = /^#{Regexp.quote(File.join(source, 'lib'))}\/?(.*).rb$/
|
303
|
+
|
304
|
+
plugins = Dir.glob(File.join(source, "lib/**/*.rb"))
|
305
|
+
|
306
|
+
if plugins.length > 0
|
307
|
+
log("Loading plugins...")
|
308
|
+
|
309
|
+
plugins.each do |file|
|
310
|
+
require file
|
311
|
+
|
312
|
+
underscore_name = file.sub(matcher, '\1')
|
313
|
+
|
314
|
+
# For helpers, make sure the module is defined, and add it to the helpers list
|
315
|
+
if underscore_name =~ /(.*?)_helper$/
|
316
|
+
class_name = underscore_name.classify
|
317
|
+
|
318
|
+
if defined? class_name
|
319
|
+
log("Loaded helper [#{class_name}]", :indent)
|
320
|
+
|
321
|
+
klass = class_name.constantize
|
322
|
+
self.helpers << klass
|
323
|
+
|
324
|
+
View.send(:include, klass)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
# Clear out the destination directory, if it exists. Leave the root of the
|
332
|
+
# destination itself, but clear any files within it.
|
333
|
+
def setup_destination!
|
334
|
+
if directory_exists?(destination)
|
335
|
+
log("Clearing destination directory [#{destination}]")
|
336
|
+
|
337
|
+
FileUtils.rm_r(Dir.glob("#{destination}**/*"), :force => true)
|
338
|
+
elsif items?
|
339
|
+
log("Creating destination directory [#{destination}]")
|
340
|
+
|
341
|
+
FileUtils.mkdir_p(destination)
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
# Setup the Site instance and prepare it for loading
|
346
|
+
def setup_site!
|
347
|
+
log("Setting up site instance")
|
348
|
+
|
349
|
+
self.site = Site.new(source, destination, options)
|
350
|
+
self.site.logger = self
|
351
|
+
self.site.cache_location = self.cache_location
|
352
|
+
|
353
|
+
log("Site data loaded from source")
|
354
|
+
end
|
355
|
+
|
356
|
+
# Create a temporary folder to build everything in. Once the build was successful,
|
357
|
+
# all files will then be placed into the actual destination.
|
358
|
+
def setup_tmp_directory!
|
359
|
+
return unless tmp_destination?
|
360
|
+
|
361
|
+
log("Setting up tmp build directory [#{tmp_destination}]")
|
362
|
+
|
363
|
+
# Clear out any existing tmp folder contents
|
364
|
+
if directory_exists?(tmp_destination)
|
365
|
+
log("Clearing existing tmp directory content")
|
366
|
+
|
367
|
+
FileUtils.rm_rf(tmp_destination)
|
368
|
+
end
|
369
|
+
|
370
|
+
FileUtils.mkdir_p(tmp_destination)
|
371
|
+
|
372
|
+
self.site.build_destination = tmp_destination
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|