From bf9dda6c9aaf0ee1cf1d9aa43349e355f7c111d9 Mon Sep 17 00:00:00 2001 From: PJ Hyett Date: Sun, 14 Dec 2008 18:40:45 -0800 Subject: [PATCH 01/49] don't require directory_watcher unless it's needed --- bin/jekyll | 2 ++ lib/jekyll.rb | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/jekyll b/bin/jekyll index 6a641f6b6..6b412c4c3 100755 --- a/bin/jekyll +++ b/bin/jekyll @@ -69,6 +69,8 @@ case ARGV.size end if options[:auto] + require 'directory_watcher' + puts "Auto-regenerating enabled: #{source} -> #{destination}" dw = DirectoryWatcher.new(source) diff --git a/lib/jekyll.rb b/lib/jekyll.rb index 1e2d0bae2..1ef73c7f9 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -17,7 +17,6 @@ begin rescue LoadError puts "The rdiscount gem is required for markdown support!" end -require 'directory_watcher' # internal requires require 'jekyll/site' From b2a1b57b9b3505d765bd45a526f5da1ea50786e1 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Mon, 15 Dec 2008 11:35:03 -0800 Subject: [PATCH 02/49] update history --- History.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/History.txt b/History.txt index a0326f16d..e2e1a6c39 100644 --- a/History.txt +++ b/History.txt @@ -1,3 +1,7 @@ +== + * Minor Enhancements + * Don't load directory_watcher unless it's needed [github.com/pjhyett] + == 0.2.0 / 2008-12-14 * Major Changes * related_posts is now found in site.related_posts From fbdcf469c454299eef8d39624a1dd01d06b36cc6 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Mon, 15 Dec 2008 12:04:19 -0800 Subject: [PATCH 03/49] add markdown test --- test/source/_includes/{sig.textile => sig.markdown} | 0 test/source/_posts/2008-12-13-include.markdown | 8 ++++++++ test/source/_posts/2008-12-13-include.textile | 6 ------ test/test_post.rb | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) rename test/source/_includes/{sig.textile => sig.markdown} (100%) create mode 100644 test/source/_posts/2008-12-13-include.markdown delete mode 100644 test/source/_posts/2008-12-13-include.textile diff --git a/test/source/_includes/sig.textile b/test/source/_includes/sig.markdown similarity index 100% rename from test/source/_includes/sig.textile rename to test/source/_includes/sig.markdown diff --git a/test/source/_posts/2008-12-13-include.markdown b/test/source/_posts/2008-12-13-include.markdown new file mode 100644 index 000000000..1b02ba2aa --- /dev/null +++ b/test/source/_posts/2008-12-13-include.markdown @@ -0,0 +1,8 @@ +--- +layout: default +title: Include +--- + +{% include sig.markdown %} + +This _is_ cool \ No newline at end of file diff --git a/test/source/_posts/2008-12-13-include.textile b/test/source/_posts/2008-12-13-include.textile deleted file mode 100644 index ab7734391..000000000 --- a/test/source/_posts/2008-12-13-include.textile +++ /dev/null @@ -1,6 +0,0 @@ ---- -layout: default -title: Include ---- - -{% include sig.textile %} \ No newline at end of file diff --git a/test/test_post.rb b/test/test_post.rb index f0723cb82..ef10d990f 100644 --- a/test/test_post.rb +++ b/test/test_post.rb @@ -86,10 +86,10 @@ class TestPost < Test::Unit::TestCase def test_include Jekyll.source = File.join(File.dirname(__FILE__), *%w[source]) - p = Post.new(File.join(File.dirname(__FILE__), *%w[source _posts]), "2008-12-13-include.textile") + p = Post.new(File.join(File.dirname(__FILE__), *%w[source _posts]), "2008-12-13-include.markdown") layouts = {"default" => Layout.new(File.join(File.dirname(__FILE__), *%w[source _layouts]), "simple.html")} p.add_layout(layouts, {"site" => {"posts" => []}}) - assert_equal "<<<


\nTom Preston-Werner
\ngithub.com/mojombo

>>>", p.output + assert_equal "<<<
\n

Tom Preston-Werner github.com/mojombo

\n\n

This is cool

>>>", p.output end end \ No newline at end of file From b0004e803a35652c2a7e84c290040c8d689faa16 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Mon, 15 Dec 2008 12:06:54 -0800 Subject: [PATCH 04/49] update history --- History.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/History.txt b/History.txt index e2e1a6c39..9d714ec5a 100644 --- a/History.txt +++ b/History.txt @@ -1,4 +1,6 @@ == + * Major Changes + * Use Maruku (pure Ruby) for Markdown by default [github.com/mreid] * Minor Enhancements * Don't load directory_watcher unless it's needed [github.com/pjhyett] From 59080271ed5100ec9b72ce69d72c38bab0ced321 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Mon, 15 Dec 2008 12:16:35 -0800 Subject: [PATCH 05/49] allow use of rdiscount if --rdiscount is set and gem is installed --- History.txt | 1 + README.textile | 9 ++++++++- bin/jekyll | 10 ++++++++++ lib/jekyll.rb | 3 ++- lib/jekyll/convertible.rb | 2 +- 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/History.txt b/History.txt index 9d714ec5a..2a220e004 100644 --- a/History.txt +++ b/History.txt @@ -1,6 +1,7 @@ == * Major Changes * Use Maruku (pure Ruby) for Markdown by default [github.com/mreid] + * Allow use of RDiscount with --rdiscount flag * Minor Enhancements * Don't load directory_watcher unless it's needed [github.com/pjhyett] diff --git a/README.textile b/README.textile index 75064b939..2352dd889 100644 --- a/README.textile +++ b/README.textile @@ -80,7 +80,7 @@ The best way to install Jekyll is via RubyGems: $ sudo gem install mojombo-jekyll -s http://gems.github.com/ Jekyll requires the gems `directory_watcher`, `liquid`, `open4`, -and `maruku` for markdown support. These are automatically +and `maruku` (for markdown support). These are automatically installed by the gem install command. Maruku comes with optional support for LaTeX to PNG rendering via @@ -123,6 +123,13 @@ during the conversion: $ jekyll --pygments +By default, Jekyll uses "Maruku":http://maruku.rubyforge.org (pure Ruby) for +Markdown support. If you'd like to use RDiscount (faster, but requires +compilation), you must install it (gem install rdiscount) and then you can +have it used instead: + + $ jekyll --rdiscount + h2. Data Jekyll traverses your site looking for files to process. Any files with YAML diff --git a/bin/jekyll b/bin/jekyll index 6b412c4c3..acf8d56fd 100755 --- a/bin/jekyll +++ b/bin/jekyll @@ -32,6 +32,16 @@ opts = OptionParser.new do |opts| opts.on("--pygments", "Use pygments to highlight code") do Jekyll.pygments = true end + + opts.on("--rdiscount", "Use rdiscount gem for Markdown") do + begin + require 'rdiscount' + Jekyll.markdown_proc = Proc.new { |x| RDiscount.new(x).to_html } + puts 'Using rdiscount for Markdown' + rescue LoadError + puts 'You must have the rdiscount gem installed first' + end + end end opts.parse! diff --git a/lib/jekyll.rb b/lib/jekyll.rb index 5bb23dc6d..02e453e3b 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -44,11 +44,12 @@ module Jekyll VERSION = '0.2.0' class << self - attr_accessor :source, :dest, :lsi, :pygments + attr_accessor :source, :dest, :lsi, :pygments, :markdown_proc end Jekyll.lsi = false Jekyll.pygments = false + Jekyll.markdown_proc = Proc.new { |x| Maruku.new(x).to_html } def self.process(source, dest) require 'classifier' if Jekyll.lsi diff --git a/lib/jekyll/convertible.rb b/lib/jekyll/convertible.rb index 08bce9a33..2ab4c7ec2 100644 --- a/lib/jekyll/convertible.rb +++ b/lib/jekyll/convertible.rb @@ -30,7 +30,7 @@ module Jekyll self.content = RedCloth.new(self.content).to_html when ".markdown": self.ext = ".html" - self.content = Maruku.new(self.content).to_html + self.content = Jekyll.markdown_proc.call(self.content) end end From ed60ad6f7203e7bd663d8948ebf958864b05d766 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Mon, 15 Dec 2008 12:34:34 -0800 Subject: [PATCH 06/49] up to 0.2.1 --- History.txt | 2 +- Manifest.txt | 4 ++-- jekyll.gemspec | 6 +++--- lib/jekyll.rb | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/History.txt b/History.txt index 2a220e004..3116d6519 100644 --- a/History.txt +++ b/History.txt @@ -1,4 +1,4 @@ -== +== 0.2.1 / 2008-12-15 * Major Changes * Use Maruku (pure Ruby) for Markdown by default [github.com/mreid] * Allow use of RDiscount with --rdiscount flag diff --git a/Manifest.txt b/Manifest.txt index f30590130..ac74dfbaf 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -17,12 +17,12 @@ lib/jekyll/site.rb lib/jekyll/tags/highlight.rb lib/jekyll/tags/include.rb test/helper.rb -test/source/_includes/sig.textile +test/source/_includes/sig.markdown test/source/_layouts/default.html test/source/_layouts/simple.html test/source/_posts/2008-10-18-foo-bar.textile test/source/_posts/2008-11-21-complex.textile -test/source/_posts/2008-12-13-include.textile +test/source/_posts/2008-12-13-include.markdown test/source/css/screen.css test/source/index.html test/source/posts/2008-12-03-permalinked-post.textile diff --git a/jekyll.gemspec b/jekyll.gemspec index 9b75d2693..625c287c8 100644 --- a/jekyll.gemspec +++ b/jekyll.gemspec @@ -1,15 +1,15 @@ Gem::Specification.new do |s| s.name = %q{jekyll} - s.version = "0.2.0" + s.version = "0.2.1" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Tom Preston-Werner"] - s.date = %q{2008-12-14} + s.date = %q{2008-12-15} s.default_executable = %q{jekyll} s.email = ["tom@mojombo.com"] s.executables = ["jekyll"] s.extra_rdoc_files = ["History.txt", "Manifest.txt"] - s.files = ["History.txt", "Manifest.txt", "README.textile", "Rakefile", "bin/jekyll", "jekyll.gemspec", "lib/jekyll.rb", "lib/jekyll/albino.rb", "lib/jekyll/converters/csv.rb", "lib/jekyll/converters/mephisto.rb", "lib/jekyll/convertible.rb", "lib/jekyll/filters.rb", "lib/jekyll/layout.rb", "lib/jekyll/page.rb", "lib/jekyll/post.rb", "lib/jekyll/site.rb", "lib/jekyll/tags/highlight.rb", "lib/jekyll/tags/include.rb", "test/helper.rb", "test/source/_includes/sig.textile", "test/source/_layouts/default.html", "test/source/_layouts/simple.html", "test/source/_posts/2008-10-18-foo-bar.textile", "test/source/_posts/2008-11-21-complex.textile", "test/source/_posts/2008-12-13-include.textile", "test/source/css/screen.css", "test/source/index.html", "test/source/posts/2008-12-03-permalinked-post.textile", "test/suite.rb", "test/test_jekyll.rb", "test/test_post.rb", "test/test_site.rb"] + s.files = ["History.txt", "Manifest.txt", "README.textile", "Rakefile", "bin/jekyll", "jekyll.gemspec", "lib/jekyll.rb", "lib/jekyll/albino.rb", "lib/jekyll/converters/csv.rb", "lib/jekyll/converters/mephisto.rb", "lib/jekyll/convertible.rb", "lib/jekyll/filters.rb", "lib/jekyll/layout.rb", "lib/jekyll/page.rb", "lib/jekyll/post.rb", "lib/jekyll/site.rb", "lib/jekyll/tags/highlight.rb", "lib/jekyll/tags/include.rb", "test/helper.rb", "test/source/_includes/sig.markdown", "test/source/_layouts/default.html", "test/source/_layouts/simple.html", "test/source/_posts/2008-10-18-foo-bar.textile", "test/source/_posts/2008-11-21-complex.textile", "test/source/_posts/2008-12-13-include.markdown", "test/source/css/screen.css", "test/source/index.html", "test/source/posts/2008-12-03-permalinked-post.textile", "test/suite.rb", "test/test_jekyll.rb", "test/test_post.rb", "test/test_site.rb"] s.has_rdoc = true s.rdoc_options = ["--main", "README.txt"] s.require_paths = ["lib"] diff --git a/lib/jekyll.rb b/lib/jekyll.rb index 02e453e3b..7233a18c4 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -41,7 +41,7 @@ require 'jekyll/tags/include' require 'jekyll/albino' module Jekyll - VERSION = '0.2.0' + VERSION = '0.2.1' class << self attr_accessor :source, :dest, :lsi, :pygments, :markdown_proc From 9ecbfb2253e11f5cb0364e24d4f13595efdd20b6 Mon Sep 17 00:00:00 2001 From: John Reilly Date: Fri, 19 Dec 2008 17:49:57 -0600 Subject: [PATCH 07/49] Added --server option to start a simple WEBrick server on destination directory --- bin/jekyll | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/bin/jekyll b/bin/jekyll index acf8d56fd..307e49364 100755 --- a/bin/jekyll +++ b/bin/jekyll @@ -25,6 +25,10 @@ opts = OptionParser.new do |opts| options[:auto] = true end + opts.on("--server", "Run a WEBrick server on destination directory") do + options[:server] = true + end + opts.on("--lsi", "Use LSI for better related posts") do Jekyll.lsi = true end @@ -78,6 +82,24 @@ case ARGV.size exit(1) end +if options[:server] + require 'webrick' + include WEBrick + + s = HTTPServer.new( + :Port => 4000, + :DocumentRoot => destination + ) + t = Thread.new { + s.start + } + + unless options[:auto] + trap("INT") { s.shutdown } + t.join() + end +end + if options[:auto] require 'directory_watcher' From 6bfaa6bac05cf734b9cb9d850998f2f4a0a8b987 Mon Sep 17 00:00:00 2001 From: John Reilly Date: Fri, 19 Dec 2008 18:16:11 -0600 Subject: [PATCH 08/49] updated readme to include --server option --- README.textile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.textile b/README.textile index 2352dd889..0f68f0e5c 100644 --- a/README.textile +++ b/README.textile @@ -129,6 +129,13 @@ compilation), you must install it (gem install rdiscount) and then you can have it used instead: $ jekyll --rdiscount + +When previewing complex sites locally, simply opening the site in a web +browser (using file://) can cause problems with links that are relative to +the site root (e.g., "/stylesheets/style.css"). To get around this, Jekyll +can launch a simple WEBrick server (works well in conjunction with --auto): + + $ jekyll --server h2. Data From 4c05729adc1630786c2f6bc5a2f4f49577aa39b2 Mon Sep 17 00:00:00 2001 From: remi Date: Sat, 20 Dec 2008 12:45:30 -0700 Subject: [PATCH 09/49] made post's YAML front matter available as post.data --- lib/jekyll/post.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/jekyll/post.rb b/lib/jekyll/post.rb index caca93545..1d2bbb798 100644 --- a/lib/jekyll/post.rb +++ b/lib/jekyll/post.rb @@ -146,7 +146,8 @@ module Jekyll "url" => self.url, "date" => self.date, "id" => self.id, - "content" => self.content } + "content" => self.content, + "data" => self.data } end end From 6d8c73349e2e05529a3e4f7b27dd808070b7ab0e Mon Sep 17 00:00:00 2001 From: remi Date: Sat, 20 Dec 2008 12:53:07 -0700 Subject: [PATCH 10/49] merged Post's YAML front matter into its to_liquid payload, just like Page does. allows {{ page.arbitrary_yaml_data }} (cleaner than {{ page.data['arbitrary_yaml_data'] }}) --- lib/jekyll/post.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/jekyll/post.rb b/lib/jekyll/post.rb index 1d2bbb798..66a8eef67 100644 --- a/lib/jekyll/post.rb +++ b/lib/jekyll/post.rb @@ -142,12 +142,11 @@ module Jekyll # # Returns def to_liquid - { "title" => self.data["title"] || "", + self.data.merge({ "title" => self.data["title"] || "", "url" => self.url, "date" => self.date, "id" => self.id, - "content" => self.content, - "data" => self.data } + "content" => self.content }) end end From 1aad12d93ebb4cb19d3f1822afb72e3a136282f9 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Sun, 21 Dec 2008 18:03:53 -0800 Subject: [PATCH 11/49] update history --- History.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/History.txt b/History.txt index 3116d6519..34ad426e0 100644 --- a/History.txt +++ b/History.txt @@ -1,3 +1,13 @@ +== + * Minor Enhancements + * Added post categories based on directories containing _posts [github.com/mreid] + * Added new date filter that shows the full month name [github.com/mreid] + * Make post's YAML front matter available as post.data [github.com/remi] + * Merge Post's YAML front matter into its to_liquid payload [github.com/remi] + * Bug Fixes + * Change YAML delimiter matcher so as to not chew up 2nd level markdown headers [github.com/mreid] + * Fix bug that meant page data (such as the date) was not available in templates [github.com/mreid] + == 0.2.1 / 2008-12-15 * Major Changes * Use Maruku (pure Ruby) for Markdown by default [github.com/mreid] From f8d76c7bee0deafb462dba41fe68175cbd28579e Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Sun, 21 Dec 2008 18:09:12 -0800 Subject: [PATCH 12/49] update history --- History.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/History.txt b/History.txt index 34ad426e0..389b0e4f0 100644 --- a/History.txt +++ b/History.txt @@ -1,4 +1,6 @@ == + * Major Enhancements + * Added --server option to start a simple WEBrick server on destination directory [github.com/johnreilly] * Minor Enhancements * Added post categories based on directories containing _posts [github.com/mreid] * Added new date filter that shows the full month name [github.com/mreid] From a9f74bc076c03ff9e077523f1338e75043d16868 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Sun, 21 Dec 2008 20:52:41 -0800 Subject: [PATCH 13/49] small stylistic change --- lib/jekyll/post.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/jekyll/post.rb b/lib/jekyll/post.rb index 9f1eec1f6..9bd624f9f 100644 --- a/lib/jekyll/post.rb +++ b/lib/jekyll/post.rb @@ -64,9 +64,11 @@ module Jekyll # Returns def dir path = @categories ? '/' + @categories.join('/') : '' - permalink ? - permalink.to_s.split("/")[0..-2].join("/") : + if permalink + permalink.to_s.split("/")[0..-2].join("/") + else "#{path}" + date.strftime("/%Y/%m/%d/") + end end # The full path and filename of the post. From bb676556a89fb3d185db1058aeadf8cc63f8b71b Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Sun, 21 Dec 2008 21:12:44 -0800 Subject: [PATCH 14/49] properly reject directories in _layouts --- History.txt | 1 + lib/jekyll/site.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.txt b/History.txt index 389b0e4f0..f0f06e138 100644 --- a/History.txt +++ b/History.txt @@ -9,6 +9,7 @@ * Bug Fixes * Change YAML delimiter matcher so as to not chew up 2nd level markdown headers [github.com/mreid] * Fix bug that meant page data (such as the date) was not available in templates [github.com/mreid] + * Properly reject directories in _layouts == 0.2.1 / 2008-12-15 * Major Changes diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index b808bc59c..433c754ad 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -35,7 +35,7 @@ module Jekyll def read_layouts base = File.join(self.source, "_layouts") entries = Dir.entries(base) - entries = entries.reject { |e| File.directory?(e) } + entries = entries.reject { |e| File.directory?(File.join(base, e)) } entries.each do |f| name = f.split(".")[0..-2].join(".") From fd88a56c5518734faf7438a948b582997d6b2f8a Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Sun, 21 Dec 2008 21:26:33 -0800 Subject: [PATCH 15/49] fix double slash caused by empty categories --- lib/jekyll/post.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jekyll/post.rb b/lib/jekyll/post.rb index 9bd624f9f..4abc4e3ab 100644 --- a/lib/jekyll/post.rb +++ b/lib/jekyll/post.rb @@ -63,7 +63,7 @@ module Jekyll # # Returns def dir - path = @categories ? '/' + @categories.join('/') : '' + path = (@categories && !@categories.empty?) ? '/' + @categories.join('/') : '' if permalink permalink.to_s.split("/")[0..-2].join("/") else From 47a894cebfe79bf01a1de54b0067357ac97a0073 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Sun, 21 Dec 2008 21:48:04 -0800 Subject: [PATCH 16/49] allow optional port argument to --server --- History.txt | 2 +- bin/jekyll | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/History.txt b/History.txt index f0f06e138..37bc9aae3 100644 --- a/History.txt +++ b/History.txt @@ -1,6 +1,6 @@ == * Major Enhancements - * Added --server option to start a simple WEBrick server on destination directory [github.com/johnreilly] + * Added --server option to start a simple WEBrick server on destination directory [github.com/johnreilly and github.com/mchung] * Minor Enhancements * Added post categories based on directories containing _posts [github.com/mreid] * Added new date filter that shows the full month name [github.com/mreid] diff --git a/bin/jekyll b/bin/jekyll index 307e49364..fb4abdc83 100755 --- a/bin/jekyll +++ b/bin/jekyll @@ -25,8 +25,9 @@ opts = OptionParser.new do |opts| options[:auto] = true end - opts.on("--server", "Run a WEBrick server on destination directory") do + opts.on("--server [PORT]", "Start web server (default port 4000)") do |port| options[:server] = true + options[:server_port] = port || 4000 end opts.on("--lsi", "Use LSI for better related posts") do @@ -87,7 +88,7 @@ if options[:server] include WEBrick s = HTTPServer.new( - :Port => 4000, + :Port => options[:server_port], :DocumentRoot => destination ) t = Thread.new { From d0fbfca2058a6a9968b7fd0c223078db2c5f9744 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Sun, 21 Dec 2008 22:12:07 -0800 Subject: [PATCH 17/49] fix location of permalink test post --- .../{posts => _posts}/2008-12-03-permalinked-post.textile | 0 test/test_post.rb | 4 ++-- test/test_site.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename test/source/{posts => _posts}/2008-12-03-permalinked-post.textile (100%) diff --git a/test/source/posts/2008-12-03-permalinked-post.textile b/test/source/_posts/2008-12-03-permalinked-post.textile similarity index 100% rename from test/source/posts/2008-12-03-permalinked-post.textile rename to test/source/_posts/2008-12-03-permalinked-post.textile diff --git a/test/test_post.rb b/test/test_post.rb index cbf374edd..a61609dff 100644 --- a/test/test_post.rb +++ b/test/test_post.rb @@ -29,7 +29,7 @@ class TestPost < Test::Unit::TestCase def test_permalink p = Post.allocate p.process("2008-12-03-permalinked-post.textile") - p.read_yaml(File.join(File.dirname(__FILE__), *%w[source posts]), "2008-12-03-permalinked-post.textile") + p.read_yaml(File.join(File.dirname(__FILE__), *%w[source _posts]), "2008-12-03-permalinked-post.textile") assert_equal "my_category/permalinked-post", p.permalink end @@ -37,7 +37,7 @@ class TestPost < Test::Unit::TestCase def test_dir_respects_permalink p = Post.allocate p.process("2008-12-03-permalinked-post.textile") - p.read_yaml(File.join(File.dirname(__FILE__), *%w[source posts]), "2008-12-03-permalinked-post.textile") + p.read_yaml(File.join(File.dirname(__FILE__), *%w[source _posts]), "2008-12-03-permalinked-post.textile") assert_equal "my_category", p.dir end diff --git a/test/test_site.rb b/test/test_site.rb index 7105671f9..ccfd4117e 100644 --- a/test/test_site.rb +++ b/test/test_site.rb @@ -19,7 +19,7 @@ class TestSite < Test::Unit::TestCase def test_read_posts @s.read_posts(File.join(@s.source, '_posts')) - assert_equal 3, @s.posts.size + assert_equal 4, @s.posts.size end def test_write_posts From 8a2a42ba7142f705bb2ef31ec204d0e3c3beef75 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Sun, 21 Dec 2008 23:16:43 -0800 Subject: [PATCH 18/49] restrict include filenames --- History.txt | 1 + lib/jekyll/tags/include.rb | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/History.txt b/History.txt index 37bc9aae3..947f56c8d 100644 --- a/History.txt +++ b/History.txt @@ -6,6 +6,7 @@ * Added new date filter that shows the full month name [github.com/mreid] * Make post's YAML front matter available as post.data [github.com/remi] * Merge Post's YAML front matter into its to_liquid payload [github.com/remi] + * Restrict includes to regular files underneath _includes * Bug Fixes * Change YAML delimiter matcher so as to not chew up 2nd level markdown headers [github.com/mreid] * Fix bug that meant page data (such as the date) was not available in templates [github.com/mreid] diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index f03ed177a..f24942433 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -7,7 +7,18 @@ module Jekyll end def render(context) - File.read(File.join(Jekyll.source, '_includes', @file)) + if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./ + return "Include file '#{@file}' contains invalid characters or sequences" + end + + Dir.chdir(File.join(Jekyll.source, '_includes')) do + choices = Dir['**/*'].reject { |x| File.symlink?(x) } + if choices.include?(@file) + File.read(@file) + else + "Included file '#{@file}' not found in _includes directory" + end + end end end From 8ed84a759027cf062aa085dbf21d48e1105ecded Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Sun, 21 Dec 2008 23:27:09 -0800 Subject: [PATCH 19/49] start server after jekyll processing so webrick has something to serve --- README.textile | 5 +++-- bin/jekyll | 40 +++++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/README.textile b/README.textile index 7cd867293..f792c4809 100644 --- a/README.textile +++ b/README.textile @@ -141,9 +141,10 @@ have it used instead: When previewing complex sites locally, simply opening the site in a web browser (using file://) can cause problems with links that are relative to the site root (e.g., "/stylesheets/style.css"). To get around this, Jekyll -can launch a simple WEBrick server (works well in conjunction with --auto): +can launch a simple WEBrick server (works well in conjunction with --auto). +Default port is 4000: - $ jekyll --server + $ jekyll --server [PORT] h2. Data diff --git a/bin/jekyll b/bin/jekyll index fb4abdc83..34a70b717 100755 --- a/bin/jekyll +++ b/bin/jekyll @@ -83,24 +83,6 @@ case ARGV.size exit(1) end -if options[:server] - require 'webrick' - include WEBrick - - s = HTTPServer.new( - :Port => options[:server_port], - :DocumentRoot => destination - ) - t = Thread.new { - s.start - } - - unless options[:auto] - trap("INT") { s.shutdown } - t.join() - end -end - if options[:auto] require 'directory_watcher' @@ -118,7 +100,27 @@ if options[:auto] dw.start - loop { sleep 1000 } + unless options[:server] + loop { sleep 1000 } + end else Jekyll.process(source, destination) +end + +if options[:server] + require 'webrick' + include WEBrick + + FileUtils.mkdir_p(destination) + + s = HTTPServer.new( + :Port => options[:server_port], + :DocumentRoot => destination + ) + t = Thread.new { + s.start + } + + trap("INT") { s.shutdown } + t.join() end \ No newline at end of file From a99e142163a6fc53708b7770b12833210aeaf646 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Tue, 23 Dec 2008 00:47:24 -0800 Subject: [PATCH 20/49] report success from a normal jekyll run --- bin/jekyll | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/jekyll b/bin/jekyll index 34a70b717..d746806f7 100755 --- a/bin/jekyll +++ b/bin/jekyll @@ -105,6 +105,7 @@ if options[:auto] end else Jekyll.process(source, destination) + puts "Successfully generated site in #{destination}" end if options[:server] From 1cadd8f5b08675821d5f85b7e4b7b1a74a604cc2 Mon Sep 17 00:00:00 2001 From: remi Date: Tue, 23 Dec 2008 03:20:27 -0700 Subject: [PATCH 21/49] Post's YAML front matter is available on post object. No longer a need for post.data (redundant). --- History.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/History.txt b/History.txt index 947f56c8d..e4b7dacf6 100644 --- a/History.txt +++ b/History.txt @@ -4,7 +4,6 @@ * Minor Enhancements * Added post categories based on directories containing _posts [github.com/mreid] * Added new date filter that shows the full month name [github.com/mreid] - * Make post's YAML front matter available as post.data [github.com/remi] * Merge Post's YAML front matter into its to_liquid payload [github.com/remi] * Restrict includes to regular files underneath _includes * Bug Fixes From 896311e572c29e3bcd28027f5f500c44acf7a96d Mon Sep 17 00:00:00 2001 From: remi Date: Tue, 23 Dec 2008 04:31:31 -0700 Subject: [PATCH 22/49] updated Manifest (rake gem wasn't working) --- Manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Manifest.txt b/Manifest.txt index ac74dfbaf..1f0b77641 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -22,10 +22,10 @@ test/source/_layouts/default.html test/source/_layouts/simple.html test/source/_posts/2008-10-18-foo-bar.textile test/source/_posts/2008-11-21-complex.textile +test/source/_posts/2008-12-03-permalinked-post.textile test/source/_posts/2008-12-13-include.markdown test/source/css/screen.css test/source/index.html -test/source/posts/2008-12-03-permalinked-post.textile test/suite.rb test/test_jekyll.rb test/test_post.rb From 0f848ee2d7c72bde0fec7c02998c7e03efa9cb46 Mon Sep 17 00:00:00 2001 From: remi Date: Tue, 23 Dec 2008 04:59:47 -0700 Subject: [PATCH 23/49] Rendered post content wasn't available when pages were being rendered (as {{ site.posts }}). This ensures that we read & render _posts before rendering other pages. --- lib/jekyll/site.rb | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 433c754ad..0a74fc232 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -54,7 +54,12 @@ module Jekyll entries = entries.reject { |e| File.directory?(e) } entries.each do |f| - self.posts << Post.new(base, f) if Post.valid?(f) + if Post.valid?(f) + post = Post.new(base, f) + post.content = Liquid::Template.parse(post.content).render(site_payload, [Jekyll::Filters]) + post.transform + self.posts << post + end end self.posts.sort! @@ -86,10 +91,15 @@ module Jekyll (e != '_posts') and ['.', '_'].include?(e[0..0]) } + # we need to make sure to process _posts *first* otherwise they + # might not be available yet to other templates as {{ site.posts }} + if entries.include? '_posts' + entries.delete '_posts' + read_posts(File.join(base, '_posts')) + end + entries.each do |f| - if f == '_posts' - read_posts(File.join(base, f)) - elsif File.directory?(File.join(base, f)) + if File.directory?(File.join(base, f)) next if self.dest.sub(/\/$/, '') == File.join(base, f) transform_pages(File.join(dir, f)) else From b45fd65a36d9e38c03e617cdf1e71c86059fe306 Mon Sep 17 00:00:00 2001 From: remi Date: Tue, 23 Dec 2008 05:32:25 -0700 Subject: [PATCH 24/49] added tests to confirm that {{ site.posts }} in index.html was empty and {{ post.content }} wasn't rendering (both are now fixed) --- test/source/index.html | 12 +++++++++++- test/test_generated_site.rb | 21 +++++++++++++++++++++ test/test_site.rb | 2 +- 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 test/test_generated_site.rb diff --git a/test/source/index.html b/test/source/index.html index b3cc75568..493fce7cb 100644 --- a/test/source/index.html +++ b/test/source/index.html @@ -5,8 +5,18 @@ title: Tom Preston-Werner h1. Welcome to my site +h2. Please read our {{ site.posts | size }} Posts + \ No newline at end of file + + +{% assign first_post = site.posts.first %} +
+

{{ first_post.title }}

+
+ {{ first_post.content }} +
+
diff --git a/test/test_generated_site.rb b/test/test_generated_site.rb new file mode 100644 index 000000000..56e5e4227 --- /dev/null +++ b/test/test_generated_site.rb @@ -0,0 +1,21 @@ +require File.dirname(__FILE__) + '/helper' + +class TestGeneratedSite < Test::Unit::TestCase + def setup + clear_dest + source = File.join(File.dirname(__FILE__), *%w[source]) + @s = Site.new(source, dest_dir) + @s.process + @index = File.read(File.join(dest_dir, 'index.html')) + end + + def test_site_posts_in_index + # confirm that {{ site.posts }} is working + assert @index.include?("#{@s.posts.size} Posts") + end + + def test_post_content_in_index + # confirm that the {{ post.content }} is rendered OK + assert @index.include?('

This is cool

') + end +end diff --git a/test/test_site.rb b/test/test_site.rb index ccfd4117e..bde6a0080 100644 --- a/test/test_site.rb +++ b/test/test_site.rb @@ -27,4 +27,4 @@ class TestSite < Test::Unit::TestCase @s.process end -end \ No newline at end of file +end From 5a954e04c8b77c5fdcd88fc962ad6a6cd0f342fa Mon Sep 17 00:00:00 2001 From: Mikael Lind Date: Wed, 24 Dec 2008 00:55:47 +0100 Subject: [PATCH 25/49] fixed a path bug in read_posts() --- lib/jekyll/site.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 433c754ad..4ccec5d59 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -51,7 +51,7 @@ module Jekyll # Returns nothing def read_posts(base) entries = Dir.entries(base) - entries = entries.reject { |e| File.directory?(e) } + entries = entries.reject { |e| File.directory?(File.join(base, e)) } entries.each do |f| self.posts << Post.new(base, f) if Post.valid?(f) From d85c0d323601e6d6b7661978e50ff6407aff6669 Mon Sep 17 00:00:00 2001 From: Mikael Lind Date: Wed, 24 Dec 2008 16:07:38 +0100 Subject: [PATCH 26/49] ignore backup files (end with "~") --- lib/jekyll/site.rb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 433c754ad..9af398c37 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -28,13 +28,14 @@ module Jekyll self.write_posts end - # Read all the files in /_layouts into memory for - # later use. + # Read all the files in /_layouts except backup files + # (end with "~") into memory for later use. # # Returns nothing def read_layouts base = File.join(self.source, "_layouts") entries = Dir.entries(base) + entries = entries.reject { |e| e[-1..-1] == '~' } entries = entries.reject { |e| File.directory?(File.join(base, e)) } entries.each do |f| @@ -45,12 +46,13 @@ module Jekyll # ignore missing layout dir end - # Read all the files in /_posts and create a new Post - # object with each one. + # Read all the files in /_posts except backup files (end with "~") + # and create a new Post object with each one. # # Returns nothing def read_posts(base) entries = Dir.entries(base) + entries = entries.reject { |e| e[-1..-1] == '~' } entries = entries.reject { |e| File.directory?(e) } entries.each do |f| @@ -73,8 +75,9 @@ module Jekyll end # Copy all regular files from to / ignoring - # any files/directories that are hidden (start with ".") or contain - # site content (start with "_") unless they are "_posts" directories + # any files/directories that are hidden or backup files (start + # with "." or end with "~") or contain site content (start with "_") + # unless they are "_posts" directories # The +dir+ String is a relative path used to call this method # recursively as it descends through directories # @@ -82,6 +85,7 @@ module Jekyll def transform_pages(dir = '') base = File.join(self.source, dir) entries = Dir.entries(base) + entries = entries.reject { |e| e[-1..-1] == '~' } entries = entries.reject { |e| (e != '_posts') and ['.', '_'].include?(e[0..0]) } From f90ff54acba847112b6a0917e48e0e1cc548cebc Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Wed, 24 Dec 2008 11:14:43 -0800 Subject: [PATCH 27/49] update manifest --- Manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Manifest.txt b/Manifest.txt index ac74dfbaf..1f0b77641 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -22,10 +22,10 @@ test/source/_layouts/default.html test/source/_layouts/simple.html test/source/_posts/2008-10-18-foo-bar.textile test/source/_posts/2008-11-21-complex.textile +test/source/_posts/2008-12-03-permalinked-post.textile test/source/_posts/2008-12-13-include.markdown test/source/css/screen.css test/source/index.html -test/source/posts/2008-12-03-permalinked-post.textile test/suite.rb test/test_jekyll.rb test/test_post.rb From c46ea4096d9b276bd66862b9531fd6c1f063a820 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Wed, 24 Dec 2008 13:17:28 -0800 Subject: [PATCH 28/49] simplify and correct rendering pipeline --- lib/jekyll/convertible.rb | 8 +++----- lib/jekyll/page.rb | 6 +++--- lib/jekyll/post.rb | 19 ++++++++++++------- lib/jekyll/site.rb | 27 +++++++++++++++------------ test/test_post.rb | 10 +++++----- 5 files changed, 38 insertions(+), 32 deletions(-) diff --git a/lib/jekyll/convertible.rb b/lib/jekyll/convertible.rb index 7d1be0ab5..997746848 100644 --- a/lib/jekyll/convertible.rb +++ b/lib/jekyll/convertible.rb @@ -19,7 +19,7 @@ module Jekyll self.data = YAML.load($1) end end - + # Transform the contents based on the file extension. # # Returns nothing @@ -39,10 +39,8 @@ module Jekyll # +site_payload+ is the site payload hash # # Returns nothing - def do_layout(payload, layouts, site_payload) - # construct payload - payload = payload.merge(site_payload) - # render content + def do_layout(payload, layouts) + # render and transform content (this becomes the final content of the object) self.content = Liquid::Template.parse(self.content).render(payload, [Jekyll::Filters]) self.transform diff --git a/lib/jekyll/page.rb b/lib/jekyll/page.rb index 01fe88021..d3488c42a 100644 --- a/lib/jekyll/page.rb +++ b/lib/jekyll/page.rb @@ -37,9 +37,9 @@ module Jekyll # +site_payload+ is the site payload hash # # Returns nothing - def add_layout(layouts, site_payload) - payload = {"page" => self.data} - do_layout(payload, layouts, site_payload) + def render(layouts, site_payload) + payload = {"page" => self.data}.merge(site_payload) + do_layout(payload, layouts) end # Write the generated page file to the destination directory. diff --git a/lib/jekyll/post.rb b/lib/jekyll/post.rb index 4abc4e3ab..76f3cf85e 100644 --- a/lib/jekyll/post.rb +++ b/lib/jekyll/post.rb @@ -123,11 +123,16 @@ module Jekyll # +site_payload+ is the site payload hash # # Returns nothing - def add_layout(layouts, site_payload) - # construct post payload - related = related_posts(site_payload["site"]["posts"]) - payload = {"page" => self.to_liquid.merge(self.data)} - do_layout(payload, layouts, site_payload.merge({"site" => {"related_posts" => related}})) + def render(layouts, site_payload) + # construct payload + payload = + { + "site" => { "related_posts" => related_posts(site_payload["site"]["posts"]) }, + "page" => self.to_liquid + } + payload = payload.merge(site_payload) + + do_layout(payload, layouts) end # Write the generated post file to the destination directory. @@ -147,11 +152,11 @@ module Jekyll # # Returns def to_liquid - self.data.merge({ "title" => self.data["title"] || "", + { "title" => self.data["title"] || "", "url" => self.url, "date" => self.date, "id" => self.id, - "content" => self.content }) + "content" => self.content }.merge(self.data) end end diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index e6ebdb553..f511fba7f 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -53,15 +53,19 @@ module Jekyll entries = Dir.entries(base) entries = entries.reject { |e| File.directory?(File.join(base, e)) } + # first pass processes, but does not yet render post content entries.each do |f| if Post.valid?(f) - post = Post.new(base, f) - post.content = Liquid::Template.parse(post.content).render(site_payload, [Jekyll::Filters]) - post.transform + post = Post.new(base, f) self.posts << post end end + # second pass renders each post now that full site payload is available + self.posts.each do |post| + post.render(self.layouts, site_payload) + end + self.posts.sort! rescue Errno::ENOENT => e # ignore missing layout dir @@ -72,7 +76,6 @@ module Jekyll # Returns nothing def write_posts self.posts.each do |post| - post.add_layout(self.layouts, site_payload) post.write(self.dest) end end @@ -87,14 +90,14 @@ module Jekyll def transform_pages(dir = '') base = File.join(self.source, dir) entries = Dir.entries(base) - entries = entries.reject { |e| - (e != '_posts') and ['.', '_'].include?(e[0..0]) - } + entries = entries.reject do |e| + (e != '_posts') and ['.', '_'].include?(e[0..0]) + end # we need to make sure to process _posts *first* otherwise they # might not be available yet to other templates as {{ site.posts }} - if entries.include? '_posts' - entries.delete '_posts' + if entries.include?('_posts') + entries.delete('_posts') read_posts(File.join(base, '_posts')) end @@ -105,13 +108,13 @@ module Jekyll else first3 = File.open(File.join(self.source, dir, f)) { |fd| fd.read(3) } - # if the file appears to have a YAML header then process it as a page if first3 == "---" + # file appears to have a YAML header so process it as a page page = Page.new(self.source, dir, f) - page.add_layout(self.layouts, site_payload) + page.render(self.layouts, site_payload) page.write(self.dest) - # otherwise copy the file without transforming it else + # otherwise copy the file without transforming it FileUtils.mkdir_p(File.join(self.dest, dir)) FileUtils.cp(File.join(self.source, dir, f), File.join(self.dest, dir, f)) end diff --git a/test/test_post.rb b/test/test_post.rb index a61609dff..d7e8eed8e 100644 --- a/test/test_post.rb +++ b/test/test_post.rb @@ -59,10 +59,10 @@ class TestPost < Test::Unit::TestCase assert_equal "

{{ page.title }}

\n

Best post ever

", p.content end - def test_add_layout + def test_render p = Post.new(File.join(File.dirname(__FILE__), *%w[source _posts]), "2008-10-18-foo-bar.textile") layouts = {"default" => Layout.new(File.join(File.dirname(__FILE__), *%w[source _layouts]), "simple.html")} - p.add_layout(layouts, {"site" => {"posts" => []}}) + p.render(layouts, {"site" => {"posts" => []}}) assert_equal "<<<

Foo Bar

\n

Best post ever

>>>", p.output end @@ -72,14 +72,14 @@ class TestPost < Test::Unit::TestCase p = Post.new(File.join(File.dirname(__FILE__), *%w[source _posts]), "2008-10-18-foo-bar.textile") layouts = {"default" => Layout.new(File.join(File.dirname(__FILE__), *%w[source _layouts]), "simple.html")} - p.add_layout(layouts, {"site" => {"posts" => []}}) + p.render(layouts, {"site" => {"posts" => []}}) p.write(dest_dir) end def test_data p = Post.new(File.join(File.dirname(__FILE__), *%w[source _posts]), "2008-11-21-complex.textile") layouts = {"default" => Layout.new(File.join(File.dirname(__FILE__), *%w[source _layouts]), "simple.html")} - p.add_layout(layouts, {"site" => {"posts" => []}}) + p.render(layouts, {"site" => {"posts" => []}}) assert_equal "<<<

url: /test/source/2008/11/21/complex.html
\ndate: #{Time.parse("2008-11-21")}
\nid: /test/source/2008/11/21/complex

>>>", p.output end @@ -88,7 +88,7 @@ class TestPost < Test::Unit::TestCase Jekyll.source = File.join(File.dirname(__FILE__), *%w[source]) p = Post.new(File.join(File.dirname(__FILE__), *%w[source _posts]), "2008-12-13-include.markdown") layouts = {"default" => Layout.new(File.join(File.dirname(__FILE__), *%w[source _layouts]), "simple.html")} - p.add_layout(layouts, {"site" => {"posts" => []}}) + p.render(layouts, {"site" => {"posts" => []}}) assert_equal "<<<
\n

Tom Preston-Werner github.com/mojombo

\n\n

This is cool

>>>", p.output end From 6de22b318c812e0605d8929d01811e0d251d9b5c Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Wed, 24 Dec 2008 13:20:39 -0800 Subject: [PATCH 29/49] small readme cleanup --- README.textile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.textile b/README.textile index f792c4809..c07e6f677 100644 --- a/README.textile +++ b/README.textile @@ -165,7 +165,7 @@ h3. Global content In layout files, this contains the content of the subview(s). In Posts or - pages, this is undefined. + Pages, this is undefined. h3. Site @@ -280,7 +280,8 @@ becomes h3. Include (Tag) -If you have small page fragments that you wish to include in multiple places on your site, you can use the include tag. +If you have small page fragments that you wish to include in multiple places +on your site, you can use the include tag.
{% include sig.textile %}
From dad9a315597d6647064573a492014424fea4ad24 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Wed, 24 Dec 2008 15:24:27 -0800 Subject: [PATCH 30/49] fix categories and add topics --- History.txt | 1 + README.textile | 28 ++++++++++++++++++---------- lib/jekyll/post.rb | 25 ++++++++++++++----------- lib/jekyll/site.rb | 15 +++++++++------ test/test_post.rb | 14 +++++++++----- test/test_site.rb | 2 +- 6 files changed, 52 insertions(+), 33 deletions(-) diff --git a/History.txt b/History.txt index e4b7dacf6..395d8e71e 100644 --- a/History.txt +++ b/History.txt @@ -3,6 +3,7 @@ * Added --server option to start a simple WEBrick server on destination directory [github.com/johnreilly and github.com/mchung] * Minor Enhancements * Added post categories based on directories containing _posts [github.com/mreid] + * Added post topics based on directories underneath _posts * Added new date filter that shows the full month name [github.com/mreid] * Merge Post's YAML front matter into its to_liquid payload [github.com/remi] * Restrict includes to regular files underneath _includes diff --git a/README.textile b/README.textile index c07e6f677..6459aa1ff 100644 --- a/README.textile +++ b/README.textile @@ -53,12 +53,11 @@ filename is used to construct the URL in the generated site. The example post, for instance, ends up at http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html. -Categories for posts are derived from the directory structure the posts were -found within. -A post that appears in the directory foo/bar/_posts is placed in the categories -'foo' and 'bar'. -By selecting posts from particular categories in your Liquid templates, you will -be able to host multiple blogs within a site. +Categories for posts are derived from the directory structure the posts were +found within. A post that appears in the directory foo/bar/_posts is placed in +the categories 'foo' and 'bar'. By selecting posts from particular categories +in your Liquid templates, you will be able to host multiple blogs within a +site. Files that do not reside in directories prefixed with an underscore are mirrored into a corresponding directory structure in the generated site. If a @@ -182,7 +181,7 @@ h3. Site --lsi (latent semantic indexing) option. site.categories.CATEGORY - The list of all posts in category CATEGORY. + The list of all Posts in category CATEGORY. h3. Post @@ -200,12 +199,21 @@ h3. Post An identifier unique to the Post (useful in RSS feeds). e.g. /2008/12/14/my-post + post.categories + The list of categories to which this post belongs. Categories are + derived from the directory structure above the _posts directory. For + example, a post at /work/code/_posts/2008-12-24-closures.textile + would have this field set to ['work', 'code']. + + post.topics + The list of topics for this Post. Topics are derived from the directory + structure beneath the _posts directory. For example, a post at + /_posts/music/metal/2008-12-24-metalocalypse.textile would have this field + set to ['music', 'metal']. + post.content The content of the Post. - post.categories - The list of categories to which this post belongs. - h2. YAML Front Matter Any files that contain a YAML front matter block will be processed by Jekyll diff --git a/lib/jekyll/post.rb b/lib/jekyll/post.rb index 76f3cf85e..53bcbb22e 100644 --- a/lib/jekyll/post.rb +++ b/lib/jekyll/post.rb @@ -8,7 +8,7 @@ module Jekyll attr_accessor :lsi end - MATCHER = /^(\d+-\d+-\d+)-(.*)(\.[^.]+)$/ + MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/ # Post name validator. Post filenames must be like: # 2008-11-05-my-awesome-post.textile @@ -18,7 +18,7 @@ module Jekyll name =~ MATCHER end - attr_accessor :date, :slug, :ext, :categories + attr_accessor :date, :slug, :ext, :categories, :topics attr_accessor :data, :content, :output # Initialize this Post instance. @@ -27,15 +27,17 @@ module Jekyll # +categories+ is an Array of Strings for the categories for this post # # Returns - def initialize(base, name) - @base = base + def initialize(source, dir, name) + @base = File.join(source, dir, '_posts') @name = name - @categories = base.split('/').reject { |p| ['.', '_posts'].include? p } + + self.categories = dir.split('/').reject { |x| x.empty? } + + parts = name.split('/') + self.topics = parts.size > 1 ? parts[0..-2] : [] self.process(name) - self.read_yaml(base, name) - #Removed to avoid munging of liquid tags, replaced in convertible.rb#48 - #self.transform + self.read_yaml(@base, name) end # Spaceship is based on Post#date @@ -50,7 +52,7 @@ module Jekyll # # Returns nothing def process(name) - m, date, slug, ext = *name.match(MATCHER) + m, cats, date, slug, ext = *name.match(MATCHER) self.date = Time.parse(date) self.slug = slug self.ext = ext @@ -63,11 +65,11 @@ module Jekyll # # Returns def dir - path = (@categories && !@categories.empty?) ? '/' + @categories.join('/') : '' if permalink permalink.to_s.split("/")[0..-2].join("/") else - "#{path}" + date.strftime("/%Y/%m/%d/") + prefix = self.categories.empty? ? '' : '/' + self.categories.join('/') + prefix + date.strftime("/%Y/%m/%d/") end end @@ -156,6 +158,7 @@ module Jekyll "url" => self.url, "date" => self.date, "id" => self.id, + "topics" => self.topics, "content" => self.content }.merge(self.data) end end diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index f511fba7f..bbd73391f 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -49,14 +49,17 @@ module Jekyll # object with each one. # # Returns nothing - def read_posts(base) - entries = Dir.entries(base) + def read_posts(dir) + base = File.join(self.source, dir, '_posts') + + entries = [] + Dir.chdir(base) { entries = Dir['**/*'] } entries = entries.reject { |e| File.directory?(File.join(base, e)) } # first pass processes, but does not yet render post content entries.each do |f| if Post.valid?(f) - post = Post.new(base, f) + post = Post.new(self.source, dir, f) self.posts << post end end @@ -98,7 +101,7 @@ module Jekyll # might not be available yet to other templates as {{ site.posts }} if entries.include?('_posts') entries.delete('_posts') - read_posts(File.join(base, '_posts')) + read_posts(dir) end entries.each do |f| @@ -128,9 +131,9 @@ module Jekyll def site_payload # Build the category hash map of category ( names => arrays of posts ) # then sort each array in reverse order - categories = Hash.new { |hash,key| hash[key] = Array.new } + categories = Hash.new { |hash, key| hash[key] = Array.new } self.posts.each { |p| p.categories.each { |c| categories[c] << p } } - categories.values.map { |cats| cats.sort! { |a,b| b <=> a} } + categories.values.map { |cats| cats.sort! { |a, b| b <=> a} } {"site" => { "time" => Time.now, diff --git a/test/test_post.rb b/test/test_post.rb index d7e8eed8e..01e1dd8b5 100644 --- a/test/test_post.rb +++ b/test/test_post.rb @@ -7,6 +7,9 @@ class TestPost < Test::Unit::TestCase def test_valid assert Post.valid?("2008-10-19-foo-bar.textile") + assert Post.valid?("foo/bar/2008-10-19-foo-bar.textile") + + assert !Post.valid?("lol2008-10-19-foo-bar.textile") assert !Post.valid?("blah") end @@ -21,6 +24,7 @@ class TestPost < Test::Unit::TestCase def test_url p = Post.allocate + p.categories = [] p.process("2008-10-19-foo-bar.textile") assert_equal "/2008/10/19/foo-bar.html", p.url @@ -60,7 +64,7 @@ class TestPost < Test::Unit::TestCase end def test_render - p = Post.new(File.join(File.dirname(__FILE__), *%w[source _posts]), "2008-10-18-foo-bar.textile") + p = Post.new(File.join(File.dirname(__FILE__), *%w[source]), '', "2008-10-18-foo-bar.textile") layouts = {"default" => Layout.new(File.join(File.dirname(__FILE__), *%w[source _layouts]), "simple.html")} p.render(layouts, {"site" => {"posts" => []}}) @@ -70,23 +74,23 @@ class TestPost < Test::Unit::TestCase def test_write clear_dest - p = Post.new(File.join(File.dirname(__FILE__), *%w[source _posts]), "2008-10-18-foo-bar.textile") + p = Post.new(File.join(File.dirname(__FILE__), *%w[source]), '', "2008-10-18-foo-bar.textile") layouts = {"default" => Layout.new(File.join(File.dirname(__FILE__), *%w[source _layouts]), "simple.html")} p.render(layouts, {"site" => {"posts" => []}}) p.write(dest_dir) end def test_data - p = Post.new(File.join(File.dirname(__FILE__), *%w[source _posts]), "2008-11-21-complex.textile") + p = Post.new(File.join(File.dirname(__FILE__), *%w[source]), '', "2008-11-21-complex.textile") layouts = {"default" => Layout.new(File.join(File.dirname(__FILE__), *%w[source _layouts]), "simple.html")} p.render(layouts, {"site" => {"posts" => []}}) - assert_equal "<<<

url: /test/source/2008/11/21/complex.html
\ndate: #{Time.parse("2008-11-21")}
\nid: /test/source/2008/11/21/complex

>>>", p.output + assert_equal "<<<

url: /2008/11/21/complex.html
\ndate: #{Time.parse("2008-11-21")}
\nid: /2008/11/21/complex

>>>", p.output end def test_include Jekyll.source = File.join(File.dirname(__FILE__), *%w[source]) - p = Post.new(File.join(File.dirname(__FILE__), *%w[source _posts]), "2008-12-13-include.markdown") + p = Post.new(File.join(File.dirname(__FILE__), *%w[source]), '', "2008-12-13-include.markdown") layouts = {"default" => Layout.new(File.join(File.dirname(__FILE__), *%w[source _layouts]), "simple.html")} p.render(layouts, {"site" => {"posts" => []}}) diff --git a/test/test_site.rb b/test/test_site.rb index bde6a0080..52c1ca83a 100644 --- a/test/test_site.rb +++ b/test/test_site.rb @@ -17,7 +17,7 @@ class TestSite < Test::Unit::TestCase end def test_read_posts - @s.read_posts(File.join(@s.source, '_posts')) + @s.read_posts('') assert_equal 4, @s.posts.size end From d435eaae5f90c1c42d0e12b9692e31ef29117b4d Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Wed, 24 Dec 2008 15:27:41 -0800 Subject: [PATCH 31/49] update manifest --- Manifest.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Manifest.txt b/Manifest.txt index 1f0b77641..5df15ac9b 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -27,6 +27,7 @@ test/source/_posts/2008-12-13-include.markdown test/source/css/screen.css test/source/index.html test/suite.rb +test/test_generated_site.rb test/test_jekyll.rb test/test_post.rb test/test_site.rb From a8ab6a0adb5121c9628d1e76fae58257d988c2b1 Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Tue, 23 Dec 2008 23:57:27 +1100 Subject: [PATCH 32/49] Added wordpress converter --- lib/jekyll/converters/wordpress.rb | 54 ++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 lib/jekyll/converters/wordpress.rb diff --git a/lib/jekyll/converters/wordpress.rb b/lib/jekyll/converters/wordpress.rb new file mode 100644 index 000000000..1074655ab --- /dev/null +++ b/lib/jekyll/converters/wordpress.rb @@ -0,0 +1,54 @@ +require 'rubygems' +require 'sequel' +require 'fileutils' + +# NOTE: This converter requires Sequel and the MySQL gems. +# The MySQL gem can be difficult to install on OS X. Once you have MySQL +# installed, running the following commands should work: +# $ sudo gem install sequel +# $ sudo gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config + +module Jekyll + module WordPress + + # Reads a MySQL database via Sequel and creates a post file for each + # post in wp_posts that has post_status = 'publish'. + # This restriction is made because 'draft' posts are not guaranteed to + # have valid dates. + QUERY = "select * from wp_posts where post_status = 'publish' and post_type = 'post'" + + def self.process(dbname, user, pass, host = 'localhost') + db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host) + + FileUtils.mkdir_p "_posts" + + db[QUERY].each do |post| + # Get required fields and construct Jekyll compatible name + title = post[:post_title] + slug = post[:post_name] + date = post[:post_date] + content = post[:post_content] + + name = [date.year, date.month, date.day, slug].join('-') + ".markdown" + + # Get the relevant fields as a hash, delete empty fields and convert + # to YAML for the header + data = { + 'layout' => 'post', + 'title' => title.to_s, + 'excerpt' => post[:post_excerpt].to_s, + 'wordpress_id' => post[:ID], + 'wordpress_url' => post[:guid] + }.delete_if { |k,v| v.nil? || v == ''}.to_yaml + + # Write out the data and content to file + File.open("_posts/#{name}", "w") do |f| + f.puts data + f.puts "---" + f.puts content + end + end + + end + end +end \ No newline at end of file From 8477cb5946edf3296bd5872c51c67398a855a4f1 Mon Sep 17 00:00:00 2001 From: Nick Gerakines Date: Wed, 24 Dec 2008 16:16:18 -0800 Subject: [PATCH 33/49] Adding Movable Type migration library to lib/jekyll/converters/. --- Manifest.txt | 2 ++ README.textile | 18 +++++++++++ Rakefile | 3 ++ lib/jekyll/converters/mt.rb | 59 +++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 lib/jekyll/converters/mt.rb diff --git a/Manifest.txt b/Manifest.txt index 5df15ac9b..f43cc645a 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -8,6 +8,8 @@ lib/jekyll.rb lib/jekyll/albino.rb lib/jekyll/converters/csv.rb lib/jekyll/converters/mephisto.rb +lib/jekyll/converters/wordpress.rb +lib/jekyll/converters/mt.rb lib/jekyll/convertible.rb lib/jekyll/filters.rb lib/jekyll/layout.rb diff --git a/README.textile b/README.textile index 6459aa1ff..e50f05247 100644 --- a/README.textile +++ b/README.textile @@ -361,6 +361,24 @@ The best way to get your changes merged back into core is as follows: # Push the branch up to GitHub # Send me (mojombo) a pull request for your branch +h2. Blog migrations + +h3. Movable Type + +To migrate your MT blog into Jekyll, you'll need read access to the database. +The lib/jekyll/converters/mt.rb module provides a simple convert to create +.markdown files in a _posts directory based on the entries contained therein. + + $ export DB=my_mtdb + $ export USER=dbuser + $ export PASS=dbpass + $ ruby -r './lib/jekyll/converters/mt' -e 'Jekyll::MT.process( \ + "#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")' + +You may need to adjust the SQL query used to retrieve MT entries. Left alone, +it will attempt to pull all entries across all blogs regardless of status. +Please check the results and verify the posts before publishing. + h2. License (The MIT License) diff --git a/Rakefile b/Rakefile index 3241e9935..a7a95707f 100644 --- a/Rakefile +++ b/Rakefile @@ -18,4 +18,7 @@ namespace :convert do task :mephisto do sh %q(ruby -r './lib/jekyll/converters/mephisto' -e 'Jekyll::Mephisto.postgres(:database => "#{ENV["DB"]}")') end + task :mt do + sh %q(ruby -r './lib/jekyll/converters/mt' -e 'Jekyll::MT.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")') + end end diff --git a/lib/jekyll/converters/mt.rb b/lib/jekyll/converters/mt.rb new file mode 100644 index 000000000..e207760af --- /dev/null +++ b/lib/jekyll/converters/mt.rb @@ -0,0 +1,59 @@ +# Created by Nick Gerakines, open source and publically available under the +# MIT license. Use this module at your own risk. +# I'm an Erlang/Perl/C++ guy so please forgive my dirty ruby. + +require 'rubygems' +require 'sequel' +require 'fileutils' + +# NOTE: This converter requires Sequel and the MySQL gems. +# The MySQL gem can be difficult to install on OS X. Once you have MySQL +# installed, running the following commands should work: +# $ sudo gem install sequel +# $ sudo gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config + +module Jekyll + module MT + # This query will pull blog posts from all entries across all blogs. If + # you've got unpublished, deleted or otherwise hidden posts please sift + # through the created posts to make sure nothing is accidently published. + QUERY = "SELECT entry_id, entry_basename, entry_text, entry_text_more, entry_created_on, entry_title FROM mt_entry" + + def self.process(dbname, user, pass, host = 'localhost') + db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host) + + FileUtils.mkdir_p "_posts" + + db[QUERY].each do |post| + title = post[:entry_title] + slug = post[:entry_basename] + date = post[:entry_created_on] + content = post[:entry_text] + more_content = post[:entry_text_more] + + # Be sure to include the body and extended body. + if more_content != nil + conent = content + " \n" + more_content + end + + # Ideally, this script would determine the post format (markdown, html + # , etc) and create files with proper extensions. At this point it + # just assumes that markdown will be acceptable. + name = [date.year, date.month, date.day, slug].join('-') + ".markdown" + + data = { + 'layout' => 'post', + 'title' => title.to_s, + 'mt_id' => post[:entry_id], + }.delete_if { |k,v| v.nil? || v == ''}.to_yaml + + File.open("_posts/#{name}", "w") do |f| + f.puts data + f.puts "---" + f.puts content + end + end + + end + end +end From dd8054411c91025ccec9bbc7aad8c8b12366d462 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Wed, 24 Dec 2008 22:05:46 -0800 Subject: [PATCH 34/49] deep merge hashes so as to not lose data --- Manifest.txt | 3 ++- lib/jekyll.rb | 1 + lib/jekyll/convertible.rb | 2 +- lib/jekyll/core_ext.rb | 22 ++++++++++++++++++++++ lib/jekyll/layout.rb | 15 --------------- lib/jekyll/page.rb | 2 +- lib/jekyll/post.rb | 8 ++++++-- 7 files changed, 33 insertions(+), 20 deletions(-) create mode 100644 lib/jekyll/core_ext.rb diff --git a/Manifest.txt b/Manifest.txt index f43cc645a..eb613ef21 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -8,9 +8,10 @@ lib/jekyll.rb lib/jekyll/albino.rb lib/jekyll/converters/csv.rb lib/jekyll/converters/mephisto.rb -lib/jekyll/converters/wordpress.rb lib/jekyll/converters/mt.rb +lib/jekyll/converters/wordpress.rb lib/jekyll/convertible.rb +lib/jekyll/core_ext.rb lib/jekyll/filters.rb lib/jekyll/layout.rb lib/jekyll/page.rb diff --git a/lib/jekyll.rb b/lib/jekyll.rb index 9e6b610e5..3676b5763 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -31,6 +31,7 @@ rescue LoadError end # internal requires +require 'jekyll/core_ext' require 'jekyll/site' require 'jekyll/convertible' require 'jekyll/layout' diff --git a/lib/jekyll/convertible.rb b/lib/jekyll/convertible.rb index 997746848..d86776571 100644 --- a/lib/jekyll/convertible.rb +++ b/lib/jekyll/convertible.rb @@ -50,7 +50,7 @@ module Jekyll # recursively render layouts layout = layouts[self.data["layout"]] while layout - payload = payload.merge({"content" => self.output, "page" => payload['page']}) + payload = payload.deep_merge({"content" => self.output, "page" => layout.data}) self.output = Liquid::Template.parse(layout.content).render(payload, [Jekyll::Filters]) layout = layouts[layout.data["layout"]] diff --git a/lib/jekyll/core_ext.rb b/lib/jekyll/core_ext.rb new file mode 100644 index 000000000..de5847110 --- /dev/null +++ b/lib/jekyll/core_ext.rb @@ -0,0 +1,22 @@ +class Hash + # Merges self with another hash, recursively. + # + # This code was lovingly stolen from some random gem: + # http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html + # + # Thanks to whoever made it. + def deep_merge(hash) + target = dup + + hash.keys.each do |key| + if hash[key].is_a? Hash and self[key].is_a? Hash + target[key] = target[key].deep_merge(hash[key]) + next + end + + target[key] = hash[key] + end + + target + end +end \ No newline at end of file diff --git a/lib/jekyll/layout.rb b/lib/jekyll/layout.rb index 50397c40c..391cf69ce 100644 --- a/lib/jekyll/layout.rb +++ b/lib/jekyll/layout.rb @@ -28,21 +28,6 @@ module Jekyll def process(name) self.ext = File.extname(name) end - - # Add any necessary layouts to this post - # +layouts+ is a Hash of {"name" => "layout"} - # +site_payload+ is the site payload hash - # - # Returns nothing - def add_layout(layouts, site_payload) - payload = {"page" => self.data}.merge(site_payload) - self.content = Liquid::Template.parse(self.content).render(payload, [Jekyll::Filters]) - - layout = layouts[self.data["layout"]] || self.content - payload = {"content" => self.content, "page" => self.data} - - self.content = Liquid::Template.parse(layout).render(payload, [Jekyll::Filters]) - end end end \ No newline at end of file diff --git a/lib/jekyll/page.rb b/lib/jekyll/page.rb index d3488c42a..140258fcc 100644 --- a/lib/jekyll/page.rb +++ b/lib/jekyll/page.rb @@ -38,7 +38,7 @@ module Jekyll # # Returns nothing def render(layouts, site_payload) - payload = {"page" => self.data}.merge(site_payload) + payload = {"page" => self.data}.deep_merge(site_payload) do_layout(payload, layouts) end diff --git a/lib/jekyll/post.rb b/lib/jekyll/post.rb index 53bcbb22e..2cebc0ff4 100644 --- a/lib/jekyll/post.rb +++ b/lib/jekyll/post.rb @@ -132,7 +132,7 @@ module Jekyll "site" => { "related_posts" => related_posts(site_payload["site"]["posts"]) }, "page" => self.to_liquid } - payload = payload.merge(site_payload) + payload = payload.deep_merge(site_payload) do_layout(payload, layouts) end @@ -159,7 +159,11 @@ module Jekyll "date" => self.date, "id" => self.id, "topics" => self.topics, - "content" => self.content }.merge(self.data) + "content" => self.content }.deep_merge(self.data) + end + + def inspect + "" end end From e7b2df11563180e3397ae46e97212ab34039868d Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Wed, 24 Dec 2008 22:10:22 -0800 Subject: [PATCH 35/49] up to 0.3.0 --- History.txt | 2 +- jekyll.gemspec | 8 ++++---- lib/jekyll.rb | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/History.txt b/History.txt index 395d8e71e..06d009ae4 100644 --- a/History.txt +++ b/History.txt @@ -1,4 +1,4 @@ -== +== 0.3.0 / 2008-12-24 * Major Enhancements * Added --server option to start a simple WEBrick server on destination directory [github.com/johnreilly and github.com/mchung] * Minor Enhancements diff --git a/jekyll.gemspec b/jekyll.gemspec index 625c287c8..ff8002f7f 100644 --- a/jekyll.gemspec +++ b/jekyll.gemspec @@ -1,22 +1,22 @@ Gem::Specification.new do |s| s.name = %q{jekyll} - s.version = "0.2.1" + s.version = "0.3.0" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Tom Preston-Werner"] - s.date = %q{2008-12-15} + s.date = %q{2008-12-24} s.default_executable = %q{jekyll} s.email = ["tom@mojombo.com"] s.executables = ["jekyll"] s.extra_rdoc_files = ["History.txt", "Manifest.txt"] - s.files = ["History.txt", "Manifest.txt", "README.textile", "Rakefile", "bin/jekyll", "jekyll.gemspec", "lib/jekyll.rb", "lib/jekyll/albino.rb", "lib/jekyll/converters/csv.rb", "lib/jekyll/converters/mephisto.rb", "lib/jekyll/convertible.rb", "lib/jekyll/filters.rb", "lib/jekyll/layout.rb", "lib/jekyll/page.rb", "lib/jekyll/post.rb", "lib/jekyll/site.rb", "lib/jekyll/tags/highlight.rb", "lib/jekyll/tags/include.rb", "test/helper.rb", "test/source/_includes/sig.markdown", "test/source/_layouts/default.html", "test/source/_layouts/simple.html", "test/source/_posts/2008-10-18-foo-bar.textile", "test/source/_posts/2008-11-21-complex.textile", "test/source/_posts/2008-12-13-include.markdown", "test/source/css/screen.css", "test/source/index.html", "test/source/posts/2008-12-03-permalinked-post.textile", "test/suite.rb", "test/test_jekyll.rb", "test/test_post.rb", "test/test_site.rb"] + s.files = ["History.txt", "Manifest.txt", "README.textile", "Rakefile", "bin/jekyll", "jekyll.gemspec", "lib/jekyll.rb", "lib/jekyll/albino.rb", "lib/jekyll/converters/csv.rb", "lib/jekyll/converters/mephisto.rb", "lib/jekyll/converters/mt.rb", "lib/jekyll/converters/wordpress.rb", "lib/jekyll/convertible.rb", "lib/jekyll/core_ext.rb", "lib/jekyll/filters.rb", "lib/jekyll/layout.rb", "lib/jekyll/page.rb", "lib/jekyll/post.rb", "lib/jekyll/site.rb", "lib/jekyll/tags/highlight.rb", "lib/jekyll/tags/include.rb", "test/helper.rb", "test/source/_includes/sig.markdown", "test/source/_layouts/default.html", "test/source/_layouts/simple.html", "test/source/_posts/2008-10-18-foo-bar.textile", "test/source/_posts/2008-11-21-complex.textile", "test/source/_posts/2008-12-03-permalinked-post.textile", "test/source/_posts/2008-12-13-include.markdown", "test/source/css/screen.css", "test/source/index.html", "test/suite.rb", "test/test_generated_site.rb", "test/test_jekyll.rb", "test/test_post.rb", "test/test_site.rb"] s.has_rdoc = true s.rdoc_options = ["--main", "README.txt"] s.require_paths = ["lib"] s.rubyforge_project = %q{jekyll} s.rubygems_version = %q{1.3.0} s.summary = %q{Jekyll is a simple, blog aware, static site generator.} - s.test_files = ["test/test_jekyll.rb", "test/test_post.rb", "test/test_site.rb"] + s.test_files = ["test/test_generated_site.rb", "test/test_jekyll.rb", "test/test_post.rb", "test/test_site.rb"] if s.respond_to? :specification_version then current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION diff --git a/lib/jekyll.rb b/lib/jekyll.rb index 3676b5763..829d1d4bd 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -43,7 +43,7 @@ require 'jekyll/tags/include' require 'jekyll/albino' module Jekyll - VERSION = '0.2.1' + VERSION = '0.3.0' class << self attr_accessor :source, :dest, :lsi, :pygments, :markdown_proc From e0e7bf10d19fdd2df1a599663b0e181fe0c1c6cc Mon Sep 17 00:00:00 2001 From: Toby DiPasquale Date: Fri, 26 Dec 2008 22:44:34 -0500 Subject: [PATCH 36/49] added Typo 4+ conversion module and docs --- README.textile | 19 ++++++++++++++ lib/jekyll/converters/typo.rb | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 lib/jekyll/converters/typo.rb diff --git a/README.textile b/README.textile index e50f05247..a88977e92 100644 --- a/README.textile +++ b/README.textile @@ -379,6 +379,25 @@ You may need to adjust the SQL query used to retrieve MT entries. Left alone, it will attempt to pull all entries across all blogs regardless of status. Please check the results and verify the posts before publishing. +h3. Typo 4+ + +To migrate your Typo blog into Jekyll, you'll need read access to the MySQL +database. The lib/jekyll/converters/typo.rb module provides a simple convert +to create .html, .textile, or .markdown files in a _posts directory based on +the entries contained therein. + + $ export DB=my_typo_db + $ export USER=dbuser + $ export PASS=dbpass + $ ruby -r './lib/jekyll/converters/typo' -e 'Jekyll::Typo.process( \ + "#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")' + +You may need to adjust the code used to filter Typo entries. Left alone, +it will attempt to pull all entries across all blogs that were published. +This code also has only been tested with Typo version 4+. Previous versions +of Typo may not convert correctly. Please check the results and verify the +posts before publishing. + h2. License (The MIT License) diff --git a/lib/jekyll/converters/typo.rb b/lib/jekyll/converters/typo.rb new file mode 100644 index 000000000..febac65dc --- /dev/null +++ b/lib/jekyll/converters/typo.rb @@ -0,0 +1,49 @@ +# Author: Toby DiPasquale +require 'fileutils' +require 'rubygems' +require 'sequel' + +module Jekyll + module Typo + # this SQL *should* work for both MySQL and PostgreSQL, but I haven't + # tested PostgreSQL yet (as of 2008-12-16) + SQL = <<-EOS + SELECT c.id id, + c.title title, + c.permalink slug, + c.body body, + c.published_at date, + c.state state, + COALESCE(tf.name, 'html') filter + FROM contents c + LEFT OUTER JOIN text_filters tf + ON c.text_filter_id = tf.id + EOS + + def self.process dbname, user, pass, host='localhost' + FileUtils.mkdir_p '_posts' + db = Sequel.mysql dbname, :user => user, :password => pass, :host => host + db[SQL].each do |post| + next unless post[:state] =~ /Published/ + + name = [ sprintf("%.04d", post[:date].year), + sprintf("%.02d", post[:date].month), + sprintf("%.02d", post[:date].day), + post[:slug].strip ].join('-') + # Can have more than one text filter in this field, but we just want + # the first one for this + name += '.' + post[:filter].split(' ')[0] + + File.open("_posts/#{name}", 'w') do |f| + f.puts({ 'layout' => 'post', + 'title' => post[:title].to_s, + 'typo_id' => post[:id] + }.delete_if { |k, v| v.nil? || v == '' }.to_yaml) + f.puts '---' + f.puts post[:body].delete("\r") + end + end + end + + end # module Typo +end # module Jekyll From 29313b046c227bf07b83ab2f262ba1035a08cfc4 Mon Sep 17 00:00:00 2001 From: Toby DiPasquale Date: Fri, 26 Dec 2008 22:51:15 -0500 Subject: [PATCH 37/49] fixing typo in lib/jekyll/converters/mt.rb --- lib/jekyll/converters/mt.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jekyll/converters/mt.rb b/lib/jekyll/converters/mt.rb index e207760af..3b98b139f 100644 --- a/lib/jekyll/converters/mt.rb +++ b/lib/jekyll/converters/mt.rb @@ -33,7 +33,7 @@ module Jekyll # Be sure to include the body and extended body. if more_content != nil - conent = content + " \n" + more_content + content = content + " \n" + more_content end # Ideally, this script would determine the post format (markdown, html From 4f677f627ef569be8896dab4b1b932196e71d6b4 Mon Sep 17 00:00:00 2001 From: Mikael Lind Date: Sat, 27 Dec 2008 13:03:03 +0100 Subject: [PATCH 38/49] apply Liquid templating to includes --- lib/jekyll/tags/include.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index f24942433..840f36bdd 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -14,7 +14,11 @@ module Jekyll Dir.chdir(File.join(Jekyll.source, '_includes')) do choices = Dir['**/*'].reject { |x| File.symlink?(x) } if choices.include?(@file) - File.read(@file) + source = File.read(@file) + partial = Liquid::Template.parse(source) + context.stack do + partial.render(context) + end else "Included file '#{@file}' not found in _includes directory" end @@ -24,4 +28,4 @@ module Jekyll end -Liquid::Template.register_tag('include', Jekyll::IncludeTag) \ No newline at end of file +Liquid::Template.register_tag('include', Jekyll::IncludeTag) From 4770882217db5cea38af839b50477b1d80495e1b Mon Sep 17 00:00:00 2001 From: Toby DiPasquale Date: Sat, 27 Dec 2008 13:19:52 -0500 Subject: [PATCH 39/49] added typo to manifest and Rakefile --- Manifest.txt | 1 + Rakefile | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/Manifest.txt b/Manifest.txt index eb613ef21..009242bd0 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -9,6 +9,7 @@ lib/jekyll/albino.rb lib/jekyll/converters/csv.rb lib/jekyll/converters/mephisto.rb lib/jekyll/converters/mt.rb +lib/jekyll/converters/typo.rb lib/jekyll/converters/wordpress.rb lib/jekyll/convertible.rb lib/jekyll/core_ext.rb diff --git a/Rakefile b/Rakefile index a7a95707f..3f301a771 100644 --- a/Rakefile +++ b/Rakefile @@ -18,7 +18,12 @@ namespace :convert do task :mephisto do sh %q(ruby -r './lib/jekyll/converters/mephisto' -e 'Jekyll::Mephisto.postgres(:database => "#{ENV["DB"]}")') end + desc "Migrate from Movable Type in the current directory" task :mt do sh %q(ruby -r './lib/jekyll/converters/mt' -e 'Jekyll::MT.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")') end + desc "Migrate from Typo in the current directory" + task :typo do + sh %q(ruby -r './lib/jekyll/converters/typo' -e 'Jekyll::Typo.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")') + end end From 87a5e747fd6573dd1ebef0b48f523067d6270438 Mon Sep 17 00:00:00 2001 From: Marc Chung Date: Tue, 30 Dec 2008 11:33:22 -0700 Subject: [PATCH 40/49] Added array_to_sentence_string filter --- lib/jekyll/filters.rb | 17 ++++++++++++++++- test/test_filters.rb | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 test/test_filters.rb diff --git a/lib/jekyll/filters.rb b/lib/jekyll/filters.rb index 6051626a8..6cfa6361d 100644 --- a/lib/jekyll/filters.rb +++ b/lib/jekyll/filters.rb @@ -19,6 +19,21 @@ module Jekyll def number_of_words(input) input.split.length - end + end + + def array_to_sentence_string(array) + connector = "and" + case array.length + when 0 + "" + when 1 + array[0].to_s + when 2 + "#{array[0]} #{connector} #{array[1]}" + else + "#{array[0...-1].join(', ')}, #{connector} #{array[-1]}" + end + end + end end \ No newline at end of file diff --git a/test/test_filters.rb b/test/test_filters.rb new file mode 100644 index 000000000..442cbc9e8 --- /dev/null +++ b/test/test_filters.rb @@ -0,0 +1,32 @@ +require File.dirname(__FILE__) + '/helper' + +class TestSite < Test::Unit::TestCase + + class JekyllFilter + include Jekyll::Filters + end + + def setup + @filter = JekyllFilter.new + end + + def test_array_to_sentence_string_with_no_args + assert_equal "", @filter.array_to_sentence_string([]) + end + + def test_array_to_sentence_string_with_one_arg + assert_equal "1", @filter.array_to_sentence_string([1]) + assert_equal "chunky", @filter.array_to_sentence_string(["chunky"]) + end + + def test_array_to_sentence_string_with_two_args + assert_equal "1 and 2", @filter.array_to_sentence_string([1, 2]) + assert_equal "chunky and bacon", @filter.array_to_sentence_string(["chunky", "bacon"]) + end + + def test_array_to_sentence_string_with_multiple_args + assert_equal "1, 2, 3, and 4", @filter.array_to_sentence_string([1, 2, 3, 4]) + assert_equal "chunky, bacon, bits, and pieces", @filter.array_to_sentence_string(["chunky", "bacon", "bits", "pieces"]) + end + +end \ No newline at end of file From 4db696152c1bac2892250de9ae1fadf2d2bacd9f Mon Sep 17 00:00:00 2001 From: Basil Shkara Date: Sat, 27 Dec 2008 11:06:25 +1100 Subject: [PATCH 41/49] Added new accessible Liquid attribute for Sites: .topics. Behaves like the .categories attribute. --- lib/jekyll/site.rb | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 9c2054312..c78938e4f 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -114,7 +114,7 @@ module Jekyll transform_pages(File.join(dir, f)) else first3 = File.open(File.join(self.source, dir, f)) { |fd| fd.read(3) } - + if first3 == "---" # file appears to have a YAML header so process it as a page page = Page.new(self.source, dir, f) @@ -128,21 +128,29 @@ module Jekyll end end end - + + # Constructs a hash map of Posts indexed by the specified Post attribute + # + # Returns {post_attr => []} + def post_attr_hash(post_attr) + # Build a hash map based on the specified post attribute ( post attr => array of posts ) + # then sort each array in reverse order + hash = Hash.new { |hash, key| hash[key] = Array.new } + self.posts.each { |p| p.send(post_attr.to_sym).each { |t| hash[t] << p } } + hash.values.map { |sortme| sortme.sort! { |a, b| b <=> a} } + return hash + end + # The Hash payload containing site-wide data # - # Returns {"site" => {"time" =>