plate 0.5.4 → 0.6.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 +15 -0
- data/README.md +21 -19
- data/Rakefile +9 -5
- data/lib/plate.rb +16 -11
- data/lib/plate/asset.rb +86 -23
- data/lib/plate/builder.rb +286 -150
- data/lib/plate/callbacks.rb +20 -4
- data/lib/plate/cli.rb +65 -53
- data/lib/plate/dsl.rb +68 -0
- data/lib/plate/errors.rb +7 -4
- data/lib/plate/hash_proxy.rb +27 -0
- data/lib/plate/helpers/url_helper.rb +19 -0
- data/lib/plate/layout.rb +41 -36
- data/lib/plate/less_template.rb +34 -0
- data/lib/plate/page.rb +108 -84
- data/lib/plate/sass_template.rb +15 -12
- data/lib/plate/site.rb +31 -1
- data/lib/plate/version.rb +1 -1
- data/lib/plate/view.rb +30 -11
- data/lib/templates/bootstrap.min.css +241 -0
- data/lib/templates/callbacks.rb +37 -0
- data/lib/templates/config.yml +9 -1
- data/lib/templates/index.html +37 -0
- data/lib/templates/layout.html.erb +41 -0
- data/lib/templates/rss.erb +32 -0
- metadata +53 -17
- data/lib/templates/index.md +0 -6
- data/lib/templates/layout.erb +0 -12
data/lib/plate/callbacks.rb
CHANGED
@@ -1,28 +1,44 @@
|
|
1
1
|
module Plate
|
2
|
+
# Callbacks are used to extend the base functionality of Plate. You might want to create
|
3
|
+
# some dynamic pages after all posts have been loaded (such as a blog archives view) or
|
4
|
+
# clean up some page output after it is rendered but before it is written to disk. Callbacks
|
5
|
+
# are the best way to achieve these and other common use cases.
|
6
|
+
#
|
7
|
+
# Callbacks must be registered with an object to be used. If you generated a new site
|
8
|
+
# using the `plate new .` or `platify` command, you should see an example callbacks file
|
9
|
+
# in `lib/callbacks.rb`.
|
10
|
+
#
|
2
11
|
module Callbacks
|
3
12
|
def self.included(base)
|
4
13
|
base.send(:include, InstanceMethods)
|
5
14
|
base.send(:extend, ClassMethods)
|
6
15
|
end
|
7
|
-
|
16
|
+
|
8
17
|
module ClassMethods
|
18
|
+
# All of the callbacks that have been registered.
|
9
19
|
def callbacks
|
10
20
|
@callbacks ||= {}
|
11
21
|
end
|
12
|
-
|
22
|
+
|
23
|
+
# Register a new callback
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# Plate::Page.register_callback(:after_render) do |page|
|
27
|
+
# puts "Rendered page! #{page.path}"
|
28
|
+
# end
|
13
29
|
def register_callback(name, method_name = nil, &block)
|
14
30
|
callbacks[name] ||= []
|
15
31
|
callbacks[name] << (block || method_name)
|
16
32
|
end
|
17
33
|
end
|
18
|
-
|
34
|
+
|
19
35
|
module InstanceMethods
|
20
36
|
def around_callback(name, &block)
|
21
37
|
run_callback "before_#{name}".to_sym
|
22
38
|
block.call
|
23
39
|
run_callback "after_#{name}".to_sym
|
24
40
|
end
|
25
|
-
|
41
|
+
|
26
42
|
def run_callback(name)
|
27
43
|
if callbacks = self.class.callbacks[name]
|
28
44
|
callbacks.each do |callback|
|
data/lib/plate/cli.rb
CHANGED
@@ -2,45 +2,45 @@ module Plate
|
|
2
2
|
# The CLI class controls the behavior of plate when it is used as a command line interface.
|
3
3
|
class CLI
|
4
4
|
require 'optparse'
|
5
|
-
|
5
|
+
|
6
6
|
attr_accessor :source, :destination, :args, :options
|
7
|
-
|
7
|
+
|
8
8
|
def initialize(args = [])
|
9
9
|
@args = String === args ? args.split(' ') : args.dup
|
10
10
|
@options = {}
|
11
|
-
|
11
|
+
|
12
12
|
# Some defaults
|
13
13
|
@source = Dir.pwd
|
14
14
|
@destination = File.join(@source, 'public')
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def builder
|
18
18
|
@builder ||= Builder.new(self.source, self.destination, self.options)
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
# The current command to be run. Pulled from the args attribute.
|
22
22
|
def command
|
23
23
|
self.args.size > 0 ? self.args[0] : 'build'
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def parse_options!
|
27
27
|
options = {}
|
28
28
|
|
29
29
|
opts = OptionParser.new do |opts|
|
30
30
|
banner = "Usage: plate [command] [options]"
|
31
|
-
|
31
|
+
|
32
32
|
opts.on('--category [CATEGORY]', '-c', 'Pass in a category for creating a new post.') do |c|
|
33
33
|
options[:category] = c
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
opts.on('--config [PATH]', '-C', 'Set the config file location for the site.') do |c|
|
37
37
|
options[:config] = c
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
opts.on('--destination [PATH]', '-d', 'Set the destination directory for this build.') do |d|
|
41
41
|
@destination = File.expand_path(d)
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
opts.on('--layout [LAYOUT]', '-l', 'Pass in a layout for creating a new post.') do |l|
|
45
45
|
options[:layout] = l
|
46
46
|
end
|
@@ -57,23 +57,23 @@ module Plate
|
|
57
57
|
puts "You're running Plate version #{Plate::VERSION}!"
|
58
58
|
exit 0
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
opts.on('--watch', '-w', 'Watch the source directory for changes.') do
|
62
62
|
options[:watch] = true
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
66
|
opts.parse!(self.args)
|
67
|
-
|
67
|
+
|
68
68
|
@options = options
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
# Run the given command. If the command does not exist, nothing will be run.
|
72
72
|
def run
|
73
73
|
parse_options!
|
74
|
-
|
74
|
+
|
75
75
|
command_name = "run_#{command}_command".to_sym
|
76
|
-
|
76
|
+
|
77
77
|
if self.respond_to?(command_name)
|
78
78
|
# remove command name
|
79
79
|
self.args.shift
|
@@ -82,20 +82,20 @@ module Plate
|
|
82
82
|
puts "Command #{command} not found"
|
83
83
|
return false
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
true
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
class << self
|
90
90
|
def run!
|
91
91
|
new(ARGV).run
|
92
92
|
end
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
protected
|
96
96
|
def process_file_change(event)
|
97
|
-
relative_path = builder.relative_path(event.path)
|
98
|
-
|
97
|
+
relative_path = builder.relative_path(event.path)
|
98
|
+
|
99
99
|
unless relative_path.start_with?('/public/')
|
100
100
|
if builder.reloadable?(relative_path)
|
101
101
|
case event.type
|
@@ -115,13 +115,15 @@ module Plate
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
def run_build_command
|
120
|
-
puts "Building your site from #{source} to #{destination}"
|
121
|
-
|
122
120
|
builder.enable_logging = true if options[:verbose]
|
121
|
+
builder.load!
|
122
|
+
|
123
|
+
puts "Building your site from #{source} to #{builder.destination}"
|
124
|
+
|
123
125
|
builder.render!
|
124
|
-
|
126
|
+
|
125
127
|
if builder.items?
|
126
128
|
# If we want to watch directories, keep the chain open
|
127
129
|
if options[:watch]
|
@@ -139,86 +141,96 @@ module Plate
|
|
139
141
|
puts "Site build complete."
|
140
142
|
end
|
141
143
|
else
|
142
|
-
puts "** There seems to be no site content in this folder. Did you mean to create a new site?\n\n
|
144
|
+
puts "** There seems to be no site content in this folder. Did you mean to create a new site first?\n\n platify .\n\n"
|
143
145
|
end
|
144
146
|
end
|
145
|
-
|
146
|
-
def run_new_command
|
147
|
+
|
148
|
+
def run_new_command
|
147
149
|
# Set the base root
|
148
150
|
root = './'
|
149
|
-
|
151
|
+
|
150
152
|
if args.size > 0
|
151
153
|
root = args[0]
|
152
154
|
end
|
153
|
-
|
155
|
+
|
154
156
|
puts "Generating new plate site at #{root}..."
|
155
|
-
|
157
|
+
|
156
158
|
# The starting path for the new site
|
157
159
|
root_path = File.expand_path(root)
|
158
|
-
|
160
|
+
|
159
161
|
# Create all folders needed for a base site.
|
160
162
|
%w(
|
161
163
|
/
|
162
164
|
config
|
163
165
|
content
|
166
|
+
content/css
|
164
167
|
layouts
|
168
|
+
lib
|
165
169
|
posts
|
166
170
|
).each do |dir|
|
167
|
-
action = File.directory?(File.join(root_path, dir)) ? "exists" : "create"
|
171
|
+
action = File.directory?(File.join(root_path, dir)) ? "exists" : "create"
|
168
172
|
puts " #{action} #{File.join(root, dir)}"
|
169
|
-
|
173
|
+
|
170
174
|
if action == "create"
|
171
175
|
FileUtils.mkdir_p(File.join(root_path, dir))
|
172
|
-
end
|
176
|
+
end
|
173
177
|
end
|
174
|
-
|
178
|
+
|
175
179
|
# Create a blank layout file
|
176
|
-
create_template('layouts/default.erb', 'layout.erb', root, root_path)
|
177
|
-
|
180
|
+
create_template('layouts/default.html.erb', 'layout.html.erb', root, root_path)
|
181
|
+
|
178
182
|
# Config file
|
179
183
|
create_template('config/plate.yml', 'config.yml', root, root_path)
|
180
|
-
|
184
|
+
|
181
185
|
# Index page
|
182
|
-
create_template('content/index.
|
183
|
-
|
186
|
+
create_template('content/index.html', 'index.html', root, root_path)
|
187
|
+
|
188
|
+
# RSS Feed
|
189
|
+
create_template('content/rss.erb', 'rss.erb', root, root_path)
|
190
|
+
|
191
|
+
# Sample callbacks file
|
192
|
+
create_template('lib/callbacks.rb', 'callbacks.rb', root, root_path)
|
193
|
+
|
194
|
+
# Default CSS file from Bootstrap
|
195
|
+
create_template('content/css/bootstrap.min.css', 'bootstrap.min.css', root, root_path)
|
196
|
+
|
184
197
|
puts "New site generated!"
|
185
198
|
end
|
186
|
-
|
199
|
+
|
187
200
|
def run_post_command
|
188
201
|
title = args.size == 0 ? "" : args[0]
|
189
202
|
slug = title.parameterize
|
190
203
|
date = Time.now
|
191
|
-
|
204
|
+
|
192
205
|
# if there are any post defaults in the config file, use those as the default options
|
193
206
|
if builder.config.has_key?(:post_defaults)
|
194
207
|
options.reverse_merge!(builder.config[:post_defaults])
|
195
208
|
end
|
196
|
-
|
209
|
+
|
197
210
|
category = options[:category] ? "\ncategory: #{options[:category]}" : ""
|
198
211
|
layout = options[:layout] ? "\nlayout: #{options[:layout]}" : ""
|
199
|
-
|
212
|
+
|
200
213
|
filename = File.join(self.source, 'posts', date.strftime('%Y/%m'), "#{date.strftime('%Y-%m-%d')}-#{slug}.md")
|
201
214
|
content = %Q(---\ntitle: "#{title}"\ndate: #{date.strftime('%Y-%m-%d %H:%M:%S')}#{category}#{layout}\ntags: []\n\n# #{title}\n\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.)
|
202
|
-
|
215
|
+
|
203
216
|
FileUtils.mkdir_p(File.dirname(filename))
|
204
217
|
File.open(filename, 'w') { |f| f.write(content) }
|
205
|
-
|
218
|
+
|
206
219
|
puts "New post file added [#{filename}]"
|
207
220
|
end
|
208
|
-
|
221
|
+
|
209
222
|
def create_template(path, template, root, root_path)
|
210
|
-
action = File.exist?(File.join(root_path, path)) ? "exists" : "create"
|
223
|
+
action = File.exist?(File.join(root_path, path)) ? "exists" : "create"
|
211
224
|
puts " #{action} #{File.join(root, path)}"
|
212
|
-
|
225
|
+
|
213
226
|
if action == "create"
|
227
|
+
dest = File.join(root_path, path)
|
214
228
|
template_root = File.expand_path(File.join(File.dirname(__FILE__), '..', 'templates'))
|
215
|
-
|
216
229
|
contents = File.read(File.join(template_root, template))
|
217
|
-
|
218
230
|
unless contents.to_s.blank?
|
219
|
-
File.open(
|
231
|
+
File.open(dest, 'w') { |f| f.write(contents) }
|
220
232
|
end
|
221
|
-
end
|
233
|
+
end
|
222
234
|
end
|
223
235
|
end
|
224
236
|
end
|
data/lib/plate/dsl.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
module Plate
|
2
|
+
# The Dsl class provides the methods available in plugin files in order to extend
|
3
|
+
# the functionality a generated site.
|
4
|
+
class Dsl
|
5
|
+
class << self
|
6
|
+
# Evaluate the given file path into the {Plate::Dsl dsl} instance.
|
7
|
+
def evaluate_plugin(file_path)
|
8
|
+
instance_eval_plugin(read_plugin_file(file_path))
|
9
|
+
end
|
10
|
+
|
11
|
+
# Performs evaluation of the file's content
|
12
|
+
def instance_eval_plugin(content)
|
13
|
+
new.instance_eval(content)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Read the given plugin file path into a string
|
17
|
+
#
|
18
|
+
# @return [String] The plugin file's contents
|
19
|
+
def read_plugin_file(file_path)
|
20
|
+
File.read(file_path)
|
21
|
+
rescue
|
22
|
+
raise PluginNotReadable
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Register a new callback for the given object and event.
|
27
|
+
#
|
28
|
+
# @example Run block after rendering a site
|
29
|
+
# callback :site, :after_render do
|
30
|
+
# puts 'done!'
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# @example Run block before rendering a page
|
34
|
+
# callback :page, :before_render do |page|
|
35
|
+
# puts "Rendering page #{page.path}"
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# @example Run a method on the site after write
|
39
|
+
# class Site
|
40
|
+
# def finished!
|
41
|
+
# log('All done.')
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# callback :site, :after_write, :finished!
|
46
|
+
#
|
47
|
+
def callback(object, event, method_name = nil, &block)
|
48
|
+
if Symbol === object
|
49
|
+
object = "Plate::#{object.to_s.classify}".constantize
|
50
|
+
end
|
51
|
+
|
52
|
+
object.register_callback(event, method_name, &block)
|
53
|
+
end
|
54
|
+
alias :register_callback :callback
|
55
|
+
|
56
|
+
# Set up a new engine designed for rendering dynamic assets.
|
57
|
+
# Engines should be compatible with the Tilt::Template syntax.
|
58
|
+
def register_asset_engine(extension, klass)
|
59
|
+
Plate.register_asset_engine(extension, klass)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Set up a new engine designed for rendering dynamic assets.
|
63
|
+
# Engines should be compatible with the Tilt::Template syntax.
|
64
|
+
def register_template_engine(extension, klass)
|
65
|
+
Plate.register_template_engine(extension, klass)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/plate/errors.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
module Plate
|
2
|
-
class SourceNotFound < StandardError
|
3
|
-
end
|
4
|
-
|
5
2
|
class FileNotFound < StandardError
|
6
3
|
end
|
7
|
-
|
4
|
+
|
8
5
|
class NoPostDateProvided < StandardError
|
9
6
|
end
|
7
|
+
|
8
|
+
class PluginNotReadable < StandardError
|
9
|
+
end
|
10
|
+
|
11
|
+
class SourceNotFound < StandardError
|
12
|
+
end
|
10
13
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Plate
|
2
|
+
# Just a blank class that allows you to call methods that return hash values
|
3
|
+
class HashProxy
|
4
|
+
# Pass in a hash object to use this class as a proxy for its keys.
|
5
|
+
def initialize(source = {})
|
6
|
+
@source = source
|
7
|
+
end
|
8
|
+
|
9
|
+
# Pass through for getting the hash's value at the given key.
|
10
|
+
def [](key)
|
11
|
+
@source[key]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Handle method missing calls and proxy methods to hash values.
|
15
|
+
#
|
16
|
+
# Allows for checking to see if a key exists and returning a key value.
|
17
|
+
def method_missing(method, *args)
|
18
|
+
if @source.has_key?(method)
|
19
|
+
self[method]
|
20
|
+
elsif method.to_s =~ /^[a-zA-Z0-9_]*\?$/
|
21
|
+
@source.has_key?(method.to_s.gsub!(/\?/, '').to_sym)
|
22
|
+
else
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,6 +1,25 @@
|
|
1
1
|
module Plate
|
2
2
|
# Includes basic helpers for managing URLs within your site.
|
3
3
|
module URLHelper
|
4
|
+
# replace all relative links within the given content block to absolute
|
5
|
+
# links containing the base url for this site.
|
6
|
+
#
|
7
|
+
# This is useful in creating RSS and/or Atom feeds that you'd like to
|
8
|
+
# contain links back to your site.
|
9
|
+
#
|
10
|
+
# href or src values that don't start with a slash are left intact.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# <a href="/posts/one"><img src="/images/sample.jpg"></a>
|
14
|
+
#
|
15
|
+
# <!-- turns into: -->
|
16
|
+
#
|
17
|
+
# <a href="http://example.com/posts/one"><img src="http://example.com/images/sample.jpg"></a>
|
18
|
+
def absolutize_paths(content)
|
19
|
+
content.gsub(Regexp.new("(src|href)=(\"|')/"), "\\1=\\2#{site.url}/")
|
20
|
+
end
|
21
|
+
alias_method :a, :absolutize_paths
|
22
|
+
|
4
23
|
# Cleans up a string to make it URl-friendly, removing all special
|
5
24
|
# characters, spaces, and sanitizing to a dashed, lowercase string.
|
6
25
|
def sanitize_slug(str)
|
data/lib/plate/layout.rb
CHANGED
@@ -1,125 +1,125 @@
|
|
1
1
|
module Plate
|
2
2
|
class Layout
|
3
3
|
attr_accessor :site, :file, :meta, :content
|
4
|
-
|
4
|
+
|
5
5
|
def initialize(site, file = nil, load_on_initialize = true)
|
6
6
|
self.site = site
|
7
7
|
self.file = file
|
8
8
|
self.meta = {}
|
9
9
|
self.content = ""
|
10
|
-
|
10
|
+
|
11
11
|
load! if load_on_initialize and file?
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
# The name of the layound, without any path data
|
15
15
|
def basename
|
16
16
|
File.basename(self.file)
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
# Is this layout the default layout, by name.
|
20
20
|
def default?
|
21
21
|
self.name.downcase.strip.start_with? "default"
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
# The layout engine to use. Based off of the last file extension for this layout.
|
25
25
|
def engine
|
26
26
|
@engine ||= self.site.registered_page_engines[self.extension.gsub(/\./, '').to_sym]
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
# The last file extension of this layout.
|
30
30
|
def extension
|
31
31
|
File.extname(self.file)
|
32
32
|
end
|
33
|
-
|
34
|
-
# Does the file exist or not.
|
33
|
+
|
34
|
+
# Does the file exist or not.
|
35
35
|
def file?
|
36
36
|
return false if self.file.nil?
|
37
37
|
File.exists?(self.file)
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
# A unique ID for this layout.
|
41
|
-
def id
|
41
|
+
def id
|
42
42
|
@id ||= Digest::MD5.hexdigest(relative_file)
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def inspect
|
46
46
|
"#<#{self.class}:0x#{object_id.to_s(16)} name=#{name.to_s.inspect}>"
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
def load!
|
50
|
-
return if @loaded
|
50
|
+
return if @loaded
|
51
51
|
raise FileNotFound unless file?
|
52
|
-
|
52
|
+
|
53
53
|
read_file!
|
54
54
|
read_metadata!
|
55
|
-
|
55
|
+
|
56
56
|
@loaded = true
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
# The name for a layout is just the lowercase, first part of the file name.
|
60
60
|
def name
|
61
|
-
return "" unless file?
|
61
|
+
return "" unless file?
|
62
62
|
@name ||= self.basename.to_s.downcase.strip.split('.')[0]
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
# A parent layout for this current layout file. If no layout is specified for this
|
66
66
|
# layout's parent, then nil is returned. If there is a parent layout for this layout,
|
67
67
|
# any pages using it will be rendered using this layout first, then sent to the parent
|
68
68
|
# for further rendering.
|
69
69
|
def parent
|
70
70
|
return @parent if @parent
|
71
|
-
|
71
|
+
|
72
72
|
if self.meta[:layout]
|
73
73
|
@parent = self.site.find_layout(self.meta[:layout])
|
74
74
|
else
|
75
75
|
@parent = nil
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
@parent
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
def relative_file
|
82
82
|
@relative_file ||= self.site.relative_path(self.file)
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
def reload!
|
86
86
|
@template = nil
|
87
87
|
@loaded = false
|
88
88
|
@name = nil
|
89
89
|
@engine = nil
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
# Render the given content against the current layout template.
|
93
93
|
def render(content, page = nil, view = nil)
|
94
94
|
if self.template
|
95
95
|
view ||= View.new(self.site, page)
|
96
96
|
result = self.template.render(view) { content }
|
97
|
-
|
97
|
+
|
98
98
|
if self.parent
|
99
99
|
result = self.parent.render(result, page, view)
|
100
100
|
end
|
101
|
-
|
101
|
+
|
102
102
|
view = nil
|
103
|
-
|
103
|
+
|
104
104
|
result
|
105
105
|
else
|
106
106
|
content.respond_to?(:rendered_content) ? content.rendered_content : content.to_s
|
107
107
|
end
|
108
108
|
end
|
109
|
-
|
110
|
-
# The render template to use for this layout. A template is only used if the
|
109
|
+
|
110
|
+
# The render template to use for this layout. A template is only used if the
|
111
111
|
# file extension for the layout is a valid layout extension from the current
|
112
112
|
# site.
|
113
113
|
def template
|
114
114
|
return @template if @template
|
115
|
-
|
115
|
+
|
116
116
|
if template?
|
117
117
|
@template = self.engine.new() { self.content }
|
118
118
|
else
|
119
119
|
nil
|
120
120
|
end
|
121
121
|
end
|
122
|
-
|
122
|
+
|
123
123
|
# Does this file have the ability to be used as a template?
|
124
124
|
#
|
125
125
|
# This currently only works if the layout is a .erb file. Otherwise anything that
|
@@ -127,31 +127,36 @@ module Plate
|
|
127
127
|
def template?
|
128
128
|
self.site.page_engine_extensions.include?(self.extension)
|
129
129
|
end
|
130
|
-
|
130
|
+
|
131
131
|
# Is this layout equal to another page being sent?
|
132
132
|
def ==(other)
|
133
133
|
other = other.relative_file if other.respond_to?(:relative_file)
|
134
134
|
self.id == other or self.relative_file == other
|
135
135
|
end
|
136
|
-
|
136
|
+
|
137
|
+
# Compare two layouts, by name.
|
138
|
+
def <=>(other)
|
139
|
+
self.name <=> other.name
|
140
|
+
end
|
141
|
+
|
137
142
|
protected
|
138
143
|
# Read the file and store it in @content
|
139
144
|
def read_file!
|
140
145
|
self.content = file? ? File.read(self.file) : nil
|
141
146
|
end
|
142
|
-
|
147
|
+
|
143
148
|
# Reads all content from a layouts's meta data. At this time, the layout only supports
|
144
149
|
# loading a parent layout. All other meta data is unused.
|
145
150
|
#
|
146
151
|
# Meta data is stored in YAML format within the head of a page after the -- declaration like so:
|
147
|
-
#
|
152
|
+
#
|
148
153
|
# ---
|
149
154
|
# layout: default
|
150
155
|
#
|
151
156
|
# # Start of layout content
|
152
157
|
def read_metadata!
|
153
158
|
return unless self.content
|
154
|
-
|
159
|
+
|
155
160
|
begin
|
156
161
|
if matches = /^(---\n)(.*?)^\s*?$/m.match(self.content)
|
157
162
|
if matches.size == 3
|
@@ -159,7 +164,7 @@ module Plate
|
|
159
164
|
self.meta = YAML.load(matches[2])
|
160
165
|
self.meta.symbolize_keys!
|
161
166
|
end
|
162
|
-
end
|
167
|
+
end
|
163
168
|
rescue Exception => e
|
164
169
|
self.meta = {}
|
165
170
|
self.site.log(" ** Problem reading YAML for file #{relative_file} (#{e.message}). Meta data skipped")
|