Class: Jekyll::Post

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

Constant Summary collapse

MATCHER =
/^(.+\/)*(\d+-\d+-\d+(?:_\d+-\d+)?)-(.*)(\.[^.]+)$/

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Convertible

#content_type, #do_layout, #read_yaml, #render_haml_in_context, #to_s, #transform

Constructor Details

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

Initialize this Post instance. site is the Site base is the String path to the dir containing the post file name is the String filename of the post file categories is an Array of Strings for the categories for this post tags is an Array of Strings for the tags for this post

Returns



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/jekyll/post.rb', line 38

def initialize(site, source, dir, name)
  @site = site
  @base = File.join(source, dir, '_posts')
  @name = name

  self.categories = dir.split('/').reject { |x| x.empty? }

  parts = name.split('/')
  self.topics = parts.size > 1 ? parts[0..-2] : []

  self.process(name)
  self.data = self.site.post_defaults.dup
  self.read_yaml(@base, name)

  extract_title_from_first_header_or_slug

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

  if self.data.has_key?("tag")
    self.tags = [self.data["tag"]]
  elsif self.data.has_key?("tags")
    self.tags = self.data['tags']
  else
    self.tags = []
  end
  
  if self.categories.empty?
    if self.data.has_key?('category')
      self.categories << self.data['category']
    elsif self.data.has_key?('categories')
      # Look for categories in the YAML-header, either specified as
      # an array or a string.
      if self.data['categories'].kind_of? String
        self.categories = self.data['categories'].split
      else
        self.categories = self.data['categories']
      end
    end
  end
end

Class Attribute Details

.lsiObject

Returns the value of attribute lsi.



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

def lsi
  @lsi
end

Instance Attribute Details

#categoriesObject



26
27
28
# File 'lib/jekyll/post.rb', line 26

def categories
  @categories ||= []
end

#contentObject

Returns the value of attribute content.



23
24
25
# File 'lib/jekyll/post.rb', line 23

def content
  @content
end

#dataObject

Returns the value of attribute data.



23
24
25
# File 'lib/jekyll/post.rb', line 23

def data
  @data
end

#dateObject

The post date and time

Returns



182
183
184
# File 'lib/jekyll/post.rb', line 182

def date
  @date
end

#excerptObject

Returns the value of attribute excerpt.



23
24
25
# File 'lib/jekyll/post.rb', line 23

def excerpt
  @excerpt
end

#extObject

Returns the value of attribute ext.



23
24
25
# File 'lib/jekyll/post.rb', line 23

def ext
  @ext
end

#outputObject

Returns the value of attribute output.



23
24
25
# File 'lib/jekyll/post.rb', line 23

def output
  @output
end

#publishedObject

Returns the value of attribute published.



23
24
25
# File 'lib/jekyll/post.rb', line 23

def published
  @published
end

#remainderObject

Returns the value of attribute remainder.



23
24
25
# File 'lib/jekyll/post.rb', line 23

def remainder
  @remainder
end

#siteObject

Returns the value of attribute site.



23
24
25
# File 'lib/jekyll/post.rb', line 23

def site
  @site
end

#slugObject

Returns the value of attribute slug.



23
24
25
# File 'lib/jekyll/post.rb', line 23

def slug
  @slug
end

#tagsObject

Returns the value of attribute tags.



23
24
25
# File 'lib/jekyll/post.rb', line 23

def tags
  @tags
end

#topicsObject

Returns the value of attribute topics.



23
24
25
# File 'lib/jekyll/post.rb', line 23

def topics
  @topics
end

Class Method Details

.valid?(name) ⇒ Boolean

Post name validator. Post filenames must be like:

2008-11-05-my-awesome-post.textile

or:

2008-11-05_12-45-my-awesome-post.textile

Returns

Returns:

  • (Boolean)


19
20
21
# File 'lib/jekyll/post.rb', line 19

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

Instance Method Details

#<=>(other) ⇒ Object

Spaceship is based on Post#date, slug

Returns -1, 0, 1



86
87
88
89
90
91
92
# File 'lib/jekyll/post.rb', line 86

def <=>(other)
  cmp = self.date <=> other.date
  if 0 == cmp
   cmp = self.slug <=> other.slug
  end
  return cmp
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



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

def dir
  File.dirname(generated_path)
end

#extract_title_from_first_header_or_slugObject

Attempt to extract title from topmost header or slug.

Returns



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

def extract_title_from_first_header_or_slug
  # Done before the transformation to HTML, or it won't go into <title>s.
  self.data["title"] ||=
    case content_type
    when 'textile'
      self.content[/\A\s*h\d\.\s*(.+)/, 1]               # h1. Header
    when 'markdown'
      self.content[/\A\s*#+\s*(.+)\s*#*$/, 1] ||         # "# Header"
      self.content[/\A\s*(\S.*)\r?\n\s*(-+|=+)\s*$/, 1]  # "Header\n====="
    end
  self.data["title"] ||= self.slug.split('-').select {|w| w.capitalize! || w }.join(' ')
end

#generated_pathObject

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

Returns



142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/jekyll/post.rb', line 142

def generated_path
  return permalink if permalink

  @generated_path ||= {
    "year"       => date.strftime("%Y"),
    "month"      => date.strftime("%m"),
    "day"        => date.strftime("%d"),
    "title"      => CGI.escape(slug),
    "categories" => categories.sort.join('/')
  }.inject(template) { |result, token|
    result.gsub(/:#{token.first}/, token.last)
  }.gsub("//", "/")
end

#idObject

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

Returns



168
169
170
# File 'lib/jekyll/post.rb', line 168

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

#inspectObject



292
293
294
# File 'lib/jekyll/post.rb', line 292

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

#nextObject



296
297
298
299
300
301
302
303
304
# File 'lib/jekyll/post.rb', line 296

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

The path to the post file.

Returns



196
197
198
# File 'lib/jekyll/post.rb', line 196

def path
  File.expand_path(File.join(@base, @name))
end

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

Returns



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

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

#previousObject



306
307
308
309
310
311
312
313
# File 'lib/jekyll/post.rb', line 306

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 is the String filename of the post file

Returns nothing



98
99
100
101
102
103
104
# File 'lib/jekyll/post.rb', line 98

def process(name)
  m, cats, date, slug, ext = *name.match(MATCHER)
  date = date.sub(/_(\d+)-(\d+)\Z/, ' \1:\2')  # Make optional time part parsable.
  self.date = Time.parse(date)
  self.slug = slug
  self.ext = ext
end

Calculate related posts.

Returns []



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/jekyll/post.rb', line 203

def related_posts(posts)
  return [] unless posts.size > 1

  if self.site.lsi
    self.class.lsi ||= begin
      puts "Running the classifier... this could take a while."
      lsi = Classifier::LSI.new
      posts.each { |x| $stdout.print(".");$stdout.flush;lsi.add_item(x) }
      puts ""
      lsi
    end

    related = self.class.lsi.find_related(self.content, 11)
    related - [self]
  else
    (posts - [self])[0..9]
  end
end

#render(layouts, site_payload) ⇒ Object

Add any necessary layouts to this post layouts is a Hash of => "layout" site_payload is the site payload hash

Returns nothing



227
228
229
230
231
232
233
234
235
236
237
# File 'lib/jekyll/post.rb', line 227

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

  do_layout(payload, layouts)
end

#templateObject



125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/jekyll/post.rb', line 125

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"
  else
    self.site.permalink_style.to_s
  end
end

#titleObject

The post title

Returns



175
176
177
# File 'lib/jekyll/post.rb', line 175

def title
  self.data && self.data["title"]
end

#to_liquidObject

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

Returns



277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/jekyll/post.rb', line 277

def to_liquid
  { "title"      => self.title,
    "url"        => self.url,
    "date"       => self.date,
    "id"         => self.id,
    "topics"     => self.topics,
    "categories" => self.categories,
    "next"       => self.next,
    "previous"   => self.previous,
    "tags"       => self.tags,
    "content"    => self.content,
    "excerpt"    => self.excerpt,
    "remainder"  => self.remainder }.deep_merge(self.data)
end

#urlObject

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

Returns



160
161
162
# File 'lib/jekyll/post.rb', line 160

def url
  site.config['multiviews'] ? generated_path.sub(/\.html$/, '') : generated_path
end

#write(dest) ⇒ Object

Write the generated post file to the destination directory. dest is the String path to the destination dir

Returns nothing



243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/jekyll/post.rb', line 243

def write(dest)
  FileUtils.mkdir_p(File.join(dest, dir))

  path = File.join(dest, self.generated_path)

  if template[/\.html$/].nil?
    FileUtils.mkdir_p(path)
    path = File.join(path, "index.html")
  end

  File.open(path, 'w') do |f|
    f.write(self.output)
  end
end