sixones-jekyll 0.4.1 → 0.5.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,22 +1,22 @@
1
1
  class Hash
2
2
  # Merges self with another hash, recursively.
3
- #
3
+ #
4
4
  # This code was lovingly stolen from some random gem:
5
5
  # http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html
6
- #
6
+ #
7
7
  # Thanks to whoever made it.
8
8
  def deep_merge(hash)
9
9
  target = dup
10
-
10
+
11
11
  hash.keys.each do |key|
12
12
  if hash[key].is_a? Hash and self[key].is_a? Hash
13
13
  target[key] = target[key].deep_merge(hash[key])
14
14
  next
15
15
  end
16
-
16
+
17
17
  target[key] = hash[key]
18
18
  end
19
-
19
+
20
20
  target
21
21
  end
22
22
  end
@@ -1,9 +1,10 @@
1
1
  module Jekyll
2
- module Filters
2
+
3
+ module Filters
3
4
  def textilize(input)
4
5
  RedCloth.new(input).to_html
5
6
  end
6
-
7
+
7
8
  def date_to_string(date)
8
9
  date.strftime("%d %b %Y")
9
10
  end
@@ -11,19 +12,19 @@ module Jekyll
11
12
  def date_to_long_string(date)
12
13
  date.strftime("%d %B %Y")
13
14
  end
14
-
15
+
15
16
  def date_to_xmlschema(date)
16
17
  date.xmlschema
17
18
  end
18
-
19
+
19
20
  def xml_escape(input)
20
21
  input.gsub("&", "&amp;").gsub("<", "&lt;").gsub(">", "&gt;")
21
22
  end
22
-
23
+
23
24
  def number_of_words(input)
24
25
  input.split.length
25
26
  end
26
-
27
+
27
28
  def array_to_sentence_string(array)
28
29
  connector = "and"
29
30
  case array.length
@@ -37,5 +38,6 @@ module Jekyll
37
38
  "#{array[0...-1].join(', ')}, #{connector} #{array[-1]}"
38
39
  end
39
40
  end
40
- end
41
+
42
+ end
41
43
  end
data/lib/jekyll/layout.rb CHANGED
@@ -2,25 +2,28 @@ module Jekyll
2
2
 
3
3
  class Layout
4
4
  include Convertible
5
-
5
+
6
+ attr_accessor :site
6
7
  attr_accessor :ext
7
8
  attr_accessor :data, :content
8
-
9
+
9
10
  # Initialize a new Layout.
11
+ # +site+ is the Site
10
12
  # +base+ is the String path to the <source>
11
13
  # +name+ is the String filename of the post file
12
14
  #
13
15
  # Returns <Page>
14
- def initialize(base, name)
16
+ def initialize(site, base, name)
17
+ @site = site
15
18
  @base = base
16
19
  @name = name
17
-
20
+
18
21
  self.data = {}
19
-
22
+
20
23
  self.process(name)
21
24
  self.read_yaml(base, name)
22
25
  end
23
-
26
+
24
27
  # Extract information from the layout filename
25
28
  # +name+ is the String filename of the layout file
26
29
  #
data/lib/jekyll/page.rb CHANGED
@@ -2,28 +2,31 @@ module Jekyll
2
2
 
3
3
  class Page
4
4
  include Convertible
5
-
5
+
6
+ attr_accessor :site
6
7
  attr_accessor :ext
7
8
  attr_accessor :data, :content, :output
8
-
9
+
9
10
  # Initialize a new Page.
11
+ # +site+ is the Site
10
12
  # +base+ is the String path to the <source>
11
13
  # +dir+ is the String path between <source> and the file
12
14
  # +name+ is the String filename of the file
13
15
  #
14
16
  # Returns <Page>
15
- def initialize(base, dir, name)
17
+ def initialize(site, base, dir, name)
18
+ @site = site
16
19
  @base = base
17
20
  @dir = dir
18
21
  @name = name
19
-
22
+
20
23
  self.data = {}
21
-
24
+
22
25
  self.process(name)
23
26
  self.read_yaml(File.join(base, dir), name)
24
27
  #self.transform
25
28
  end
26
-
29
+
27
30
  # Extract information from the page filename
28
31
  # +name+ is the String filename of the page file
29
32
  #
@@ -31,7 +34,7 @@ module Jekyll
31
34
  def process(name)
32
35
  self.ext = File.extname(name)
33
36
  end
34
-
37
+
35
38
  # Add any necessary layouts to this post
36
39
  # +layouts+ is a Hash of {"name" => "layout"}
37
40
  # +site_payload+ is the site payload hash
@@ -41,19 +44,19 @@ module Jekyll
41
44
  payload = {"page" => self.data}.deep_merge(site_payload)
42
45
  do_layout(payload, layouts)
43
46
  end
44
-
47
+
45
48
  # Write the generated page file to the destination directory.
46
49
  # +dest+ is the String path to the destination dir
47
50
  #
48
51
  # Returns nothing
49
52
  def write(dest)
50
53
  FileUtils.mkdir_p(File.join(dest, @dir))
51
-
54
+
52
55
  name = @name
53
56
  if self.ext != ""
54
57
  name = @name.split(".")[0..-2].join('.') + self.ext
55
58
  end
56
-
59
+
57
60
  path = File.join(dest, @dir, name)
58
61
  File.open(path, 'w') do |f|
59
62
  f.write(self.output)
data/lib/jekyll/post.rb CHANGED
@@ -3,13 +3,13 @@ module Jekyll
3
3
  class Post
4
4
  include Comparable
5
5
  include Convertible
6
-
6
+
7
7
  class << self
8
8
  attr_accessor :lsi
9
9
  end
10
-
10
+
11
11
  MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
12
-
12
+
13
13
  # Post name validator. Post filenames must be like:
14
14
  # 2008-11-05-my-awesome-post.textile
15
15
  #
@@ -17,34 +17,37 @@ module Jekyll
17
17
  def self.valid?(name)
18
18
  name =~ MATCHER
19
19
  end
20
-
20
+
21
+ attr_accessor :site
21
22
  attr_accessor :date, :slug, :ext, :categories, :topics, :published
22
23
  attr_accessor :data, :content, :output
23
-
24
+
24
25
  # Initialize this Post instance.
26
+ # +site+ is the Site
25
27
  # +base+ is the String path to the dir containing the post file
26
28
  # +name+ is the String filename of the post file
27
29
  # +categories+ is an Array of Strings for the categories for this post
28
30
  #
29
31
  # Returns <Post>
30
- def initialize(source, dir, name)
32
+ def initialize(site, source, dir, name)
33
+ @site = site
31
34
  @base = File.join(source, dir, '_posts')
32
35
  @name = name
33
-
36
+
34
37
  self.categories = dir.split('/').reject { |x| x.empty? }
35
-
38
+
36
39
  parts = name.split('/')
37
40
  self.topics = parts.size > 1 ? parts[0..-2] : []
38
-
41
+
39
42
  self.process(name)
40
43
  self.read_yaml(@base, name)
41
44
 
42
- if self.data.has_key?('published') && self.data['published'] == false
43
- self.published = false
44
- else
45
- self.published = true
46
- end
47
-
45
+ if self.data.has_key?('published') && self.data['published'] == false
46
+ self.published = false
47
+ else
48
+ self.published = true
49
+ end
50
+
48
51
  if self.categories.empty?
49
52
  if self.data.has_key?('category')
50
53
  self.categories << self.data['category']
@@ -59,14 +62,14 @@ module Jekyll
59
62
  end
60
63
  end
61
64
  end
62
-
65
+
63
66
  # Spaceship is based on Post#date
64
67
  #
65
68
  # Returns -1, 0, 1
66
69
  def <=>(other)
67
70
  self.date <=> other.date
68
71
  end
69
-
72
+
70
73
  # Extract information from the post filename
71
74
  # +name+ is the String filename of the post file
72
75
  #
@@ -77,7 +80,7 @@ module Jekyll
77
80
  self.slug = slug
78
81
  self.ext = ext
79
82
  end
80
-
83
+
81
84
  # The generated directory into which the post will be placed
82
85
  # upon generation. This is derived from the permalink or, if
83
86
  # permalink is absent, set to the default date
@@ -89,14 +92,14 @@ module Jekyll
89
92
  permalink.to_s.split("/")[0..-2].join("/") + '/'
90
93
  else
91
94
  prefix = self.categories.empty? ? '' : '/' + self.categories.join('/')
92
- if [:date, :pretty].include?(Jekyll.permalink_style)
95
+ if [:date, :pretty].include?(self.site.permalink_style)
93
96
  prefix + date.strftime("/%Y/%m/%d/")
94
97
  else
95
98
  prefix + '/'
96
99
  end
97
100
  end
98
101
  end
99
-
102
+
100
103
  # The full path and filename of the post.
101
104
  # Defined in the YAML of the post body
102
105
  # (Optional)
@@ -105,16 +108,16 @@ module Jekyll
105
108
  def permalink
106
109
  self.data && self.data['permalink']
107
110
  end
108
-
111
+
109
112
  # The generated relative url of this post
110
113
  # e.g. /2008/11/05/my-awesome-post.html
111
114
  #
112
115
  # Returns <String>
113
116
  def url
114
- ext = Jekyll.permalink_style == :pretty ? '' : '.html'
117
+ ext = self.site.permalink_style == :pretty ? '' : '.html'
115
118
  permalink || self.id + ext
116
119
  end
117
-
120
+
118
121
  # The UID for this post (useful in feeds)
119
122
  # e.g. /2008/11/05/my-awesome-post
120
123
  #
@@ -122,14 +125,14 @@ module Jekyll
122
125
  def id
123
126
  self.dir + self.slug
124
127
  end
125
-
128
+
126
129
  # Calculate related posts.
127
130
  #
128
131
  # Returns [<Post>]
129
132
  def related_posts(posts)
130
133
  return [] unless posts.size > 1
131
-
132
- if Jekyll.lsi
134
+
135
+ if self.site.lsi
133
136
  self.class.lsi ||= begin
134
137
  puts "Running the classifier... this could take a while."
135
138
  lsi = Classifier::LSI.new
@@ -144,7 +147,7 @@ module Jekyll
144
147
  (posts - [self])[0..9]
145
148
  end
146
149
  end
147
-
150
+
148
151
  # Add any necessary layouts to this post
149
152
  # +layouts+ is a Hash of {"name" => "layout"}
150
153
  # +site_payload+ is the site payload hash
@@ -158,20 +161,20 @@ module Jekyll
158
161
  "page" => self.to_liquid
159
162
  }
160
163
  payload = payload.deep_merge(site_payload)
161
-
164
+
162
165
  do_layout(payload, layouts)
163
166
  end
164
-
167
+
165
168
  # Write the generated post file to the destination directory.
166
169
  # +dest+ is the String path to the destination dir
167
170
  #
168
171
  # Returns nothing
169
172
  def write(dest)
170
173
  FileUtils.mkdir_p(File.join(dest, dir))
171
-
174
+
172
175
  path = File.join(dest, self.url)
173
176
 
174
- if Jekyll.permalink_style == :pretty
177
+ if self.site.permalink_style == :pretty
175
178
  FileUtils.mkdir_p(path)
176
179
  path = File.join(path, "index.html")
177
180
  end
@@ -180,7 +183,7 @@ module Jekyll
180
183
  f.write(self.output)
181
184
  end
182
185
  end
183
-
186
+
184
187
  # Convert this post into a Hash for use in Liquid templates.
185
188
  #
186
189
  # Returns <Hash>
@@ -190,9 +193,10 @@ module Jekyll
190
193
  "date" => self.date,
191
194
  "id" => self.id,
192
195
  "topics" => self.topics,
196
+ "categories" => self.categories,
193
197
  "content" => self.content }.deep_merge(self.data)
194
198
  end
195
-
199
+
196
200
  def inspect
197
201
  "<Post: #{self.id}>"
198
202
  end
data/lib/jekyll/site.rb CHANGED
@@ -1,50 +1,102 @@
1
1
  module Jekyll
2
-
2
+
3
3
  class Site
4
- attr_accessor :source, :dest
5
- attr_accessor :layouts, :posts, :categories
6
-
4
+ attr_accessor :config, :layouts, :posts, :categories
5
+ attr_accessor :source, :dest, :lsi, :pygments, :permalink_style
6
+
7
7
  # Initialize the site
8
- # +source+ is String path to the source directory containing
9
- # the proto-site
10
- # +dest+ is the String path to the directory where the generated
11
- # site should be written
8
+ # +config+ is a Hash containing site configurations details
12
9
  #
13
10
  # Returns <Site>
14
- def initialize(source, dest)
15
- self.source = source
16
- self.dest = dest
17
- self.layouts = {}
18
- self.posts = []
19
- self.categories = Hash.new { |hash, key| hash[key] = Array.new }
11
+ def initialize(config)
12
+ self.config = config.clone
13
+
14
+ self.source = config['source']
15
+ self.dest = config['destination']
16
+ self.lsi = config['lsi']
17
+ self.pygments = config['pygments']
18
+ self.permalink_style = config['permalink'].to_sym
19
+
20
+ self.reset
21
+ self.setup
20
22
  end
21
-
23
+
24
+ def reset
25
+ self.layouts = {}
26
+ self.posts = []
27
+ self.categories = Hash.new { |hash, key| hash[key] = Array.new }
28
+ end
29
+
30
+ def setup
31
+ # Check to see if LSI is enabled.
32
+ require 'classifier' if self.lsi
33
+
34
+ # Set the Markdown interpreter (and Maruku self.config, if necessary)
35
+ case self.config['markdown']
36
+ when 'rdiscount'
37
+ begin
38
+ require 'rdiscount'
39
+
40
+ def markdown(content)
41
+ RDiscount.new(content).to_html
42
+ end
43
+
44
+ puts 'Using rdiscount for Markdown'
45
+ rescue LoadError
46
+ puts 'You must have the rdiscount gem installed first'
47
+ end
48
+ when 'maruku'
49
+ begin
50
+ require 'maruku'
51
+
52
+ def markdown(content)
53
+ Maruku.new(content).to_html
54
+ end
55
+
56
+ if self.config['maruku']['use_divs']
57
+ require 'maruku/ext/div'
58
+ puts 'Maruku: Using extended syntax for div elements.'
59
+ end
60
+
61
+ if self.config['maruku']['use_tex']
62
+ require 'maruku/ext/math'
63
+ puts "Maruku: Using LaTeX extension. Images in `#{self.config['maruku']['png_dir']}`."
64
+
65
+ # Switch off MathML output
66
+ MaRuKu::Globals[:html_math_output_mathml] = false
67
+ MaRuKu::Globals[:html_math_engine] = 'none'
68
+
69
+ # Turn on math to PNG support with blahtex
70
+ # Resulting PNGs stored in `images/latex`
71
+ MaRuKu::Globals[:html_math_output_png] = true
72
+ MaRuKu::Globals[:html_png_engine] = self.config['maruku']['png_engine']
73
+ MaRuKu::Globals[:html_png_dir] = self.config['maruku']['png_dir']
74
+ MaRuKu::Globals[:html_png_url] = self.config['maruku']['png_url']
75
+ end
76
+ rescue LoadError
77
+ puts "The maruku gem is required for markdown support!"
78
+ end
79
+ end
80
+
81
+ if self.config['custom_filters']
82
+ self.read_filters
83
+ end
84
+ end
85
+
86
+ def textile(content)
87
+ RedCloth.new(content).to_html
88
+ end
89
+
22
90
  # Do the actual work of processing the site and generating the
23
91
  # real deal.
24
92
  #
25
93
  # Returns nothing
26
94
  def process
27
- self.read_filters
95
+ self.reset
28
96
  self.read_layouts
29
97
  self.transform_pages
30
98
  self.write_posts
31
99
  end
32
-
33
- def read_filters
34
- if Jekyll.custom_filters
35
- base = File.join(self.source, "_filters")
36
-
37
- if File.exists?(base)
38
- entries = [ ]
39
-
40
- Dir.chdir(base) { entries = filter_entries(Dir['*.rb*']) }
41
-
42
- entries.each do |f|
43
- require File.join(base, f)
44
- end
45
- end
46
- end
47
- end
48
100
 
49
101
  # Read all the files in <source>/_layouts into memory for later use.
50
102
  #
@@ -53,15 +105,25 @@ module Jekyll
53
105
  base = File.join(self.source, "_layouts")
54
106
  entries = []
55
107
  Dir.chdir(base) { entries = filter_entries(Dir['*.*']) }
56
-
108
+
57
109
  entries.each do |f|
58
110
  name = f.split(".")[0..-2].join(".")
59
- self.layouts[name] = Layout.new(base, f)
111
+ self.layouts[name] = Layout.new(self, base, f)
60
112
  end
61
113
  rescue Errno::ENOENT => e
62
114
  # ignore missing layout dir
63
115
  end
64
116
 
117
+ def read_filters
118
+ base = File.join(self.source, '_filters')
119
+ entries = []
120
+ Dir.chdir(base) { entries = filter_entries(Dir['*.rb']) }
121
+
122
+ entries.each do |f|
123
+ require File.join(base, f)
124
+ end
125
+ end
126
+
65
127
  # Read all the files in <base>/_posts and create a new Post object with each one.
66
128
  #
67
129
  # Returns nothing
@@ -73,7 +135,7 @@ module Jekyll
73
135
  # first pass processes, but does not yet render post content
74
136
  entries.each do |f|
75
137
  if Post.valid?(f)
76
- post = Post.new(self.source, dir, f)
138
+ post = Post.new(self, self.source, dir, f)
77
139
 
78
140
  if post.published
79
141
  self.posts << post
@@ -81,18 +143,18 @@ module Jekyll
81
143
  end
82
144
  end
83
145
  end
84
-
146
+
85
147
  # second pass renders each post now that full site payload is available
86
148
  self.posts.each do |post|
87
149
  post.render(self.layouts, site_payload)
88
150
  end
89
-
151
+
90
152
  self.posts.sort!
91
153
  self.categories.values.map { |cats| cats.sort! { |a, b| b <=> a} }
92
154
  rescue Errno::ENOENT => e
93
155
  # ignore missing layout dir
94
156
  end
95
-
157
+
96
158
  # Write each post to <dest>/<year>/<month>/<day>/<slug>
97
159
  #
98
160
  # Returns nothing
@@ -101,7 +163,7 @@ module Jekyll
101
163
  post.write(self.dest)
102
164
  end
103
165
  end
104
-
166
+
105
167
  # Copy all regular files from <source> to <dest>/ ignoring
106
168
  # any files/directories that are hidden or backup files (start
107
169
  # with "." or "#" or end with "~") or contain site content (start with "_")
@@ -117,7 +179,7 @@ module Jekyll
117
179
  directories = entries.select { |e| File.directory?(File.join(base, e)) }
118
180
  files = entries.reject { |e| File.directory?(File.join(base, e)) }
119
181
 
120
- # we need to make sure to process _posts *first* otherwise they
182
+ # we need to make sure to process _posts *first* otherwise they
121
183
  # might not be available yet to other templates as {{ site.posts }}
122
184
  if directories.include?('_posts')
123
185
  directories.delete('_posts')
@@ -130,10 +192,10 @@ module Jekyll
130
192
  transform_pages(File.join(dir, f))
131
193
  else
132
194
  first3 = File.open(File.join(self.source, dir, f)) { |fd| fd.read(3) }
133
-
195
+
134
196
  if first3 == "---"
135
197
  # file appears to have a YAML header so process it as a page
136
- page = Page.new(self.source, dir, f)
198
+ page = Page.new(self, self.source, dir, f)
137
199
  page.render(self.layouts, site_payload)
138
200
  page.write(self.dest)
139
201
  else
@@ -166,7 +228,7 @@ module Jekyll
166
228
  # "topics" => [<Post>] }}
167
229
  def site_payload
168
230
  {"site" => {
169
- "time" => Time.now,
231
+ "time" => Time.now,
170
232
  "posts" => self.posts.sort { |a,b| b <=> a },
171
233
  "categories" => post_attr_hash('categories'),
172
234
  "topics" => post_attr_hash('topics')
@@ -1,10 +1,11 @@
1
1
  module Jekyll
2
-
2
+
3
3
  class HighlightBlock < Liquid::Block
4
4
  include Liquid::StandardFilters
5
+
5
6
  # we need a language, but the linenos argument is optional.
6
7
  SYNTAX = /(\w+)\s?(:?linenos)?\s?/
7
-
8
+
8
9
  def initialize(tag_name, markup, tokens)
9
10
  super
10
11
  if markup =~ SYNTAX
@@ -19,23 +20,25 @@ module Jekyll
19
20
  raise SyntaxError.new("Syntax Error in 'highlight' - Valid syntax: highlight <lang> [linenos]")
20
21
  end
21
22
  end
22
-
23
+
23
24
  def render(context)
24
- if Jekyll.pygments
25
+ if context.registers[:site].pygments
25
26
  render_pygments(context, super.to_s)
26
27
  else
27
28
  render_codehighlighter(context, super.to_s)
28
29
  end
29
30
  end
30
-
31
+
31
32
  def render_pygments(context, code)
32
- if Jekyll.content_type == :markdown
33
+ if context["content_type"] == :markdown
33
34
  return "\n" + Albino.new(code, @lang).to_s(@options) + "\n"
35
+ elsif context["content_type"] == :textile
36
+ return "<notextile>" + Albino.new(code, @lang).to_s(@options) + "</notextile>"
34
37
  else
35
- "<notextile>" + Albino.new(code, @lang).to_s(@options) + "</notextile>"
38
+ return Albino.new(code, @lang).to_s(@options)
36
39
  end
37
40
  end
38
-
41
+
39
42
  def render_codehighlighter(context, code)
40
43
  #The div is required because RDiscount blows ass
41
44
  <<-HTML
@@ -47,7 +50,7 @@ module Jekyll
47
50
  HTML
48
51
  end
49
52
  end
50
-
53
+
51
54
  end
52
55
 
53
56
  Liquid::Template.register_tag('highlight', Jekyll::HighlightBlock)
@@ -1,17 +1,17 @@
1
1
  module Jekyll
2
-
2
+
3
3
  class IncludeTag < Liquid::Tag
4
4
  def initialize(tag_name, file, tokens)
5
5
  super
6
6
  @file = file.strip
7
7
  end
8
-
8
+
9
9
  def render(context)
10
10
  if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./
11
11
  return "Include file '#{@file}' contains invalid characters or sequences"
12
12
  end
13
-
14
- Dir.chdir(File.join(Jekyll.source, '_includes')) do
13
+
14
+ Dir.chdir(File.join(context.registers[:site].source, '_includes')) do
15
15
  choices = Dir['**/*'].reject { |x| File.symlink?(x) }
16
16
  if choices.include?(@file)
17
17
  source = File.read(@file)
@@ -25,7 +25,7 @@ module Jekyll
25
25
  end
26
26
  end
27
27
  end
28
-
28
+
29
29
  end
30
30
 
31
31
  Liquid::Template.register_tag('include', Jekyll::IncludeTag)