Class: Bunto::Post

Inherits:
Object
  • Object
show all
Includes:
Convertible, Comparable
Defined in:
lib/bunto/post.rb

Constant Summary collapse

MATCHER =

Valid post name regex.

/^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
EXCERPT_ATTRIBUTES_FOR_LIQUID =
%w[
  title
  url
  dir
  date
  id
  categories
  next
  previous
  tags
  path
]
ATTRIBUTES_FOR_LIQUID =

Attributes for Liquid templates

EXCERPT_ATTRIBUTES_FOR_LIQUID + %w[
  content
  excerpt
  excerpt_separator
  draft?
]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Convertible

#[], #asset_file?, #coffeescript_file?, #converters, #do_layout, #hook_owner, #invalid_layout?, #output_ext, #place_in_layout?, #render_all_layouts, #render_liquid, #render_with_liquid?, #sass_file?, #to_liquid, #to_s, #transform, #type, #validate_data!, #validate_permalink!, #write

Constructor Details

#initialize(site, source, dir, name) ⇒ Post

Initialize this Post instance.

site - The Site. base - The String path to the dir containing the post file. name - The String filename of the post file.

Returns the new Post.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/bunto/post.rb', line 51

def initialize(site, source, dir, name)
  @site = site
  @dir = dir
  @base = containing_dir(dir)
  @name = name

  self.categories = dir.split('/').reject { |x| x.empty? }
  process(name)
  read_yaml(@base, name)

  data.default_proc = proc do |hash, key|
    site.frontmatter_defaults.find(relative_path, type, key)
  end

  if data.key?('date')
    self.date = Utils.parse_date(data["date"].to_s, "Post '#{relative_path}' does not have a valid date in the YAML front matter.")
  end

  populate_categories
  populate_tags
end

Instance Attribute Details

#categoriesObject

Returns the value of attribute categories.



40
41
42
# File 'lib/bunto/post.rb', line 40

def categories
  @categories
end

#contentObject

Returns the value of attribute content.



39
40
41
# File 'lib/bunto/post.rb', line 39

def content
  @content
end

#dataObject

Returns the value of attribute data.



39
40
41
# File 'lib/bunto/post.rb', line 39

def data
  @data
end

#dateObject

Returns the value of attribute date.



40
41
42
# File 'lib/bunto/post.rb', line 40

def date
  @date
end

#extObject

Returns the value of attribute ext.



39
40
41
# File 'lib/bunto/post.rb', line 39

def ext
  @ext
end

#extracted_excerptObject

Returns the value of attribute extracted_excerpt.



39
40
41
# File 'lib/bunto/post.rb', line 39

def extracted_excerpt
  @extracted_excerpt
end

#nameObject (readonly)

Returns the value of attribute name.



42
43
44
# File 'lib/bunto/post.rb', line 42

def name
  @name
end

#outputObject

Returns the value of attribute output.



39
40
41
# File 'lib/bunto/post.rb', line 39

def output
  @output
end

#siteObject

Returns the value of attribute site.



38
39
40
# File 'lib/bunto/post.rb', line 38

def site
  @site
end

#slugObject

Returns the value of attribute slug.



40
41
42
# File 'lib/bunto/post.rb', line 40

def slug
  @slug
end

#tagsObject

Returns the value of attribute tags.



40
41
42
# File 'lib/bunto/post.rb', line 40

def tags
  @tags
end

Class Method Details

.valid?(name) ⇒ Boolean

Post name validator. Post filenames must be like: 2008-11-05-my-awesome-post.textile

Returns true if valid, false if not.

Returns:

  • (Boolean)


34
35
36
# File 'lib/bunto/post.rb', line 34

def self.valid?(name)
  name =~ MATCHER
end

Instance Method Details

#<=>(other) ⇒ Object

Compares Post objects. First compares the Post date. If the dates are equal, it compares the Post slugs.

other - The other Post we are comparing to.

Returns -1, 0, 1



157
158
159
160
161
162
163
# File 'lib/bunto/post.rb', line 157

def <=>(other)
  cmp = self.date <=> other.date
  if 0 == cmp
   cmp = self.slug <=> other.slug
  end
  return cmp
end

#containing_dir(dir) ⇒ Object

Get the full path to the directory containing the post files



93
94
95
# File 'lib/bunto/post.rb', line 93

def containing_dir(dir)
  site.in_source_dir(dir, '_posts')
end

#destination(dest) ⇒ Object

Obtain destination path.

dest - The String path to the destination dir.

Returns destination file path String.



279
280
281
282
283
284
285
# File 'lib/bunto/post.rb', line 279

def destination(dest)
  # The url needs to be unescaped in order to preserve the correct filename
  path = site.in_dest_dir(dest, URL.unescape_path(url))
  path = File.join(path, "index.html") if self.url.end_with?("/")
  path << output_ext unless path.end_with?(output_ext)
  path
end

#dirObject

The generated directory into which the post will be placed upon generation. This is derived from the permalink or, if permalink is absent, set to the default date e.g. “/2008/11/05/” if the permalink style is :date, otherwise nothing.

Returns the String directory.



183
184
185
# File 'lib/bunto/post.rb', line 183

def dir
  File.dirname(url)
end

#draft?Boolean

Returns if this Post is a Draft

Returns:

  • (Boolean)


311
312
313
# File 'lib/bunto/post.rb', line 311

def draft?
  is_a?(Bunto::Draft)
end

#excerptObject

The post excerpt. This is either a custom excerpt set in YAML front matter or the result of extract_excerpt.

Returns excerpt string.



112
113
114
# File 'lib/bunto/post.rb', line 112

def excerpt
  data.fetch('excerpt') { extracted_excerpt.to_s }
end

#excerpt_separatorObject

Public: the Post excerpt_separator, from the YAML Front-Matter or site default

excerpt_separator value

Returns the post excerpt_separator



127
128
129
# File 'lib/bunto/post.rb', line 127

def excerpt_separator
  (data['excerpt_separator'] || site.config['excerpt_separator']).to_s
end

#idObject

The UID for this post (useful in feeds). e.g. /2008/11/05/my-awesome-post

Returns the String UID.



243
244
245
# File 'lib/bunto/post.rb', line 243

def id
  File.join(dir, slug)
end

#inspectObject

Returns the shorthand String identifier of this Post.



288
289
290
# File 'lib/bunto/post.rb', line 288

def inspect
  "<Post: #{id}>"
end

#nextObject



292
293
294
295
296
297
298
299
# File 'lib/bunto/post.rb', line 292

def next
  pos = site.posts.index {|post| post.equal?(self) }
  if pos && pos < site.posts.length - 1
    site.posts[pos + 1]
  else
    nil
  end
end

#pathObject

Public: the path to the post relative to the site source,

from the YAML Front-Matter or from a combination of
the directory it's in, "_posts", and the name of the
post file

Returns the path to the file relative to the site source



142
143
144
# File 'lib/bunto/post.rb', line 142

def path
  data.fetch('path') { relative_path.sub(/\A\//, '') }
end

The full path and filename of the post. Defined in the YAML of the post body (optional).

Returns the String permalink.



191
192
193
# File 'lib/bunto/post.rb', line 191

def permalink
  data && data['permalink']
end

#populate_categoriesObject



81
82
83
84
85
86
# File 'lib/bunto/post.rb', line 81

def populate_categories
  categories_from_data = Utils.pluralized_array_from_hash(data, 'category', 'categories')
  self.categories = (
    Array(categories) + categories_from_data
  ).map { |c| c.to_s }.flatten.uniq
end

#populate_tagsObject



88
89
90
# File 'lib/bunto/post.rb', line 88

def populate_tags
  self.tags = Utils.pluralized_array_from_hash(data, "tag", "tags").flatten
end

#previousObject



301
302
303
304
305
306
307
308
# File 'lib/bunto/post.rb', line 301

def previous
  pos = site.posts.index {|post| post.equal?(self) }
  if pos && pos > 0
    site.posts[pos - 1]
  else
    nil
  end
end

#process(name) ⇒ Object

Extract information from the post filename.

name - The String filename of the post file.

Returns nothing.



170
171
172
173
174
175
# File 'lib/bunto/post.rb', line 170

def process(name)
  m, cats, date, slug, ext = *name.match(MATCHER)
  self.date = Utils.parse_date(date, "Post '#{relative_path}' does not have a valid date in the filename.")
  self.slug = slug
  self.ext = ext
end

#published?Boolean

Returns:

  • (Boolean)


73
74
75
76
77
78
79
# File 'lib/bunto/post.rb', line 73

def published?
  if data.key?('published') && data['published'] == false
    false
  else
    true
  end
end

#read_yaml(base, name) ⇒ Object

Read the YAML frontmatter.

base - The String path to the dir containing the file. name - The String filename of the file.

Returns nothing.



103
104
105
106
# File 'lib/bunto/post.rb', line 103

def read_yaml(base, name)
  super(base, name)
  self.extracted_excerpt = extract_excerpt
end

Calculate related posts.

Returns an Array of related Posts.



250
251
252
# File 'lib/bunto/post.rb', line 250

def related_posts(posts)
  Bunto::RelatedPosts.new(self).build
end

#relative_pathObject

The path to the post source file, relative to the site source



147
148
149
# File 'lib/bunto/post.rb', line 147

def relative_path
  File.join(*[@dir, "_posts", @name].map(&:to_s).reject(&:empty?))
end

#render(layouts, site_payload) ⇒ Object

Add any necessary layouts to this post.

layouts - A Hash of => “layout”. site_payload - The site payload hash.

Returns nothing.



260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/bunto/post.rb', line 260

def render(layouts, site_payload)
  # construct payload
  payload = Utils.deep_merge_hashes({
    "site" => { "related_posts" => related_posts(site_payload["site"]["posts"]) },
    "page" => to_liquid(self.class::EXCERPT_ATTRIBUTES_FOR_LIQUID)
  }, site_payload)

  if generate_excerpt?
    extracted_excerpt.do_layout(payload, {})
  end

  do_layout(payload.merge({"page" => to_liquid}), layouts)
end

#templateObject



195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/bunto/post.rb', line 195

def template
  case site.permalink_style
  when :pretty
    "/:categories/:year/:month/:day/:title/"
  when :none
    "/:categories/:title.html"
  when :date
    "/:categories/:year/:month/:day/:title.html"
  when :ordinal
    "/:categories/:year/:y_day/:title.html"
  else
    site.permalink_style.to_s
  end
end

#titleObject

Public: the Post title, from the YAML Front-Matter or from the slug

Returns the post title



119
120
121
# File 'lib/bunto/post.rb', line 119

def title
  data.fetch('title') { titleized_slug }
end

#titleized_slugObject

Turns the post slug into a suitable title



132
133
134
# File 'lib/bunto/post.rb', line 132

def titleized_slug
  slug.split('-').select {|w| w.capitalize! || w }.join(' ')
end

#urlObject

The generated relative url of this post.

Returns the String url.



213
214
215
216
217
218
219
# File 'lib/bunto/post.rb', line 213

def url
  @url ||= URL.new({
    :template => template,
    :placeholders => url_placeholders,
    :permalink => permalink
  }).to_s
end

#url_placeholdersObject

Returns a hash of URL placeholder names (as symbols) mapping to the desired placeholder replacements. For details see “url.rb”



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/bunto/post.rb', line 223

def url_placeholders
  {
    :year        => date.strftime("%Y"),
    :month       => date.strftime("%m"),
    :day         => date.strftime("%d"),
    :title       => slug,
    :i_day       => date.strftime("%-d"),
    :i_month     => date.strftime("%-m"),
    :categories  => (categories || []).map { |c| c.to_s.downcase }.uniq.join('/'),
    :short_month => date.strftime("%b"),
    :short_year  => date.strftime("%y"),
    :y_day       => date.strftime("%j"),
    :output_ext  => output_ext
  }
end