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
@@ -0,0 +1,34 @@
|
|
1
|
+
module Plate
|
2
|
+
# Slightly modified from the Tilt default to just use the Less::Parse instead of Engine.
|
3
|
+
#
|
4
|
+
# Also adds support for paths
|
5
|
+
#
|
6
|
+
# Original source: https://github.com/rtomayko/tilt/blob/master/lib/tilt/css.rb
|
7
|
+
class LessTemplate < Tilt::Template
|
8
|
+
self.default_mime_type = 'text/css'
|
9
|
+
|
10
|
+
def self.engine_initialized?
|
11
|
+
defined? ::Less
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize_engine
|
15
|
+
require_template_library 'less'
|
16
|
+
end
|
17
|
+
|
18
|
+
def prepare
|
19
|
+
end
|
20
|
+
|
21
|
+
def evaluate(scope, locals, &block)
|
22
|
+
paths = [ scope.pathname, File.join(scope.site.source, 'content') ]
|
23
|
+
|
24
|
+
less_options = options.merge({
|
25
|
+
:filename => eval_file,
|
26
|
+
:line => line,
|
27
|
+
:paths => paths
|
28
|
+
})
|
29
|
+
|
30
|
+
parser = ::Less::Parser.new(less_options)
|
31
|
+
parser.parse(data).to_css
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/plate/page.rb
CHANGED
@@ -3,46 +3,46 @@ require 'digest'
|
|
3
3
|
module Plate
|
4
4
|
class Page
|
5
5
|
include Callbacks
|
6
|
-
|
7
|
-
attr_accessor :body, :content, :file, :meta, :site
|
8
|
-
|
6
|
+
|
7
|
+
attr_accessor :body, :content, :file, :meta, :site, :layout
|
8
|
+
|
9
9
|
def initialize(site, file = nil, load_on_initialize = true)
|
10
10
|
self.site = site
|
11
11
|
self.file = file
|
12
12
|
self.meta = {}
|
13
13
|
self.content = ""
|
14
|
-
|
14
|
+
|
15
15
|
load! if load_on_initialize and file?
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
# Setup some shortcut getters for meta attributes
|
19
19
|
%w( title description tags category ).each do |meta_attribute|
|
20
20
|
class_eval <<-META
|
21
21
|
def #{meta_attribute} # def title
|
22
22
|
self.meta[:#{meta_attribute}] # self.meta[:title]
|
23
23
|
end # end
|
24
|
-
|
24
|
+
|
25
25
|
def #{meta_attribute}=(value) # def title=(value)
|
26
26
|
self.meta[:#{meta_attribute}] = value # self.meta[:title] = value
|
27
27
|
end # end
|
28
28
|
META
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
# The name of the file, without any path data
|
32
32
|
def basename
|
33
33
|
File.basename(self.file)
|
34
34
|
end
|
35
35
|
alias_method :name, :basename
|
36
|
-
|
36
|
+
|
37
37
|
# The directory this page is located in, relative to the site root.
|
38
38
|
def directory
|
39
39
|
return @directory if @directory
|
40
|
-
|
40
|
+
|
41
41
|
base = Pathname.new(File.join(self.site.source, 'content'))
|
42
42
|
current = Pathname.new(self.file)
|
43
|
-
|
43
|
+
|
44
44
|
dirs = current.relative_path_from(base).to_s.split('/')
|
45
|
-
|
45
|
+
|
46
46
|
if dirs.size > 1
|
47
47
|
dirs.pop
|
48
48
|
@directory = "/#{dirs.join('/')}"
|
@@ -50,131 +50,147 @@ module Plate
|
|
50
50
|
@directory = "/"
|
51
51
|
end
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
def engines
|
55
55
|
@engines ||= self.extensions.reverse.collect { |e| self.site.registered_page_engines[e.gsub(/\./, '').to_sym] }.reject { |e| !e }
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
def extensions
|
59
59
|
@extensions ||= self.basename.scan(/\.[^.]+/)
|
60
60
|
end
|
61
|
-
|
62
|
-
# Does the file exist or not.
|
61
|
+
|
62
|
+
# Does the file exist or not.
|
63
63
|
def file?
|
64
64
|
return false if self.file.nil?
|
65
65
|
File.exists?(self.file)
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
# Returns just the file name, no extension.
|
69
69
|
def file_name
|
70
70
|
File.basename(self.file, '.*')
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
# The full file path of where this file will be written to. (Relative to site root)
|
74
74
|
def file_path
|
75
|
-
return self.meta[:path] if self.meta.has_key?(:path)
|
76
75
|
return @file_path if @file_path
|
77
|
-
|
78
|
-
result =
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
76
|
+
|
77
|
+
result = nil
|
78
|
+
|
79
|
+
if self.meta.has_key?(:path)
|
80
|
+
result = self.meta[:path]
|
81
|
+
result = "/#{result}" unless result.start_with?('/')
|
82
|
+
else
|
83
|
+
result = directory
|
84
|
+
result << '/' unless result =~ /\/$/
|
85
|
+
result << slug unless slug == 'index'
|
86
|
+
|
87
|
+
# Remove any double slashes
|
88
|
+
result.gsub!(/\/\//, '/')
|
89
|
+
|
90
|
+
# Remove file extensions, and cleanup URL
|
91
|
+
result = result.split('/').reject{ |segment| segment =~ /^\.+$/ }.join('/')
|
92
|
+
|
93
|
+
# Add a trailing slash
|
94
|
+
result << '/' unless result =~ /\/$/
|
95
|
+
|
96
|
+
# Tack on index.html for the folder
|
97
|
+
result << 'index.html'
|
98
|
+
end
|
99
|
+
|
93
100
|
@file_path = result
|
94
101
|
end
|
95
|
-
|
96
|
-
def format_extension
|
102
|
+
|
103
|
+
def format_extension
|
97
104
|
format = self.extensions.reverse.detect() { |e| !self.site.page_engine_extensions.include?(e) }
|
98
105
|
format = ".html" if format.nil?
|
99
106
|
format
|
100
107
|
end
|
101
108
|
|
102
109
|
# A unique ID for this page.
|
103
|
-
def id
|
110
|
+
def id
|
104
111
|
@id ||= Digest::MD5.hexdigest(relative_file)
|
105
112
|
end
|
106
|
-
|
113
|
+
|
107
114
|
def inspect
|
108
115
|
"#<#{self.class}:0x#{object_id.to_s(16)} name=#{name.to_s.inspect}>"
|
109
116
|
end
|
110
|
-
|
117
|
+
|
111
118
|
# Utility method to sanitize keywords output. Keywords are returned as an array.
|
112
119
|
def keywords
|
113
120
|
@keywords ||= (Array === self.meta[:keywords] ? self.meta[:keywords] : self.meta[:keywords].to_s.strip.split(',').collect(&:strip))
|
114
121
|
end
|
115
|
-
|
122
|
+
|
116
123
|
# The layout to use when rendering this page. Returns nil if no default layout is available,
|
117
124
|
# or the layout has specifically been turned off within the config.
|
118
125
|
def layout
|
119
|
-
return
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
126
|
+
return @layout if defined?(@layout)
|
127
|
+
self.layout = self.meta[:layout]
|
128
|
+
@layout
|
129
|
+
end
|
130
|
+
|
131
|
+
# Manually set the layout
|
132
|
+
def layout=(value)
|
133
|
+
if value == false
|
134
|
+
@layout = nil
|
135
|
+
elsif value
|
136
|
+
@layout = self.site.find_layout(value)
|
124
137
|
else
|
125
138
|
@layout = self.site.default_layout
|
126
139
|
end
|
127
|
-
|
128
|
-
@layout
|
129
140
|
end
|
130
|
-
|
141
|
+
|
131
142
|
# Has this page been loaded from file?
|
132
143
|
def loaded?
|
133
144
|
!!@loaded
|
134
145
|
end
|
135
|
-
|
146
|
+
|
136
147
|
# Read the file data for this page
|
137
148
|
def load!
|
138
|
-
return if @loaded
|
149
|
+
return if @loaded
|
139
150
|
raise FileNotFound unless file?
|
140
|
-
|
151
|
+
|
141
152
|
read_file!
|
142
153
|
read_metadata!
|
143
|
-
|
154
|
+
|
144
155
|
@loaded = true
|
145
156
|
end
|
146
|
-
|
157
|
+
|
147
158
|
def path
|
148
159
|
return '/' if self.file_path == '/index.html'
|
149
|
-
@path ||= self.file_path.sub(/(.*?)\/index\.html$/i, '\1')
|
160
|
+
@path ||= self.file_path.sub(/(.*?)\/index\.html$/i, '\1')
|
150
161
|
end
|
151
|
-
|
162
|
+
|
152
163
|
# The file's source path, relative to site root.
|
153
164
|
def relative_file
|
154
165
|
@relative_file ||= self.site.relative_path(self.file)
|
155
166
|
end
|
156
|
-
|
167
|
+
|
157
168
|
def reload!
|
158
|
-
@layout = nil
|
159
169
|
@loaded = false
|
160
170
|
@content = nil
|
161
171
|
@meta = {}
|
162
172
|
@keywords = nil
|
163
173
|
@rendered_content = nil
|
164
174
|
@body = nil
|
165
|
-
|
175
|
+
|
166
176
|
load!
|
167
177
|
end
|
168
|
-
|
178
|
+
|
169
179
|
# Returns the rendered body of this page, without the layout.
|
180
|
+
#
|
181
|
+
# The callbacks `before_render` and `after_render` are called here. To perform
|
182
|
+
# custom actions before or after a page file is written to disk, use these callback
|
183
|
+
# methods.
|
184
|
+
#
|
185
|
+
# See {Plate::Callbacks} for more information on setting up callbacks.
|
170
186
|
def rendered_body
|
171
187
|
return @body if @body
|
172
|
-
|
188
|
+
|
173
189
|
result = ""
|
174
|
-
|
190
|
+
|
175
191
|
around_callback :render do
|
176
192
|
result = self.content
|
177
|
-
|
193
|
+
|
178
194
|
view = View.new(self.site, self)
|
179
195
|
|
180
196
|
self.engines.each do |engine|
|
@@ -183,67 +199,75 @@ module Plate
|
|
183
199
|
end
|
184
200
|
|
185
201
|
view = nil
|
186
|
-
|
202
|
+
|
187
203
|
@body = result
|
188
204
|
end
|
189
|
-
|
205
|
+
|
190
206
|
@body
|
191
207
|
end
|
192
|
-
|
208
|
+
|
193
209
|
def rendered_content
|
194
210
|
@rendered_content ||= self.apply_layout_to(rendered_body)
|
195
211
|
end
|
196
|
-
|
212
|
+
|
197
213
|
# Name of the file to be saved. Just takes the current file name and removes any extensions.
|
198
214
|
def slug
|
199
215
|
self.basename.to_s.downcase.split('.')[0].dasherize.parameterize
|
200
216
|
end
|
201
|
-
|
217
|
+
|
202
218
|
# The title from this page's meta data, turned into a parameter for use in a url.
|
203
219
|
def title_for_url
|
204
220
|
self.title.to_s.dasherize.parameterize
|
205
221
|
end
|
206
|
-
|
222
|
+
|
207
223
|
# Returns this page's content
|
208
224
|
def to_s
|
209
225
|
self.inspect
|
210
226
|
end
|
211
|
-
|
227
|
+
|
212
228
|
# The full URL of this page. Depends on the site's URL attribute and a config option of `:base_url`
|
213
229
|
def url
|
214
230
|
@url ||= "#{site.url}#{path}"
|
215
231
|
end
|
216
|
-
|
217
|
-
# Write
|
218
|
-
|
232
|
+
|
233
|
+
# Write the compiled page file to the destination. The content is written to disk
|
234
|
+
# using the path designated in `file_path` and the content from `rendered_content`.
|
235
|
+
#
|
236
|
+
# The callbacks `before_write` and `after_write` are included here. To perform
|
237
|
+
# custom actions before or after a page file is written to disk, use these callback
|
238
|
+
# methods.
|
239
|
+
#
|
240
|
+
# See {Plate::Callbacks} for more information on setting up callbacks.
|
241
|
+
def write!
|
219
242
|
path = File.join(site.build_destination, file_path)
|
220
|
-
|
221
243
|
FileUtils.mkdir_p(File.dirname(path))
|
222
|
-
|
223
|
-
|
224
|
-
|
244
|
+
|
245
|
+
around_callback :write do
|
246
|
+
File.open(path, 'w') do |f|
|
247
|
+
f.write(self.rendered_content)
|
248
|
+
end
|
225
249
|
end
|
226
|
-
|
250
|
+
|
227
251
|
path
|
228
252
|
end
|
229
|
-
|
253
|
+
|
230
254
|
# Is this page equal to another page being sent?
|
231
255
|
def ==(other)
|
232
256
|
other = other.relative_file if other.respond_to?(:relative_file)
|
233
257
|
self.id == other or self.relative_file == other
|
234
258
|
end
|
235
|
-
|
259
|
+
|
236
260
|
# Compare two posts, by date.
|
237
261
|
def <=>(other)
|
238
262
|
self.path <=> other.path
|
239
263
|
end
|
240
|
-
|
264
|
+
|
241
265
|
protected
|
242
266
|
def apply_layout_to(content)
|
243
267
|
return content unless Layout === self.layout
|
244
268
|
self.layout.render(content, self)
|
245
269
|
end
|
246
|
-
|
270
|
+
|
247
271
|
# Reading page details
|
248
272
|
# #####################################################################
|
249
273
|
|
@@ -255,7 +279,7 @@ module Plate
|
|
255
279
|
# Reads all content from a page's meta data
|
256
280
|
#
|
257
281
|
# Meta data is stored in YAML format within the head of a page after the -- declaration like so:
|
258
|
-
#
|
282
|
+
#
|
259
283
|
# ---
|
260
284
|
# title: "Hello"
|
261
285
|
# description: "This is some meta data"
|
@@ -267,7 +291,7 @@ module Plate
|
|
267
291
|
# # Start of actual content
|
268
292
|
def read_metadata!
|
269
293
|
return unless self.content
|
270
|
-
|
294
|
+
|
271
295
|
begin
|
272
296
|
if matches = /^(---\n)(.*?)^\s*?$/m.match(self.content)
|
273
297
|
if matches.size == 3
|
@@ -275,7 +299,7 @@ module Plate
|
|
275
299
|
self.meta = YAML.load(matches[2])
|
276
300
|
self.meta.symbolize_keys!
|
277
301
|
end
|
278
|
-
end
|
302
|
+
end
|
279
303
|
rescue Exception => e
|
280
304
|
self.meta = {}
|
281
305
|
self.site.log(" ** Problem reading YAML for file #{relative_file} (#{e.message}). Meta data skipped")
|
data/lib/plate/sass_template.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Plate
|
2
|
-
#
|
2
|
+
# Extended from the base Tilt::Template class at:
|
3
3
|
# https://github.com/rtomayko/tilt/blob/master/lib/tilt/css.rb
|
4
4
|
#
|
5
|
-
# Modifications have been made to use the site caching folder
|
5
|
+
# Modifications have been made to use the site caching folder.
|
6
6
|
class SassTemplate < Tilt::Template
|
7
7
|
self.default_mime_type = 'text/css'
|
8
8
|
|
@@ -14,26 +14,29 @@ module Plate
|
|
14
14
|
require_template_library 'sass'
|
15
15
|
end
|
16
16
|
|
17
|
-
def prepare
|
17
|
+
def prepare
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def syntax
|
21
21
|
:sass
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def evaluate(scope, locals, &block)
|
25
|
+
paths = [ scope.pathname, File.join(scope.site.source, 'content') ]
|
26
|
+
style = scope.site.options[:sass_style] || 'expanded'
|
27
|
+
|
25
28
|
options = {
|
26
|
-
:filename => eval_file,
|
27
|
-
:line => line,
|
29
|
+
:filename => eval_file,
|
30
|
+
:line => line,
|
28
31
|
:syntax => syntax,
|
29
|
-
:style =>
|
30
|
-
:load_paths =>
|
32
|
+
:style => style.to_sym,
|
33
|
+
:load_paths => paths
|
31
34
|
}
|
32
|
-
|
35
|
+
|
33
36
|
if scope.site.cache_location
|
34
37
|
options[:cache_location] = File.join(scope.site.cache_location, 'sass-cache')
|
35
|
-
end
|
36
|
-
|
38
|
+
end
|
39
|
+
|
37
40
|
::Sass::Engine.new(data, options).render
|
38
41
|
end
|
39
42
|
end
|