git merge mojombo/master

This commit is contained in:
Christian Hellsten 2010-06-22 15:42:51 +03:00
commit 46a95bc036
56 changed files with 1690 additions and 655 deletions

View File

@ -1,60 +1,133 @@
== Edge
* Major Enhancements
* Proper plugin system (#19, #100)
* Add safe mode so unsafe converters/generators can be added
* Minor Enhancements
* Inclusion/exclusion of future dated posts (#59)
* Generation for a specific time (#59)
* Allocate site.time on render not per site_payload invocation (#59)
* Pages now present in the site payload and can be used through the
site.pages and site.html_pages variables
* Generate phase added to site#process and pagination is now a generator
* Switch to RakeGem for build/test process
* Only regenerate static files when they have changed (#142)
* Allow arbitrary options to Pygments (#31)
* Bug Fixes
* Render highlighted code for non markdown/textile pages (#116)
* Expand source to full path so includes work anywhere (#101)
* Fix highlighting on Ruby 1.9 (#65)
* Fix extension munging when pretty permalinks are enabled (#64)
* Stop sorting categories (#33)
* Preserve generated attributes over front matter (#119)
== 0.5.7 / 2010-01-12
* Minor Enhancements
* Allow overriding of post date in the front matter (#62, #38)
* Bug Fixes
* Categories isn't always an array (#73)
* Empty tags causes error in read_posts (#84)
* Fix pagination to adhere to read/render/write paradigm
* Test Enhancement
* cucumber features no longer use site.ports.first where a better
alternative is available
== 0.5.6 / 2010-01-08
* Bug Fixes
* Require redcloth >= 4.2.1 in tests (#92)
* Don't break on triple dashes in yaml frontmatter (#93)
* Minor Enhancements
* Allow .mkd as markdown extension
* Use $stdout/err instead of constants (#99)
* Properly wrap code blocks (#91)
* Add javascript mime type for webrick (#98)
== 0.5.5 / 2010-01-08
* Bug Fixes
* Fix pagination % 0 bug (#78)
* Ensure all posts are processed first (#71)
== NOTE
* After this point I will no longer be giving credit in the history;
that is what the commit log is for.
== 0.5.4 / 2009-08-23 == 0.5.4 / 2009-08-23
* Bug Fixes * Bug Fixes
* Do not allow symlinks (security vulnerability) * Do not allow symlinks (security vulnerability)
== 0.5.3 / 2009-07-14 == 0.5.3 / 2009-07-14
* Bug Fixes * Bug Fixes
* Solving the permalink bug where non-html files wouldn't work [github.com/jeffrydegrande] * Solving the permalink bug where non-html files wouldn't work
[github.com/jeffrydegrande]
== 0.5.2 / 2009-06-24 == 0.5.2 / 2009-06-24
* Enhancements * Enhancements
* Added --paginate option to the executable along with a paginator object for the payload [github.com/calavera] * Added --paginate option to the executable along with a paginator object
* Upgraded RedCloth to 4.2.1, which makes <notextile> tags work once again. for the payload [github.com/calavera]
* Configuration options set in config.yml are now available through the site payload [github.com/vilcans] * Upgraded RedCloth to 4.2.1, which makes <notextile> tags work once
* Posts can now have an empty YAML front matter or none at all [github.com/bahuvrihi] again.
* Configuration options set in config.yml are now available through the
site payload [github.com/vilcans]
* Posts can now have an empty YAML front matter or none at all
[github.com/bahuvrihi]
* Bug Fixes * Bug Fixes
* Fixing Ruby 1.9 issue that requires to_s on the err object [github.com/Chrononaut] * Fixing Ruby 1.9 issue that requires to_s on the err object
[github.com/Chrononaut]
* Fixes for pagination and ordering posts on the same day [github.com/ujh] * Fixes for pagination and ordering posts on the same day [github.com/ujh]
* Made pages respect permalinks style and permalinks in yml front matter [github.com/eugenebolshakov] * Made pages respect permalinks style and permalinks in yml front matter
* Index.html file should always have index.html permalink [github.com/eugenebolshakov] [github.com/eugenebolshakov]
* Added trailing slash to pretty permalink style so Apache is happy [github.com/eugenebolshakov] * Index.html file should always have index.html permalink
* Bad markdown processor in config fails sooner and with better message [github.com/gcnovus] [github.com/eugenebolshakov]
* Added trailing slash to pretty permalink style so Apache is happy
[github.com/eugenebolshakov]
* Bad markdown processor in config fails sooner and with better message
[github.com/gcnovus]
* Allow CRLFs in yaml frontmatter [github.com/juretta] * Allow CRLFs in yaml frontmatter [github.com/juretta]
* Added Date#xmlschema for Ruby versions < 1.9 * Added Date#xmlschema for Ruby versions < 1.9
== 0.5.1 / 2009-05-06 == 0.5.1 / 2009-05-06
* Major Enhancements * Major Enhancements
* Next/previous posts in site payload [github.com/pantulis, github.com/tomo] * Next/previous posts in site payload [github.com/pantulis,
github.com/tomo]
* Permalink templating system * Permalink templating system
* Moved most of the README out to the GitHub wiki * Moved most of the README out to the GitHub wiki
* Exclude option in configuration so specified files won't be brought over with generated site [github.com/duritong] * Exclude option in configuration so specified files won't be brought over
with generated site [github.com/duritong]
* Bug Fixes * Bug Fixes
* Making sure config.yaml references are all gone, using only config.yml * Making sure config.yaml references are all gone, using only config.yml
* Fixed syntax highlighting breaking for UTF-8 code [github.com/henrik] * Fixed syntax highlighting breaking for UTF-8 code [github.com/henrik]
* Worked around RDiscount bug that prevents Markdown from getting parsed after highlight [github.com/henrik] * Worked around RDiscount bug that prevents Markdown from getting parsed
after highlight [github.com/henrik]
* CGI escaped post titles [github.com/Chrononaut] * CGI escaped post titles [github.com/Chrononaut]
== 0.5.0 / 2009-04-07 == 0.5.0 / 2009-04-07
* Minor Enhancements * Minor Enhancements
* Ability to set post categories via YAML [github.com/qrush] * Ability to set post categories via YAML [github.com/qrush]
* Ability to set prevent a post from publishing via YAML [github.com/qrush] * Ability to set prevent a post from publishing via YAML
[github.com/qrush]
* Add textilize filter [github.com/willcodeforfoo] * Add textilize filter [github.com/willcodeforfoo]
* Add 'pretty' permalink style for wordpress-like urls [github.com/dysinger] * Add 'pretty' permalink style for wordpress-like urls
* Made it possible to enter categories from YAML as an array [github.com/Chrononaut] [github.com/dysinger]
* Made it possible to enter categories from YAML as an array
[github.com/Chrononaut]
* Ignore Emacs autosave files [github.com/Chrononaut] * Ignore Emacs autosave files [github.com/Chrononaut]
* Bug Fixes * Bug Fixes
* Use block syntax of popen4 to ensure that subprocesses are properly disposed [github.com/jqr] * Use block syntax of popen4 to ensure that subprocesses are properly
disposed [github.com/jqr]
* Close open4 streams to prevent zombies [github.com/rtomayko] * Close open4 streams to prevent zombies [github.com/rtomayko]
* Only query required fields from the WP Database [github.com/ariejan] * Only query required fields from the WP Database [github.com/ariejan]
* Prevent _posts from being copied to the destination directory [github.com/bdimcheff] * Prevent _posts from being copied to the destination directory
[github.com/bdimcheff]
* Refactors * Refactors
* Factored the filtering code into a method [github.com/Chrononaut] * Factored the filtering code into a method [github.com/Chrononaut]
* Fix tests and convert to Shoulda [github.com/qrush, github.com/technicalpickles] * Fix tests and convert to Shoulda [github.com/qrush,
* Add Cucumber acceptance test suite [github.com/qrush, github.com/technicalpickles] github.com/technicalpickles]
* Add Cucumber acceptance test suite [github.com/qrush,
github.com/technicalpickles]
== 0.4.1 == 0.4.1
* Minor Enhancements * Minor Enhancements
* Changed date format on wordpress converter (zeropadding) [github.com/dysinger] * Changed date format on wordpress converter (zeropadding)
[github.com/dysinger]
* Bug Fixes * Bug Fixes
* Add jekyll binary as executable to gemspec [github.com/dysinger] * Add jekyll binary as executable to gemspec [github.com/dysinger]
@ -67,28 +140,35 @@
* Add array_to_sentence_string filter [github.com/mchung] * Add array_to_sentence_string filter [github.com/mchung]
* Add a converter for textpattern [github.com/PerfectlyNormal] * Add a converter for textpattern [github.com/PerfectlyNormal]
* Add a working Mephisto / MySQL converter [github.com/ivey] * Add a working Mephisto / MySQL converter [github.com/ivey]
* Allowing .htaccess files to be copied over into the generated site [github.com/briandoll] * Allowing .htaccess files to be copied over into the generated site
[github.com/briandoll]
* Add option to not put file date in permalink URL [github.com/mreid] * Add option to not put file date in permalink URL [github.com/mreid]
* Add line number capabilities to highlight blocks [github.com/jcon] * Add line number capabilities to highlight blocks [github.com/jcon]
* Bug Fixes * Bug Fixes
* Fix permalink behavior [github.com/cavalle] * Fix permalink behavior [github.com/cavalle]
* Fixed an issue with pygments, markdown, and newlines [github.com/zpinter] * Fixed an issue with pygments, markdown, and newlines
[github.com/zpinter]
* Ampersands need to be escaped [github.com/pufuwozu, github.com/ap] * Ampersands need to be escaped [github.com/pufuwozu, github.com/ap]
* Test and fix the site.categories hash [github.com/zzot] * Test and fix the site.categories hash [github.com/zzot]
* Fix site payload available to files [github.com/matrix9180] * Fix site payload available to files [github.com/matrix9180]
== 0.3.0 / 2008-12-24 == 0.3.0 / 2008-12-24
* Major Enhancements * Major Enhancements
* Added --server option to start a simple WEBrick server on destination directory [github.com/johnreilly and github.com/mchung] * Added --server option to start a simple WEBrick server on destination
directory [github.com/johnreilly and github.com/mchung]
* Minor Enhancements * Minor Enhancements
* Added post categories based on directories containing _posts [github.com/mreid] * Added post categories based on directories containing _posts
[github.com/mreid]
* Added post topics based on directories underneath _posts * Added post topics based on directories underneath _posts
* Added new date filter that shows the full month name [github.com/mreid] * 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] * Merge Post's YAML front matter into its to_liquid payload
[github.com/remi]
* Restrict includes to regular files underneath _includes * Restrict includes to regular files underneath _includes
* Bug Fixes * Bug Fixes
* Change YAML delimiter matcher so as to not chew up 2nd level markdown headers [github.com/mreid] * Change YAML delimiter matcher so as to not chew up 2nd level markdown
* Fix bug that meant page data (such as the date) was not available in templates [github.com/mreid] 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 * Properly reject directories in _layouts
== 0.2.1 / 2008-12-15 == 0.2.1 / 2008-12-15
@ -111,9 +191,11 @@
* Code highlighting with Pygments if --pygments is specified * Code highlighting with Pygments if --pygments is specified
* Disable true LSI by default, enable with --lsi * Disable true LSI by default, enable with --lsi
* Minor Enhancements * Minor Enhancements
* Output informative message if RDiscount is not available [github.com/JackDanger] * Output informative message if RDiscount is not available
[github.com/JackDanger]
* Bug Fixes * Bug Fixes
* Prevent Jekyll from picking up the output directory as a source [github.com/JackDanger] * Prevent Jekyll from picking up the output directory as a source
[github.com/JackDanger]
* Skip related_posts when there is only one post [github.com/JackDanger] * Skip related_posts when there is only one post [github.com/JackDanger]
== 0.1.4 / 2008-12-08 == 0.1.4 / 2008-12-08

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
(The MIT License)
Copyright (c) 2008 Tom Preston-Werner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the 'Software'), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -20,23 +20,22 @@ h2. Diving In
* Customize the "Permalinks":http://wiki.github.com/mojombo/jekyll/permalinks your posts are generated with * Customize the "Permalinks":http://wiki.github.com/mojombo/jekyll/permalinks your posts are generated with
* Use the built-in "Liquid Extensions":http://wiki.github.com/mojombo/jekyll/liquid-extensions to make your life easier * Use the built-in "Liquid Extensions":http://wiki.github.com/mojombo/jekyll/liquid-extensions to make your life easier
h2. Dependencies h2. Runtime Dependencies
* RedCloth: Textile support * RedCloth: Textile support (Ruby)
* Liquid: Templating system * Liquid: Templating system (Ruby)
* Classifier: Generating related posts * Classifier: Generating related posts (Ruby)
* Maruku: Default markdown engine * Maruku: Default markdown engine (Ruby)
* Directory Watcher: Auto-regeneration of sites * Directory Watcher: Auto-regeneration of sites (Ruby)
* Open4: Talking to pygments for syntax highlighting * Open4: Talking to pygments for syntax highlighting (Ruby)
* Pygments: Syntax highlighting (Python)
h2. Developer Dependencies
* Shoulda: Test framework (Ruby)
* RR: Mocking (Ruby)
* RedGreen: Nicer test output (Ruby)
h2. License h2. License
(The MIT License) See LICENSE.
Copyright (c) 2008 Tom Preston-Werner
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

178
Rakefile
View File

@ -1,85 +1,101 @@
require 'rubygems'
require 'rake' require 'rake'
require 'date'
#############################################################################
#
# Helper functions
#
#############################################################################
def name
@name ||= Dir['*.gemspec'].first.split('.').first
end
def version
line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
end
def date
Date.today.to_s
end
def rubyforge_project
name
end
def gemspec_file
"#{name}.gemspec"
end
def gem_file
"#{name}-#{version}.gem"
end
def replace_header(head, header_name)
head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
end
#############################################################################
#
# Standard tasks
#
#############################################################################
task :default => [:test, :features]
require 'rake/testtask' require 'rake/testtask'
Rake::TestTask.new(:test) do |test|
test.libs << 'lib' << 'test'
test.pattern = 'test/**/test_*.rb'
test.verbose = true
end
desc "Generate RCov test coverage and open in your browser"
task :coverage do
require 'rcov'
sh "rm -fr coverage"
sh "rcov test/test_*.rb"
sh "open coverage/index.html"
end
require 'rake/rdoctask' require 'rake/rdoctask'
begin
gem 'jeweler', '>= 0.11.0'
require 'jeweler'
Jeweler::Tasks.new do |s|
s.name = "jekyll"
s.summary = %Q{Jekyll is a simple, blog aware, static site generator.}
s.email = "tom@mojombo.com"
s.homepage = "http://github.com/mojombo/jekyll"
s.description = "Jekyll is a simple, blog aware, static site generator."
s.authors = ["Tom Preston-Werner"]
s.rubyforge_project = "jekyll"
s.files.exclude 'test/dest'
s.test_files.exclude 'test/dest'
s.add_dependency('RedCloth', '>= 4.2.1')
s.add_dependency('liquid', '>= 1.9.0')
s.add_dependency('classifier', '>= 1.3.1')
s.add_dependency('maruku', '>= 0.5.9')
s.add_dependency('directory_watcher', '>= 1.1.1')
s.add_dependency('open4', '>= 0.9.6')
end
rescue LoadError
puts "Jeweler not available. Install it with: sudo gem install jeweler --version '>= 0.11.0'"
exit(1)
end
Rake::TestTask.new do |t|
t.libs << 'lib'
t.pattern = 'test/**/test_*.rb'
t.verbose = false
end
Rake::RDocTask.new do |rdoc| Rake::RDocTask.new do |rdoc|
rdoc.rdoc_dir = 'rdoc' rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'jekyll' rdoc.title = "#{name} #{version}"
rdoc.options << '--line-numbers' << '--inline-source'
rdoc.rdoc_files.include('README*') rdoc.rdoc_files.include('README*')
rdoc.rdoc_files.include('lib/**/*.rb') rdoc.rdoc_files.include('lib/**/*.rb')
end end
begin
require 'rcov/rcovtask'
Rcov::RcovTask.new do |t|
t.libs << 'test'
t.test_files = FileList['test/**/test_*.rb']
t.verbose = true
end
rescue LoadError
end
task :default => [:test, :features]
# console
desc "Open an irb session preloaded with this library" desc "Open an irb session preloaded with this library"
task :console do task :console do
sh "irb -rubygems -I lib -r jekyll.rb" sh "irb -rubygems -r ./lib/#{name}.rb"
end end
# converters #############################################################################
#
# Custom tasks (add your own tasks here)
#
#############################################################################
namespace :convert do namespace :migrate do
desc "Migrate from mephisto in the current directory" desc "Migrate from mephisto in the current directory"
task :mephisto do task :mephisto do
sh %q(ruby -r './lib/jekyll/converters/mephisto' -e 'Jekyll::Mephisto.postgres(:database => "#{ENV["DB"]}")') sh %q(ruby -r './lib/jekyll/migrators/mephisto' -e 'Jekyll::Mephisto.postgres(:database => "#{ENV["DB"]}")')
end end
desc "Migrate from Movable Type in the current directory" desc "Migrate from Movable Type in the current directory"
task :mt do task :mt do
sh %q(ruby -r './lib/jekyll/converters/mt' -e 'Jekyll::MT.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")') sh %q(ruby -r './lib/jekyll/migrators/mt' -e 'Jekyll::MT.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")')
end end
desc "Migrate from Typo in the current directory" desc "Migrate from Typo in the current directory"
task :typo do task :typo do
sh %q(ruby -r './lib/jekyll/converters/typo' -e 'Jekyll::Typo.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")') sh %q(ruby -r './lib/jekyll/migrators/typo' -e 'Jekyll::Typo.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")')
end end
end end
begin begin
require 'cucumber/rake/task' require 'cucumber/rake/task'
Cucumber::Rake::Task.new(:features) do |t| Cucumber::Rake::Task.new(:features) do |t|
t.cucumber_opts = "--format progress" t.cucumber_opts = "--format progress"
end end
@ -89,3 +105,55 @@ rescue LoadError
abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin' abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
end end
end end
#############################################################################
#
# Packaging tasks
#
#############################################################################
task :release => :build do
unless `git branch` =~ /^\* master$/
puts "You must be on the master branch to release!"
exit!
end
sh "git commit --allow-empty -a -m 'Release #{version}'"
sh "git tag v#{version}"
sh "git push origin master"
sh "git push v#{version}"
sh "gem push pkg/#{name}-#{version}.gem"
end
task :build => :gemspec do
sh "mkdir -p pkg"
sh "gem build #{gemspec_file}"
sh "mv #{gem_file} pkg"
end
task :gemspec do
# read spec file and split out manifest section
spec = File.read(gemspec_file)
head, manifest, tail = spec.split(" # = MANIFEST =\n")
# replace name version and date
replace_header(head, :name)
replace_header(head, :version)
replace_header(head, :date)
#comment this out if your rubyforge_project has a different name
replace_header(head, :rubyforge_project)
# determine file list from git ls-files
files = `git ls-files`.
split("\n").
sort.
reject { |file| file =~ /^\./ }.
reject { |file| file =~ /^(rdoc|pkg|coverage)/ }.
map { |file| " #{file}" }.
join("\n")
# piece file back together and write
manifest = " s.files = %w[\n#{files}\n ]\n"
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
File.open(gemspec_file, 'w') { |io| io.write(spec) }
puts "Updated #{gemspec_file}"
end

View File

@ -1,4 +0,0 @@
---
:patch: 4
:major: 0
:minor: 5

View File

@ -23,6 +23,10 @@ options = {}
opts = OptionParser.new do |opts| opts = OptionParser.new do |opts|
opts.banner = help opts.banner = help
opts.on("--safe", "Safe mode (default unsafe)") do
options['safe'] = true
end
opts.on("--auto", "Auto-regenerate") do opts.on("--auto", "Auto-regenerate") do
options['auto'] = true options['auto'] = true
end end
@ -48,6 +52,18 @@ opts = OptionParser.new do |opts|
options['markdown'] = 'rdiscount' options['markdown'] = 'rdiscount'
end end
opts.on("--time [TIME]", "Time to generate the site for") do |time|
options['time'] = Time.parse(time)
end
opts.on("--future", "Render future dated posts") do
options['future'] = true
end
opts.on("--no-future", "Do not render future dated posts") do
options['future'] = false
end
opts.on("--permalink [TYPE]", "Use 'date' (default) for YYYY/MM/DD") do |style| opts.on("--permalink [TYPE]", "Use 'date' (default) for YYYY/MM/DD") do |style|
options['permalink'] = style unless style.nil? options['permalink'] = style unless style.nil?
end end
@ -63,7 +79,7 @@ opts = OptionParser.new do |opts|
end end
opts.on("--version", "Display current version") do opts.on("--version", "Display current version") do
puts "Jekyll " + Jekyll.version puts "Jekyll " + Jekyll::VERSION
exit 0 exit 0
end end
end end
@ -139,6 +155,9 @@ if options['server']
mime_types = WEBrick::HTTPUtils::DefaultMimeTypes mime_types = WEBrick::HTTPUtils::DefaultMimeTypes
mime_types.store 'js', 'application/javascript' mime_types.store 'js', 'application/javascript'
mime_types = WEBrick::HTTPUtils::DefaultMimeTypes
mime_types.store 'js', 'application/javascript'
s = HTTPServer.new( s = HTTPServer.new(
:Port => options['server_port'], :Port => options['server_port'],
:DocumentRoot => destination, :DocumentRoot => destination,

1
cucumber.yml Normal file
View File

@ -0,0 +1 @@
default: --format progress

View File

@ -29,7 +29,7 @@ Feature: Create sites
Scenario: Basic site with layout and a post Scenario: Basic site with layout and a post
Given I have a _layouts directory Given I have a _layouts directory
And I have a _posts directory And I have a _posts directory
And I have the following post: And I have the following posts:
| title | date | layout | content | | title | date | layout | content |
| Wargames | 3/27/2009 | default | The only winning move is not to play. | | Wargames | 3/27/2009 | default | The only winning move is not to play. |
And I have a default layout that contains "Post Layout: {{ content }}" And I have a default layout that contains "Post Layout: {{ content }}"
@ -37,6 +37,36 @@ Feature: Create sites
Then the _site directory should exist Then the _site directory should exist
And I should see "Post Layout: <p>The only winning move is not to play.</p>" in "_site/2009/03/27/wargames.html" And I should see "Post Layout: <p>The only winning move is not to play.</p>" in "_site/2009/03/27/wargames.html"
Scenario: Basic site with layouts, pages, posts and files
Given I have a _layouts directory
And I have a page layout that contains "Page {{ page.title }}: {{ content }}"
And I have a post layout that contains "Post {{ page.title }}: {{ content }}"
And I have an "index.html" page with layout "page" that contains "Site contains {{ site.pages.size }} pages and {{ site.posts.size }} posts"
And I have a blog directory
And I have a "blog/index.html" page with layout "page" that contains "blog category index page"
And I have an "about.html" file that contains "No replacement {{ site.posts.size }}"
And I have an "another_file" file that contains ""
And I have a _posts directory
And I have the following posts:
| title | date | layout | content |
| entry1 | 3/27/2009 | post | content for entry1. |
| entry2 | 4/27/2009 | post | content for entry2. |
And I have a category/_posts directory
And I have the following posts in "category":
| title | date | layout | content |
| entry3 | 5/27/2009 | post | content for entry3. |
| entry4 | 6/27/2009 | post | content for entry4. |
When I run jekyll
Then the _site directory should exist
And I should see "Page : Site contains 2 pages and 4 posts" in "_site/index.html"
And I should see "No replacement \{\{ site.posts.size \}\}" in "_site/about.html"
And I should see "" in "_site/another_file"
And I should see "Page : blog category index page" in "_site/blog/index.html"
And I should see "Post entry1: <p>content for entry1.</p>" in "_site/2009/03/27/entry1.html"
And I should see "Post entry2: <p>content for entry2.</p>" in "_site/2009/04/27/entry2.html"
And I should see "Post entry3: <p>content for entry3.</p>" in "_site/category/2009/05/27/entry3.html"
And I should see "Post entry4: <p>content for entry4.</p>" in "_site/category/2009/06/27/entry4.html"
Scenario: Basic site with include tag Scenario: Basic site with include tag
Given I have a _includes directory Given I have a _includes directory
And I have an "index.html" page that contains "Basic Site with include tag: {% include about.textile %}" And I have an "index.html" page that contains "Basic Site with include tag: {% include about.textile %}"
@ -44,3 +74,21 @@ Feature: Create sites
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Basic Site with include tag: Generated by Jekyll" in "_site/index.html" And I should see "Basic Site with include tag: Generated by Jekyll" in "_site/index.html"
Scenario: Basic site with subdir include tag
Given I have a _includes directory
And I have an "_includes/about.textile" file that contains "Generated by Jekyll"
And I have an info directory
And I have an "info/index.html" page that contains "Basic Site with subdir include tag: {% include about.textile %}"
When I run jekyll
Then the _site directory should exist
And I should see "Basic Site with subdir include tag: Generated by Jekyll" in "_site/info/index.html"
Scenario: Basic site with nested include tag
Given I have a _includes directory
And I have an "_includes/about.textile" file that contains "Generated by {% include jekyll.textile %}"
And I have an "_includes/jekyll.textile" file that contains "Jekyll"
And I have an "index.html" page that contains "Basic Site with include tag: {% include about.textile %}"
When I run jekyll
Then the _site directory should exist
And I should see "Basic Site with include tag: Generated by Jekyll" in "_site/index.html"

View File

@ -20,7 +20,7 @@ Feature: Embed filters
And I have the following post: And I have the following post:
| title | date | layout | content | | title | date | layout | content |
| Star & Wars | 3/27/2009 | default | These aren't the droids you're looking for. | | Star & Wars | 3/27/2009 | default | These aren't the droids you're looking for. |
And I have a default layout that contains "{{ site.posts.first.title | xml_escape }}" And I have a default layout that contains "{{ page.title | xml_escape }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Star &amp; Wars" in "_site/2009/03/27/star-wars.html" And I should see "Star &amp; Wars" in "_site/2009/03/27/star-wars.html"
@ -31,7 +31,7 @@ Feature: Embed filters
And I have the following post: And I have the following post:
| title | date | layout | content | | title | date | layout | content |
| Star Wars | 3/27/2009 | default | These aren't the droids you're looking for. | | Star Wars | 3/27/2009 | default | These aren't the droids you're looking for. |
And I have a default layout that contains "{{ site.posts.first.content | xml_escape }}" And I have a default layout that contains "{{ content | xml_escape }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "7" in "_site/2009/03/27/star-wars.html" And I should see "7" in "_site/2009/03/27/star-wars.html"
@ -42,7 +42,7 @@ Feature: Embed filters
And I have the following post: And I have the following post:
| title | date | layout | tags | content | | title | date | layout | tags | content |
| Star Wars | 3/27/2009 | default | [scifi, movies, force] | These aren't the droids you're looking for. | | Star Wars | 3/27/2009 | default | [scifi, movies, force] | These aren't the droids you're looking for. |
And I have a default layout that contains "{{ site.posts.first.tags | array_to_sentence_string }}" And I have a default layout that contains "{{ page.tags | array_to_sentence_string }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "scifi, movies, and force" in "_site/2009/03/27/star-wars.html" And I should see "scifi, movies, and force" in "_site/2009/03/27/star-wars.html"

30
features/markdown.feature Normal file
View File

@ -0,0 +1,30 @@
Feature: Markdown
As a hacker who likes to blog
I want to be able to make a static site
In order to share my awesome ideas with the interwebs
Scenario: Markdown in list on index
Given I have a configuration file with "paginate" set to "5"
And I have an "index.html" page that contains "Index - {% for post in site.posts %} {{ post.content }} {% endfor %}"
And I have a _posts directory
And I have the following post:
| title | date | content | type |
| Hackers | 3/27/2009 | # My Title | markdown |
When I run jekyll
Then the _site directory should exist
And I should see "Index" in "_site/index.html"
And I should see "<h1 id='my_title'>My Title</h1>" in "_site/2009/03/27/hackers.html"
And I should see "<h1 id='my_title'>My Title</h1>" in "_site/index.html"
Scenario: Markdown in pagination on index
Given I have a configuration file with "paginate" set to "5"
And I have an "index.html" page that contains "Index - {% for post in paginator.posts %} {{ post.content }} {% endfor %}"
And I have a _posts directory
And I have the following post:
| title | date | content | type |
| Hackers | 3/27/2009 | # My Title | markdown |
When I run jekyll
Then the _site directory should exist
And I should see "Index" in "_site/index.html"
And I should see "<h1 id='my_title'>My Title</h1>" in "_site/index.html"

View File

@ -6,35 +6,22 @@ Feature: Site pagination
Scenario Outline: Paginate with N posts per page Scenario Outline: Paginate with N posts per page
Given I have a configuration file with "paginate" set to "<num>" Given I have a configuration file with "paginate" set to "<num>"
And I have a _layouts directory And I have a _layouts directory
And I have an "index.html" file that contains "Basic Site" And I have an "index.html" page that contains "{{ paginator.posts.size }}"
And I have a _posts directory And I have a _posts directory
And I have the following post: And I have the following post:
| title | date | layout | content | | title | date | layout | content |
| Wargames | 3/27/2009 | default | The only winning move is not to play. | | Wargames | 3/27/2009 | default | The only winning move is not to play. |
| Wargames2 | 4/27/2009 | default | The only winning move is not to play2. | | Wargames2 | 4/27/2009 | default | The only winning move is not to play2. |
| Wargames3 | 5/27/2009 | default | The only winning move is not to play2. | | Wargames3 | 5/27/2009 | default | The only winning move is not to play3. |
| Wargames4 | 6/27/2009 | default | The only winning move is not to play4. |
When I run jekyll When I run jekyll
Then the _site/page2 directory should exist Then the _site/page<exist> directory should exist
And the _site/page2/index.html file should exist And the "_site/page<exist>/index.html" file should exist
And I should see "<posts>" in "_site/page<exist>/index.html"
And the "_site/page<not_exist>/index.html" file should not exist
Examples: Examples:
| num | | num | exist | posts | not_exist |
| 1 | | 1 | 4 | 1 | 5 |
| 2 | | 2 | 2 | 2 | 3 |
| 3 | 2 | 1 | 3 |
Scenario: Correct liquid paginator replacements
Given I have a configuration file with "paginate" set to "1"
And I have a _layouts directory
And I have an "index.html" file that contains "{{ paginator.page }}"
And I have a _posts directory
And I have the following post:
| title | date | layout | content |
| Wargames | 3/27/2009 | default | The only winning move is not to play. |
| Wargames2 | 4/27/2009 | default | The only winning move is not to play2. |
When I run jekyll
Then the _site/index.html file should exist
And I should see "1" in "_site/index.html"
Then the _site/page2 directory should exist
And the _site/page2/index.html file should exist
And I should see "2" in "_site/page2/index.html"

View File

@ -9,7 +9,7 @@ Feature: Post data
And I have the following post: And I have the following post:
| title | date | layout | content | | title | date | layout | content |
| Star Wars | 3/27/2009 | simple | Luke, I am your father. | | Star Wars | 3/27/2009 | simple | Luke, I am your father. |
And I have a simple layout that contains "Post title: {{ site.posts.first.title }}" And I have a simple layout that contains "Post title: {{ page.title }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Post title: Star Wars" in "_site/2009/03/27/star-wars.html" And I should see "Post title: Star Wars" in "_site/2009/03/27/star-wars.html"
@ -20,7 +20,7 @@ Feature: Post data
And I have the following post: And I have the following post:
| title | date | layout | content | | title | date | layout | content |
| Star Wars | 3/27/2009 | simple | Luke, I am your father. | | Star Wars | 3/27/2009 | simple | Luke, I am your father. |
And I have a simple layout that contains "Post url: {{ site.posts.first.url }}" And I have a simple layout that contains "Post url: {{ page.url }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Post url: /2009/03/27/star-wars.html" in "_site/2009/03/27/star-wars.html" And I should see "Post url: /2009/03/27/star-wars.html" in "_site/2009/03/27/star-wars.html"
@ -31,7 +31,7 @@ Feature: Post data
And I have the following post: And I have the following post:
| title | date | layout | content | | title | date | layout | content |
| Star Wars | 3/27/2009 | simple | Luke, I am your father. | | Star Wars | 3/27/2009 | simple | Luke, I am your father. |
And I have a simple layout that contains "Post date: {{ site.posts.first.date }}" And I have a simple layout that contains "Post date: {{ page.date }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Post date: Fri Mar 27" in "_site/2009/03/27/star-wars.html" And I should see "Post date: Fri Mar 27" in "_site/2009/03/27/star-wars.html"
@ -42,7 +42,7 @@ Feature: Post data
And I have the following post: And I have the following post:
| title | date | layout | content | | title | date | layout | content |
| Star Wars | 3/27/2009 | simple | Luke, I am your father. | | Star Wars | 3/27/2009 | simple | Luke, I am your father. |
And I have a simple layout that contains "Post id: {{ site.posts.first.id }}" And I have a simple layout that contains "Post id: {{ page.id }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Post id: /2009/03/27/star-wars" in "_site/2009/03/27/star-wars.html" And I should see "Post id: /2009/03/27/star-wars" in "_site/2009/03/27/star-wars.html"
@ -53,7 +53,7 @@ Feature: Post data
And I have the following post: And I have the following post:
| title | date | layout | content | | title | date | layout | content |
| Star Wars | 3/27/2009 | simple | Luke, I am your father. | | Star Wars | 3/27/2009 | simple | Luke, I am your father. |
And I have a simple layout that contains "Post content: {{ site.posts.first.content }}" And I have a simple layout that contains "Post content: {{ content }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Post content: <p>Luke, I am your father.</p>" in "_site/2009/03/27/star-wars.html" And I should see "Post content: <p>Luke, I am your father.</p>" in "_site/2009/03/27/star-wars.html"
@ -65,7 +65,7 @@ Feature: Post data
And I have the following post in "movies": And I have the following post in "movies":
| title | date | layout | content | | title | date | layout | content |
| Star Wars | 3/27/2009 | simple | Luke, I am your father. | | Star Wars | 3/27/2009 | simple | Luke, I am your father. |
And I have a simple layout that contains "Post category: {{ site.posts.first.categories }}" And I have a simple layout that contains "Post category: {{ page.categories }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html" And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html"
@ -76,23 +76,23 @@ Feature: Post data
And I have the following post: And I have the following post:
| title | date | layout | tag | content | | title | date | layout | tag | content |
| Star Wars | 5/18/2009 | simple | twist | Luke, I am your father. | | Star Wars | 5/18/2009 | simple | twist | Luke, I am your father. |
And I have a simple layout that contains "Post tags: {{ site.posts.first.tags }}" And I have a simple layout that contains "Post tags: {{ page.tags }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Post tags: twist" in "_site/2009/05/18/star-wars.html" And I should see "Post tags: twist" in "_site/2009/05/18/star-wars.html"
Scenario: Use post.categories variable when categories are in folders Scenario: Use post.categories variable when categories are in folders
Given I have a movies directory Given I have a scifi directory
And I have a movies/scifi directory And I have a scifi/movies directory
And I have a movies/scifi/_posts directory And I have a scifi/movies/_posts directory
And I have a _layouts directory And I have a _layouts directory
And I have the following post in "movies/scifi": And I have the following post in "scifi/movies":
| title | date | layout | content | | title | date | layout | content |
| Star Wars | 3/27/2009 | simple | Luke, I am your father. | | Star Wars | 3/27/2009 | simple | Luke, I am your father. |
And I have a simple layout that contains "Post categories: {{ site.posts.first.categories | array_to_sentence_string }}" And I have a simple layout that contains "Post categories: {{ page.categories | array_to_sentence_string }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Post categories: movies and scifi" in "_site/movies/scifi/2009/03/27/star-wars.html" And I should see "Post categories: scifi and movies" in "_site/scifi/movies/2009/03/27/star-wars.html"
Scenario: Use post.categories variable when category is in YAML Scenario: Use post.categories variable when category is in YAML
Given I have a _posts directory Given I have a _posts directory
@ -100,7 +100,7 @@ Feature: Post data
And I have the following post: And I have the following post:
| title | date | layout | category | content | | title | date | layout | category | content |
| Star Wars | 3/27/2009 | simple | movies | Luke, I am your father. | | Star Wars | 3/27/2009 | simple | movies | Luke, I am your father. |
And I have a simple layout that contains "Post category: {{ site.posts.first.categories }}" And I have a simple layout that contains "Post category: {{ page.categories }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html" And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html"
@ -110,11 +110,11 @@ Feature: Post data
And I have a _layouts directory And I have a _layouts directory
And I have the following post: And I have the following post:
| title | date | layout | categories | content | | title | date | layout | categories | content |
| Star Wars | 3/27/2009 | simple | ['movies', 'scifi'] | Luke, I am your father. | | Star Wars | 3/27/2009 | simple | ['scifi', 'movies'] | Luke, I am your father. |
And I have a simple layout that contains "Post categories: {{ site.posts.first.categories | array_to_sentence_string }}" And I have a simple layout that contains "Post categories: {{ page.categories | array_to_sentence_string }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Post categories: movies and scifi" in "_site/movies/scifi/2009/03/27/star-wars.html" And I should see "Post categories: scifi and movies" in "_site/scifi/movies/2009/03/27/star-wars.html"
Scenario: Disable a post from being published Scenario: Disable a post from being published
Given I have a _posts directory Given I have a _posts directory
@ -133,7 +133,7 @@ Feature: Post data
And I have the following post: And I have the following post:
| title | date | layout | author | content | | title | date | layout | author | content |
| Star Wars | 3/27/2009 | simple | Darth Vader | Luke, I am your father. | | Star Wars | 3/27/2009 | simple | Darth Vader | Luke, I am your father. |
And I have a simple layout that contains "Post author: {{ site.posts.first.author }}" And I have a simple layout that contains "Post author: {{ page.author }}"
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "Post author: Darth Vader" in "_site/2009/03/27/star-wars.html" And I should see "Post author: Darth Vader" in "_site/2009/03/27/star-wars.html"

View File

@ -33,7 +33,7 @@ Feature: Site configuration
And I have an "README" file that contains "I want to be excluded" And I have an "README" file that contains "I want to be excluded"
And I have an "index.html" file that contains "I want to be included" And I have an "index.html" file that contains "I want to be included"
And I have a configuration file with "exclude" set to: And I have a configuration file with "exclude" set to:
| Value | | value |
| README | | README |
| Rakefile | | Rakefile |
When I run jekyll When I run jekyll
@ -61,3 +61,43 @@ Feature: Site configuration
When I run jekyll When I run jekyll
Then the _site directory should exist Then the _site directory should exist
And I should see "puts 'Hello world!'" in "_site/index.html" And I should see "puts 'Hello world!'" in "_site/index.html"
Scenario: Set time and no future dated posts
Given I have a _layouts directory
And I have a page layout that contains "Page Layout: {{ site.posts.size }} on {{ site.time | date: "%Y-%m-%d" }}"
And I have a post layout that contains "Post Layout: {{ content }}"
And I have an "index.html" page with layout "page" that contains "site index page"
And I have a configuration file with:
| key | value |
| time | 2010-01-01 |
| future | false |
And I have a _posts directory
And I have the following posts:
| title | date | layout | content |
| entry1 | 12/31/2007 | post | content for entry1. |
| entry2 | 01/31/2020 | post | content for entry2. |
When I run jekyll
Then the _site directory should exist
And I should see "Page Layout: 1 on 2010-01-01" in "_site/index.html"
And I should see "Post Layout: <p>content for entry1.</p>" in "_site/2007/12/31/entry1.html"
And the "_site/2020/01/31/entry2.html" file should not exist
Scenario: Set time and future dated posts allowed
Given I have a _layouts directory
And I have a page layout that contains "Page Layout: {{ site.posts.size }} on {{ site.time | date: "%Y-%m-%d" }}"
And I have a post layout that contains "Post Layout: {{ content }}"
And I have an "index.html" page with layout "page" that contains "site index page"
And I have a configuration file with:
| key | value |
| time | 2010-01-01 |
| future | true |
And I have a _posts directory
And I have the following posts:
| title | date | layout | content |
| entry1 | 12/31/2007 | post | content for entry1. |
| entry2 | 01/31/2020 | post | content for entry2. |
When I run jekyll
Then the _site directory should exist
And I should see "Page Layout: 2 on 2010-01-01" in "_site/index.html"
And I should see "Post Layout: <p>content for entry1.</p>" in "_site/2007/12/31/entry1.html"
And I should see "Post Layout: <p>content for entry2.</p>" in "_site/2020/01/31/entry2.html"

View File

@ -13,7 +13,7 @@ Given /^I have a blank site in "(.*)"$/ do |path|
end end
# Like "I have a foo file" but gives a yaml front matter so jekyll actually processes it # Like "I have a foo file" but gives a yaml front matter so jekyll actually processes it
Given /^I have an "(.*)" page(?: with (.*) "(.*)")? that contains "(.*)"$/ do |file, key, value, text| Given /^I have an? "(.*)" page(?: with (.*) "(.*)")? that contains "(.*)"$/ do |file, key, value, text|
File.open(file, 'w') do |f| File.open(file, 'w') do |f|
f.write <<EOF f.write <<EOF
--- ---
@ -25,7 +25,7 @@ EOF
end end
end end
Given /^I have an "(.*)" file that contains "(.*)"$/ do |file, text| Given /^I have an? "(.*)" file that contains "(.*)"$/ do |file, text|
File.open(file, 'w') do |f| File.open(file, 'w') do |f|
f.write(text) f.write(text)
f.close f.close
@ -39,13 +39,13 @@ Given /^I have a (.*) layout that contains "(.*)"$/ do |layout, text|
end end
end end
Given /^I have a (.*) directory$/ do |dir| Given /^I have an? (.*) directory$/ do |dir|
FileUtils.mkdir(dir) FileUtils.mkdir_p(dir)
end end
Given /^I have the following posts?(?: (.*) "(.*)")?:$/ do |direction, folder, table| Given /^I have the following posts?(?: (.*) "(.*)")?:$/ do |direction, folder, table|
table.hashes.each do |post| table.hashes.each do |post|
date = Date.parse(post['date']).strftime('%Y-%m-%d') date = Date.strptime(post['date'], '%m/%d/%Y').strftime('%Y-%m-%d')
title = post['title'].downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') title = post['title'].downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-')
if direction && direction == "in" if direction && direction == "in"
@ -81,7 +81,16 @@ end
Given /^I have a configuration file with "(.*)" set to "(.*)"$/ do |key, value| Given /^I have a configuration file with "(.*)" set to "(.*)"$/ do |key, value|
File.open('_config.yml', 'w') do |f| File.open('_config.yml', 'w') do |f|
f.write("#{key}: #{value}") f.write("#{key}: #{value}\n")
f.close
end
end
Given /^I have a configuration file with:$/ do |table|
File.open('_config.yml', 'w') do |f|
table.hashes.each do |row|
f.write("#{row["key"]}: #{row["value"]}\n")
end
f.close f.close
end end
end end
@ -90,7 +99,7 @@ Given /^I have a configuration file with "([^\"]*)" set to:$/ do |key, table|
File.open('_config.yml', 'w') do |f| File.open('_config.yml', 'w') do |f|
f.write("#{key}:\n") f.write("#{key}:\n")
table.hashes.each do |row| table.hashes.each do |row|
f.write("- #{row["Value"]}\n") f.write("- #{row["value"]}\n")
end end
f.close f.close
end end
@ -115,14 +124,14 @@ Then /^the (.*) directory should exist$/ do |dir|
assert File.directory?(dir) assert File.directory?(dir)
end end
Then /^the (.*) file should exist$/ do |file|
assert File.file?(file)
end
Then /^I should see "(.*)" in "(.*)"$/ do |text, file| Then /^I should see "(.*)" in "(.*)"$/ do |text, file|
assert_match Regexp.new(text), File.open(file).readlines.join assert_match Regexp.new(text), File.open(file).readlines.join
end end
Then /^the "(.*)" file should exist$/ do |file|
assert File.file?(file)
end
Then /^the "(.*)" file should not exist$/ do |file| Then /^the "(.*)" file should not exist$/ do |file|
assert !File.exists?(file) assert !File.exists?(file)
end end

View File

@ -1,135 +1,127 @@
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.name = %q{jekyll} s.specification_version = 2 if s.respond_to? :specification_version=
s.version = "0.5.4"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.rubygems_version = '1.3.5'
s.name = 'jekyll'
s.version = '0.5.7'
s.date = '2010-04-21'
s.rubyforge_project = 'jekyll'
s.summary = "A simple, blog aware, static site generator."
s.description = "Jekyll is a simple, blog aware, static site generator."
s.authors = ["Tom Preston-Werner"] s.authors = ["Tom Preston-Werner"]
s.date = %q{2009-08-24} s.email = 'tom@mojombo.com'
s.default_executable = %q{jekyll} s.homepage = 'http://github.com/mojombo/jekyll'
s.description = %q{Jekyll is a simple, blog aware, static site generator.}
s.email = %q{tom@mojombo.com} s.require_paths = %w[lib]
s.executables = ["jekyll"] s.executables = ["jekyll"]
s.extra_rdoc_files = [ s.default_executable = 'jekyll'
"README.textile"
]
s.files = [
".gitignore",
"History.txt",
"README.textile",
"Rakefile",
"VERSION.yml",
"bin/jekyll",
"features/create_sites.feature",
"features/embed_filters.feature",
"features/pagination.feature",
"features/permalinks.feature",
"features/post_data.feature",
"features/site_configuration.feature",
"features/site_data.feature",
"features/step_definitions/jekyll_steps.rb",
"features/support/env.rb",
"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/textpattern.rb",
"lib/jekyll/converters/typo.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/pager.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-02-02-not-published.textile",
"test/source/_posts/2008-02-02-published.textile",
"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/_posts/2009-01-27-array-categories.textile",
"test/source/_posts/2009-01-27-categories.textile",
"test/source/_posts/2009-01-27-category.textile",
"test/source/_posts/2009-03-12-hash-#1.markdown",
"test/source/_posts/2009-05-18-tag.textile",
"test/source/_posts/2009-05-18-tags.textile",
"test/source/_posts/2009-06-22-empty-yaml.textile",
"test/source/_posts/2009-06-22-no-yaml.textile",
"test/source/about.html",
"test/source/category/_posts/2008-9-23-categories.textile",
"test/source/contacts.html",
"test/source/css/screen.css",
"test/source/foo/_posts/bar/2008-12-12-topical-post.textile",
"test/source/index.html",
"test/source/sitemap.xml",
"test/source/win/_posts/2009-05-24-yaml-linebreak.markdown",
"test/source/z_category/_posts/2008-9-23-categories.textile",
"test/suite.rb",
"test/test_configuration.rb",
"test/test_filters.rb",
"test/test_generated_site.rb",
"test/test_page.rb",
"test/test_pager.rb",
"test/test_post.rb",
"test/test_site.rb",
"test/test_tags.rb"
]
s.homepage = %q{http://github.com/mojombo/jekyll}
s.rdoc_options = ["--charset=UTF-8"] s.rdoc_options = ["--charset=UTF-8"]
s.require_paths = ["lib"] s.extra_rdoc_files = %w[README.textile LICENSE]
s.rubyforge_project = %q{jekyll}
s.rubygems_version = %q{1.3.5} s.add_runtime_dependency('RedCloth', [">= 4.2.1"])
s.summary = %q{Jekyll is a simple, blog aware, static site generator.} s.add_runtime_dependency('liquid', [">= 1.9.0"])
s.test_files = [ s.add_runtime_dependency('classifier', [">= 1.3.1"])
"test/helper.rb", s.add_runtime_dependency('maruku', [">= 0.5.9"])
"test/suite.rb", s.add_runtime_dependency('directory_watcher', [">= 1.1.1"])
"test/test_configuration.rb",
"test/test_filters.rb", s.add_development_dependency('DEVDEPNAME', [">= 1.1.0", "< 2.0.0"])
"test/test_generated_site.rb",
"test/test_page.rb", # = MANIFEST =
"test/test_pager.rb", s.files = %w[
"test/test_post.rb", History.txt
"test/test_site.rb", README.textile
"test/test_tags.rb" Rakefile
bin/jekyll
cucumber.yml
features/create_sites.feature
features/embed_filters.feature
features/markdown.feature
features/pagination.feature
features/permalinks.feature
features/post_data.feature
features/site_configuration.feature
features/site_data.feature
features/step_definitions/jekyll_steps.rb
features/support/env.rb
jekyll.gemspec
lib/jekyll.rb
lib/jekyll/albino.rb
lib/jekyll/converter.rb
lib/jekyll/converters/identity.rb
lib/jekyll/converters/markdown.rb
lib/jekyll/converters/textile.rb
lib/jekyll/convertible.rb
lib/jekyll/core_ext.rb
lib/jekyll/extension.rb
lib/jekyll/filters.rb
lib/jekyll/generator.rb
lib/jekyll/generators/pagination.rb
lib/jekyll/layout.rb
lib/jekyll/migrators/csv.rb
lib/jekyll/migrators/mephisto.rb
lib/jekyll/migrators/mt.rb
lib/jekyll/migrators/textpattern.rb
lib/jekyll/migrators/typo.rb
lib/jekyll/migrators/wordpress.rb
lib/jekyll/page.rb
lib/jekyll/post.rb
lib/jekyll/site.rb
lib/jekyll/static_file.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-02-02-not-published.textile
test/source/_posts/2008-02-02-published.textile
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/_posts/2009-01-27-array-categories.textile
test/source/_posts/2009-01-27-categories.textile
test/source/_posts/2009-01-27-category.textile
test/source/_posts/2009-01-27-empty-categories.textile
test/source/_posts/2009-01-27-empty-category.textile
test/source/_posts/2009-03-12-hash-#1.markdown
test/source/_posts/2009-05-18-empty-tag.textile
test/source/_posts/2009-05-18-empty-tags.textile
test/source/_posts/2009-05-18-tag.textile
test/source/_posts/2009-05-18-tags.textile
test/source/_posts/2009-06-22-empty-yaml.textile
test/source/_posts/2009-06-22-no-yaml.textile
test/source/_posts/2010-01-08-triple-dash.markdown
test/source/_posts/2010-01-09-date-override.textile
test/source/_posts/2010-01-09-time-override.textile
test/source/_posts/2010-01-09-timezone-override.textile
test/source/_posts/2010-01-16-override-data.textile
test/source/about.html
test/source/category/_posts/2008-9-23-categories.textile
test/source/contacts.html
test/source/css/screen.css
test/source/foo/_posts/bar/2008-12-12-topical-post.textile
test/source/index.html
test/source/sitemap.xml
test/source/win/_posts/2009-05-24-yaml-linebreak.markdown
test/source/z_category/_posts/2008-9-23-categories.textile
test/suite.rb
test/test_configuration.rb
test/test_core_ext.rb
test/test_filters.rb
test/test_generated_site.rb
test/test_page.rb
test/test_pager.rb
test/test_post.rb
test/test_site.rb
test/test_tags.rb
] ]
# = MANIFEST =
if s.respond_to? :specification_version then s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 3
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<RedCloth>, [">= 4.2.1"])
s.add_runtime_dependency(%q<liquid>, [">= 1.9.0"])
s.add_runtime_dependency(%q<classifier>, [">= 1.3.1"])
s.add_runtime_dependency(%q<maruku>, [">= 0.5.9"])
s.add_runtime_dependency(%q<directory_watcher>, [">= 1.1.1"])
s.add_runtime_dependency(%q<open4>, [">= 0.9.6"])
else
s.add_dependency(%q<RedCloth>, [">= 4.2.1"])
s.add_dependency(%q<liquid>, [">= 1.9.0"])
s.add_dependency(%q<classifier>, [">= 1.3.1"])
s.add_dependency(%q<maruku>, [">= 0.5.9"])
s.add_dependency(%q<directory_watcher>, [">= 1.1.1"])
s.add_dependency(%q<open4>, [">= 0.9.6"])
end
else
s.add_dependency(%q<RedCloth>, [">= 4.2.1"])
s.add_dependency(%q<liquid>, [">= 1.9.0"])
s.add_dependency(%q<classifier>, [">= 1.3.1"])
s.add_dependency(%q<maruku>, [">= 0.5.9"])
s.add_dependency(%q<directory_watcher>, [">= 1.1.1"])
s.add_dependency(%q<open4>, [">= 0.9.6"])
end
end end

View File

@ -1,43 +1,64 @@
$:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
# Require all of the Ruby files in the given directory.
#
# path - The String relative path from here to the directory.
#
# Returns nothing.
def require_all(path)
glob = File.join(File.dirname(__FILE__), path, '*.rb')
Dir[glob].each do |f|
require f
end
end
# rubygems # rubygems
require 'rubygems' require 'rubygems'
# core # stdlib
require 'fileutils' require 'fileutils'
require 'time' require 'time'
require 'yaml' require 'yaml'
# stdlib
# 3rd party # 3rd party
require 'liquid' require 'liquid'
require 'redcloth' require 'redcloth'
# internal requires # internal requires
require 'jekyll/core_ext' require 'jekyll/core_ext'
require 'jekyll/pager'
require 'jekyll/site' require 'jekyll/site'
require 'jekyll/convertible' require 'jekyll/convertible'
require 'jekyll/layout' require 'jekyll/layout'
require 'jekyll/page' require 'jekyll/page'
require 'jekyll/post' require 'jekyll/post'
require 'jekyll/filters' require 'jekyll/filters'
require 'jekyll/tags/highlight'
require 'jekyll/tags/include'
require 'jekyll/albino' require 'jekyll/albino'
require 'jekyll/static_file'
# extensions
require 'jekyll/plugin'
require 'jekyll/converter'
require 'jekyll/generator'
require_all 'jekyll/converters'
require_all 'jekyll/generators'
require_all 'jekyll/tags'
module Jekyll module Jekyll
VERSION = '0.5.7'
# Default options. Overriden by values in _config.yml or command-line opts. # Default options. Overriden by values in _config.yml or command-line opts.
# (Strings rather symbols used for compatability with YAML) # (Strings rather symbols used for compatability with YAML).
DEFAULTS = { DEFAULTS = {
'safe' => false,
'auto' => false, 'auto' => false,
'server' => false, 'server' => false,
'server_port' => 4000, 'server_port' => 4000,
'source' => Dir.pwd, 'source' => Dir.pwd,
'destination' => File.join('.', '_site'), 'destination' => File.join('.', '_site'),
'plugins' => File.join('.', '_plugins'),
'future' => true,
'lsi' => false, 'lsi' => false,
'pygments' => false, 'pygments' => false,
'markdown' => 'maruku', 'markdown' => 'maruku',
@ -53,10 +74,13 @@ module Jekyll
} }
# Generate a Jekyll configuration Hash by merging the default options # Generate a Jekyll configuration Hash by merging the default options
# with anything in _config.yml, and adding the given options on top # with anything in _config.yml, and adding the given options on top.
# +override+ is a Hash of config directives
# #
# Returns Hash # override - A Hash of config directives that override any options in both
# the defaults and the config file. See Jekyll::DEFAULTS for a
# list of option names and their defaults.
#
# Returns the final configuration Hash.
def self.configuration(override) def self.configuration(override)
# _config.yml may override default source location, but until # _config.yml may override default source location, but until
# then, we need to know where to look for _config.yml # then, we need to know where to look for _config.yml
@ -67,19 +91,15 @@ module Jekyll
begin begin
config = YAML.load_file(config_file) config = YAML.load_file(config_file)
raise "Invalid configuration - #{config_file}" if !config.is_a?(Hash) raise "Invalid configuration - #{config_file}" if !config.is_a?(Hash)
STDOUT.puts "Configuration from #{config_file}" $stdout.puts "Configuration from #{config_file}"
rescue => err rescue => err
STDERR.puts "WARNING: Could not read configuration. Using defaults (and options)." $stderr.puts "WARNING: Could not read configuration. " +
STDERR.puts "\t" + err.to_s "Using defaults (and options)."
$stderr.puts "\t" + err.to_s
config = {} config = {}
end end
# Merge DEFAULTS < _config.yml < override # Merge DEFAULTS < _config.yml < override
Jekyll::DEFAULTS.deep_merge(config).deep_merge(override) Jekyll::DEFAULTS.deep_merge(config).deep_merge(override)
end end
def self.version
yml = YAML.load(File.read(File.join(File.dirname(__FILE__), *%w[.. VERSION.yml])))
"#{yml[:major]}.#{yml[:minor]}.#{yml[:patch]}"
end
end end

View File

@ -41,7 +41,6 @@
# Chris Wanstrath // chris@ozmm.org # Chris Wanstrath // chris@ozmm.org
# GitHub // http://github.com # GitHub // http://github.com
# #
require 'open4'
class Albino class Albino
@@bin = Rails.development? ? 'pygmentize' : '/usr/bin/pygmentize' rescue 'pygmentize' @@bin = Rails.development? ? 'pygmentize' : '/usr/bin/pygmentize' rescue 'pygmentize'
@ -61,11 +60,10 @@ class Albino
def execute(command) def execute(command)
output = '' output = ''
Open4.popen4(command) do |pid, stdin, stdout, stderr| IO.popen(command, mode='r+') do |p|
stdin.puts @target p.write @target
stdin.close p.close_write
output = stdout.read.strip output = p.read.strip
[stdout, stderr].each { |io| io.close }
end end
output output
end end

43
lib/jekyll/converter.rb Normal file
View File

@ -0,0 +1,43 @@
module Jekyll
class Converter < Plugin
# Public: Get or set the pygments prefix. When an argument is specified,
# the prefix will be set. If no argument is specified, the current prefix
# will be returned.
#
# pygments_prefix - The String prefix (default: nil).
#
# Returns the String prefix.
def self.pygments_prefix(pygments_prefix = nil)
@pygments_prefix = pygments_prefix if pygments_prefix
@pygments_prefix
end
# Public: Get or set the pygments suffix. When an argument is specified,
# the suffix will be set. If no argument is specified, the current suffix
# will be returned.
#
# pygments_suffix - The String suffix (default: nil).
#
# Returns the String suffix.
def self.pygments_suffix(pygments_suffix = nil)
@pygments_suffix = pygments_suffix if pygments_suffix
@pygments_suffix
end
# Get the pygments prefix.
#
# Returns the String prefix.
def pygments_prefix
self.class.pygments_prefix
end
# Get the pygments suffix.
#
# Returns the String suffix.
def pygments_suffix
self.class.pygments_suffix
end
end
end

View File

@ -0,0 +1,22 @@
module Jekyll
class IdentityConverter < Converter
safe true
priority :lowest
def matches(ext)
true
end
def output_ext(ext)
ext
end
def convert(content)
content
end
end
end

View File

@ -0,0 +1,69 @@
module Jekyll
class MarkdownConverter < Converter
safe true
pygments_prefix '\n'
pygments_suffix '\n'
def initialize(config = {})
# Set the Markdown interpreter (and Maruku self.config, if necessary)
case config['markdown']
when 'rdiscount'
begin
require 'rdiscount'
def convert(content)
RDiscount.new(content).to_html
end
rescue LoadError
puts 'You must have the rdiscount gem installed first'
end
when 'maruku'
begin
require 'maruku'
def convert(content)
Maruku.new(content).to_html
end
if config['maruku']['use_divs']
require 'maruku/ext/div'
puts 'Maruku: Using extended syntax for div elements.'
end
if config['maruku']['use_tex']
require 'maruku/ext/math'
puts "Maruku: Using LaTeX extension. Images in `#{config['maruku']['png_dir']}`."
# Switch off MathML output
MaRuKu::Globals[:html_math_output_mathml] = false
MaRuKu::Globals[:html_math_engine] = 'none'
# Turn on math to PNG support with blahtex
# Resulting PNGs stored in `images/latex`
MaRuKu::Globals[:html_math_output_png] = true
MaRuKu::Globals[:html_png_engine] = config['maruku']['png_engine']
MaRuKu::Globals[:html_png_dir] = config['maruku']['png_dir']
MaRuKu::Globals[:html_png_url] = config['maruku']['png_url']
end
rescue LoadError
puts "The maruku gem is required for markdown support!"
end
else
raise "Invalid Markdown processor: '#{config['markdown']}' -- did you mean 'maruku' or 'rdiscount'?"
end
end
def matches(ext)
ext =~ /(markdown|mkdn?|md)/i
end
def output_ext(ext)
".html"
end
end
end

View File

@ -0,0 +1,23 @@
module Jekyll
class TextileConverter < Converter
safe true
pygments_prefix '<notextile>'
pygments_suffix '</notextile>'
def matches(ext)
ext =~ /textile/i
end
def output_ext(ext)
".html"
end
def convert(content)
RedCloth.new(content).to_html
end
end
end

View File

@ -3,6 +3,11 @@
# #
# Requires # Requires
# self.site -> Jekyll::Site # self.site -> Jekyll::Site
# self.content
# self.content=
# self.data=
# self.ext=
# self.output=
module Jekyll module Jekyll
module Convertible module Convertible
# Return the contents as a string # Return the contents as a string
@ -18,7 +23,7 @@ module Jekyll
def read_yaml(base, name) def read_yaml(base, name)
self.content = File.read(File.join(base, name)) self.content = File.read(File.join(base, name))
if self.content =~ /^(---\s*\n.*?\n?)(---.*?\n)/m if self.content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
self.content = self.content[($1.size + $2.size)..-1] self.content = self.content[($1.size + $2.size)..-1]
self.data = YAML.load($1) self.data = YAML.load($1)
@ -27,32 +32,24 @@ module Jekyll
self.data ||= {} self.data ||= {}
end end
# Transform the contents based on the file extension. # Transform the contents based on the content type.
# #
# Returns nothing # Returns nothing
def transform def transform
case self.content_type self.content = converter.convert(self.content)
when 'textile'
self.ext = ".html"
self.content = self.site.textile(self.content)
when 'markdown'
self.ext = ".html"
self.content = self.site.markdown(self.content)
end
end end
# Determine which formatting engine to use based on this convertible's # Determine the extension depending on content_type
# extension
# #
# Returns one of :textile, :markdown or :unknown # Returns the extensions for the output file
def content_type def output_ext
case self.ext[1..-1] converter.output_ext(self.ext)
when /textile/i
return 'textile'
when /markdown/i, /mkdn/i, /md/i
return 'markdown'
end end
return 'unknown'
# Determine which converter to use based on this convertible's
# extension
def converter
@converter ||= self.site.converters.find { |c| c.matches(self.ext) }
end end
# Add any necessary layouts to this convertible document # Add any necessary layouts to this convertible document
@ -64,7 +61,8 @@ module Jekyll
info = { :filters => [Jekyll::Filters], :registers => { :site => self.site } } info = { :filters => [Jekyll::Filters], :registers => { :site => self.site } }
# render and transform content (this becomes the final content of the object) # render and transform content (this becomes the final content of the object)
payload["content_type"] = self.content_type payload["pygments_prefix"] = converter.pygments_prefix
payload["pygments_suffix"] = converter.pygments_suffix
self.content = Liquid::Template.parse(self.content).render(payload, info) self.content = Liquid::Template.parse(self.content).render(payload, info)
self.transform self.transform

View File

@ -19,6 +19,28 @@ class Hash
target target
end end
# Read array from the supplied hash favouring the singular key
# and then the plural key, and handling any nil entries.
# +hash+ the hash to read from
# +singular_key+ the singular key
# +plural_key+ the singular key
#
# Returns an array
def pluralized_array(singular_key, plural_key)
hash = self
if hash.has_key?(singular_key)
array = [hash[singular_key]] if hash[singular_key]
elsif hash.has_key?(plural_key)
case hash[plural_key]
when String
array = hash[plural_key].split
when Array
array = hash[plural_key].compact
end
end
array || []
end
end end
# Thanks, ActiveSupport! # Thanks, ActiveSupport!

7
lib/jekyll/generator.rb Normal file
View File

@ -0,0 +1,7 @@
module Jekyll
class Generator < Plugin
end
end

View File

@ -0,0 +1,87 @@
module Jekyll
class Pagination < Generator
safe true
def generate(site)
site.pages.dup.each do |page|
paginate(site, page) if Pager.pagination_enabled?(site.config, page.name)
end
end
# Paginates the blog's posts. Renders the index.html file into paginated
# directories, ie: page2/index.html, page3/index.html, etc and adds more
# site-wide data.
# +page+ is the index.html Page that requires pagination
#
# {"paginator" => { "page" => <Number>,
# "per_page" => <Number>,
# "posts" => [<Post>],
# "total_posts" => <Number>,
# "total_pages" => <Number>,
# "previous_page" => <Number>,
# "next_page" => <Number> }}
def paginate(site, page)
all_posts = site.site_payload['site']['posts']
pages = Pager.calculate_pages(all_posts, site.config['paginate'].to_i)
(1..pages).each do |num_page|
pager = Pager.new(site.config, num_page, all_posts, pages)
if num_page > 1
newpage = Page.new(site, site.source, page.dir, page.name)
newpage.pager = pager
newpage.dir = File.join(page.dir, "page#{num_page}")
site.pages << newpage
else
page.pager = pager
end
end
end
end
class Pager
attr_reader :page, :per_page, :posts, :total_posts, :total_pages, :previous_page, :next_page
def self.calculate_pages(all_posts, per_page)
num_pages = all_posts.size / per_page.to_i
num_pages = num_pages + 1 if all_posts.size % per_page.to_i != 0
num_pages
end
def self.pagination_enabled?(config, file)
file == 'index.html' && !config['paginate'].nil?
end
def initialize(config, page, all_posts, num_pages = nil)
@page = page
@per_page = config['paginate'].to_i
@total_pages = num_pages || Pager.calculate_pages(all_posts, @per_page)
if @page > @total_pages
raise RuntimeError, "page number can't be greater than total pages: #{@page} > #{@total_pages}"
end
init = (@page - 1) * @per_page
offset = (init + @per_page - 1) >= all_posts.size ? all_posts.size : (init + @per_page - 1)
@total_posts = all_posts.size
@posts = all_posts[init..offset]
@previous_page = @page != 1 ? @page - 1 : nil
@next_page = @page != @total_pages ? @page + 1 : nil
end
def to_liquid
{
'page' => page,
'per_page' => per_page,
'posts' => posts,
'total_posts' => total_posts,
'total_pages' => total_pages,
'previous_page' => previous_page,
'next_page' => next_page
}
end
end
end

View File

@ -1,6 +1,7 @@
require 'rubygems' require 'rubygems'
require 'sequel' require 'sequel'
require 'fileutils' require 'fileutils'
require 'yaml'
# NOTE: This converter requires Sequel and the MySQL gems. # NOTE: This converter requires Sequel and the MySQL gems.
# The MySQL gem can be difficult to install on OS X. Once you have MySQL # The MySQL gem can be difficult to install on OS X. Once you have MySQL

View File

@ -3,8 +3,8 @@ module Jekyll
class Page class Page
include Convertible include Convertible
attr_accessor :site attr_accessor :site, :pager
attr_accessor :name, :ext, :basename attr_accessor :name, :ext, :basename, :dir
attr_accessor :data, :content, :output attr_accessor :data, :content, :output
# Initialize a new Page. # Initialize a new Page.
@ -43,10 +43,10 @@ module Jekyll
end end
def template def template
if self.site.permalink_style == :pretty && !index? if self.site.permalink_style == :pretty && !index? && html?
"/:name/" "/:basename/"
else else
"/:name.html" "/:basename:output_ext"
end end
end end
@ -57,7 +57,12 @@ module Jekyll
def url def url
return permalink if permalink return permalink if permalink
@url ||= (ext == '.html') ? template.gsub(':name', basename) : "/#{name}" @url ||= {
"basename" => self.basename,
"output_ext" => self.output_ext,
}.inject(template) { |result, token|
result.gsub(/:#{token.first}/, token.last)
}.gsub(/\/\//, "/")
end end
# Extract information from the page filename # Extract information from the page filename
@ -75,10 +80,20 @@ module Jekyll
# #
# Returns nothing # Returns nothing
def render(layouts, site_payload) def render(layouts, site_payload)
payload = {"page" => self.data}.deep_merge(site_payload) payload = {
"page" => self.to_liquid,
'paginator' => pager.to_liquid
}.deep_merge(site_payload)
do_layout(payload, layouts) do_layout(payload, layouts)
end end
def to_liquid
self.data.deep_merge({
"url" => self.url,
"content" => self.content })
end
# Write the generated page file to the destination directory. # Write the generated page file to the destination directory.
# +dest_prefix+ is the String path to the destination dir # +dest_prefix+ is the String path to the destination dir
# +dest_suffix+ is a suffix path to the destination dir # +dest_suffix+ is a suffix path to the destination dir
@ -91,7 +106,7 @@ module Jekyll
# The url needs to be unescaped in order to preserve the correct filename # The url needs to be unescaped in order to preserve the correct filename
path = File.join(dest, CGI.unescape(self.url)) path = File.join(dest, CGI.unescape(self.url))
if self.ext == '.html' && self.url[/\.html$/].nil? if self.url =~ /\/$/
FileUtils.mkdir_p(path) FileUtils.mkdir_p(path)
path = File.join(path, "index.html") path = File.join(path, "index.html")
end end
@ -101,7 +116,13 @@ module Jekyll
end end
end end
private def inspect
"#<Jekyll:Page @name=#{self.name.inspect}>"
end
def html?
output_ext == '.html'
end
def index? def index?
basename == 'index' basename == 'index'

View File

@ -1,45 +0,0 @@
module Jekyll
class Pager
attr_reader :page, :per_page, :posts, :total_posts, :total_pages, :previous_page, :next_page
def self.calculate_pages(all_posts, per_page)
num_pages = all_posts.size / per_page.to_i
num_pages.abs + 1 if all_posts.size % per_page.to_i != 0
num_pages
end
def self.pagination_enabled?(config, file)
file == 'index.html' && !config['paginate'].nil?
end
def initialize(config, page, all_posts, num_pages = nil)
@page = page
@per_page = config['paginate'].to_i
@total_pages = num_pages || Pager.calculate_pages(all_posts, @per_page)
if @page > @total_pages
raise RuntimeError, "page number can't be greater than total pages: #{@page} > #{@total_pages}"
end
init = (@page - 1) * @per_page
offset = (init + @per_page - 1) >= all_posts.size ? all_posts.size : (init + @per_page - 1)
@total_posts = all_posts.size
@posts = all_posts[init..offset]
@previous_page = @page != 1 ? @page - 1 : nil
@next_page = @page != @total_pages ? @page + 1 : nil
end
def to_hash
{
'page' => page,
'per_page' => per_page,
'posts' => posts,
'total_posts' => total_posts,
'total_pages' => total_pages,
'previous_page' => previous_page,
'next_page' => next_page
}
end
end
end

76
lib/jekyll/plugin.rb Normal file
View File

@ -0,0 +1,76 @@
module Jekyll
class Plugin
PRIORITIES = { :lowest => -100,
:low => -10,
:normal => 0,
:high => 10,
:highest => 100 }
# Install a hook so that subclasses are recorded. This method is only
# ever called by Ruby itself.
#
# base - The Class subclass.
#
# Returns nothing.
def self.inherited(base)
subclasses << base
subclasses.sort!
end
# The list of Classes that have been subclassed.
#
# Returns an Array of Class objects.
def self.subclasses
@subclasses ||= []
end
# Get or set the priority of this plugin. When called without an
# argument it returns the priority. When an argument is given, it will
# set the priority.
#
# priority - The Symbol priority (default: nil). Valid options are:
# :lowest, :low, :normal, :high, :highest
#
# Returns the Symbol priority.
def self.priority(priority = nil)
if priority && PRIORITIES.has_key?(priority)
@priority = priority
end
@priority || :normal
end
# Get or set the safety of this plugin. When called without an argument
# it returns the safety. When an argument is given, it will set the
# safety.
#
# safe - The Boolean safety (default: nil).
#
# Returns the safety Boolean.
def self.safe(safe = nil)
if safe
@safe = safe
end
@safe || false
end
# Spaceship is priority [higher -> lower]
#
# other - The class to be compared.
#
# Returns -1, 0, 1.
def self.<=>(other)
PRIORITIES[other.priority] <=> PRIORITIES[self.priority]
end
# Initialize a new plugin. This should be overridden by the subclass.
#
# config - The Hash of configuration options.
#
# Returns a new instance.
def initialize(config = {})
# no-op for default
end
end
end

View File

@ -18,12 +18,9 @@ module Jekyll
name =~ MATCHER name =~ MATCHER
end end
attr_accessor :site, :date, :slug, :ext, :published, :data, :content, :output, :tags attr_accessor :site
attr_writer :categories attr_accessor :data, :content, :output, :ext
attr_accessor :date, :slug, :published, :tags, :categories
def categories
@categories ||= []
end
# Initialize this Post instance. # Initialize this Post instance.
# +site+ is the Site # +site+ is the Site
@ -41,32 +38,23 @@ module Jekyll
self.process(name) self.process(name)
self.read_yaml(@base, name) self.read_yaml(@base, name)
#If we've added a date and time to the yaml, use that instead of the filename date
#Means we'll sort correctly.
if self.data.has_key?('date')
# ensure Time via to_s and reparse
self.date = Time.parse(self.data["date"].to_s)
end
if self.data.has_key?('published') && self.data['published'] == false if self.data.has_key?('published') && self.data['published'] == false
self.published = false self.published = false
else else
self.published = true self.published = true
end end
if self.data.has_key?("tag") self.tags = self.data.pluralized_array("tag", "tags")
self.tags = [self.data["tag"]]
elsif self.data.has_key?("tags")
self.tags = self.data['tags']
else
self.tags = []
end
if self.categories.empty? if self.categories.empty?
if self.data.has_key?('category') self.categories = self.data.pluralized_array('category', 'categories')
self.categories << self.data['category']
elsif self.data.has_key?('categories')
# Look for categories in the YAML-header, either specified as
# an array or a string.
if self.data['categories'].kind_of? String
self.categories = self.data['categories'].split
else
self.categories = self.data['categories']
end
end
end end
end end
@ -136,9 +124,12 @@ module Jekyll
"month" => date.strftime("%m"), "month" => date.strftime("%m"),
"day" => date.strftime("%d"), "day" => date.strftime("%d"),
"title" => CGI.escape(slug), "title" => CGI.escape(slug),
"categories" => categories.sort.join('/') "i_day" => date.strftime("%d").to_i.to_s,
"i_month" => date.strftime("%m").to_i.to_s,
"categories" => categories.join('/'),
"output_ext" => self.output_ext
}.inject(template) { |result, token| }.inject(template) { |result, token|
result.gsub(/:#{token.first}/, token.last) result.gsub(/:#{Regexp.escape token.first}/, token.last)
}.gsub(/\/\//, "/") }.gsub(/\/\//, "/")
end end
@ -179,12 +170,10 @@ module Jekyll
# Returns nothing # Returns nothing
def render(layouts, site_payload) def render(layouts, site_payload)
# construct payload # construct payload
payload = payload = {
{
"site" => { "related_posts" => related_posts(site_payload["site"]["posts"]) }, "site" => { "related_posts" => related_posts(site_payload["site"]["posts"]) },
"page" => self.to_liquid "page" => self.to_liquid
} }.deep_merge(site_payload)
payload = payload.deep_merge(site_payload)
do_layout(payload, layouts) do_layout(payload, layouts)
end end
@ -213,7 +202,8 @@ module Jekyll
# #
# Returns <Hash> # Returns <Hash>
def to_liquid def to_liquid
{ "title" => self.data["title"] || self.slug.split('-').select {|w| w.capitalize! || w }.join(' '), self.data.deep_merge({
"title" => self.data["title"] || self.slug.split('-').select {|w| w.capitalize! || w }.join(' '),
"url" => self.url, "url" => self.url,
"date" => self.date, "date" => self.date,
"id" => self.id, "id" => self.id,
@ -221,7 +211,7 @@ module Jekyll
"next" => self.next, "next" => self.next,
"previous" => self.previous, "previous" => self.previous,
"tags" => self.tags, "tags" => self.tags,
"content" => self.content }.deep_merge(self.data) "content" => self.content })
end end
def inspect def inspect

View File

@ -1,8 +1,10 @@
module Jekyll module Jekyll
class Site class Site
attr_accessor :config, :layouts, :posts, :categories, :exclude, attr_accessor :config, :layouts, :posts, :pages, :static_files,
:source, :dest, :lsi, :pygments, :permalink_style, :tags :categories, :exclude, :source, :dest, :lsi, :pygments,
:permalink_style, :tags, :time, :future, :safe, :plugins
attr_accessor :converters, :generators
# Initialize the site # Initialize the site
# +config+ is a Hash containing site configurations details # +config+ is a Hash containing site configurations details
@ -11,97 +13,79 @@ module Jekyll
def initialize(config) def initialize(config)
self.config = config.clone self.config = config.clone
self.source = config['source'] self.safe = config['safe']
self.source = File.expand_path(config['source'])
self.dest = config['destination'] self.dest = config['destination']
self.plugins = File.expand_path(config['plugins'])
self.lsi = config['lsi'] self.lsi = config['lsi']
self.pygments = config['pygments'] self.pygments = config['pygments']
self.permalink_style = config['permalink'].to_sym self.permalink_style = config['permalink'].to_sym
self.exclude = config['exclude'] || [] self.exclude = config['exclude'] || []
self.future = config['future']
self.reset self.reset
self.setup self.setup
end end
def reset def reset
self.time = Time.parse(self.config['time'].to_s) || Time.now
self.layouts = {} self.layouts = {}
self.posts = [] self.posts = []
self.pages = []
self.static_files = []
self.categories = Hash.new { |hash, key| hash[key] = [] } self.categories = Hash.new { |hash, key| hash[key] = [] }
self.tags = Hash.new { |hash, key| hash[key] = [] } self.tags = Hash.new { |hash, key| hash[key] = [] }
end end
def setup def setup
# Check to see if LSI is enabled.
require 'classifier' if self.lsi require 'classifier' if self.lsi
# Set the Markdown interpreter (and Maruku self.config, if necessary) # If safe mode is off, load in any ruby files under the plugins
case self.config['markdown'] # directory.
when 'rdiscount' unless self.safe
begin Dir[File.join(self.plugins, "**/*.rb")].each do |f|
require 'rdiscount' require f
def markdown(content)
RDiscount.new(content).to_html
end
rescue LoadError
puts 'You must have the rdiscount gem installed first'
end
when 'maruku'
begin
require 'maruku'
def markdown(content)
Maruku.new(content).to_html
end
if self.config['maruku']['use_divs']
require 'maruku/ext/div'
puts 'Maruku: Using extended syntax for div elements.'
end
if self.config['maruku']['use_tex']
require 'maruku/ext/math'
puts "Maruku: Using LaTeX extension. Images in `#{self.config['maruku']['png_dir']}`."
# Switch off MathML output
MaRuKu::Globals[:html_math_output_mathml] = false
MaRuKu::Globals[:html_math_engine] = 'none'
# Turn on math to PNG support with blahtex
# Resulting PNGs stored in `images/latex`
MaRuKu::Globals[:html_math_output_png] = true
MaRuKu::Globals[:html_png_engine] = self.config['maruku']['png_engine']
MaRuKu::Globals[:html_png_dir] = self.config['maruku']['png_dir']
MaRuKu::Globals[:html_png_url] = self.config['maruku']['png_url']
end
rescue LoadError
puts "The maruku gem is required for markdown support!"
end
else
raise "Invalid Markdown processor: '#{self.config['markdown']}' -- did you mean 'maruku' or 'rdiscount'?"
end end
end end
def textile(content) self.converters = Jekyll::Converter.subclasses.select do |c|
RedCloth.new(content).to_html !self.safe || c.safe
end.map do |c|
c.new(self.config)
end
self.generators = Jekyll::Generator.subclasses.select do |c|
!self.safe || c.safe
end.map do |c|
c.new(self.config)
end
end end
# Do the actual work of processing the site and generating the # Do the actual work of processing the site and generating the
# real deal. # real deal. 5 phases; reset, read, generate, render, write. This allows
# rendering to have full site payload available.
# #
# Returns nothing # Returns nothing
def process def process
self.reset self.reset
self.read_layouts self.read
self.transform_pages self.generate
self.write_posts self.render
self.write
end end
# Read all the files in <source>/_layouts into memory for later use. def read
self.read_layouts # existing implementation did this at top level only so preserved that
self.read_directories
end
# Read all the files in <source>/<dir>/_layouts and create a new Layout
# object with each one.
# #
# Returns nothing # Returns nothing
def read_layouts def read_layouts(dir = '')
base = File.join(self.source, "_layouts") base = File.join(self.source, dir, "_layouts")
return unless File.exists?(base)
entries = [] entries = []
Dir.chdir(base) { entries = filter_entries(Dir['*.*']) } Dir.chdir(base) { entries = filter_entries(Dir['*.*']) }
@ -109,24 +93,23 @@ module Jekyll
name = f.split(".")[0..-2].join(".") name = f.split(".")[0..-2].join(".")
self.layouts[name] = Layout.new(self, base, f) self.layouts[name] = Layout.new(self, base, f)
end end
rescue Errno::ENOENT => e
# ignore missing layout dir
end end
# Read all the files in <base>/_posts and create a new Post object with each one. # Read all the files in <source>/<dir>/_posts and create a new Post
# object with each one.
# #
# Returns nothing # Returns nothing
def read_posts(dir) def read_posts(dir)
base = File.join(self.source, dir, '_posts') base = File.join(self.source, dir, '_posts')
entries = [] return unless File.exists?(base)
Dir.chdir(base) { entries = filter_entries(Dir['**/*']) } entries = Dir.chdir(base) { filter_entries(Dir['**/*']) }
# first pass processes, but does not yet render post content # first pass processes, but does not yet render post content
entries.each do |f| entries.each do |f|
if Post.valid?(f) if Post.valid?(f)
post = Post.new(self, self.source, dir, f) post = Post.new(self, self.source, dir, f)
if post.published if post.published && (self.future || post.date <= self.time)
self.posts << post self.posts << post
post.categories.each { |c| self.categories[c] << post } post.categories.each { |c| self.categories[c] << post }
post.tags.each { |c| self.tags[c] << post } post.tags.each { |c| self.tags[c] << post }
@ -135,68 +118,70 @@ module Jekyll
end end
self.posts.sort! self.posts.sort!
end
# second pass renders each post now that full site payload is available def generate
self.generators.each do |generator|
generator.generate(self)
end
end
def render
self.posts.each do |post| self.posts.each do |post|
post.render(self.layouts, site_payload) post.render(self.layouts, site_payload)
end end
self.pages.each do |page|
page.render(self.layouts, site_payload)
end
self.categories.values.map { |ps| ps.sort! { |a, b| b <=> a} } self.categories.values.map { |ps| ps.sort! { |a, b| b <=> a} }
self.tags.values.map { |ps| ps.sort! { |a, b| b <=> a} } self.tags.values.map { |ps| ps.sort! { |a, b| b <=> a} }
rescue Errno::ENOENT => e rescue Errno::ENOENT => e
# ignore missing layout dir # ignore missing layout dir
end end
# Write each post to <dest>/<year>/<month>/<day>/<slug> # Write static files, pages and posts
# #
# Returns nothing # Returns nothing
def write_posts def write
self.posts.each do |post| self.posts.each do |post|
post.write(self.dest) post.write(self.dest)
end end
self.pages.each do |page|
page.write(self.dest)
end
self.static_files.each do |sf|
sf.write(self.dest)
end
end end
# Copy all regular files from <source> to <dest>/ ignoring # Reads the directories and finds posts, pages and static files that will
# any files/directories that are hidden or backup files (start # become part of the valid site according to the rules in +filter_entries+.
# with "." or "#" or end with "~") or contain site content (start with "_")
# unless they are "_posts" directories or web server files such as
# '.htaccess'
# The +dir+ String is a relative path used to call this method # The +dir+ String is a relative path used to call this method
# recursively as it descends through directories # recursively as it descends through directories
# #
# Returns nothing # Returns nothing
def transform_pages(dir = '') def read_directories(dir = '')
base = File.join(self.source, dir) base = File.join(self.source, dir)
entries = filter_entries(Dir.entries(base)) entries = filter_entries(Dir.entries(base))
directories = entries.select { |e| File.directory?(File.join(base, e)) }
files = entries.reject { |e| File.directory?(File.join(base, e)) || File.symlink?(File.join(base, e)) }
# we need to make sure to process _posts *first* otherwise they self.read_posts(dir)
# might not be available yet to other templates as {{ site.posts }}
if directories.include?('_posts')
directories.delete('_posts')
read_posts(dir)
end
[directories, files].each do |entries|
entries.each do |f| entries.each do |f|
if File.directory?(File.join(base, f)) f_abs = File.join(base, f)
next if self.dest.sub(/\/$/, '') == File.join(base, f) f_rel = File.join(dir, f)
transform_pages(File.join(dir, f)) if File.directory?(f_abs)
elsif Pager.pagination_enabled?(self.config, f) next if self.dest.sub(/\/$/, '') == f_abs
paginate_posts(f, dir) read_directories(f_rel)
else elsif !File.symlink?(f_abs)
first3 = File.open(File.join(self.source, dir, f)) { |fd| fd.read(3) } first3 = File.open(f_abs) { |fd| fd.read(3) }
if first3 == "---" if first3 == "---"
# file appears to have a YAML header so process it as a page # file appears to have a YAML header so process it as a page
page = Page.new(self, self.source, dir, f) pages << Page.new(self, self.source, dir, f)
page.render(self.layouts, site_payload)
page.write(self.dest)
else else
# otherwise copy the file without transforming it # otherwise treat it as a static file
FileUtils.mkdir_p(File.join(self.dest, dir)) static_files << StaticFile.new(self, self.source, dir, f)
FileUtils.cp(File.join(self.source, dir, f), File.join(self.dest, dir, f))
end
end end
end end
end end
@ -218,48 +203,29 @@ module Jekyll
# #
# Returns {"site" => {"time" => <Time>, # Returns {"site" => {"time" => <Time>,
# "posts" => [<Post>], # "posts" => [<Post>],
# "pages" => [<Page>],
# "categories" => [<Post>]} # "categories" => [<Post>]}
def site_payload def site_payload
{"site" => self.config.merge({ {"site" => self.config.merge({
"time" => Time.now, "time" => self.time,
"posts" => self.posts.sort { |a,b| b <=> a }, "posts" => self.posts.sort { |a,b| b <=> a },
"pages" => self.pages,
"html_pages" => self.pages.reject { |page| !page.html? },
"categories" => post_attr_hash('categories'), "categories" => post_attr_hash('categories'),
"tags" => post_attr_hash('tags')})} "tags" => post_attr_hash('tags')})}
end end
# Filter out any files/directories that are hidden or backup files (start # Filter out any files/directories that are hidden or backup files (start
# with "." or "#" or end with "~") or contain site content (start with "_") # with "." or "#" or end with "~"), or contain site content (start with "_"),
# unless they are "_posts" directories or web server files such as # or are excluded in the site configuration, unless they are web server
# '.htaccess' # files such as '.htaccess'
def filter_entries(entries) def filter_entries(entries)
entries = entries.reject do |e| entries = entries.reject do |e|
unless ['_posts', '.htaccess'].include?(e) unless ['.htaccess'].include?(e)
['.', '_', '#'].include?(e[0..0]) || e[-1..-1] == '~' || self.exclude.include?(e) ['.', '_', '#'].include?(e[0..0]) || e[-1..-1] == '~' || self.exclude.include?(e)
end end
end end
end end
# Paginates the blog's posts. Renders the index.html file into paginated directories, ie: page2, page3...
# and adds more wite-wide data
#
# {"paginator" => { "page" => <Number>,
# "per_page" => <Number>,
# "posts" => [<Post>],
# "total_posts" => <Number>,
# "total_pages" => <Number>,
# "previous_page" => <Number>,
# "next_page" => <Number> }}
def paginate_posts(file, dir)
all_posts = self.posts.sort { |a,b| b <=> a }
pages = Pager.calculate_pages(all_posts, self.config['paginate'].to_i)
pages += 1
(1..pages).each do |num_page|
pager = Pager.new(self.config, num_page, all_posts, pages)
page = Page.new(self, self.source, dir, file)
page.render(self.layouts, site_payload.merge({'paginator' => pager.to_hash}))
suffix = "page#{num_page}" if num_page > 1
page.write(self.dest, suffix)
end
end
end end
end end

76
lib/jekyll/static_file.rb Normal file
View File

@ -0,0 +1,76 @@
module Jekyll
class StaticFile
@@mtimes = Hash.new # the cache of last modification times [path] -> mtime
# Initialize a new StaticFile.
# +site+ is the Site
# +base+ is the String path to the <source>
# +dir+ is the String path between <source> and the file
# +name+ is the String filename of the file
#
# Returns <StaticFile>
def initialize(site, base, dir, name)
@site = site
@base = base
@dir = dir
@name = name
end
# Obtains source file path.
#
# Returns source file path.
def path
File.join(@base, @dir, @name)
end
# Obtain destination path.
# +dest+ is the String path to the destination dir
#
# Returns destination file path.
def destination(dest)
File.join(dest, @dir, @name)
end
# Obtain mtime of the source path.
#
# Returns last modifiaction time for this file.
def mtime
File.stat(path).mtime.to_i
end
# Is source path modified?
#
# Returns true if modified since last write.
def modified?
@@mtimes[path] != mtime
end
# Write the static file to the destination directory (if modified).
# +dest+ is the String path to the destination dir
#
# Returns false if the file was not modified since last time (no-op).
def write(dest)
dest_path = destination(dest)
dest_dir = File.join(dest, @dir)
return false if File.exist? dest_path and !modified?
@@mtimes[path] = mtime
FileUtils.mkdir_p(dest_dir)
FileUtils.cp(path, dest_path)
true
end
# Reset the mtimes cache (for testing purposes).
#
# Returns nothing.
def self.reset_cache
@@mtimes = Hash.new
nil
end
end
end

View File

@ -4,15 +4,28 @@ module Jekyll
include Liquid::StandardFilters include Liquid::StandardFilters
# we need a language, but the linenos argument is optional. # we need a language, but the linenos argument is optional.
SYNTAX = /(\w+)\s?(:?linenos)?\s?/ SYNTAX = /(\w+)\s?([\w\s=]+)*/
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, tokens)
super super
if markup =~ SYNTAX if markup =~ SYNTAX
@lang = $1 @lang = $1
if defined? $2 if defined? $2
tmp_options = {}
$2.split.each do |opt|
key, value = opt.split('=')
if value.nil?
if key == 'linenos'
value = 'inline'
else
value = true
end
end
tmp_options[key] = value
end
tmp_options = tmp_options.to_a.collect { |opt| opt.join('=') }
# additional options to pass to Albino. # additional options to pass to Albino.
@options = { 'O' => 'linenos=inline' } @options = { 'O' => tmp_options.join(',') }
else else
@options = {} @options = {}
end end
@ -23,21 +36,17 @@ module Jekyll
def render(context) def render(context)
if context.registers[:site].pygments if context.registers[:site].pygments
output = render_pygments(context, super.to_s) render_pygments(context, super.join)
else else
output = render_codehighlighter(context, super.to_s) render_codehighlighter(context, super.join)
end end
output
end end
def render_pygments(context, code) def render_pygments(context, code)
if context["content_type"] == "markdown" output = add_code_tags(Albino.new(code, @lang).to_s(@options), @lang)
return "\n" + Albino.new(code, @lang).to_s(@options) + "\n" output = context["pygments_prefix"] + output if context["pygments_prefix"]
elsif context["content_type"] == "textile" output = output + context["pygments_suffix"] if context["pygments_suffix"]
return "<notextile>" + Albino.new(code, @lang).to_s(@options) + "</notextile>" output
else
return Albino.new(code, @lang).to_s(@options)
end
end end
def render_codehighlighter(context, code) def render_codehighlighter(context, code)
@ -50,6 +59,13 @@ module Jekyll
</div> </div>
HTML HTML
end end
def add_code_tags(code, lang)
# Add nested <code> tags to code blocks
code = code.sub(/<pre>/,'<pre><code class="' + lang + '">')
code = code.sub(/<\/pre>/,"</code></pre>")
end
end end
end end

View File

@ -1,5 +1,5 @@
require 'rubygems' require 'rubygems'
gem 'RedCloth', '= 4.2.1' gem 'RedCloth', '>= 4.2.1'
require File.join(File.dirname(__FILE__), *%w[.. lib jekyll]) require File.join(File.dirname(__FILE__), *%w[.. lib jekyll])

View File

@ -0,0 +1,7 @@
---
layout: default
title: Category in YAML
categories:
---
Best *post* ever

View File

@ -0,0 +1,7 @@
---
layout: default
title: Category in YAML
category:
---
Best *post* ever

View File

@ -0,0 +1,6 @@
---
title: A Tag
tag:
---
Whoa.

View File

@ -0,0 +1,6 @@
---
title: Some Tags
tags:
---
Awesome!

View File

@ -0,0 +1,5 @@
---
title: Foo --- Bar
---
Triple the fun!

View File

@ -0,0 +1,7 @@
---
date: 2010-01-10
---
Post with a front matter date
{{ page.date | date_to_string }}

View File

@ -0,0 +1,7 @@
---
date: 2010-01-10 13:07:09
---
Post with a front matter time
{{ page.date | date_to_string }}

View File

@ -0,0 +1,7 @@
---
date: 2010-01-10 13:07:09 +00:00
---
Post with a front matter time with timezone
{{ page.date | date_to_string }}

View File

@ -0,0 +1,4 @@
---
date: 2010-01-10 13:07:09
tags: A string
---

View File

@ -7,17 +7,26 @@ layout: nil
<url> <url>
<loc>http://example.com</loc> <loc>http://example.com</loc>
<lastmod>{{ site.time | date_to_xmlschema }}</lastmod> <lastmod>{{ site.time | date: "%Y-%m-%d" }}</lastmod>
<changefreq>daily</changefreq> <changefreq>daily</changefreq>
<priority>1.0</priority> <priority>1.0</priority>
</url> </url>
{% for post in site.posts %} {% for post in site.posts %}
<url> <url>
<loc>http://example.com/{{ post.url }}/</loc> <loc>http://example.com{{ post.url }}/</loc>
<lastmod>{{ site.time }}</lastmod> <lastmod>{{ post.date | date: "%Y-%m-%d" }}</lastmod>
<changefreq>monthly</changefreq> <changefreq>monthly</changefreq>
<priority>0.2</priority> <priority>0.2</priority>
</url> </url>
{% endfor %} {% endfor %}
{% for page in site.html_pages %}
<url>
<loc>http://example.com{{ page.url }}</loc>
<lastmod>{{ site.time | date: "%Y-%m-%d" }}</lastmod>
{% if page.changefreq %}<changefreq>{{ page.changefreq }}</changefreq>{% endif %}
{% if page.priority %}<priority>{{ page.priority }}</priority>{% endif %}
</url>
{% endfor %}
</urlset> </urlset>

View File

@ -8,21 +8,21 @@ class TestConfiguration < Test::Unit::TestCase
should "fire warning with no _config.yml" do should "fire warning with no _config.yml" do
mock(YAML).load_file(@path) { raise "No such file or directory - #{@path}" } mock(YAML).load_file(@path) { raise "No such file or directory - #{@path}" }
mock(STDERR).puts("WARNING: Could not read configuration. Using defaults (and options).") mock($stderr).puts("WARNING: Could not read configuration. Using defaults (and options).")
mock(STDERR).puts("\tNo such file or directory - #{@path}") mock($stderr).puts("\tNo such file or directory - #{@path}")
assert_equal Jekyll::DEFAULTS, Jekyll.configuration({}) assert_equal Jekyll::DEFAULTS, Jekyll.configuration({})
end end
should "load configuration as hash" do should "load configuration as hash" do
mock(YAML).load_file(@path) { Hash.new } mock(YAML).load_file(@path) { Hash.new }
mock(STDOUT).puts("Configuration from #{@path}") mock($stdout).puts("Configuration from #{@path}")
assert_equal Jekyll::DEFAULTS, Jekyll.configuration({}) assert_equal Jekyll::DEFAULTS, Jekyll.configuration({})
end end
should "fire warning with bad config" do should "fire warning with bad config" do
mock(YAML).load_file(@path) { Array.new } mock(YAML).load_file(@path) { Array.new }
mock(STDERR).puts("WARNING: Could not read configuration. Using defaults (and options).") mock($stderr).puts("WARNING: Could not read configuration. Using defaults (and options).")
mock(STDERR).puts("\tInvalid configuration - #{@path}") mock($stderr).puts("\tInvalid configuration - #{@path}")
assert_equal Jekyll::DEFAULTS, Jekyll.configuration({}) assert_equal Jekyll::DEFAULTS, Jekyll.configuration({})
end end
end end

66
test/test_core_ext.rb Normal file
View File

@ -0,0 +1,66 @@
require File.dirname(__FILE__) + '/helper'
class TestCoreExt < Test::Unit::TestCase
context "hash" do
context "pluralized_array" do
should "return empty array with no values" do
data = {}
assert_equal [], data.pluralized_array('tag', 'tags')
end
should "return empty array with no matching values" do
data = { 'foo' => 'bar' }
assert_equal [], data.pluralized_array('tag', 'tags')
end
should "return empty array with matching nil singular" do
data = { 'foo' => 'bar', 'tag' => nil, 'tags' => ['dog', 'cat'] }
assert_equal [], data.pluralized_array('tag', 'tags')
end
should "return single value array with matching singular" do
data = { 'foo' => 'bar', 'tag' => 'dog', 'tags' => ['dog', 'cat'] }
assert_equal ['dog'], data.pluralized_array('tag', 'tags')
end
should "return single value array with matching singular with spaces" do
data = { 'foo' => 'bar', 'tag' => 'dog cat', 'tags' => ['dog', 'cat'] }
assert_equal ['dog cat'], data.pluralized_array('tag', 'tags')
end
should "return empty array with matching nil plural" do
data = { 'foo' => 'bar', 'tags' => nil }
assert_equal [], data.pluralized_array('tag', 'tags')
end
should "return empty array with matching empty array" do
data = { 'foo' => 'bar', 'tags' => [] }
assert_equal [], data.pluralized_array('tag', 'tags')
end
should "return single value array with matching plural with single string value" do
data = { 'foo' => 'bar', 'tags' => 'dog' }
assert_equal ['dog'], data.pluralized_array('tag', 'tags')
end
should "return multiple value array with matching plural with single string value with spaces" do
data = { 'foo' => 'bar', 'tags' => 'dog cat' }
assert_equal ['dog', 'cat'], data.pluralized_array('tag', 'tags')
end
should "return single value array with matching plural with single value array" do
data = { 'foo' => 'bar', 'tags' => ['dog'] }
assert_equal ['dog'], data.pluralized_array('tag', 'tags')
end
should "return multiple value array with matching plural with multiple value array" do
data = { 'foo' => 'bar', 'tags' => ['dog', 'cat'] }
assert_equal ['dog', 'cat'], data.pluralized_array('tag', 'tags')
end
end
end
end

View File

@ -13,6 +13,10 @@ class TestGeneratedSite < Test::Unit::TestCase
@index = File.read(dest_dir('index.html')) @index = File.read(dest_dir('index.html'))
end end
should "ensure post count is as expected" do
assert_equal 26, @site.posts.size
end
should "insert site.posts into the index" do should "insert site.posts into the index" do
assert @index.include?("#{@site.posts.size} Posts") assert @index.include?("#{@site.posts.size} Posts")
end end

View File

@ -1,7 +1,34 @@
require File.dirname(__FILE__) + '/helper' require File.dirname(__FILE__) + '/helper'
class TestPager < Test::Unit::TestCase class TestPager < Test::Unit::TestCase
context "pagination enabled" do
should "calculate number of pages" do
assert_equal(0, Pager.calculate_pages([], '2'))
assert_equal(1, Pager.calculate_pages([1], '2'))
assert_equal(1, Pager.calculate_pages([1,2], '2'))
assert_equal(2, Pager.calculate_pages([1,2,3], '2'))
assert_equal(2, Pager.calculate_pages([1,2,3,4], '2'))
assert_equal(3, Pager.calculate_pages([1,2,3,4,5], '2'))
end
context "pagination disabled" do
setup do
stub(Jekyll).configuration do
Jekyll::DEFAULTS.merge({
'source' => source_dir,
'destination' => dest_dir
})
end
@config = Jekyll.configuration
end
should "report that pagination is disabled" do
assert !Pager.pagination_enabled?(@config, 'index.html')
end
end
context "pagination enabled for 2" do
setup do setup do
stub(Jekyll).configuration do stub(Jekyll).configuration do
Jekyll::DEFAULTS.merge({ Jekyll::DEFAULTS.merge({
@ -13,16 +40,22 @@ class TestPager < Test::Unit::TestCase
@config = Jekyll.configuration @config = Jekyll.configuration
@site = Site.new(@config) @site = Site.new(@config)
@posts = @site.read_posts('') @site.process
@posts = @site.posts
end end
should "calculate number of pages" do should "report that pagination is enabled" do
assert_equal(2, Pager.calculate_pages(@posts, @config['paginate'])) assert Pager.pagination_enabled?(@config, 'index.html')
end
context "with 4 posts" do
setup do
@posts = @site.posts[1..4] # limit to 4
end end
should "create first pager" do should "create first pager" do
pager = Pager.new(@config, 1, @posts) pager = Pager.new(@config, 1, @posts)
assert_equal(@config['paginate'].to_i, pager.posts.size) assert_equal(2, pager.posts.size)
assert_equal(2, pager.total_pages) assert_equal(2, pager.total_pages)
assert_nil(pager.previous_page) assert_nil(pager.previous_page)
assert_equal(2, pager.next_page) assert_equal(2, pager.next_page)
@ -30,7 +63,7 @@ class TestPager < Test::Unit::TestCase
should "create second pager" do should "create second pager" do
pager = Pager.new(@config, 2, @posts) pager = Pager.new(@config, 2, @posts)
assert_equal(@posts.size - @config['paginate'].to_i, pager.posts.size) assert_equal(2, pager.posts.size)
assert_equal(2, pager.total_pages) assert_equal(2, pager.total_pages)
assert_equal(1, pager.previous_page) assert_equal(1, pager.previous_page)
assert_nil(pager.next_page) assert_nil(pager.next_page)
@ -40,8 +73,41 @@ class TestPager < Test::Unit::TestCase
assert_raise(RuntimeError) { Pager.new(@config, 3, @posts) } assert_raise(RuntimeError) { Pager.new(@config, 3, @posts) }
end end
should "report that pagination is enabled" do end
assert Pager.pagination_enabled?(@config, 'index.html')
context "with 5 posts" do
setup do
@posts = @site.posts[1..5] # limit to 5
end
should "create first pager" do
pager = Pager.new(@config, 1, @posts)
assert_equal(2, pager.posts.size)
assert_equal(3, pager.total_pages)
assert_nil(pager.previous_page)
assert_equal(2, pager.next_page)
end
should "create second pager" do
pager = Pager.new(@config, 2, @posts)
assert_equal(2, pager.posts.size)
assert_equal(3, pager.total_pages)
assert_equal(1, pager.previous_page)
assert_equal(3, pager.next_page)
end
should "create third pager" do
pager = Pager.new(@config, 3, @posts)
assert_equal(1, pager.posts.size)
assert_equal(3, pager.total_pages)
assert_equal(2, pager.previous_page)
assert_nil(pager.next_page)
end
should "not create fourth pager" do
assert_raise(RuntimeError) { Pager.new(@config, 4, @posts) }
end
end end
end end
end end

View File

@ -18,10 +18,10 @@ class TestPost < Test::Unit::TestCase
end end
should "ensure valid posts are valid" do should "ensure valid posts are valid" do
assert Post.valid?("2008-10-19-foo-bar.textile") assert Post.valid?("2008-09-09-foo-bar.textile")
assert Post.valid?("foo/bar/2008-10-19-foo-bar.textile") assert Post.valid?("foo/bar/2008-09-09-foo-bar.textile")
assert !Post.valid?("lol2008-10-19-foo-bar.textile") assert !Post.valid?("lol2008-09-09-foo-bar.textile")
assert !Post.valid?("blah") assert !Post.valid?("blah")
end end
@ -31,24 +31,25 @@ class TestPost < Test::Unit::TestCase
@post.site = @site @post.site = @site
@real_file = "2008-10-18-foo-bar.textile" @real_file = "2008-10-18-foo-bar.textile"
@fake_file = "2008-10-19-foo-bar.textile" @fake_file = "2008-09-09-foo-bar.textile"
@source = source_dir('_posts') @source = source_dir('_posts')
end end
should "keep date, title, and markup type" do should "keep date, title, and markup type" do
@post.categories = []
@post.process(@fake_file) @post.process(@fake_file)
assert_equal Time.parse("2008-10-19"), @post.date assert_equal Time.parse("2008-09-09"), @post.date
assert_equal "foo-bar", @post.slug assert_equal "foo-bar", @post.slug
assert_equal ".textile", @post.ext assert_equal ".textile", @post.ext
assert_equal "/2008/10/19", @post.dir assert_equal "/2008/09/09", @post.dir
assert_equal "/2008/10/19/foo-bar", @post.id assert_equal "/2008/09/09/foo-bar", @post.id
end end
should "create url based on date and title" do should "create url based on date and title" do
@post.categories = [] @post.categories = []
@post.process(@fake_file) @post.process(@fake_file)
assert_equal "/2008/10/19/foo-bar.html", @post.url assert_equal "/2008/09/09/foo-bar.html", @post.url
end end
should "CGI escape urls" do should "CGI escape urls" do
@ -77,7 +78,19 @@ class TestPost < Test::Unit::TestCase
@post.read_yaml(@source, @real_file) @post.read_yaml(@source, @real_file)
assert_equal({"title" => "Test title", "layout" => "post", "tag" => "Ruby"}, @post.data) assert_equal({"title" => "Test title", "layout" => "post", "tag" => "Ruby"}, @post.data)
assert_equal "\r\nThis is the content", @post.content assert_equal "This is the content", @post.content
end
end
context "with embedded triple dash" do
setup do
@real_file = "2010-01-08-triple-dash.markdown"
end
should "consume the embedded dashes" do
@post.read_yaml(@source, @real_file)
assert_equal({"title" => "Foo --- Bar"}, @post.data)
assert_equal "Triple the fun!", @post.content
end end
end end
@ -93,7 +106,7 @@ class TestPost < Test::Unit::TestCase
should "process the url correctly" do should "process the url correctly" do
assert_equal "/:categories/:year/:month/:day/:title.html", @post.template assert_equal "/:categories/:year/:month/:day/:title.html", @post.template
assert_equal "/2008/10/19/foo-bar.html", @post.url assert_equal "/2008/09/09/foo-bar.html", @post.url
end end
end end
@ -105,7 +118,7 @@ class TestPost < Test::Unit::TestCase
should "process the url correctly" do should "process the url correctly" do
assert_equal "/:categories/:year/:month/:day/:title.html", @post.template assert_equal "/:categories/:year/:month/:day/:title.html", @post.template
assert_equal "/beer/2008/10/19/foo-bar.html", @post.url assert_equal "/beer/2008/09/09/foo-bar.html", @post.url
end end
end end
@ -118,7 +131,7 @@ class TestPost < Test::Unit::TestCase
should "process the url correctly" do should "process the url correctly" do
assert_equal "/:categories/:year/:month/:day/:title.html", @post.template assert_equal "/:categories/:year/:month/:day/:title.html", @post.template
assert_equal "/beer/food/2008/10/19/foo-bar.html", @post.url assert_equal "/food/beer/2008/09/09/foo-bar.html", @post.url
end end
end end
@ -142,7 +155,18 @@ class TestPost < Test::Unit::TestCase
should "process the url correctly" do should "process the url correctly" do
assert_equal "/:categories/:year/:month/:day/:title/", @post.template assert_equal "/:categories/:year/:month/:day/:title/", @post.template
assert_equal "/2008/10/19/foo-bar/", @post.url assert_equal "/2008/09/09/foo-bar/", @post.url
end
end
context "with custom date permalink" do
setup do
@post.site.permalink_style = '/:categories/:year/:i_month/:i_day/:title/'
@post.process(@fake_file)
end
should "process the url correctly" do
assert_equal "/2008/9/9/foo-bar/", @post.url
end end
end end
@ -163,7 +187,7 @@ class TestPost < Test::Unit::TestCase
@post.read_yaml(@source, @real_file) @post.read_yaml(@source, @real_file)
assert_equal({"title" => "Foo Bar", "layout" => "default"}, @post.data) assert_equal({"title" => "Foo Bar", "layout" => "default"}, @post.data)
assert_equal "\nh1. {{ page.title }}\n\nBest *post* ever", @post.content assert_equal "h1. {{ page.title }}\n\nBest *post* ever", @post.content
end end
should "transform textile" do should "transform textile" do
@ -212,6 +236,41 @@ class TestPost < Test::Unit::TestCase
assert_equal false, post.published assert_equal false, post.published
end end
should "recognize date in yaml" do
post = setup_post("2010-01-09-date-override.textile")
do_render(post)
assert_equal Time, post.date.class
assert_equal Time, post.to_liquid["date"].class
assert_equal "/2010/01/10/date-override.html", post.url
assert_equal "<p>Post with a front matter date</p>\n<p>10 Jan 2010</p>", post.output
end
should "recognize time in yaml" do
post = setup_post("2010-01-09-time-override.textile")
do_render(post)
assert_equal Time, post.date.class
assert_equal Time, post.to_liquid["date"].class
assert_equal "/2010/01/10/time-override.html", post.url
assert_equal "<p>Post with a front matter time</p>\n<p>10 Jan 2010</p>", post.output
end
should "recognize time with timezone in yaml" do
post = setup_post("2010-01-09-timezone-override.textile")
do_render(post)
assert_equal Time, post.date.class
assert_equal Time, post.to_liquid["date"].class
assert_equal "/2010/01/10/timezone-override.html", post.url
assert_equal "<p>Post with a front matter time with timezone</p>\n<p>10 Jan 2010</p>", post.output
end
should "to_liquid prioritizes post attributes over data" do
post = setup_post("2010-01-16-override-data.textile")
assert_equal Array, post.tags.class
assert_equal Array, post.to_liquid["tags"].class
assert_equal Time, post.date.class
assert_equal Time, post.to_liquid["date"].class
end
should "recognize category in yaml" do should "recognize category in yaml" do
post = setup_post("2009-01-27-category.textile") post = setup_post("2009-01-27-category.textile")
assert post.categories.include?('foo') assert post.categories.include?('foo')
@ -224,6 +283,16 @@ class TestPost < Test::Unit::TestCase
assert post.categories.include?('baz') assert post.categories.include?('baz')
end end
should "recognize empty category in yaml" do
post = setup_post("2009-01-27-empty-category.textile")
assert_equal [], post.categories
end
should "recognize empty categories in yaml" do
post = setup_post("2009-01-27-empty-categories.textile")
assert_equal [], post.categories
end
should "recognize tag in yaml" do should "recognize tag in yaml" do
post = setup_post("2009-05-18-tag.textile") post = setup_post("2009-05-18-tag.textile")
assert post.tags.include?('code') assert post.tags.include?('code')
@ -236,6 +305,16 @@ class TestPost < Test::Unit::TestCase
assert post.tags.include?('pizza') assert post.tags.include?('pizza')
end end
should "recognize empty tag in yaml" do
post = setup_post("2009-05-18-empty-tag.textile")
assert_equal [], post.tags
end
should "recognize empty tags in yaml" do
post = setup_post("2009-05-18-empty-tags.textile")
assert_equal [], post.tags
end
should "allow no yaml" do should "allow no yaml" do
post = setup_post("2009-06-22-no-yaml.textile") post = setup_post("2009-06-22-no-yaml.textile")
assert_equal "No YAML.", post.content assert_equal "No YAML.", post.content
@ -290,6 +369,21 @@ class TestPost < Test::Unit::TestCase
assert_equal "<<< <hr />\n<p>Tom Preston-Werner github.com/mojombo</p>\n\n<p>This <em>is</em> cool</p> >>>", post.output assert_equal "<<< <hr />\n<p>Tom Preston-Werner github.com/mojombo</p>\n\n<p>This <em>is</em> cool</p> >>>", post.output
end end
should "render date specified in front matter properly" do
post = setup_post("2010-01-09-date-override.textile")
do_render(post)
assert_equal "<p>Post with a front matter date</p>\n<p>10 Jan 2010</p>", post.output
end
should "render time specified in front matter properly" do
post = setup_post("2010-01-09-time-override.textile")
do_render(post)
assert_equal "<p>Post with a front matter time</p>\n<p>10 Jan 2010</p>", post.output
end
end end
end end

View File

@ -19,11 +19,77 @@ class TestSite < Test::Unit::TestCase
before_posts = @site.posts.length before_posts = @site.posts.length
before_layouts = @site.layouts.length before_layouts = @site.layouts.length
before_categories = @site.categories.length before_categories = @site.categories.length
before_tags = @site.tags.length
before_pages = @site.pages.length
before_static_files = @site.static_files.length
before_time = @site.time
@site.process @site.process
assert_equal before_posts, @site.posts.length assert_equal before_posts, @site.posts.length
assert_equal before_layouts, @site.layouts.length assert_equal before_layouts, @site.layouts.length
assert_equal before_categories, @site.categories.length assert_equal before_categories, @site.categories.length
assert_equal before_tags, @site.tags.length
assert_equal before_pages, @site.pages.length
assert_equal before_static_files, @site.static_files.length
assert before_time <= @site.time
end
should "write only modified static files" do
clear_dest
StaticFile.reset_cache
@site.process
some_static_file = @site.static_files[0].path
dest = File.expand_path(@site.static_files[0].destination(@site.dest))
mtime1 = File.stat(dest).mtime.to_i # first run must generate dest file
# need to sleep because filesystem timestamps have best resolution in seconds
sleep 1
@site.process
mtime2 = File.stat(dest).mtime.to_i
assert_equal mtime1, mtime2
# simulate file modification by user
FileUtils.touch some_static_file
sleep 1
@site.process
mtime3 = File.stat(dest).mtime.to_i
assert_not_equal mtime2, mtime3 # must be regenerated!
sleep 1
@site.process
mtime4 = File.stat(dest).mtime.to_i
assert_equal mtime3, mtime4 # no modifications, so must be the same
end
should "write static files if not modified but missing in destination" do
clear_dest
StaticFile.reset_cache
@site.process
some_static_file = @site.static_files[0].path
dest = File.expand_path(@site.static_files[0].destination(@site.dest))
mtime1 = File.stat(dest).mtime.to_i # first run must generate dest file
# need to sleep because filesystem timestamps have best resolution in seconds
sleep 1
@site.process
mtime2 = File.stat(dest).mtime.to_i
assert_equal mtime1, mtime2
# simulate destination file deletion
File.unlink dest
sleep 1
@site.process
mtime3 = File.stat(dest).mtime.to_i
assert_not_equal mtime2, mtime3 # must be regenerated and differ!
sleep 1
@site.process
mtime4 = File.stat(dest).mtime.to_i
assert_equal mtime3, mtime4 # no modifications, so must be the same
end end
should "read layouts" do should "read layouts" do
@ -52,10 +118,10 @@ class TestSite < Test::Unit::TestCase
should "filter entries" do should "filter entries" do
ent1 = %w[foo.markdown bar.markdown baz.markdown #baz.markdown# ent1 = %w[foo.markdown bar.markdown baz.markdown #baz.markdown#
.baz.markdow foo.markdown~] .baz.markdow foo.markdown~]
ent2 = %w[.htaccess _posts bla.bla] ent2 = %w[.htaccess _posts _pages bla.bla]
assert_equal %w[foo.markdown bar.markdown baz.markdown], @site.filter_entries(ent1) assert_equal %w[foo.markdown bar.markdown baz.markdown], @site.filter_entries(ent1)
assert_equal ent2, @site.filter_entries(ent2) assert_equal %w[.htaccess bla.bla], @site.filter_entries(ent2)
end end
should "filter entries with exclude" do should "filter entries with exclude" do

View File

@ -2,26 +2,18 @@ require File.dirname(__FILE__) + '/helper'
class TestTags < Test::Unit::TestCase class TestTags < Test::Unit::TestCase
def create_post(content, override = {}, markdown = true) def create_post(content, override = {}, converter_class = Jekyll::MarkdownConverter)
stub(Jekyll).configuration do stub(Jekyll).configuration do
Jekyll::DEFAULTS.merge({'pygments' => true}).merge(override) Jekyll::DEFAULTS.merge({'pygments' => true}).merge(override)
end end
site = Site.new(Jekyll.configuration) site = Site.new(Jekyll.configuration)
info = { :filters => [Jekyll::Filters], :registers => { :site => site } } info = { :filters => [Jekyll::Filters], :registers => { :site => site } }
@converter = site.converters.find { |c| c.class == converter_class }
if markdown payload = { "pygments_prefix" => @converter.pygments_prefix,
payload = {"content_type" => "markdown"} "pygments_suffix" => @converter.pygments_suffix }
else
payload = {"content_type" => "textile"}
end
@result = Liquid::Template.parse(content).render(payload, info) @result = Liquid::Template.parse(content).render(payload, info)
@result = @converter.convert(@result)
if markdown
@result = site.markdown(@result)
else
@result = site.textile(@result)
end
end end
def fill_post(code, override = {}) def fill_post(code, override = {})
@ -49,7 +41,7 @@ CONTENT
end end
should "render markdown with pygments line handling" do should "render markdown with pygments line handling" do
assert_match %{<pre>test\n</pre>}, @result assert_match %{<pre><code class='text'>test\n</code></pre>}, @result
end end
end end
@ -59,7 +51,7 @@ CONTENT
end end
should "render markdown with pygments line handling" do should "render markdown with pygments line handling" do
assert_match %{<pre>Æ\n</pre>}, @result assert_match %{<pre><code class='text'>Æ\n</code></pre>}, @result
end end
end end
@ -82,7 +74,7 @@ CONTENT
context "using Textile" do context "using Textile" do
setup do setup do
create_post(@content, {}, false) create_post(@content, {}, Jekyll::TextileConverter)
end end
# Broken in RedCloth 4.1.9 # Broken in RedCloth 4.1.9