nirvdrum-jekyll 0.6.1 → 0.7.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.
@@ -1,6 +1,3 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
1
  # -*- encoding: utf-8 -*-
5
2
 
6
3
  Gem::Specification.new do |s|
@@ -9,7 +6,7 @@ Gem::Specification.new do |s|
9
6
 
10
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
8
  s.authors = ["Tom Preston-Werner"]
12
- s.date = %q{2010-02-11}
9
+ s.date = %q{2009-07-14}
13
10
  s.default_executable = %q{jekyll}
14
11
  s.description = %q{Jekyll is a simple, blog aware, static site generator.}
15
12
  s.email = %q{tom@mojombo.com}
@@ -71,15 +68,15 @@ Gem::Specification.new do |s|
71
68
  "test/source/_posts/2009-05-18-tags.textile",
72
69
  "test/source/_posts/2009-06-22-empty-yaml.textile",
73
70
  "test/source/_posts/2009-06-22-no-yaml.textile",
74
- "test/source/_stylesheets/nested/override.less",
75
- "test/source/_stylesheets/simple.less",
71
+ "test/source/_posts/2010-01-08-triple-dash.markdown",
72
+ "test/source/_posts/2010-01-09-date-override.textile",
73
+ "test/source/_posts/2010-01-09-time-override.textile",
76
74
  "test/source/about.html",
77
75
  "test/source/category/_posts/2008-9-23-categories.textile",
78
76
  "test/source/contacts.html",
79
77
  "test/source/css/screen.css",
80
78
  "test/source/foo/_posts/bar/2008-12-12-topical-post.textile",
81
79
  "test/source/index.html",
82
- "test/source/sitemap.xml",
83
80
  "test/source/win/_posts/2009-05-24-yaml-linebreak.markdown",
84
81
  "test/source/z_category/_posts/2008-9-23-categories.textile",
85
82
  "test/suite.rb",
@@ -97,7 +94,6 @@ Gem::Specification.new do |s|
97
94
  s.rdoc_options = ["--charset=UTF-8"]
98
95
  s.require_paths = ["lib"]
99
96
  s.rubyforge_project = %q{jekyll}
100
- s.rubygems_version = %q{1.3.5}
101
97
  s.summary = %q{Jekyll is a simple, blog aware, static site generator.}
102
98
  s.test_files = [
103
99
  "test/helper.rb",
@@ -141,4 +137,3 @@ Gem::Specification.new do |s|
141
137
  s.add_dependency(%q<open4>, [">= 0.9.6"])
142
138
  end
143
139
  end
144
-
@@ -27,6 +27,7 @@ require 'jekyll/filters'
27
27
  require 'jekyll/tags/highlight'
28
28
  require 'jekyll/tags/include'
29
29
  require 'jekyll/albino'
30
+ require 'jekyll/static_file'
30
31
 
31
32
  module Jekyll
32
33
  # Default options. Overriden by values in _config.yml or command-line opts.
@@ -68,10 +69,10 @@ module Jekyll
68
69
  begin
69
70
  config = YAML.load_file(config_file)
70
71
  raise "Invalid configuration - #{config_file}" if !config.is_a?(Hash)
71
- STDOUT.puts "Configuration from #{config_file}"
72
+ $stdout.puts "Configuration from #{config_file}"
72
73
  rescue => err
73
- STDERR.puts "WARNING: Could not read configuration. Using defaults (and options)."
74
- STDERR.puts "\t" + err.to_s
74
+ $stderr.puts "WARNING: Could not read configuration. Using defaults (and options)."
75
+ $stderr.puts "\t" + err.to_s
75
76
  config = {}
76
77
  end
77
78
 
@@ -3,6 +3,10 @@
3
3
  #
4
4
  # Requires
5
5
  # self.site -> Jekyll::Site
6
+ # self.content=
7
+ # self.data=
8
+ # self.ext=
9
+ # self.output=
6
10
  module Jekyll
7
11
  module Convertible
8
12
  # Return the contents as a string
@@ -18,7 +22,7 @@ module Jekyll
18
22
  def read_yaml(base, name)
19
23
  self.content = File.read(File.join(base, name))
20
24
 
21
- if self.content =~ /^(---\s*\n.*?\n?)(---.*?\n)/m
25
+ if self.content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
22
26
  self.content = self.content[($1.size + $2.size)..-1]
23
27
 
24
28
  self.data = YAML.load($1)
@@ -52,7 +56,7 @@ module Jekyll
52
56
  case self.ext[1..-1]
53
57
  when /textile/i
54
58
  return 'textile'
55
- when /markdown/i, /mkdn/i, /md/i
59
+ when /markdown/i, /mkdn/i, /md/i, /mkd/i
56
60
  return 'markdown'
57
61
  when /less/i
58
62
  return 'less'
@@ -19,6 +19,28 @@ class Hash
19
19
 
20
20
  target
21
21
  end
22
+
23
+ # Read array from the supplied hash favouring the singular key
24
+ # and then the plural key, and handling any nil entries.
25
+ # +hash+ the hash to read from
26
+ # +singular_key+ the singular key
27
+ # +plural_key+ the singular key
28
+ #
29
+ # Returns an array
30
+ def pluralized_array(singular_key, plural_key)
31
+ hash = self
32
+ if hash.has_key?(singular_key)
33
+ array = [hash[singular_key]] if hash[singular_key]
34
+ elsif hash.has_key?(plural_key)
35
+ case hash[plural_key]
36
+ when String
37
+ array = hash[plural_key].split
38
+ when Array
39
+ array = hash[plural_key].compact
40
+ end
41
+ end
42
+ array || []
43
+ end
22
44
  end
23
45
 
24
46
  # Thanks, ActiveSupport!
@@ -4,7 +4,7 @@ module Jekyll
4
4
  include Convertible
5
5
 
6
6
  attr_accessor :site
7
- attr_accessor :name, :ext, :basename
7
+ attr_accessor :name, :ext, :basename, :dir
8
8
  attr_accessor :data, :content, :output
9
9
 
10
10
  # Initialize a new Page.
@@ -101,6 +101,10 @@ module Jekyll
101
101
  end
102
102
  end
103
103
 
104
+ def inspect
105
+ "#<Jekyll:Page @name=#{self.name.inspect}>"
106
+ end
107
+
104
108
  private
105
109
 
106
110
  def index?
@@ -4,7 +4,7 @@ module Jekyll
4
4
 
5
5
  def self.calculate_pages(all_posts, per_page)
6
6
  num_pages = all_posts.size / per_page.to_i
7
- num_pages.abs + 1 if all_posts.size % per_page.to_i != 0
7
+ num_pages = num_pages + 1 if all_posts.size % per_page.to_i != 0
8
8
  num_pages
9
9
  end
10
10
 
@@ -18,12 +18,9 @@ module Jekyll
18
18
  name =~ MATCHER
19
19
  end
20
20
 
21
- attr_accessor :site, :date, :slug, :ext, :published, :data, :content, :output, :tags
22
- attr_writer :categories
23
-
24
- def categories
25
- @categories ||= []
26
- end
21
+ attr_accessor :site
22
+ attr_accessor :data, :content, :output, :ext
23
+ attr_accessor :date, :slug, :published, :tags, :categories
27
24
 
28
25
  # Initialize this Post instance.
29
26
  # +site+ is the Site
@@ -41,32 +38,23 @@ module Jekyll
41
38
  self.process(name)
42
39
  self.read_yaml(@base, name)
43
40
 
41
+ #If we've added a date and time to the yaml, use that instead of the filename date
42
+ #Means we'll sort correctly.
43
+ if self.data.has_key?('date')
44
+ # ensure Time via to_s and reparse
45
+ self.date = Time.parse(self.data["date"].to_s)
46
+ end
47
+
44
48
  if self.data.has_key?('published') && self.data['published'] == false
45
49
  self.published = false
46
50
  else
47
51
  self.published = true
48
52
  end
49
53
 
50
- if self.data.has_key?("tag")
51
- self.tags = [self.data["tag"]]
52
- elsif self.data.has_key?("tags")
53
- self.tags = self.data['tags']
54
- else
55
- self.tags = []
56
- end
54
+ self.tags = self.data.pluralized_array("tag", "tags")
57
55
 
58
56
  if self.categories.empty?
59
- if self.data.has_key?('category')
60
- self.categories << self.data['category']
61
- elsif self.data.has_key?('categories')
62
- # Look for categories in the YAML-header, either specified as
63
- # an array or a string.
64
- if self.data['categories'].kind_of? String
65
- self.categories = self.data['categories'].split
66
- else
67
- self.categories = self.data['categories']
68
- end
69
- end
57
+ self.categories = self.data.pluralized_array('category', 'categories')
70
58
  end
71
59
  end
72
60
 
@@ -136,7 +124,7 @@ module Jekyll
136
124
  "month" => date.strftime("%m"),
137
125
  "day" => date.strftime("%d"),
138
126
  "title" => CGI.escape(slug),
139
- "categories" => categories.sort.join('/')
127
+ "categories" => categories.join('/')
140
128
  }.inject(template) { |result, token|
141
129
  result.gsub(/:#{token.first}/, token.last)
142
130
  }.gsub(/\/\//, "/")
@@ -1,7 +1,7 @@
1
1
  module Jekyll
2
2
 
3
3
  class Site
4
- attr_accessor :config, :layouts, :posts, :categories, :exclude,
4
+ attr_accessor :config, :layouts, :stylesheets, :posts, :pages, :static_files, :categories, :exclude,
5
5
  :source, :dest, :lsi, :pygments, :permalink_style, :tags
6
6
 
7
7
  # Initialize the site
@@ -11,7 +11,7 @@ module Jekyll
11
11
  def initialize(config)
12
12
  self.config = config.clone
13
13
 
14
- self.source = config['source']
14
+ self.source = File.expand_path(config['source'])
15
15
  self.dest = config['destination']
16
16
  self.lsi = config['lsi']
17
17
  self.pygments = config['pygments']
@@ -24,7 +24,10 @@ module Jekyll
24
24
 
25
25
  def reset
26
26
  self.layouts = {}
27
+ self.stylesheets = []
27
28
  self.posts = []
29
+ self.pages = []
30
+ self.static_files = []
28
31
  self.categories = Hash.new { |hash, key| hash[key] = [] }
29
32
  self.tags = Hash.new { |hash, key| hash[key] = [] }
30
33
  end
@@ -97,22 +100,29 @@ module Jekyll
97
100
  end
98
101
 
99
102
  # Do the actual work of processing the site and generating the
100
- # real deal.
103
+ # real deal. Now has 4 phases; reset, read, render, write. This allows
104
+ # rendering to have full site payload available.
101
105
  #
102
106
  # Returns nothing
103
107
  def process
104
108
  self.reset
105
- self.read_layouts
106
- self.transform_stylesheets
107
- self.transform_pages
108
- self.write_posts
109
+ self.read
110
+ self.render
111
+ self.write
109
112
  end
110
113
 
111
- # Read all the files in <source>/_layouts into memory for later use.
114
+ def read
115
+ self.read_layouts # existing implementation did this at top level only so preserved that
116
+ self.read_directories
117
+ end
118
+
119
+ # Read all the files in <source>/<dir>/_layouts and create a new Layout
120
+ # object with each one.
112
121
  #
113
122
  # Returns nothing
114
- def read_layouts
115
- base = File.join(self.source, "_layouts")
123
+ def read_layouts(dir = '')
124
+ base = File.join(self.source, dir, "_layouts")
125
+ return unless File.exists?(base)
116
126
  entries = []
117
127
  Dir.chdir(base) { entries = filter_entries(Dir['*.*']) }
118
128
 
@@ -120,17 +130,16 @@ module Jekyll
120
130
  name = f.split(".")[0..-2].join(".")
121
131
  self.layouts[name] = Layout.new(self, base, f)
122
132
  end
123
- rescue Errno::ENOENT => e
124
- # ignore missing layout dir
125
133
  end
126
134
 
127
- # Read all the files in <base>/_posts and create a new Post object with each one.
135
+ # Read all the files in <source>/<dir>/_posts and create a new Post
136
+ # object with each one.
128
137
  #
129
138
  # Returns nothing
130
139
  def read_posts(dir)
131
140
  base = File.join(self.source, dir, '_posts')
132
- entries = []
133
- Dir.chdir(base) { entries = filter_entries(Dir['**/*']) }
141
+ return unless File.exists?(base)
142
+ entries = Dir.chdir(base) { filter_entries(Dir['**/*']) }
134
143
 
135
144
  # first pass processes, but does not yet render post content
136
145
  entries.each do |f|
@@ -146,87 +155,86 @@ module Jekyll
146
155
  end
147
156
 
148
157
  self.posts.sort!
158
+ end
159
+
160
+ def read_stylesheets(dir)
161
+ base = File.join(self.source, dir, '_stylesheets')
162
+ return unless File.exists?(base)
163
+
164
+ entries = []
165
+ Dir.chdir(base) { entries = filter_entries(Dir['**/*.*']) }
166
+
167
+ entries.each do |f|
168
+ stylesheet = Stylesheet.new(self, base, dir, f)
169
+ stylesheet.render()
170
+ stylesheet.write(self.dest)
171
+ end
172
+ end
149
173
 
150
- # second pass renders each post now that full site payload is available
174
+ def render
151
175
  self.posts.each do |post|
152
176
  post.render(self.layouts, site_payload)
153
177
  end
154
178
 
179
+ self.pages.dup.each do |page|
180
+ if Pager.pagination_enabled?(self.config, page.name)
181
+ paginate(page)
182
+ else
183
+ page.render(self.layouts, site_payload)
184
+ end
185
+ end
186
+
155
187
  self.categories.values.map { |ps| ps.sort! { |a, b| b <=> a} }
156
188
  self.tags.values.map { |ps| ps.sort! { |a, b| b <=> a} }
157
189
  rescue Errno::ENOENT => e
158
190
  # ignore missing layout dir
159
191
  end
160
192
 
161
- # Write each post to <dest>/<year>/<month>/<day>/<slug>
193
+ # Write static files, pages and posts
162
194
  #
163
195
  # Returns nothing
164
- def write_posts
196
+ def write
165
197
  self.posts.each do |post|
166
198
  post.write(self.dest)
167
199
  end
200
+ self.pages.each do |page|
201
+ page.write(self.dest)
202
+ end
203
+ self.static_files.each do |sf|
204
+ sf.write(self.dest)
205
+ end
168
206
  end
169
207
 
170
- # Copy all regular files from <source> to <dest>/ ignoring
171
- # any files/directories that are hidden or backup files (start
172
- # with "." or "#" or end with "~") or contain site content (start with "_")
173
- # unless they are "_posts" directories or web server files such as
174
- # '.htaccess'
208
+ # Reads the directories and finds posts, pages and static files that will
209
+ # become part of the valid site according to the rules in +filter_entries+.
175
210
  # The +dir+ String is a relative path used to call this method
176
211
  # recursively as it descends through directories
177
212
  #
178
213
  # Returns nothing
179
- def transform_pages(dir = '')
214
+ def read_directories(dir = '')
180
215
  base = File.join(self.source, dir)
181
216
  entries = filter_entries(Dir.entries(base))
182
- directories = entries.select { |e| File.directory?(File.join(base, e)) }
183
- files = entries.reject { |e| File.directory?(File.join(base, e)) }
184
-
185
- # we need to make sure to process _posts *first* otherwise they
186
- # might not be available yet to other templates as {{ site.posts }}
187
- if directories.include?('_posts')
188
- directories.delete('_posts')
189
- read_posts(dir)
190
- end
191
-
192
- [directories, files].each do |entries|
193
- entries.each do |f|
194
- if File.directory?(File.join(base, f))
195
- next if self.dest.sub(/\/$/, '') == File.join(base, f)
196
- transform_pages(File.join(dir, f))
197
- elsif Pager.pagination_enabled?(self.config, f)
198
- paginate_posts(f, dir)
199
- else
200
- first3 = File.open(File.join(self.source, dir, f)) { |fd| fd.read(3) }
201
-
202
- if first3 == "---"
203
- # file appears to have a YAML header so process it as a page
204
- page = Page.new(self, self.source, dir, f)
205
- page.render(self.layouts, site_payload)
206
- page.write(self.dest)
207
- else
208
- # otherwise copy the file without transforming it
209
- FileUtils.mkdir_p(File.join(self.dest, dir))
210
- FileUtils.cp(File.join(self.source, dir, f), File.join(self.dest, dir, f))
211
- end
212
- end
213
- end
214
- end
215
- end
216
217
 
217
- def transform_stylesheets
218
- dir = "_stylesheets"
219
- base = File.join(self.source, dir)
220
- entries = []
221
- Dir.chdir(base) { entries = filter_entries(Dir['**/*.*']) }
218
+ self.read_posts(dir)
219
+ self.read_stylesheets(dir)
222
220
 
223
221
  entries.each do |f|
224
- stylesheet = Stylesheet.new(self, self.source, dir, f)
225
- stylesheet.render()
226
- stylesheet.write(self.dest)
222
+ f_abs = File.join(base, f)
223
+ f_rel = File.join(dir, f)
224
+ if File.directory?(f_abs)
225
+ next if self.dest.sub(/\/$/, '') == f_abs
226
+ read_directories(f_rel)
227
+ elsif !File.symlink?(f_abs)
228
+ first3 = File.open(f_abs) { |fd| fd.read(3) }
229
+ if first3 == "---"
230
+ # file appears to have a YAML header so process it as a page
231
+ pages << Page.new(self, self.source, dir, f)
232
+ else
233
+ # otherwise treat it as a static file
234
+ static_files << StaticFile.new(self, self.source, dir, f)
235
+ end
236
+ end
227
237
  end
228
- rescue Errno::ENOENT => e
229
- # ignore missing stylesheet dir
230
238
  end
231
239
 
232
240
  # Constructs a hash map of Posts indexed by the specified Post attribute
@@ -255,19 +263,21 @@ module Jekyll
255
263
  end
256
264
 
257
265
  # Filter out any files/directories that are hidden or backup files (start
258
- # with "." or "#" or end with "~") or contain site content (start with "_")
259
- # unless they are "_posts" directories or web server files such as
260
- # '.htaccess'
266
+ # with "." or "#" or end with "~"), or contain site content (start with "_"),
267
+ # or are excluded in the site configuration, unless they are web server
268
+ # files such as '.htaccess'
261
269
  def filter_entries(entries)
262
270
  entries = entries.reject do |e|
263
- unless ['_posts', '.htaccess'].include?(e)
271
+ unless ['.htaccess'].include?(e)
264
272
  ['.', '_', '#'].include?(e[0..0]) || e[-1..-1] == '~' || self.exclude.include?(e)
265
273
  end
266
274
  end
267
275
  end
268
276
 
269
- # Paginates the blog's posts. Renders the index.html file into paginated directories, ie: page2, page3...
270
- # and adds more wite-wide data
277
+ # Paginates the blog's posts. Renders the index.html file into paginated
278
+ # directories, ie: page2/index.html, page3/index.html, etc and adds more
279
+ # site-wide data.
280
+ # +page+ is the index.html Page that requires pagination
271
281
  #
272
282
  # {"paginator" => { "page" => <Number>,
273
283
  # "per_page" => <Number>,
@@ -276,16 +286,19 @@ module Jekyll
276
286
  # "total_pages" => <Number>,
277
287
  # "previous_page" => <Number>,
278
288
  # "next_page" => <Number> }}
279
- def paginate_posts(file, dir)
280
- all_posts = self.posts.sort { |a,b| b <=> a }
289
+ def paginate(page)
290
+ all_posts = site_payload['site']['posts']
281
291
  pages = Pager.calculate_pages(all_posts, self.config['paginate'].to_i)
282
- pages += 1
283
292
  (1..pages).each do |num_page|
284
293
  pager = Pager.new(self.config, num_page, all_posts, pages)
285
- page = Page.new(self, self.source, dir, file)
286
- page.render(self.layouts, site_payload.merge({'paginator' => pager.to_hash}))
287
- suffix = "page#{num_page}" if num_page > 1
288
- page.write(self.dest, suffix)
294
+ if num_page > 1
295
+ newpage = Page.new(self, self.source, page.dir, page.name)
296
+ newpage.render(self.layouts, site_payload.merge({'paginator' => pager.to_hash}))
297
+ newpage.dir = File.join(page.dir, "page#{num_page}")
298
+ self.pages << newpage
299
+ else
300
+ page.render(self.layouts, site_payload.merge({'paginator' => pager.to_hash}))
301
+ end
289
302
  end
290
303
  end
291
304
  end