plate 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|