jekyll 0.4.1 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of jekyll might be problematic. Click here for more details.

Files changed (51) hide show
  1. data/History.txt +31 -1
  2. data/README.textile +23 -457
  3. data/Rakefile +91 -0
  4. data/VERSION.yml +2 -2
  5. data/bin/jekyll +61 -57
  6. data/lib/jekyll.rb +48 -32
  7. data/lib/jekyll/albino.rb +13 -7
  8. data/lib/jekyll/converters/mephisto.rb +8 -8
  9. data/lib/jekyll/converters/mt.rb +8 -8
  10. data/lib/jekyll/converters/textpattern.rb +4 -4
  11. data/lib/jekyll/converters/typo.rb +8 -8
  12. data/lib/jekyll/converters/wordpress.rb +1 -2
  13. data/lib/jekyll/convertible.rb +33 -22
  14. data/lib/jekyll/core_ext.rb +5 -5
  15. data/lib/jekyll/filters.rb +15 -7
  16. data/lib/jekyll/layout.rb +9 -6
  17. data/lib/jekyll/page.rb +13 -10
  18. data/lib/jekyll/post.rb +108 -39
  19. data/lib/jekyll/site.rb +121 -51
  20. data/lib/jekyll/tags/highlight.rb +12 -9
  21. data/lib/jekyll/tags/include.rb +5 -5
  22. data/test/helper.rb +20 -6
  23. data/test/source/_posts/2008-02-02-not-published.textile +8 -0
  24. data/test/source/_posts/2008-02-02-published.textile +8 -0
  25. data/test/source/_posts/2009-01-27-array-categories.textile +10 -0
  26. data/test/source/_posts/2009-01-27-categories.textile +7 -0
  27. data/test/source/_posts/2009-01-27-category.textile +7 -0
  28. data/test/source/_posts/2009-03-12-hash-#1.markdown +6 -0
  29. data/test/test_filters.rb +39 -27
  30. data/test/test_generated_site.rb +32 -16
  31. data/test/test_post.rb +258 -102
  32. data/test/test_site.rb +60 -28
  33. data/test/test_tags.rb +103 -18
  34. metadata +25 -70
  35. data/test/dest/2008/10/18/foo-bar.html +0 -28
  36. data/test/dest/2008/11/21/complex.html +0 -29
  37. data/test/dest/2008/12/13/include.html +0 -30
  38. data/test/dest/_posts/2008-10-18-foo-bar.html +0 -28
  39. data/test/dest/_posts/2008-11-21-complex.html +0 -29
  40. data/test/dest/_posts/2008-12-03-permalinked-post.html +0 -2
  41. data/test/dest/_posts/2008-12-13-include.html +0 -30
  42. data/test/dest/category/2008/09/23/categories.html +0 -27
  43. data/test/dest/category/_posts/2008-9-23-categories.html +0 -27
  44. data/test/dest/css/screen.css +0 -76
  45. data/test/dest/foo/2008/12/12/topical-post.html +0 -28
  46. data/test/dest/foo/_posts/bar/2008-12-12-topical-post.html +0 -28
  47. data/test/dest/index.html +0 -60
  48. data/test/dest/my_category/permalinked-post +0 -2
  49. data/test/dest/z_category/2008/09/23/categories.html +0 -27
  50. data/test/dest/z_category/_posts/2008-9-23-categories.html +0 -27
  51. data/test/test_jekyll.rb +0 -0
@@ -0,0 +1,91 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ begin
6
+ gem 'jeweler', '>= 0.11.0'
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |s|
9
+ s.name = "jekyll"
10
+ s.summary = %Q{Jekyll is a simple, blog aware, static site generator.}
11
+ s.email = "tom@mojombo.com"
12
+ s.homepage = "http://github.com/mojombo/jekyll"
13
+ s.description = "Jekyll is a simple, blog aware, static site generator."
14
+ s.authors = ["Tom Preston-Werner"]
15
+ s.rubyforge_project = "jekyll"
16
+ s.files.exclude 'test/dest'
17
+ s.test_files.exclude 'test/dest'
18
+ s.add_dependency('RedCloth', '= 4.1.0')
19
+ s.add_dependency('liquid', '>= 1.9.0')
20
+ s.add_dependency('classifier', '>= 1.3.1')
21
+ s.add_dependency('maruku', '>= 0.5.9')
22
+ s.add_dependency('directory_watcher', '>= 1.1.1')
23
+ s.add_dependency('open4', '>= 0.9.6')
24
+ end
25
+ rescue LoadError
26
+ puts "Jeweler not available. Install it with: sudo gem install jeweler --version '>= 0.11.0'"
27
+ exit(1)
28
+ end
29
+
30
+ Rake::TestTask.new do |t|
31
+ t.libs << 'lib'
32
+ t.pattern = 'test/**/test_*.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+ Rake::RDocTask.new do |rdoc|
37
+ rdoc.rdoc_dir = 'rdoc'
38
+ rdoc.title = 'jekyll'
39
+ rdoc.options << '--line-numbers' << '--inline-source'
40
+ rdoc.rdoc_files.include('README*')
41
+ rdoc.rdoc_files.include('lib/**/*.rb')
42
+ end
43
+
44
+ begin
45
+ require 'rcov/rcovtask'
46
+ Rcov::RcovTask.new do |t|
47
+ t.libs << 'test'
48
+ t.test_files = FileList['test/**/test_*.rb']
49
+ t.verbose = true
50
+ end
51
+ rescue LoadError
52
+ end
53
+
54
+ task :default => [:test, :features]
55
+
56
+ # console
57
+
58
+ desc "Open an irb session preloaded with this library"
59
+ task :console do
60
+ sh "irb -rubygems -I lib -r jekyll.rb"
61
+ end
62
+
63
+ # converters
64
+
65
+ namespace :convert do
66
+ desc "Migrate from mephisto in the current directory"
67
+ task :mephisto do
68
+ sh %q(ruby -r './lib/jekyll/converters/mephisto' -e 'Jekyll::Mephisto.postgres(:database => "#{ENV["DB"]}")')
69
+ end
70
+ desc "Migrate from Movable Type in the current directory"
71
+ task :mt do
72
+ sh %q(ruby -r './lib/jekyll/converters/mt' -e 'Jekyll::MT.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")')
73
+ end
74
+ desc "Migrate from Typo in the current directory"
75
+ task :typo do
76
+ sh %q(ruby -r './lib/jekyll/converters/typo' -e 'Jekyll::Typo.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")')
77
+ end
78
+ end
79
+
80
+ begin
81
+ require 'cucumber/rake/task'
82
+
83
+ Cucumber::Rake::Task.new(:features) do |t|
84
+ t.cucumber_opts = "--format pretty"
85
+ end
86
+ rescue LoadError
87
+ desc 'Cucumber rake task not available'
88
+ task :features do
89
+ abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
90
+ end
91
+ end
@@ -1,4 +1,4 @@
1
1
  ---
2
- :minor: 4
3
- :patch: 1
4
2
  :major: 0
3
+ :minor: 5
4
+ :patch: 1
data/bin/jekyll CHANGED
@@ -9,62 +9,78 @@ Basic Command Line Usage:
9
9
  jekyll # . -> ./_site
10
10
  jekyll <path to write generated site> # . -> <path>
11
11
  jekyll <path to source> <path to write generated site> # <path> -> <path>
12
-
13
- Options:
12
+
13
+ Configuration is read from '<source>/_config.yml' but can be overriden
14
+ using the following options:
15
+
14
16
  HELP
15
17
 
16
18
  require 'optparse'
17
19
  require 'jekyll'
18
20
 
21
+ exec = {}
19
22
  options = {}
20
-
21
23
  opts = OptionParser.new do |opts|
22
24
  opts.banner = help
23
25
 
24
26
  opts.on("--auto", "Auto-regenerate") do
25
- options[:auto] = true
27
+ options['auto'] = true
28
+ end
29
+
30
+ opts.on("--no-auto", "No auto-regenerate") do
31
+ options['auto'] = false
26
32
  end
27
-
33
+
28
34
  opts.on("--server [PORT]", "Start web server (default port 4000)") do |port|
29
- options[:server] = true
30
- options[:server_port] = port || 4000
35
+ options['server'] = true
36
+ options['server_port'] = port unless port.nil?
31
37
  end
32
-
38
+
33
39
  opts.on("--lsi", "Use LSI for better related posts") do
34
- Jekyll.lsi = true
40
+ options['lsi'] = true
35
41
  end
36
-
42
+
37
43
  opts.on("--pygments", "Use pygments to highlight code") do
38
- Jekyll.pygments = true
44
+ options['pygments'] = true
39
45
  end
40
-
46
+
41
47
  opts.on("--rdiscount", "Use rdiscount gem for Markdown") do
42
- begin
43
- require 'rdiscount'
44
- Jekyll.markdown_proc = Proc.new { |x| RDiscount.new(x).to_html }
45
- puts 'Using rdiscount for Markdown'
46
- rescue LoadError
47
- puts 'You must have the rdiscount gem installed first'
48
- end
48
+ options['markdown'] = 'rdiscount'
49
49
  end
50
-
51
- opts.on("--permalink [TYPE]", "Use 'date' (default) for YYYY/MM/DD") do |style|
52
- Jekyll.permalink_style = (style || 'date').to_sym
50
+
51
+ opts.on("--permalink [TYPE]", "Use 'date' (default) for YYYY/MM/DD") do |style|
52
+ options['permalink'] = style unless style.nil?
53
53
  end
54
-
54
+
55
55
  opts.on("--version", "Display current version") do
56
56
  puts "Jekyll " + Jekyll.version
57
57
  exit 0
58
58
  end
59
59
  end
60
60
 
61
+ # Read command line options into `options` hash
61
62
  opts.parse!
62
63
 
63
- def clean(dest)
64
- FileUtils.rm_rf(dest)
65
- FileUtils.mkdir_p(dest)
64
+ # Get source and destintation from command line
65
+ case ARGV.size
66
+ when 0
67
+ when 1
68
+ options['destination'] = ARGV[0]
69
+ when 2
70
+ options['source'] = ARGV[0]
71
+ options['destination'] = ARGV[1]
72
+ else
73
+ puts "Invalid options. Run `jekyll --help` for assistance."
74
+ exit(1)
66
75
  end
67
76
 
77
+ options = Jekyll.configuration(options)
78
+
79
+ # Get source and destination directories (possibly set by config file)
80
+ source = options['source']
81
+ destination = options['destination']
82
+
83
+ # Files to watch
68
84
  def globs(source)
69
85
  Dir.chdir(source) do
70
86
  dirs = Dir['*'].select { |x| File.directory?(x) }
@@ -74,63 +90,51 @@ def globs(source)
74
90
  end
75
91
  end
76
92
 
77
- source = nil
78
- destination = nil
79
-
80
- case ARGV.size
81
- when 0
82
- source = '.'
83
- destination = File.join('.', '_site')
84
- when 1
85
- source = '.'
86
- destination = ARGV[0]
87
- when 2
88
- source = ARGV[0]
89
- destination = ARGV[1]
90
- else
91
- puts "Invalid options. Run `jekyll --help` for assistance."
92
- exit(1)
93
- end
93
+ # Create the Site
94
+ site = Jekyll::Site.new(options)
94
95
 
95
- if options[:auto]
96
+ # Run the directory watcher for auto-generation, if required
97
+ if options['auto']
96
98
  require 'directory_watcher'
97
99
 
98
100
  puts "Auto-regenerating enabled: #{source} -> #{destination}"
99
-
101
+
100
102
  dw = DirectoryWatcher.new(source)
101
103
  dw.interval = 1
102
104
  dw.glob = globs(source)
103
-
105
+
104
106
  dw.add_observer do |*args|
105
107
  t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
106
108
  puts "[#{t}] regeneration: #{args.size} files changed"
107
- Jekyll.process(source, destination)
109
+ site.process
108
110
  end
109
-
111
+
110
112
  dw.start
111
-
112
- unless options[:server]
113
+
114
+ unless options['server']
113
115
  loop { sleep 1000 }
114
116
  end
115
117
  else
116
- Jekyll.process(source, destination)
117
- puts "Successfully generated site in #{destination}"
118
+ puts "Building site: #{source} -> #{destination}"
119
+ site.process
120
+ puts "Successfully generated site: #{source} -> #{destination}"
118
121
  end
119
122
 
120
- if options[:server]
123
+ # Run the server on the specified port, if required
124
+ if options['server']
121
125
  require 'webrick'
122
126
  include WEBrick
123
-
127
+
124
128
  FileUtils.mkdir_p(destination)
125
129
 
126
130
  s = HTTPServer.new(
127
- :Port => options[:server_port],
131
+ :Port => options['server_port'],
128
132
  :DocumentRoot => destination
129
133
  )
130
134
  t = Thread.new {
131
135
  s.start
132
136
  }
133
-
137
+
134
138
  trap("INT") { s.shutdown }
135
139
  t.join()
136
- end
140
+ end
@@ -13,22 +13,6 @@ require 'yaml'
13
13
  # 3rd party
14
14
  require 'liquid'
15
15
  require 'redcloth'
16
- begin
17
- require 'maruku'
18
- require 'maruku/ext/math'
19
- # Switch off MathML output
20
- MaRuKu::Globals[:html_math_output_mathml] = false
21
- MaRuKu::Globals[:html_math_engine] = 'none'
22
-
23
- # Turn on math to PNG support with blahtex
24
- # Resulting PNGs stored in `images/latex`
25
- MaRuKu::Globals[:html_math_output_png] = true
26
- MaRuKu::Globals[:html_png_engine] = 'blahtex'
27
- MaRuKu::Globals[:html_png_dir] = 'images/latex'
28
- MaRuKu::Globals[:html_png_url] = '/images/latex/'
29
- rescue LoadError
30
- puts "The maruku gem is required for markdown support!"
31
- end
32
16
 
33
17
  # internal requires
34
18
  require 'jekyll/core_ext'
@@ -43,23 +27,55 @@ require 'jekyll/tags/include'
43
27
  require 'jekyll/albino'
44
28
 
45
29
  module Jekyll
46
- class << self
47
- attr_accessor :source, :dest, :lsi, :pygments, :markdown_proc, :content_type, :permalink_style
48
- end
49
-
50
- Jekyll.lsi = false
51
- Jekyll.pygments = false
52
- Jekyll.markdown_proc = Proc.new { |x| Maruku.new(x).to_html }
53
- Jekyll.permalink_style = :date
54
-
55
- def self.process(source, dest)
56
- require 'classifier' if Jekyll.lsi
57
-
58
- Jekyll.source = source
59
- Jekyll.dest = dest
60
- Jekyll::Site.new(source, dest).process
30
+ # Default options. Overriden by values in _config.yml or command-line opts.
31
+ # (Strings rather symbols used for compatability with YAML)
32
+ DEFAULTS = {
33
+ 'auto' => false,
34
+ 'server' => false,
35
+ 'server_port' => 4000,
36
+
37
+ 'source' => '.',
38
+ 'destination' => File.join('.', '_site'),
39
+
40
+ 'lsi' => false,
41
+ 'pygments' => false,
42
+ 'markdown' => 'maruku',
43
+ 'permalink' => 'date',
44
+
45
+ 'maruku' => {
46
+ 'use_tex' => false,
47
+ 'use_divs' => false,
48
+ 'png_engine' => 'blahtex',
49
+ 'png_dir' => 'images/latex',
50
+ 'png_url' => '/images/latex'
51
+ }
52
+ }
53
+
54
+ # Generate a Jekyll configuration Hash by merging the default options
55
+ # with anything in _config.yml, and adding the given options on top
56
+ # +override+ is a Hash of config directives
57
+ #
58
+ # Returns Hash
59
+ def self.configuration(override)
60
+ # _config.yml may override default source location, but until
61
+ # then, we need to know where to look for _config.yml
62
+ source = override['source'] || Jekyll::DEFAULTS['source']
63
+
64
+ # Get configuration from <source>/_config.yml
65
+ config = {}
66
+ config_file = File.join(source, '_config.yml')
67
+ begin
68
+ config = YAML.load_file(config_file)
69
+ puts "Configuration from #{config_file}"
70
+ rescue => err
71
+ puts "WARNING: Could not read configuration. Using defaults (and options)."
72
+ puts "\t" + err
73
+ end
74
+
75
+ # Merge DEFAULTS < _config.yml < override
76
+ Jekyll::DEFAULTS.deep_merge(config).deep_merge(override)
61
77
  end
62
-
78
+
63
79
  def self.version
64
80
  yml = YAML.load(File.read(File.join(File.dirname(__FILE__), *%w[.. VERSION.yml])))
65
81
  "#{yml[:major]}.#{yml[:minor]}.#{yml[:patch]}"
@@ -38,7 +38,7 @@
38
38
  #
39
39
  # To see all lexers and formatters available, run `pygmentize -L`.
40
40
  #
41
- # Chris Wanstrath // chris@ozmm.org
41
+ # Chris Wanstrath // chris@ozmm.org
42
42
  # GitHub // http://github.com
43
43
  #
44
44
  require 'open4'
@@ -56,18 +56,24 @@ class Albino
56
56
 
57
57
  def initialize(target, lexer = :text, format = :html)
58
58
  @target = File.exists?(target) ? File.read(target) : target rescue target
59
- @options = { :l => lexer, :f => format }
59
+ @options = { :l => lexer, :f => format, :O => 'encoding=utf-8' }
60
60
  end
61
61
 
62
62
  def execute(command)
63
- pid, stdin, stdout, stderr = Open4.popen4(command)
64
- stdin.puts @target
65
- stdin.close
66
- stdout.read.strip
63
+ output = ''
64
+ Open4.popen4(command) do |pid, stdin, stdout, stderr|
65
+ stdin.puts @target
66
+ stdin.close
67
+ output = stdout.read.strip
68
+ [stdout, stderr].each { |io| io.close }
69
+ end
70
+ output
67
71
  end
68
72
 
69
73
  def colorize(options = {})
70
- execute @@bin + convert_options(options)
74
+ html = execute(@@bin + convert_options(options))
75
+ # Work around an RDiscount bug: http://gist.github.com/97682
76
+ html.to_s.sub(%r{</pre></div>\Z}, "</pre>\n</div>")
71
77
  end
72
78
  alias_method :to_s, :colorize
73
79
 
@@ -13,7 +13,7 @@ require File.join(File.dirname(__FILE__),"csv.rb")
13
13
  # installed, running the following commands should work:
14
14
  # $ sudo gem install sequel
15
15
  # $ sudo gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
16
-
16
+
17
17
  module Jekyll
18
18
  module Mephisto
19
19
  #Accepts a hash with database config variables, exports mephisto posts into a csv
@@ -38,24 +38,24 @@ module Jekyll
38
38
  # through the created posts to make sure nothing is accidently published.
39
39
 
40
40
  QUERY = "SELECT id, permalink, body, published_at, title FROM contents WHERE user_id = 1 AND type = 'Article' AND published_at IS NOT NULL ORDER BY published_at"
41
-
41
+
42
42
  def self.process(dbname, user, pass, host = 'localhost')
43
43
  db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host)
44
-
44
+
45
45
  FileUtils.mkdir_p "_posts"
46
-
46
+
47
47
  db[QUERY].each do |post|
48
48
  title = post[:title]
49
49
  slug = post[:permalink]
50
50
  date = post[:published_at]
51
51
  content = post[:body]
52
52
  # more_content = ''
53
-
53
+
54
54
  # Be sure to include the body and extended body.
55
55
  # if more_content != nil
56
56
  # content = content + " \n" + more_content
57
57
  # end
58
-
58
+
59
59
  # Ideally, this script would determine the post format (markdown, html
60
60
  # , etc) and create files with proper extensions. At this point it
61
61
  # just assumes that markdown will be acceptable.
@@ -66,14 +66,14 @@ module Jekyll
66
66
  'title' => title.to_s,
67
67
  'mt_id' => post[:entry_id],
68
68
  }.delete_if { |k,v| v.nil? || v == ''}.to_yaml
69
-
69
+
70
70
  File.open("_posts/#{name}", "w") do |f|
71
71
  f.puts data
72
72
  f.puts "---"
73
73
  f.puts content
74
74
  end
75
75
  end
76
-
76
+
77
77
  end
78
78
  end
79
79
  end