Class: Jekyll::Post

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

Direct Known Subclasses

Draft

Constant Summary

MATCHER =

Valid post name regex.

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

Attributes for Liquid templates

EXCERPT_ATTRIBUTES_FOR_LIQUID.concat(%w[
  content
  excerpt
])

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Convertible

#converter, #do_layout, #output_ext, #render_all_layouts, #render_liquid, #to_s, #transform, #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.



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

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

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

  if self.data.has_key?('date')
    self.date = Time.parse(self.data["date"].to_s)
  end

  self.published = self.published?

  self.populate_categories
  self.populate_tags
end

Class Attribute Details

.lsiObject

Returns the value of attribute lsi



7
8
9
# File 'lib/jekyll/post.rb', line 7

def lsi
  @lsi
end

Instance Attribute Details

#categoriesObject

Returns the value of attribute categories



41
42
43
# File 'lib/jekyll/post.rb', line 41

def categories
  @categories
end

#contentObject

Returns the value of attribute content



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

def content
  @content
end

#dataObject

Returns the value of attribute data



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

def data
  @data
end

#dateObject

Returns the value of attribute date



41
42
43
# File 'lib/jekyll/post.rb', line 41

def date
  @date
end

#extObject

Returns the value of attribute ext



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

def ext
  @ext
end

#extracted_excerptObject

Returns the value of attribute extracted_excerpt



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

def extracted_excerpt
  @extracted_excerpt
end

#nameObject (readonly)

Returns the value of attribute name



43
44
45
# File 'lib/jekyll/post.rb', line 43

def name
  @name
end

#outputObject

Returns the value of attribute output



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

def output
  @output
end

#publishedObject

Returns the value of attribute published



41
42
43
# File 'lib/jekyll/post.rb', line 41

def published
  @published
end

#siteObject

Returns the value of attribute site



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

def site
  @site
end

#slugObject

Returns the value of attribute slug



41
42
43
# File 'lib/jekyll/post.rb', line 41

def slug
  @slug
end

#tagsObject

Returns the value of attribute tags



41
42
43
# File 'lib/jekyll/post.rb', line 41

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.



35
36
37
# File 'lib/jekyll/post.rb', line 35

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



142
143
144
145
146
147
148
# File 'lib/jekyll/post.rb', line 142

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

#containing_dir(source, dir) ⇒ Object

Get the full path to the directory containing the post files



92
93
94
# File 'lib/jekyll/post.rb', line 92

def containing_dir(source, dir)
  return File.join(source, dir, '_posts')
end

#destination(dest) ⇒ Object

Obtain destination path.

dest - The String path to the destination dir.

Returns destination file path String.



268
269
270
271
272
273
# File 'lib/jekyll/post.rb', line 268

def destination(dest)
  # The url needs to be unescaped in order to preserve the correct filename
  path = File.join(dest, CGI.unescape(self.url))
  path = File.join(path, "index.html") if template[/\.html$/].nil?
  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.



170
171
172
# File 'lib/jekyll/post.rb', line 170

def dir
  File.dirname(url)
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.



111
112
113
114
115
116
117
# File 'lib/jekyll/post.rb', line 111

def excerpt
  if self.data.has_key? 'excerpt'
    self.data['excerpt']
  else
    self.extracted_excerpt.to_s
  end
end

#idObject

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

Returns the String UID.



234
235
236
# File 'lib/jekyll/post.rb', line 234

def id
  File.join(self.dir, self.slug)
end

#inspectObject

Returns the shorthand String identifier of this Post.



286
287
288
# File 'lib/jekyll/post.rb', line 286

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

#nextObject



290
291
292
293
294
295
296
297
298
# File 'lib/jekyll/post.rb', line 290

def next
  pos = self.site.posts.index(self)

  if pos && pos < self.site.posts.length-1
    self.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

Returns the path to the file relative to the site source



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

def path
  self.data['path'] || File.join(@dir, '_posts', @name).sub(/\A\//, '')
end

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

Returns the String permalink.



178
179
180
# File 'lib/jekyll/post.rb', line 178

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

#populate_categoriesObject



80
81
82
83
84
85
# File 'lib/jekyll/post.rb', line 80

def populate_categories
  if self.categories.empty?
    self.categories = self.data.pluralized_array('category', 'categories').map {|c| c.to_s.downcase}
  end
  self.categories.flatten!
end

#populate_tagsObject



87
88
89
# File 'lib/jekyll/post.rb', line 87

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

#previousObject



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

def previous
  pos = self.site.posts.index(self)
  if pos && pos > 0
    self.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.



155
156
157
158
159
160
161
162
# File 'lib/jekyll/post.rb', line 155

def process(name)
  m, cats, date, slug, ext = *name.match(MATCHER)
  self.date = Time.parse(date)
  self.slug = slug
  self.ext = ext
rescue ArgumentError
  raise FatalException.new("Post #{name} does not have a valid date.")
end

#published?Boolean



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

def published?
  if self.data.has_key?('published') && self.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.



102
103
104
105
# File 'lib/jekyll/post.rb', line 102

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

Calculate related posts.

Returns an Array of related Posts.



241
242
243
# File 'lib/jekyll/post.rb', line 241

def related_posts(posts)
  Jekyll::RelatedPosts.new(self).build
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.



251
252
253
254
255
256
257
258
259
260
261
# File 'lib/jekyll/post.rb', line 251

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

  self.extracted_excerpt.do_layout(payload, {})

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

#templateObject



182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/jekyll/post.rb', line 182

def template
  case self.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
    self.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



122
123
124
# File 'lib/jekyll/post.rb', line 122

def title
  self.data["title"] || self.slug.split('-').select {|w| w.capitalize! || w }.join(' ')
end

#to_liquid(attrs = ATTRIBUTES_FOR_LIQUID) ⇒ Object

Convert this post into a Hash for use in Liquid templates.

Returns the representative Hash.



278
279
280
281
282
283
# File 'lib/jekyll/post.rb', line 278

def to_liquid(attrs = ATTRIBUTES_FOR_LIQUID)
  further_data = Hash[attrs.map { |attribute|
    [attribute, send(attribute)]
  }]
  data.deep_merge(further_data)
end

#urlObject

The generated relative url of this post. e.g. /2008/11/05/my-awesome-post.html

Returns the String URL.



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/jekyll/post.rb', line 201

def url
  return @url if @url

  url = if permalink
    permalink
  else
    {
      "year"       => date.strftime("%Y"),
      "month"      => date.strftime("%m"),
      "day"        => date.strftime("%d"),
      "title"      => CGI.escape(slug),
      "i_day"      => date.strftime("%d").to_i.to_s,
      "i_month"    => date.strftime("%m").to_i.to_s,
      "categories" => categories.map { |c| URI.escape(c.to_s) }.join('/'),
      "short_month" => date.strftime("%b"),
      "y_day"      => date.strftime("%j"),
      "output_ext" => self.output_ext
    }.inject(template) { |result, token|
      result.gsub(/:#{Regexp.escape token.first}/, token.last)
    }.gsub(/\/\//, "/")
  end

  # sanitize url
  @url = url.split('/').reject{ |part| part =~ /^\.+$/ }.join('/')
  @url += "/" if url =~ /\/$/
  @url.gsub!(/\A([^\/])/, '/\1')
  @url
end