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.
@@ -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
@@ -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 = directory
79
- result << '/' unless result =~ /\/$/
80
- result << slug unless slug == "index"
81
-
82
- # Remove any double slashes
83
- result.gsub!(/\/\//, '/')
84
-
85
- # Remove file extensions, and cleanup URL
86
- result = result.split('/').reject{ |segment| segment =~ /^\.+$/ }.join('/')
87
-
88
- # Add a trailing slash
89
- result << '/' unless result =~ /\/$/
90
-
91
- # Tack on index.html for the folder
92
- result << "index.html"
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 nil if self.meta[:layout] == false
120
- return @layout if @layout
121
-
122
- if self.meta[:layout]
123
- @layout = self.site.find_layout(self.meta[:layout])
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 this compiled page to its destination file.
218
- def write!
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
- File.open(path, 'w') do |f|
224
- f.write(self.rendered_content)
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")
@@ -1,8 +1,8 @@
1
1
  module Plate
2
- # Mostly lifted from the default SassTemplate class at
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 => :expanded,
30
- :load_paths => [ scope.pathname ]
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