plate 0.6.0 → 0.6.1

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 CHANGED
@@ -1,4 +1,8 @@
1
- ## Plate 0.6.0 (Unreleased)
1
+ ## Plate 0.6.1
2
+
3
+ * Added basis support for asset partials with Sass and Less. When using watch mode, partials will reload any referencing files if they are modified.
4
+
5
+ ## Plate 0.6.0
2
6
 
3
7
  * Meta data can be read from the config file and used to store common site data such as title, description, author, etc.
4
8
  * Modified new site generator to use meta data structure
data/README.md CHANGED
@@ -8,6 +8,8 @@ In addition to basic formatting with Markdown, Plate also supports generating mo
8
8
 
9
9
  Plate is a command line utility installed as a Ruby Gem. Installation requires Ruby 1.8.7, 1.9.2 or 1.9.3. For additional processing, install CoffeeScript, Sass, Haml and other formatters.
10
10
 
11
+ Current version is **0.6.0**
12
+
11
13
  ## Installation
12
14
 
13
15
  gem install plate
data/lib/plate/builder.rb CHANGED
@@ -232,7 +232,24 @@ module Plate
232
232
  end
233
233
  end
234
234
  else
235
- log("Cannot render file, it doesn't exist. [#{relative_file_path}]")
235
+ # Check for partials, and run any files that reference it.
236
+ if File.basename(relative_file_path) =~ /^_/
237
+ partial_name = File.basename(relative_file_path, '.*').gsub(/^_/, '')
238
+
239
+ log("Partial modified. Reloading referencing files", :indent)
240
+
241
+ other_files = site.find_by_extension(File.extname(relative_file_path))
242
+
243
+ other_files.each do |file|
244
+ if Array === file.partials
245
+ if file.partials.include?(partial_name)
246
+ self.render_file!(file.relative_file)
247
+ end
248
+ end
249
+ end
250
+ else
251
+ log("Cannot render file, it doesn't exist. [#{relative_file_path}]")
252
+ end
236
253
  end
237
254
 
238
255
  true
@@ -1,24 +1,56 @@
1
1
  module Plate
2
- class DynamicPage < Page
3
- attr_accessor :file_path, :locals
4
-
2
+ # Allows the creation of one-off pages generated entirely from a dynamic source. The root
3
+ # content for a `DynamicPage` instance is not read from the source directory, as opposed
4
+ # to normal files. Instead, dynamic pages are typically used to create pages with dynamic
5
+ # data and content.
6
+ #
7
+ # Examples may include a blog archives page, list of tags, categories pages, etc.
8
+ #
9
+ # @example Generate a page with custom content
10
+ #
11
+ # # This callback creates a tag index page for each tag in your posts.
12
+ # callback :site, :after_render do |site|
13
+ # site.tags.each do |tag|
14
+ # tag_page = DynamicPage.new(site, "/tags/#{site.to_url(tag)}/index.html", :layout => 'tag')
15
+ # tag_page.locals = { :tag => tag }
16
+ # tag_page.write!
17
+ # end
18
+ # end
19
+ #
20
+ class DynamicPage < Page
21
+ # The full file system path of where this file will be written to. Set from the
22
+ # destination path on initialize.
23
+ attr_accessor :file_path
24
+
25
+ # Provides a hash to the page with variables that are accessible from with dynamic
26
+ # layouts or dynamic templates for this page.
27
+ attr_accessor :locals
28
+
29
+ # Set up a new instance of Dynamic Page
5
30
  def initialize(site, destination_path, meta = {})
6
31
  self.site = site
7
32
  self.file_path = destination_path
8
- self.meta = meta
33
+ self.meta = meta
9
34
  self.content = ""
10
35
  self.locals = {}
11
36
  end
12
-
37
+
38
+ # Set the full hash to be provided to the view. Hash keys are symbolized before
39
+ # sending to the view.
13
40
  def locals=(hash)
14
41
  @locals = hash.symbolize_keys!
15
42
  end
16
-
43
+
44
+ # Alias for the content that is provided
17
45
  def rendered_body
18
46
  self.content
19
47
  end
20
-
21
- # Check to see if a method called is in your locals.
48
+
49
+ # Check to see if a method called is in your locals. Allows the view to call variables in the locals
50
+ # hash directly without having to call `page.locals`.
51
+ #
52
+ # For example, in a view you can call `page.locals[:local_key]` `locals[:local_key]` or just `local_key`.
53
+ # They all will return the same value (provided :local_key exists in the locals of course)
22
54
  def method_missing(sym, *args)
23
55
  return locals[sym] if locals.has_key?(sym)
24
56
  super
data/lib/plate/errors.rb CHANGED
@@ -1,13 +1,17 @@
1
1
  module Plate
2
+ # Raised if a given file by name is not found within the source tree.
2
3
  class FileNotFound < StandardError
3
4
  end
4
5
 
6
+ # Raised when a blog post does not contain a date within the meta data or within the file name.
5
7
  class NoPostDateProvided < StandardError
6
8
  end
7
9
 
10
+ # Raised if Plate is unable to read a plugin file from the lib directory.
8
11
  class PluginNotReadable < StandardError
9
12
  end
10
13
 
14
+ # Raised if the site's source directory was not found.
11
15
  class SourceNotFound < StandardError
12
16
  end
13
17
  end
@@ -27,7 +27,9 @@ module Plate
27
27
  :paths => paths
28
28
  })
29
29
 
30
- parser = ::Less::Parser.new(less_options)
30
+ scope.partials = data.to_s.scan(/@import\s"_?(.*?)";/i).flatten
31
+
32
+ parser = ::Less::Parser.new(less_options)
31
33
  parser.parse(data).to_css
32
34
  end
33
35
  end
data/lib/plate/page.rb CHANGED
@@ -6,6 +6,12 @@ module Plate
6
6
 
7
7
  attr_accessor :body, :content, :file, :meta, :site, :layout
8
8
 
9
+ # If set, will return an array of partial names used within this page.
10
+ #
11
+ # In watch mode, this allows the current page to be reloaded when any
12
+ # of its partials are reloaded.
13
+ attr_accessor :partials
14
+
9
15
  def initialize(site, file = nil, load_on_initialize = true)
10
16
  self.site = site
11
17
  self.file = file
@@ -55,6 +61,12 @@ module Plate
55
61
  @engines ||= self.extensions.reverse.collect { |e| self.site.registered_page_engines[e.gsub(/\./, '').to_sym] }.reject { |e| !e }
56
62
  end
57
63
 
64
+ # the last file extension for this page
65
+ def extension
66
+ extensions.last.gsub(/^\./, '')
67
+ end
68
+
69
+ # List of all extensions for this page
58
70
  def extensions
59
71
  @extensions ||= self.basename.scan(/\.[^.]+/)
60
72
  end
@@ -37,6 +37,8 @@ module Plate
37
37
  options[:cache_location] = File.join(scope.site.cache_location, 'sass-cache')
38
38
  end
39
39
 
40
+ scope.partials = data.to_s.scan(/@import\s"(.*?)";/i).flatten
41
+
40
42
  ::Sass::Engine.new(data, options).render
41
43
  end
42
44
  end
data/lib/plate/site.rb CHANGED
@@ -1,136 +1,142 @@
1
1
  module Plate
2
2
  require 'tilt'
3
-
3
+
4
4
  # This class contains everything you'll want to know about a site. It contains all data
5
5
  # about the site, including blog posts, content pages, static files, assets and anything else.
6
6
  class Site
7
7
  include Callbacks
8
-
9
- attr_accessor :assets, :build_destination, :cache_location, :destination,
8
+
9
+ attr_accessor :assets, :build_destination, :cache_location, :destination,
10
10
  :layouts, :logger, :metadata, :options, :pages, :posts, :source
11
-
11
+
12
12
  def initialize(source, destination, options = {})
13
13
  # Setup source and destination for the site files
14
14
  self.source = source
15
15
  self.destination = destination
16
-
16
+
17
17
  # By default, the build goes into the destination folder.
18
18
  # Override this to output to a different folder by default
19
19
  self.build_destination = destination
20
-
20
+
21
21
  # Sanitize options
22
22
  self.options = Hash === options ? options.clone : {}
23
23
  self.options.symbolize_keys!
24
-
24
+
25
25
  clear
26
26
  end
27
-
27
+
28
28
  %w( assets layouts pages posts ).each do |group|
29
29
  class_eval "def #{group}; load!; @#{group}; end"
30
30
  end
31
-
31
+
32
32
  def all_files
33
33
  @all_files ||= self.assets + self.layouts + self.pages + self.posts.to_a
34
34
  end
35
-
35
+
36
36
  # All extensions that are registered, as strings.
37
37
  def asset_engine_extensions
38
38
  @asset_engine_extensions ||= self.registered_asset_engines.keys.collect { |e| ".#{e}" }
39
39
  end
40
-
40
+
41
41
  # Alphabetical list of all blog post categories used.
42
42
  def categories
43
43
  @categories ||= self.posts.collect(&:category).uniq.sort
44
44
  end
45
-
45
+
46
46
  # Clear out all data related to this site. Prepare for a reload, or first time load.
47
47
  def clear
48
48
  @loaded = false
49
49
  @tags_counts = nil
50
50
  @default_layout = nil
51
-
51
+
52
52
  self.assets = []
53
53
  self.layouts = []
54
54
  self.pages = []
55
55
  self.posts = PostCollection.new
56
-
56
+
57
57
  @metadata = {}
58
58
  end
59
-
59
+
60
60
  # The default blog post category
61
61
  def default_category
62
62
  options[:default_category] || 'Posts'
63
63
  end
64
-
64
+
65
65
  # The default layout for all pages that do not specifically name their own
66
66
  def default_layout
67
67
  return nil if self.layouts.size == 0
68
68
  return @default_layout if @default_layout
69
-
69
+
70
70
  layout ||= self.layouts.reject { |l| !l.default? }
71
71
  layout = self.layouts if layout.size == 0
72
-
72
+
73
73
  if Array === layout and layout.size > 0
74
74
  layout = layout[0]
75
75
  end
76
-
76
+
77
77
  @default_layout = layout
78
78
  end
79
-
79
+
80
80
  # Find a page, asset or layout by source relative file path
81
81
  def find(search_path)
82
82
  self.all_files.find { |file| file == search_path }
83
83
  end
84
-
84
+
85
+ # Find all registered files by the given file extension
86
+ def find_by_extension(extension)
87
+ extension = extension.to_s.downcase.gsub(/^\./, '')
88
+ self.all_files.select { |file| file.extension.to_s.downcase.gsub(/^\./, '') == extension }
89
+ end
90
+
85
91
  # Find all pages and posts with this layout
86
92
  def find_by_layout(layout_name)
87
93
  result = []
88
-
94
+
89
95
  result += self.pages.find_all { |page| page.layout == layout_name }
90
96
  result += self.posts.find_all { |post| post.layout == layout_name }
91
-
97
+
92
98
  result
93
99
  end
94
-
95
- # Find a specific layout by its file name. Any extensions are removed.
100
+
101
+ # Find a specific layout by its file name. Any extensions are removed.
96
102
  def find_layout(layout_name)
97
103
  search_name = layout_name.to_s.downcase.strip.split('.')[0]
98
104
  matches = self.layouts.reject { |l| l.name != search_name }
99
105
  matches.empty? ? self.default_layout : matches[0]
100
106
  end
101
-
107
+
102
108
  def inspect
103
109
  "#<#{self.class}:0x#{object_id.to_s(16)} source=#{source.to_s.inspect}>"
104
110
  end
105
-
111
+
106
112
  # Load all data from the various source directories.
107
113
  def load!
108
114
  return if @loaded
109
-
115
+
110
116
  log("Loading site from source [#{source}]")
111
-
117
+
112
118
  run_callback :before_load
113
-
119
+
114
120
  self.load_pages!
115
121
  self.load_layouts!
116
122
  self.load_posts!
117
-
123
+
118
124
  run_callback :after_load
119
-
125
+
120
126
  @loaded = true
121
127
  end
122
-
128
+
123
129
  # Returns true if the site has been loaded from the source directories.
124
130
  def loaded?
125
131
  !!@loaded
126
132
  end
127
-
133
+
128
134
  # Write to the log if enable_logging is enabled
129
135
  def log(message, style = :indent)
130
136
  logger.send(:log, message, style) if logger and logger.respond_to?(:log)
131
137
  end
132
-
133
- # Access to read all meta data for this site. Meta data can be set on the
138
+
139
+ # Access to read all meta data for this site. Meta data can be set on the
134
140
  # site instance by passing in the `metadata` hash, or it can be pulled
135
141
  # from the config file under the heading of `meta`.
136
142
  #
@@ -149,43 +155,43 @@ module Plate
149
155
  def meta
150
156
  @meta ||= HashProxy.new(self.metadata)
151
157
  end
152
-
158
+
153
159
  # Set the meta data hash object for this site.
154
160
  def meta=(hash)
155
161
  # Reset the meta hash proxy
156
162
  @meta = nil
157
-
158
- self.metadata = hash
163
+
164
+ self.metadata = hash
159
165
  end
160
-
166
+
161
167
  def page_engine_extensions
162
168
  @page_engine_extensions ||= self.registered_page_engines.keys.collect { |e| ".#{e}" }
163
169
  end
164
-
170
+
165
171
  def relative_path(file_or_directory)
166
172
  file_or_directory.to_s.gsub(/^#{Regexp.quote(source)}(.*)$/, '\1')
167
173
  end
168
-
174
+
169
175
  def reload!
170
176
  clear
171
177
  load!
172
178
  end
173
-
179
+
174
180
  # Returns the asset engines that are available for use.
175
181
  def registered_asset_engines
176
182
  Plate.asset_engines
177
183
  end
178
-
184
+
179
185
  # Returns the engines available for use in page and layout formatting.
180
186
  def registered_page_engines
181
- Plate.template_engines
187
+ Plate.template_engines
182
188
  end
183
-
189
+
184
190
  # All tags used on this site
185
191
  def tags
186
192
  @tags ||= self.posts.tag_list
187
193
  end
188
-
194
+
189
195
  def to_url(str)
190
196
  result = str.to_s.strip.downcase
191
197
  result = result.gsub(/[^-a-z0-9~\s\.:;+=_]/, '')
@@ -194,7 +200,7 @@ module Plate
194
200
  result
195
201
  end
196
202
  alias_method :sanitize_slug, :to_url
197
-
203
+
198
204
  # The base URL for this site. The url can be set using the config option named `:base_url`.
199
205
  #
200
206
  # The base URL will not have any trailing slashes.
@@ -202,28 +208,28 @@ module Plate
202
208
  return '' unless self.options[:base_url]
203
209
  @url ||= self.options[:base_url].to_s.gsub(/(.*?)\/?$/, '\1')
204
210
  end
205
-
211
+
206
212
  protected
207
213
  # Load all layouts from layouts/
208
214
  def load_layouts!(log = true)
209
215
  @layouts = []
210
-
216
+
211
217
  Dir.glob(File.join(source, "layouts/**/*")).each do |file|
212
218
  # If this 'file' is a directory, just skip it. We only care about files.
213
- unless File.directory?(file)
219
+ unless File.directory?(file)
214
220
  @layouts << Layout.new(self, file)
215
221
  end
216
222
  end
217
223
 
218
224
  log("#{@layouts.size} layouts loaded") if log
219
-
225
+
220
226
  @layouts
221
227
  end
222
-
228
+
223
229
  def load_pages!(log = true)
224
230
  @assets = []
225
231
  @pages = []
226
-
232
+
227
233
  # Load all pages, static pages and assets from content/
228
234
  Dir.glob(File.join(source, "content/**/*")).each do |file|
229
235
  # If this 'file' is a directory, just skip it. We only care about files.
@@ -252,14 +258,14 @@ module Plate
252
258
 
253
259
  log("#{@assets.size} assets loaded") if log
254
260
  log("#{@pages.size} pages and other files loaded") if log
255
-
261
+
256
262
  @pages
257
263
  end
258
-
264
+
259
265
  # Load blog posts from posts/
260
266
  def load_posts!(log = true)
261
267
  @posts = PostCollection.new
262
-
268
+
263
269
  Dir.glob(File.join(source, "posts/**/*")).each do |file|
264
270
  # If this 'file' is a directory, just skip it. We only care about files.
265
271
  unless File.directory?(file)
@@ -270,13 +276,13 @@ module Plate
270
276
  if intro == "---"
271
277
  @posts.add(Post.new(self, file))
272
278
  end
273
- end
279
+ end
274
280
  end
275
-
281
+
276
282
  @posts.sort!
277
-
278
- log("#{@posts.size} posts loaded") if log
279
-
283
+
284
+ log("#{@posts.size} posts loaded") if log
285
+
280
286
  @posts
281
287
  end
282
288
  end
data/lib/plate/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Plate
2
- VERSION = "0.6.0" unless defined?(::Plate::VERSION)
2
+ VERSION = "0.6.1" unless defined?(::Plate::VERSION)
3
3
  end
data/lib/plate.rb CHANGED
@@ -48,14 +48,14 @@ module Plate
48
48
  # https://github.com/sstephenson/sprockets
49
49
 
50
50
  # Assets
51
- register_asset_engine :coffee, Tilt::CoffeeScriptTemplate
52
- register_asset_engine :less, LessTemplate
53
- register_asset_engine :sass, SassTemplate
54
- register_asset_engine :scss, ScssTemplate
51
+ register_asset_engine :coffee, Tilt::CoffeeScriptTemplate
52
+ register_asset_engine :less, LessTemplate
53
+ register_asset_engine :sass, SassTemplate
54
+ register_asset_engine :scss, ScssTemplate
55
55
 
56
56
  # Layouts & Markup
57
- register_template_engine :erb, Tilt::ERBTemplate
58
- register_template_engine :haml, HamlTemplate
59
- register_template_engine :md, MarkdownTemplate
60
- register_template_engine :markdown, MarkdownTemplate
57
+ register_template_engine :erb, Tilt::ERBTemplate
58
+ register_template_engine :haml, HamlTemplate
59
+ register_template_engine :md, MarkdownTemplate
60
+ register_template_engine :markdown, MarkdownTemplate
61
61
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-10 00:00:00.000000000 Z
12
+ date: 2012-05-24 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: !ruby/object:Gem::Requirement
16
+ requirement: &70231552834360 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,15 +21,10 @@ dependencies:
21
21
  version: '3.2'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ~>
28
- - !ruby/object:Gem::Version
29
- version: '3.2'
24
+ version_requirements: *70231552834360
30
25
  - !ruby/object:Gem::Dependency
31
26
  name: directory_watcher
32
- requirement: !ruby/object:Gem::Requirement
27
+ requirement: &70231552833980 !ruby/object:Gem::Requirement
33
28
  none: false
34
29
  requirements:
35
30
  - - ! '>='
@@ -37,15 +32,10 @@ dependencies:
37
32
  version: '0'
38
33
  type: :runtime
39
34
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
35
+ version_requirements: *70231552833980
46
36
  - !ruby/object:Gem::Dependency
47
37
  name: i18n
48
- requirement: !ruby/object:Gem::Requirement
38
+ requirement: &70231552833440 !ruby/object:Gem::Requirement
49
39
  none: false
50
40
  requirements:
51
41
  - - ~>
@@ -53,15 +43,10 @@ dependencies:
53
43
  version: '0.6'
54
44
  type: :runtime
55
45
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: '0.6'
46
+ version_requirements: *70231552833440
62
47
  - !ruby/object:Gem::Dependency
63
48
  name: rake
64
- requirement: !ruby/object:Gem::Requirement
49
+ requirement: &70231552833020 !ruby/object:Gem::Requirement
65
50
  none: false
66
51
  requirements:
67
52
  - - ! '>='
@@ -69,15 +54,10 @@ dependencies:
69
54
  version: '0'
70
55
  type: :runtime
71
56
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: '0'
57
+ version_requirements: *70231552833020
78
58
  - !ruby/object:Gem::Dependency
79
59
  name: redcarpet
80
- requirement: !ruby/object:Gem::Requirement
60
+ requirement: &70231552832480 !ruby/object:Gem::Requirement
81
61
  none: false
82
62
  requirements:
83
63
  - - ~>
@@ -85,15 +65,10 @@ dependencies:
85
65
  version: '2'
86
66
  type: :runtime
87
67
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ~>
92
- - !ruby/object:Gem::Version
93
- version: '2'
68
+ version_requirements: *70231552832480
94
69
  - !ruby/object:Gem::Dependency
95
70
  name: tilt
96
- requirement: !ruby/object:Gem::Requirement
71
+ requirement: &70231552831980 !ruby/object:Gem::Requirement
97
72
  none: false
98
73
  requirements:
99
74
  - - ~>
@@ -101,12 +76,7 @@ dependencies:
101
76
  version: '1.3'
102
77
  type: :runtime
103
78
  prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
107
- - - ~>
108
- - !ruby/object:Gem::Version
109
- version: '1.3'
79
+ version_requirements: *70231552831980
110
80
  description: Plate is a simple, static site generator and blog engine.
111
81
  email:
112
82
  - john@johntornow.com
@@ -174,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
174
144
  version: 1.8.12
175
145
  requirements: []
176
146
  rubyforge_project:
177
- rubygems_version: 1.8.21
147
+ rubygems_version: 1.8.15
178
148
  signing_key:
179
149
  specification_version: 3
180
150
  summary: A static site generator and blog engine.