git merge mojombo/master
This commit is contained in:
commit
46a95bc036
142
History.txt
142
History.txt
|
@ -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
|
||||
* Bug Fixes
|
||||
* Do not allow symlinks (security vulnerability)
|
||||
|
||||
== 0.5.3 / 2009-07-14
|
||||
* 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
|
||||
* Enhancements
|
||||
* Added --paginate option to the executable along with a paginator object for the payload [github.com/calavera]
|
||||
* Upgraded RedCloth to 4.2.1, which makes <notextile> tags work once 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]
|
||||
* Added --paginate option to the executable along with a paginator object
|
||||
for the payload [github.com/calavera]
|
||||
* Upgraded RedCloth to 4.2.1, which makes <notextile> tags work once
|
||||
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
|
||||
* 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]
|
||||
* Made pages respect permalinks style and permalinks in yml front matter [github.com/eugenebolshakov]
|
||||
* Index.html file should always have index.html permalink [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]
|
||||
* Made pages respect permalinks style and permalinks in yml front matter
|
||||
[github.com/eugenebolshakov]
|
||||
* Index.html file should always have index.html permalink
|
||||
[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]
|
||||
* Added Date#xmlschema for Ruby versions < 1.9
|
||||
|
||||
== 0.5.1 / 2009-05-06
|
||||
* 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
|
||||
* 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
|
||||
* Making sure config.yaml references are all gone, using only config.yml
|
||||
* 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]
|
||||
|
||||
== 0.5.0 / 2009-04-07
|
||||
* Minor Enhancements
|
||||
* 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 'pretty' permalink style for wordpress-like urls [github.com/dysinger]
|
||||
* Made it possible to enter categories from YAML as an array [github.com/Chrononaut]
|
||||
* Add 'pretty' permalink style for wordpress-like urls
|
||||
[github.com/dysinger]
|
||||
* Made it possible to enter categories from YAML as an array
|
||||
[github.com/Chrononaut]
|
||||
* Ignore Emacs autosave files [github.com/Chrononaut]
|
||||
* 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]
|
||||
* 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
|
||||
* Factored the filtering code into a method [github.com/Chrononaut]
|
||||
* Fix tests and convert to Shoulda [github.com/qrush, github.com/technicalpickles]
|
||||
* Add Cucumber acceptance test suite [github.com/qrush, github.com/technicalpickles]
|
||||
* Fix tests and convert to Shoulda [github.com/qrush,
|
||||
github.com/technicalpickles]
|
||||
* Add Cucumber acceptance test suite [github.com/qrush,
|
||||
github.com/technicalpickles]
|
||||
|
||||
== 0.4.1
|
||||
* Minor Enhancements
|
||||
* Changed date format on wordpress converter (zeropadding) [github.com/dysinger]
|
||||
* Changed date format on wordpress converter (zeropadding)
|
||||
[github.com/dysinger]
|
||||
* Bug Fixes
|
||||
* Add jekyll binary as executable to gemspec [github.com/dysinger]
|
||||
|
||||
|
@ -67,28 +140,35 @@
|
|||
* Add array_to_sentence_string filter [github.com/mchung]
|
||||
* Add a converter for textpattern [github.com/PerfectlyNormal]
|
||||
* 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 line number capabilities to highlight blocks [github.com/jcon]
|
||||
* Bug Fixes
|
||||
* 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]
|
||||
* Test and fix the site.categories hash [github.com/zzot]
|
||||
* Fix site payload available to files [github.com/matrix9180]
|
||||
|
||||
== 0.3.0 / 2008-12-24
|
||||
* Major Enhancements
|
||||
* Added --server option to start a simple WEBrick server on destination directory [github.com/johnreilly and github.com/mchung]
|
||||
* Added --server option to start a simple WEBrick server on destination
|
||||
directory [github.com/johnreilly and github.com/mchung]
|
||||
* Minor Enhancements
|
||||
* Added post categories based on directories containing _posts [github.com/mreid]
|
||||
* Added post categories based on directories containing _posts
|
||||
[github.com/mreid]
|
||||
* Added post topics based on directories underneath _posts
|
||||
* Added new date filter that shows the full month name [github.com/mreid]
|
||||
* Merge Post's YAML front matter into its to_liquid payload [github.com/remi]
|
||||
* Merge Post's YAML front matter into its to_liquid payload
|
||||
[github.com/remi]
|
||||
* Restrict includes to regular files underneath _includes
|
||||
* Bug Fixes
|
||||
* Change YAML delimiter matcher so as to not chew up 2nd level markdown headers [github.com/mreid]
|
||||
* Fix bug that meant page data (such as the date) was not available in templates [github.com/mreid]
|
||||
* Change YAML delimiter matcher so as to not chew up 2nd level markdown
|
||||
headers [github.com/mreid]
|
||||
* Fix bug that meant page data (such as the date) was not available in
|
||||
templates [github.com/mreid]
|
||||
* Properly reject directories in _layouts
|
||||
|
||||
== 0.2.1 / 2008-12-15
|
||||
|
@ -111,9 +191,11 @@
|
|||
* Code highlighting with Pygments if --pygments is specified
|
||||
* Disable true LSI by default, enable with --lsi
|
||||
* 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
|
||||
* 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]
|
||||
|
||||
== 0.1.4 / 2008-12-08
|
||||
|
|
|
@ -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.
|
|
@ -20,23 +20,22 @@ h2. Diving In
|
|||
* 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
|
||||
|
||||
h2. Dependencies
|
||||
h2. Runtime Dependencies
|
||||
|
||||
* RedCloth: Textile support
|
||||
* Liquid: Templating system
|
||||
* Classifier: Generating related posts
|
||||
* Maruku: Default markdown engine
|
||||
* Directory Watcher: Auto-regeneration of sites
|
||||
* Open4: Talking to pygments for syntax highlighting
|
||||
* RedCloth: Textile support (Ruby)
|
||||
* Liquid: Templating system (Ruby)
|
||||
* Classifier: Generating related posts (Ruby)
|
||||
* Maruku: Default markdown engine (Ruby)
|
||||
* Directory Watcher: Auto-regeneration of sites (Ruby)
|
||||
* 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
|
||||
|
||||
(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.
|
||||
See LICENSE.
|
||||
|
|
178
Rakefile
178
Rakefile
|
@ -1,85 +1,101 @@
|
|||
require 'rubygems'
|
||||
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'
|
||||
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'
|
||||
|
||||
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|
|
||||
rdoc.rdoc_dir = 'rdoc'
|
||||
rdoc.title = 'jekyll'
|
||||
rdoc.options << '--line-numbers' << '--inline-source'
|
||||
rdoc.title = "#{name} #{version}"
|
||||
rdoc.rdoc_files.include('README*')
|
||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||
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"
|
||||
task :console do
|
||||
sh "irb -rubygems -I lib -r jekyll.rb"
|
||||
sh "irb -rubygems -r ./lib/#{name}.rb"
|
||||
end
|
||||
|
||||
# converters
|
||||
#############################################################################
|
||||
#
|
||||
# Custom tasks (add your own tasks here)
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
namespace :convert do
|
||||
namespace :migrate do
|
||||
desc "Migrate from mephisto in the current directory"
|
||||
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
|
||||
desc "Migrate from Movable Type in the current directory"
|
||||
task :mt do
|
||||
sh %q(ruby -r './lib/jekyll/converters/mt' -e 'Jekyll::MT.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")')
|
||||
sh %q(ruby -r './lib/jekyll/migrators/mt' -e 'Jekyll::MT.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")')
|
||||
end
|
||||
desc "Migrate from Typo in the current directory"
|
||||
task :typo do
|
||||
sh %q(ruby -r './lib/jekyll/converters/typo' -e 'Jekyll::Typo.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")')
|
||||
sh %q(ruby -r './lib/jekyll/migrators/typo' -e 'Jekyll::Typo.process("#{ENV["DB"]}", "#{ENV["USER"]}", "#{ENV["PASS"]}")')
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
require 'cucumber/rake/task'
|
||||
|
||||
Cucumber::Rake::Task.new(:features) do |t|
|
||||
t.cucumber_opts = "--format progress"
|
||||
end
|
||||
|
@ -89,3 +105,55 @@ rescue LoadError
|
|||
abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
|
||||
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
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
:patch: 4
|
||||
:major: 0
|
||||
:minor: 5
|
21
bin/jekyll
21
bin/jekyll
|
@ -23,6 +23,10 @@ options = {}
|
|||
opts = OptionParser.new do |opts|
|
||||
opts.banner = help
|
||||
|
||||
opts.on("--safe", "Safe mode (default unsafe)") do
|
||||
options['safe'] = true
|
||||
end
|
||||
|
||||
opts.on("--auto", "Auto-regenerate") do
|
||||
options['auto'] = true
|
||||
end
|
||||
|
@ -48,6 +52,18 @@ opts = OptionParser.new do |opts|
|
|||
options['markdown'] = 'rdiscount'
|
||||
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|
|
||||
options['permalink'] = style unless style.nil?
|
||||
end
|
||||
|
@ -63,7 +79,7 @@ opts = OptionParser.new do |opts|
|
|||
end
|
||||
|
||||
opts.on("--version", "Display current version") do
|
||||
puts "Jekyll " + Jekyll.version
|
||||
puts "Jekyll " + Jekyll::VERSION
|
||||
exit 0
|
||||
end
|
||||
end
|
||||
|
@ -139,6 +155,9 @@ if options['server']
|
|||
mime_types = WEBrick::HTTPUtils::DefaultMimeTypes
|
||||
mime_types.store 'js', 'application/javascript'
|
||||
|
||||
mime_types = WEBrick::HTTPUtils::DefaultMimeTypes
|
||||
mime_types.store 'js', 'application/javascript'
|
||||
|
||||
s = HTTPServer.new(
|
||||
:Port => options['server_port'],
|
||||
:DocumentRoot => destination,
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
default: --format progress
|
|
@ -29,7 +29,7 @@ Feature: Create sites
|
|||
Scenario: Basic site with layout and a post
|
||||
Given I have a _layouts directory
|
||||
And I have a _posts directory
|
||||
And I have the following post:
|
||||
And I have the following posts:
|
||||
| title | date | layout | content |
|
||||
| Wargames | 3/27/2009 | default | The only winning move is not to play. |
|
||||
And I have a default layout that contains "Post Layout: {{ content }}"
|
||||
|
@ -37,6 +37,36 @@ Feature: Create sites
|
|||
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"
|
||||
|
||||
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
|
||||
Given I have a _includes directory
|
||||
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
|
||||
Then the _site directory should exist
|
||||
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"
|
|
@ -20,7 +20,7 @@ Feature: Embed filters
|
|||
And I have the following post:
|
||||
| title | date | layout | content |
|
||||
| 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
|
||||
Then the _site directory should exist
|
||||
And I should see "Star & Wars" in "_site/2009/03/27/star-wars.html"
|
||||
|
@ -31,7 +31,7 @@ Feature: Embed filters
|
|||
And I have the following post:
|
||||
| title | date | layout | content |
|
||||
| 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
|
||||
Then the _site directory should exist
|
||||
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:
|
||||
| title | date | layout | tags | content |
|
||||
| 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
|
||||
Then the _site directory should exist
|
||||
And I should see "scifi, movies, and force" in "_site/2009/03/27/star-wars.html"
|
||||
|
|
|
@ -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"
|
||||
|
|
@ -6,35 +6,22 @@ Feature: Site pagination
|
|||
Scenario Outline: Paginate with N posts per page
|
||||
Given I have a configuration file with "paginate" set to "<num>"
|
||||
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 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. |
|
||||
| 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
|
||||
Then the _site/page2 directory should exist
|
||||
And the _site/page2/index.html file should exist
|
||||
|
||||
Then the _site/page<exist> directory 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:
|
||||
| num |
|
||||
| 1 |
|
||||
| 2 |
|
||||
|
||||
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"
|
||||
|
||||
| num | exist | posts | not_exist |
|
||||
| 1 | 4 | 1 | 5 |
|
||||
| 2 | 2 | 2 | 3 |
|
||||
| 3 | 2 | 1 | 3 |
|
||||
|
|
|
@ -9,7 +9,7 @@ Feature: Post data
|
|||
And I have the following post:
|
||||
| title | date | layout | content |
|
||||
| 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
|
||||
Then the _site directory should exist
|
||||
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:
|
||||
| title | date | layout | content |
|
||||
| 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
|
||||
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"
|
||||
|
@ -31,7 +31,7 @@ Feature: Post data
|
|||
And I have the following post:
|
||||
| title | date | layout | content |
|
||||
| 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
|
||||
Then the _site directory should exist
|
||||
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:
|
||||
| title | date | layout | content |
|
||||
| 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
|
||||
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"
|
||||
|
@ -53,7 +53,7 @@ Feature: Post data
|
|||
And I have the following post:
|
||||
| title | date | layout | content |
|
||||
| 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
|
||||
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"
|
||||
|
@ -65,7 +65,7 @@ Feature: Post data
|
|||
And I have the following post in "movies":
|
||||
| title | date | layout | content |
|
||||
| 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
|
||||
Then the _site directory should exist
|
||||
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:
|
||||
| title | date | layout | tag | content |
|
||||
| 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
|
||||
Then the _site directory should exist
|
||||
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
|
||||
Given I have a movies directory
|
||||
And I have a movies/scifi directory
|
||||
And I have a movies/scifi/_posts directory
|
||||
Given I have a scifi directory
|
||||
And I have a scifi/movies directory
|
||||
And I have a scifi/movies/_posts 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 |
|
||||
| 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
|
||||
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
|
||||
Given I have a _posts directory
|
||||
|
@ -100,7 +100,7 @@ Feature: Post data
|
|||
And I have the following post:
|
||||
| title | date | layout | category | content |
|
||||
| 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
|
||||
Then the _site directory should exist
|
||||
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 the following post:
|
||||
| title | date | layout | categories | content |
|
||||
| Star Wars | 3/27/2009 | simple | ['movies', 'scifi'] | Luke, I am your father. |
|
||||
And I have a simple layout that contains "Post categories: {{ site.posts.first.categories | array_to_sentence_string }}"
|
||||
| Star Wars | 3/27/2009 | simple | ['scifi', 'movies'] | Luke, I am your father. |
|
||||
And I have a simple layout that contains "Post categories: {{ page.categories | array_to_sentence_string }}"
|
||||
When I run jekyll
|
||||
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
|
||||
Given I have a _posts directory
|
||||
|
@ -133,7 +133,7 @@ Feature: Post data
|
|||
And I have the following post:
|
||||
| title | date | layout | author | content |
|
||||
| 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
|
||||
Then the _site directory should exist
|
||||
And I should see "Post author: Darth Vader" in "_site/2009/03/27/star-wars.html"
|
||||
|
|
|
@ -33,7 +33,7 @@ Feature: Site configuration
|
|||
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 a configuration file with "exclude" set to:
|
||||
| Value |
|
||||
| value |
|
||||
| README |
|
||||
| Rakefile |
|
||||
When I run jekyll
|
||||
|
@ -61,3 +61,43 @@ Feature: Site configuration
|
|||
When I run jekyll
|
||||
Then the _site directory should exist
|
||||
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"
|
||||
|
|
|
@ -13,7 +13,7 @@ Given /^I have a blank site in "(.*)"$/ do |path|
|
|||
end
|
||||
|
||||
# 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|
|
||||
f.write <<EOF
|
||||
---
|
||||
|
@ -25,7 +25,7 @@ EOF
|
|||
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|
|
||||
f.write(text)
|
||||
f.close
|
||||
|
@ -39,13 +39,13 @@ Given /^I have a (.*) layout that contains "(.*)"$/ do |layout, text|
|
|||
end
|
||||
end
|
||||
|
||||
Given /^I have a (.*) directory$/ do |dir|
|
||||
FileUtils.mkdir(dir)
|
||||
Given /^I have an? (.*) directory$/ do |dir|
|
||||
FileUtils.mkdir_p(dir)
|
||||
end
|
||||
|
||||
Given /^I have the following posts?(?: (.*) "(.*)")?:$/ do |direction, folder, table|
|
||||
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+/, '-')
|
||||
|
||||
if direction && direction == "in"
|
||||
|
@ -81,7 +81,16 @@ end
|
|||
|
||||
Given /^I have a configuration file with "(.*)" set to "(.*)"$/ do |key, value|
|
||||
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
|
||||
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|
|
||||
f.write("#{key}:\n")
|
||||
table.hashes.each do |row|
|
||||
f.write("- #{row["Value"]}\n")
|
||||
f.write("- #{row["value"]}\n")
|
||||
end
|
||||
f.close
|
||||
end
|
||||
|
@ -115,14 +124,14 @@ Then /^the (.*) directory should exist$/ do |dir|
|
|||
assert File.directory?(dir)
|
||||
end
|
||||
|
||||
Then /^the (.*) file should exist$/ do |file|
|
||||
assert File.file?(file)
|
||||
end
|
||||
|
||||
Then /^I should see "(.*)" in "(.*)"$/ do |text, file|
|
||||
assert_match Regexp.new(text), File.open(file).readlines.join
|
||||
end
|
||||
|
||||
Then /^the "(.*)" file should exist$/ do |file|
|
||||
assert File.file?(file)
|
||||
end
|
||||
|
||||
Then /^the "(.*)" file should not exist$/ do |file|
|
||||
assert !File.exists?(file)
|
||||
end
|
||||
|
|
248
jekyll.gemspec
248
jekyll.gemspec
|
@ -1,135 +1,127 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = %q{jekyll}
|
||||
s.version = "0.5.4"
|
||||
|
||||
s.specification_version = 2 if s.respond_to? :specification_version=
|
||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = ["Tom Preston-Werner"]
|
||||
s.date = %q{2009-08-24}
|
||||
s.default_executable = %q{jekyll}
|
||||
s.description = %q{Jekyll is a simple, blog aware, static site generator.}
|
||||
s.email = %q{tom@mojombo.com}
|
||||
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.email = 'tom@mojombo.com'
|
||||
s.homepage = 'http://github.com/mojombo/jekyll'
|
||||
|
||||
s.require_paths = %w[lib]
|
||||
|
||||
s.executables = ["jekyll"]
|
||||
s.extra_rdoc_files = [
|
||||
"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.default_executable = 'jekyll'
|
||||
|
||||
s.rdoc_options = ["--charset=UTF-8"]
|
||||
s.require_paths = ["lib"]
|
||||
s.rubyforge_project = %q{jekyll}
|
||||
s.rubygems_version = %q{1.3.5}
|
||||
s.summary = %q{Jekyll is a simple, blog aware, static site generator.}
|
||||
s.test_files = [
|
||||
"test/helper.rb",
|
||||
"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.extra_rdoc_files = %w[README.textile LICENSE]
|
||||
|
||||
s.add_runtime_dependency('RedCloth', [">= 4.2.1"])
|
||||
s.add_runtime_dependency('liquid', [">= 1.9.0"])
|
||||
s.add_runtime_dependency('classifier', [">= 1.3.1"])
|
||||
s.add_runtime_dependency('maruku', [">= 0.5.9"])
|
||||
s.add_runtime_dependency('directory_watcher', [">= 1.1.1"])
|
||||
|
||||
s.add_development_dependency('DEVDEPNAME', [">= 1.1.0", "< 2.0.0"])
|
||||
|
||||
# = MANIFEST =
|
||||
s.files = %w[
|
||||
History.txt
|
||||
README.textile
|
||||
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
|
||||
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
|
||||
s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
|
||||
end
|
||||
|
|
|
@ -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
|
||||
require 'rubygems'
|
||||
|
||||
# core
|
||||
# stdlib
|
||||
require 'fileutils'
|
||||
require 'time'
|
||||
require 'yaml'
|
||||
|
||||
# stdlib
|
||||
|
||||
# 3rd party
|
||||
require 'liquid'
|
||||
require 'redcloth'
|
||||
|
||||
# internal requires
|
||||
require 'jekyll/core_ext'
|
||||
require 'jekyll/pager'
|
||||
require 'jekyll/site'
|
||||
require 'jekyll/convertible'
|
||||
require 'jekyll/layout'
|
||||
require 'jekyll/page'
|
||||
require 'jekyll/post'
|
||||
require 'jekyll/filters'
|
||||
require 'jekyll/tags/highlight'
|
||||
require 'jekyll/tags/include'
|
||||
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
|
||||
VERSION = '0.5.7'
|
||||
|
||||
# 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 = {
|
||||
'safe' => false,
|
||||
'auto' => false,
|
||||
'server' => false,
|
||||
'server_port' => 4000,
|
||||
|
||||
'source' => Dir.pwd,
|
||||
'destination' => File.join('.', '_site'),
|
||||
'plugins' => File.join('.', '_plugins'),
|
||||
|
||||
'future' => true,
|
||||
'lsi' => false,
|
||||
'pygments' => false,
|
||||
'markdown' => 'maruku',
|
||||
|
@ -53,10 +74,13 @@ module Jekyll
|
|||
}
|
||||
|
||||
# Generate a Jekyll configuration Hash by merging the default options
|
||||
# with anything in _config.yml, and adding the given options on top
|
||||
# +override+ is a Hash of config directives
|
||||
# with anything in _config.yml, and adding the given options on top.
|
||||
#
|
||||
# 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)
|
||||
# _config.yml may override default source location, but until
|
||||
# then, we need to know where to look for _config.yml
|
||||
|
@ -67,19 +91,15 @@ module Jekyll
|
|||
begin
|
||||
config = YAML.load_file(config_file)
|
||||
raise "Invalid configuration - #{config_file}" if !config.is_a?(Hash)
|
||||
STDOUT.puts "Configuration from #{config_file}"
|
||||
$stdout.puts "Configuration from #{config_file}"
|
||||
rescue => err
|
||||
STDERR.puts "WARNING: Could not read configuration. Using defaults (and options)."
|
||||
STDERR.puts "\t" + err.to_s
|
||||
$stderr.puts "WARNING: Could not read configuration. " +
|
||||
"Using defaults (and options)."
|
||||
$stderr.puts "\t" + err.to_s
|
||||
config = {}
|
||||
end
|
||||
|
||||
# Merge DEFAULTS < _config.yml < override
|
||||
Jekyll::DEFAULTS.deep_merge(config).deep_merge(override)
|
||||
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
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
# Chris Wanstrath // chris@ozmm.org
|
||||
# GitHub // http://github.com
|
||||
#
|
||||
require 'open4'
|
||||
|
||||
class Albino
|
||||
@@bin = Rails.development? ? 'pygmentize' : '/usr/bin/pygmentize' rescue 'pygmentize'
|
||||
|
@ -61,11 +60,10 @@ class Albino
|
|||
|
||||
def execute(command)
|
||||
output = ''
|
||||
Open4.popen4(command) do |pid, stdin, stdout, stderr|
|
||||
stdin.puts @target
|
||||
stdin.close
|
||||
output = stdout.read.strip
|
||||
[stdout, stderr].each { |io| io.close }
|
||||
IO.popen(command, mode='r+') do |p|
|
||||
p.write @target
|
||||
p.close_write
|
||||
output = p.read.strip
|
||||
end
|
||||
output
|
||||
end
|
||||
|
@ -119,4 +117,4 @@ if $0 == __FILE__
|
|||
assert_equal @syntaxer.colorize, Albino.colorize(__FILE__, :ruby)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -3,6 +3,11 @@
|
|||
#
|
||||
# Requires
|
||||
# self.site -> Jekyll::Site
|
||||
# self.content
|
||||
# self.content=
|
||||
# self.data=
|
||||
# self.ext=
|
||||
# self.output=
|
||||
module Jekyll
|
||||
module Convertible
|
||||
# Return the contents as a string
|
||||
|
@ -17,42 +22,34 @@ module Jekyll
|
|||
# Returns nothing
|
||||
def read_yaml(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.data = YAML.load($1)
|
||||
end
|
||||
|
||||
|
||||
self.data ||= {}
|
||||
end
|
||||
|
||||
# Transform the contents based on the file extension.
|
||||
# Transform the contents based on the content type.
|
||||
#
|
||||
# Returns nothing
|
||||
def transform
|
||||
case self.content_type
|
||||
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
|
||||
self.content = converter.convert(self.content)
|
||||
end
|
||||
|
||||
# Determine which formatting engine to use based on this convertible's
|
||||
# extension
|
||||
# Determine the extension depending on content_type
|
||||
#
|
||||
# Returns one of :textile, :markdown or :unknown
|
||||
def content_type
|
||||
case self.ext[1..-1]
|
||||
when /textile/i
|
||||
return 'textile'
|
||||
when /markdown/i, /mkdn/i, /md/i
|
||||
return 'markdown'
|
||||
end
|
||||
return 'unknown'
|
||||
# Returns the extensions for the output file
|
||||
def output_ext
|
||||
converter.output_ext(self.ext)
|
||||
end
|
||||
|
||||
# Determine which converter to use based on this convertible's
|
||||
# extension
|
||||
def converter
|
||||
@converter ||= self.site.converters.find { |c| c.matches(self.ext) }
|
||||
end
|
||||
|
||||
# Add any necessary layouts to this convertible document
|
||||
|
@ -64,7 +61,8 @@ module Jekyll
|
|||
info = { :filters => [Jekyll::Filters], :registers => { :site => self.site } }
|
||||
|
||||
# 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.transform
|
||||
|
||||
|
|
|
@ -19,6 +19,28 @@ class Hash
|
|||
|
||||
target
|
||||
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
|
||||
|
||||
# Thanks, ActiveSupport!
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
module Jekyll
|
||||
|
||||
class Generator < Plugin
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -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
|
|
@ -1,6 +1,7 @@
|
|||
require 'rubygems'
|
||||
require 'sequel'
|
||||
require 'fileutils'
|
||||
require 'yaml'
|
||||
|
||||
# NOTE: This converter requires Sequel and the MySQL gems.
|
||||
# The MySQL gem can be difficult to install on OS X. Once you have MySQL
|
|
@ -3,8 +3,8 @@ module Jekyll
|
|||
class Page
|
||||
include Convertible
|
||||
|
||||
attr_accessor :site
|
||||
attr_accessor :name, :ext, :basename
|
||||
attr_accessor :site, :pager
|
||||
attr_accessor :name, :ext, :basename, :dir
|
||||
attr_accessor :data, :content, :output
|
||||
|
||||
# Initialize a new Page.
|
||||
|
@ -43,10 +43,10 @@ module Jekyll
|
|||
end
|
||||
|
||||
def template
|
||||
if self.site.permalink_style == :pretty && !index?
|
||||
"/:name/"
|
||||
if self.site.permalink_style == :pretty && !index? && html?
|
||||
"/:basename/"
|
||||
else
|
||||
"/:name.html"
|
||||
"/:basename:output_ext"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -57,7 +57,12 @@ module Jekyll
|
|||
def url
|
||||
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
|
||||
|
||||
# Extract information from the page filename
|
||||
|
@ -75,10 +80,20 @@ module Jekyll
|
|||
#
|
||||
# Returns nothing
|
||||
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)
|
||||
end
|
||||
|
||||
def to_liquid
|
||||
self.data.deep_merge({
|
||||
"url" => self.url,
|
||||
"content" => self.content })
|
||||
end
|
||||
|
||||
# Write the generated page file to the destination directory.
|
||||
# +dest_prefix+ is the String 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
|
||||
path = File.join(dest, CGI.unescape(self.url))
|
||||
if self.ext == '.html' && self.url[/\.html$/].nil?
|
||||
if self.url =~ /\/$/
|
||||
FileUtils.mkdir_p(path)
|
||||
path = File.join(path, "index.html")
|
||||
end
|
||||
|
@ -101,11 +116,17 @@ module Jekyll
|
|||
end
|
||||
end
|
||||
|
||||
private
|
||||
def inspect
|
||||
"#<Jekyll:Page @name=#{self.name.inspect}>"
|
||||
end
|
||||
|
||||
def index?
|
||||
basename == 'index'
|
||||
end
|
||||
def html?
|
||||
output_ext == '.html'
|
||||
end
|
||||
|
||||
def index?
|
||||
basename == 'index'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -18,12 +18,9 @@ module Jekyll
|
|||
name =~ MATCHER
|
||||
end
|
||||
|
||||
attr_accessor :site, :date, :slug, :ext, :published, :data, :content, :output, :tags
|
||||
attr_writer :categories
|
||||
|
||||
def categories
|
||||
@categories ||= []
|
||||
end
|
||||
attr_accessor :site
|
||||
attr_accessor :data, :content, :output, :ext
|
||||
attr_accessor :date, :slug, :published, :tags, :categories
|
||||
|
||||
# Initialize this Post instance.
|
||||
# +site+ is the Site
|
||||
|
@ -41,32 +38,23 @@ module Jekyll
|
|||
self.process(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
|
||||
self.published = false
|
||||
else
|
||||
self.published = true
|
||||
end
|
||||
|
||||
if self.data.has_key?("tag")
|
||||
self.tags = [self.data["tag"]]
|
||||
elsif self.data.has_key?("tags")
|
||||
self.tags = self.data['tags']
|
||||
else
|
||||
self.tags = []
|
||||
end
|
||||
self.tags = self.data.pluralized_array("tag", "tags")
|
||||
|
||||
if self.categories.empty?
|
||||
if self.data.has_key?('category')
|
||||
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
|
||||
self.categories = self.data.pluralized_array('category', 'categories')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -136,9 +124,12 @@ module Jekyll
|
|||
"month" => date.strftime("%m"),
|
||||
"day" => date.strftime("%d"),
|
||||
"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|
|
||||
result.gsub(/:#{token.first}/, token.last)
|
||||
result.gsub(/:#{Regexp.escape token.first}/, token.last)
|
||||
}.gsub(/\/\//, "/")
|
||||
end
|
||||
|
||||
|
@ -179,12 +170,10 @@ module Jekyll
|
|||
# Returns nothing
|
||||
def render(layouts, site_payload)
|
||||
# construct payload
|
||||
payload =
|
||||
{
|
||||
payload = {
|
||||
"site" => { "related_posts" => related_posts(site_payload["site"]["posts"]) },
|
||||
"page" => self.to_liquid
|
||||
}
|
||||
payload = payload.deep_merge(site_payload)
|
||||
}.deep_merge(site_payload)
|
||||
|
||||
do_layout(payload, layouts)
|
||||
end
|
||||
|
@ -213,7 +202,8 @@ module Jekyll
|
|||
#
|
||||
# Returns <Hash>
|
||||
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,
|
||||
"date" => self.date,
|
||||
"id" => self.id,
|
||||
|
@ -221,7 +211,7 @@ module Jekyll
|
|||
"next" => self.next,
|
||||
"previous" => self.previous,
|
||||
"tags" => self.tags,
|
||||
"content" => self.content }.deep_merge(self.data)
|
||||
"content" => self.content })
|
||||
end
|
||||
|
||||
def inspect
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
module Jekyll
|
||||
|
||||
class Site
|
||||
attr_accessor :config, :layouts, :posts, :categories, :exclude,
|
||||
:source, :dest, :lsi, :pygments, :permalink_style, :tags
|
||||
attr_accessor :config, :layouts, :posts, :pages, :static_files,
|
||||
:categories, :exclude, :source, :dest, :lsi, :pygments,
|
||||
:permalink_style, :tags, :time, :future, :safe, :plugins
|
||||
attr_accessor :converters, :generators
|
||||
|
||||
# Initialize the site
|
||||
# +config+ is a Hash containing site configurations details
|
||||
|
@ -11,97 +13,79 @@ module Jekyll
|
|||
def initialize(config)
|
||||
self.config = config.clone
|
||||
|
||||
self.source = config['source']
|
||||
self.safe = config['safe']
|
||||
self.source = File.expand_path(config['source'])
|
||||
self.dest = config['destination']
|
||||
self.plugins = File.expand_path(config['plugins'])
|
||||
self.lsi = config['lsi']
|
||||
self.pygments = config['pygments']
|
||||
self.permalink_style = config['permalink'].to_sym
|
||||
self.exclude = config['exclude'] || []
|
||||
self.future = config['future']
|
||||
|
||||
self.reset
|
||||
self.setup
|
||||
end
|
||||
|
||||
def reset
|
||||
self.time = Time.parse(self.config['time'].to_s) || Time.now
|
||||
self.layouts = {}
|
||||
self.posts = []
|
||||
self.pages = []
|
||||
self.static_files = []
|
||||
self.categories = Hash.new { |hash, key| hash[key] = [] }
|
||||
self.tags = Hash.new { |hash, key| hash[key] = [] }
|
||||
end
|
||||
|
||||
def setup
|
||||
# Check to see if LSI is enabled.
|
||||
require 'classifier' if self.lsi
|
||||
|
||||
# Set the Markdown interpreter (and Maruku self.config, if necessary)
|
||||
case self.config['markdown']
|
||||
when 'rdiscount'
|
||||
begin
|
||||
require 'rdiscount'
|
||||
# If safe mode is off, load in any ruby files under the plugins
|
||||
# directory.
|
||||
unless self.safe
|
||||
Dir[File.join(self.plugins, "**/*.rb")].each do |f|
|
||||
require f
|
||||
end
|
||||
end
|
||||
|
||||
def markdown(content)
|
||||
RDiscount.new(content).to_html
|
||||
end
|
||||
self.converters = Jekyll::Converter.subclasses.select do |c|
|
||||
!self.safe || c.safe
|
||||
end.map do |c|
|
||||
c.new(self.config)
|
||||
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'?"
|
||||
self.generators = Jekyll::Generator.subclasses.select do |c|
|
||||
!self.safe || c.safe
|
||||
end.map do |c|
|
||||
c.new(self.config)
|
||||
end
|
||||
end
|
||||
|
||||
def textile(content)
|
||||
RedCloth.new(content).to_html
|
||||
end
|
||||
|
||||
# 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
|
||||
def process
|
||||
self.reset
|
||||
self.read_layouts
|
||||
self.transform_pages
|
||||
self.write_posts
|
||||
self.read
|
||||
self.generate
|
||||
self.render
|
||||
self.write
|
||||
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
|
||||
def read_layouts
|
||||
base = File.join(self.source, "_layouts")
|
||||
def read_layouts(dir = '')
|
||||
base = File.join(self.source, dir, "_layouts")
|
||||
return unless File.exists?(base)
|
||||
entries = []
|
||||
Dir.chdir(base) { entries = filter_entries(Dir['*.*']) }
|
||||
|
||||
|
@ -109,24 +93,23 @@ module Jekyll
|
|||
name = f.split(".")[0..-2].join(".")
|
||||
self.layouts[name] = Layout.new(self, base, f)
|
||||
end
|
||||
rescue Errno::ENOENT => e
|
||||
# ignore missing layout dir
|
||||
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
|
||||
def read_posts(dir)
|
||||
base = File.join(self.source, dir, '_posts')
|
||||
entries = []
|
||||
Dir.chdir(base) { entries = filter_entries(Dir['**/*']) }
|
||||
return unless File.exists?(base)
|
||||
entries = Dir.chdir(base) { filter_entries(Dir['**/*']) }
|
||||
|
||||
# first pass processes, but does not yet render post content
|
||||
entries.each do |f|
|
||||
if Post.valid?(f)
|
||||
post = Post.new(self, self.source, dir, f)
|
||||
|
||||
if post.published
|
||||
if post.published && (self.future || post.date <= self.time)
|
||||
self.posts << post
|
||||
post.categories.each { |c| self.categories[c] << post }
|
||||
post.tags.each { |c| self.tags[c] << post }
|
||||
|
@ -135,68 +118,70 @@ module Jekyll
|
|||
end
|
||||
|
||||
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|
|
||||
post.render(self.layouts, site_payload)
|
||||
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.tags.values.map { |ps| ps.sort! { |a, b| b <=> a} }
|
||||
rescue Errno::ENOENT => e
|
||||
# ignore missing layout dir
|
||||
end
|
||||
|
||||
# Write each post to <dest>/<year>/<month>/<day>/<slug>
|
||||
# Write static files, pages and posts
|
||||
#
|
||||
# Returns nothing
|
||||
def write_posts
|
||||
def write
|
||||
self.posts.each do |post|
|
||||
post.write(self.dest)
|
||||
end
|
||||
self.pages.each do |page|
|
||||
page.write(self.dest)
|
||||
end
|
||||
self.static_files.each do |sf|
|
||||
sf.write(self.dest)
|
||||
end
|
||||
end
|
||||
|
||||
# Copy all regular files from <source> to <dest>/ ignoring
|
||||
# any files/directories that are hidden or backup files (start
|
||||
# with "." or "#" or end with "~") or contain site content (start with "_")
|
||||
# unless they are "_posts" directories or web server files such as
|
||||
# '.htaccess'
|
||||
# Reads the directories and finds posts, pages and static files that will
|
||||
# become part of the valid site according to the rules in +filter_entries+.
|
||||
# The +dir+ String is a relative path used to call this method
|
||||
# recursively as it descends through directories
|
||||
#
|
||||
# Returns nothing
|
||||
def transform_pages(dir = '')
|
||||
def read_directories(dir = '')
|
||||
base = File.join(self.source, dir)
|
||||
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
|
||||
# might not be available yet to other templates as {{ site.posts }}
|
||||
if directories.include?('_posts')
|
||||
directories.delete('_posts')
|
||||
read_posts(dir)
|
||||
end
|
||||
self.read_posts(dir)
|
||||
|
||||
[directories, files].each do |entries|
|
||||
entries.each do |f|
|
||||
if File.directory?(File.join(base, f))
|
||||
next if self.dest.sub(/\/$/, '') == File.join(base, f)
|
||||
transform_pages(File.join(dir, f))
|
||||
elsif Pager.pagination_enabled?(self.config, f)
|
||||
paginate_posts(f, dir)
|
||||
entries.each do |f|
|
||||
f_abs = File.join(base, f)
|
||||
f_rel = File.join(dir, f)
|
||||
if File.directory?(f_abs)
|
||||
next if self.dest.sub(/\/$/, '') == f_abs
|
||||
read_directories(f_rel)
|
||||
elsif !File.symlink?(f_abs)
|
||||
first3 = File.open(f_abs) { |fd| fd.read(3) }
|
||||
if first3 == "---"
|
||||
# file appears to have a YAML header so process it as a page
|
||||
pages << Page.new(self, self.source, dir, f)
|
||||
else
|
||||
first3 = File.open(File.join(self.source, dir, f)) { |fd| fd.read(3) }
|
||||
if first3 == "---"
|
||||
# file appears to have a YAML header so process it as a page
|
||||
page = Page.new(self, self.source, dir, f)
|
||||
page.render(self.layouts, site_payload)
|
||||
page.write(self.dest)
|
||||
else
|
||||
# otherwise copy the file without transforming it
|
||||
FileUtils.mkdir_p(File.join(self.dest, dir))
|
||||
FileUtils.cp(File.join(self.source, dir, f), File.join(self.dest, dir, f))
|
||||
end
|
||||
# otherwise treat it as a static file
|
||||
static_files << StaticFile.new(self, self.source, dir, f)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -218,48 +203,29 @@ module Jekyll
|
|||
#
|
||||
# Returns {"site" => {"time" => <Time>,
|
||||
# "posts" => [<Post>],
|
||||
# "pages" => [<Page>],
|
||||
# "categories" => [<Post>]}
|
||||
def site_payload
|
||||
{"site" => self.config.merge({
|
||||
"time" => Time.now,
|
||||
"time" => self.time,
|
||||
"posts" => self.posts.sort { |a,b| b <=> a },
|
||||
"pages" => self.pages,
|
||||
"html_pages" => self.pages.reject { |page| !page.html? },
|
||||
"categories" => post_attr_hash('categories'),
|
||||
"tags" => post_attr_hash('tags')})}
|
||||
end
|
||||
|
||||
# Filter out any files/directories that are hidden or backup files (start
|
||||
# with "." or "#" or end with "~") or contain site content (start with "_")
|
||||
# unless they are "_posts" directories or web server files such as
|
||||
# '.htaccess'
|
||||
# with "." or "#" or end with "~"), or contain site content (start with "_"),
|
||||
# or are excluded in the site configuration, unless they are web server
|
||||
# files such as '.htaccess'
|
||||
def filter_entries(entries)
|
||||
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)
|
||||
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
|
||||
|
|
|
@ -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
|
|
@ -4,15 +4,28 @@ module Jekyll
|
|||
include Liquid::StandardFilters
|
||||
|
||||
# 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)
|
||||
super
|
||||
if markup =~ SYNTAX
|
||||
@lang = $1
|
||||
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.
|
||||
@options = { 'O' => 'linenos=inline' }
|
||||
@options = { 'O' => tmp_options.join(',') }
|
||||
else
|
||||
@options = {}
|
||||
end
|
||||
|
@ -23,21 +36,17 @@ module Jekyll
|
|||
|
||||
def render(context)
|
||||
if context.registers[:site].pygments
|
||||
output = render_pygments(context, super.to_s)
|
||||
render_pygments(context, super.join)
|
||||
else
|
||||
output = render_codehighlighter(context, super.to_s)
|
||||
render_codehighlighter(context, super.join)
|
||||
end
|
||||
output
|
||||
end
|
||||
|
||||
def render_pygments(context, code)
|
||||
if context["content_type"] == "markdown"
|
||||
return "\n" + Albino.new(code, @lang).to_s(@options) + "\n"
|
||||
elsif context["content_type"] == "textile"
|
||||
return "<notextile>" + Albino.new(code, @lang).to_s(@options) + "</notextile>"
|
||||
else
|
||||
return Albino.new(code, @lang).to_s(@options)
|
||||
end
|
||||
output = add_code_tags(Albino.new(code, @lang).to_s(@options), @lang)
|
||||
output = context["pygments_prefix"] + output if context["pygments_prefix"]
|
||||
output = output + context["pygments_suffix"] if context["pygments_suffix"]
|
||||
output
|
||||
end
|
||||
|
||||
def render_codehighlighter(context, code)
|
||||
|
@ -50,6 +59,13 @@ module Jekyll
|
|||
</div>
|
||||
HTML
|
||||
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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
require 'rubygems'
|
||||
gem 'RedCloth', '= 4.2.1'
|
||||
gem 'RedCloth', '>= 4.2.1'
|
||||
|
||||
require File.join(File.dirname(__FILE__), *%w[.. lib jekyll])
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
layout: default
|
||||
title: Category in YAML
|
||||
categories:
|
||||
---
|
||||
|
||||
Best *post* ever
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
layout: default
|
||||
title: Category in YAML
|
||||
category:
|
||||
---
|
||||
|
||||
Best *post* ever
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: A Tag
|
||||
tag:
|
||||
---
|
||||
|
||||
Whoa.
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Some Tags
|
||||
tags:
|
||||
---
|
||||
|
||||
Awesome!
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Foo --- Bar
|
||||
---
|
||||
|
||||
Triple the fun!
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
date: 2010-01-10
|
||||
---
|
||||
|
||||
Post with a front matter date
|
||||
|
||||
{{ page.date | date_to_string }}
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
date: 2010-01-10 13:07:09
|
||||
---
|
||||
|
||||
Post with a front matter time
|
||||
|
||||
{{ page.date | date_to_string }}
|
|
@ -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 }}
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
date: 2010-01-10 13:07:09
|
||||
tags: A string
|
||||
---
|
|
@ -2,22 +2,31 @@
|
|||
layout: nil
|
||||
---
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
|
||||
<urlset
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
|
||||
<url>
|
||||
<loc>http://example.com</loc>
|
||||
<lastmod>{{ site.time | date_to_xmlschema }}</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
|
||||
{% for post in site.posts %}
|
||||
<url>
|
||||
<loc>http://example.com/{{ post.url }}/</loc>
|
||||
<lastmod>{{ site.time }}</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.2</priority>
|
||||
</url>
|
||||
{% endfor %}
|
||||
</urlset>
|
||||
<loc>http://example.com</loc>
|
||||
<lastmod>{{ site.time | date: "%Y-%m-%d" }}</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
|
||||
{% for post in site.posts %}
|
||||
<url>
|
||||
<loc>http://example.com{{ post.url }}/</loc>
|
||||
<lastmod>{{ post.date | date: "%Y-%m-%d" }}</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.2</priority>
|
||||
</url>
|
||||
{% 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>
|
||||
|
|
|
@ -8,21 +8,21 @@ class TestConfiguration < Test::Unit::TestCase
|
|||
|
||||
should "fire warning with no _config.yml" do
|
||||
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("\tNo such file or directory - #{@path}")
|
||||
mock($stderr).puts("WARNING: Could not read configuration. Using defaults (and options).")
|
||||
mock($stderr).puts("\tNo such file or directory - #{@path}")
|
||||
assert_equal Jekyll::DEFAULTS, Jekyll.configuration({})
|
||||
end
|
||||
|
||||
should "load configuration as hash" do
|
||||
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({})
|
||||
end
|
||||
|
||||
should "fire warning with bad config" do
|
||||
mock(YAML).load_file(@path) { Array.new }
|
||||
mock(STDERR).puts("WARNING: Could not read configuration. Using defaults (and options).")
|
||||
mock(STDERR).puts("\tInvalid configuration - #{@path}")
|
||||
mock($stderr).puts("WARNING: Could not read configuration. Using defaults (and options).")
|
||||
mock($stderr).puts("\tInvalid configuration - #{@path}")
|
||||
assert_equal Jekyll::DEFAULTS, Jekyll.configuration({})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
|
@ -13,6 +13,10 @@ class TestGeneratedSite < Test::Unit::TestCase
|
|||
@index = File.read(dest_dir('index.html'))
|
||||
end
|
||||
|
||||
should "ensure post count is as expected" do
|
||||
assert_equal 26, @site.posts.size
|
||||
end
|
||||
|
||||
should "insert site.posts into the index" do
|
||||
assert @index.include?("#{@site.posts.size} Posts")
|
||||
end
|
||||
|
|
|
@ -1,11 +1,38 @@
|
|||
require File.dirname(__FILE__) + '/helper'
|
||||
|
||||
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,
|
||||
'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
|
||||
stub(Jekyll).configuration do
|
||||
Jekyll::DEFAULTS.merge({
|
||||
'source' => source_dir,
|
||||
'destination' => dest_dir,
|
||||
'paginate' => 2
|
||||
})
|
||||
|
@ -13,35 +40,74 @@ class TestPager < Test::Unit::TestCase
|
|||
|
||||
@config = Jekyll.configuration
|
||||
@site = Site.new(@config)
|
||||
@posts = @site.read_posts('')
|
||||
@site.process
|
||||
@posts = @site.posts
|
||||
end
|
||||
|
||||
should "calculate number of pages" do
|
||||
assert_equal(2, Pager.calculate_pages(@posts, @config['paginate']))
|
||||
end
|
||||
|
||||
should "create first pager" do
|
||||
pager = Pager.new(@config, 1, @posts)
|
||||
assert_equal(@config['paginate'].to_i, pager.posts.size)
|
||||
assert_equal(2, 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(@posts.size - @config['paginate'].to_i, pager.posts.size)
|
||||
assert_equal(2, pager.total_pages)
|
||||
assert_equal(1, pager.previous_page)
|
||||
assert_nil(pager.next_page)
|
||||
end
|
||||
|
||||
should "not create third pager" do
|
||||
assert_raise(RuntimeError) { Pager.new(@config, 3, @posts) }
|
||||
end
|
||||
|
||||
should "report that pagination is enabled" do
|
||||
assert Pager.pagination_enabled?(@config, 'index.html')
|
||||
end
|
||||
|
||||
context "with 4 posts" do
|
||||
setup do
|
||||
@posts = @site.posts[1..4] # limit to 4
|
||||
end
|
||||
|
||||
should "create first pager" do
|
||||
pager = Pager.new(@config, 1, @posts)
|
||||
assert_equal(2, pager.posts.size)
|
||||
assert_equal(2, 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(2, pager.total_pages)
|
||||
assert_equal(1, pager.previous_page)
|
||||
assert_nil(pager.next_page)
|
||||
end
|
||||
|
||||
should "not create third pager" do
|
||||
assert_raise(RuntimeError) { Pager.new(@config, 3, @posts) }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
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
|
||||
|
|
|
@ -18,10 +18,10 @@ class TestPost < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
should "ensure valid posts are valid" do
|
||||
assert Post.valid?("2008-10-19-foo-bar.textile")
|
||||
assert Post.valid?("foo/bar/2008-10-19-foo-bar.textile")
|
||||
assert Post.valid?("2008-09-09-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")
|
||||
end
|
||||
|
||||
|
@ -31,24 +31,25 @@ class TestPost < Test::Unit::TestCase
|
|||
@post.site = @site
|
||||
|
||||
@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')
|
||||
end
|
||||
|
||||
should "keep date, title, and markup type" do
|
||||
@post.categories = []
|
||||
@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 ".textile", @post.ext
|
||||
assert_equal "/2008/10/19", @post.dir
|
||||
assert_equal "/2008/10/19/foo-bar", @post.id
|
||||
assert_equal "/2008/09/09", @post.dir
|
||||
assert_equal "/2008/09/09/foo-bar", @post.id
|
||||
end
|
||||
|
||||
should "create url based on date and title" do
|
||||
@post.categories = []
|
||||
@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
|
||||
|
||||
should "CGI escape urls" do
|
||||
|
@ -77,7 +78,19 @@ class TestPost < Test::Unit::TestCase
|
|||
@post.read_yaml(@source, @real_file)
|
||||
|
||||
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
|
||||
|
||||
|
@ -93,7 +106,7 @@ class TestPost < Test::Unit::TestCase
|
|||
|
||||
should "process the url correctly" do
|
||||
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
|
||||
|
||||
|
@ -105,7 +118,7 @@ class TestPost < Test::Unit::TestCase
|
|||
|
||||
should "process the url correctly" do
|
||||
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
|
||||
|
||||
|
@ -118,7 +131,7 @@ class TestPost < Test::Unit::TestCase
|
|||
|
||||
should "process the url correctly" do
|
||||
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
|
||||
|
||||
|
@ -142,7 +155,18 @@ class TestPost < Test::Unit::TestCase
|
|||
|
||||
should "process the url correctly" do
|
||||
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
|
||||
|
||||
|
@ -163,7 +187,7 @@ class TestPost < Test::Unit::TestCase
|
|||
@post.read_yaml(@source, @real_file)
|
||||
|
||||
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
|
||||
|
||||
should "transform textile" do
|
||||
|
@ -212,6 +236,41 @@ class TestPost < Test::Unit::TestCase
|
|||
assert_equal false, post.published
|
||||
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
|
||||
post = setup_post("2009-01-27-category.textile")
|
||||
assert post.categories.include?('foo')
|
||||
|
@ -224,6 +283,16 @@ class TestPost < Test::Unit::TestCase
|
|||
assert post.categories.include?('baz')
|
||||
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
|
||||
post = setup_post("2009-05-18-tag.textile")
|
||||
assert post.tags.include?('code')
|
||||
|
@ -236,6 +305,16 @@ class TestPost < Test::Unit::TestCase
|
|||
assert post.tags.include?('pizza')
|
||||
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
|
||||
post = setup_post("2009-06-22-no-yaml.textile")
|
||||
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
|
||||
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
|
||||
|
||||
|
|
|
@ -19,11 +19,77 @@ class TestSite < Test::Unit::TestCase
|
|||
before_posts = @site.posts.length
|
||||
before_layouts = @site.layouts.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
|
||||
assert_equal before_posts, @site.posts.length
|
||||
assert_equal before_layouts, @site.layouts.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
|
||||
|
||||
should "read layouts" do
|
||||
|
@ -52,10 +118,10 @@ class TestSite < Test::Unit::TestCase
|
|||
should "filter entries" do
|
||||
ent1 = %w[foo.markdown bar.markdown baz.markdown #baz.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 ent2, @site.filter_entries(ent2)
|
||||
assert_equal %w[.htaccess bla.bla], @site.filter_entries(ent2)
|
||||
end
|
||||
|
||||
should "filter entries with exclude" do
|
||||
|
|
|
@ -2,26 +2,18 @@ require File.dirname(__FILE__) + '/helper'
|
|||
|
||||
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
|
||||
Jekyll::DEFAULTS.merge({'pygments' => true}).merge(override)
|
||||
end
|
||||
site = Site.new(Jekyll.configuration)
|
||||
info = { :filters => [Jekyll::Filters], :registers => { :site => site } }
|
||||
|
||||
if markdown
|
||||
payload = {"content_type" => "markdown"}
|
||||
else
|
||||
payload = {"content_type" => "textile"}
|
||||
end
|
||||
@converter = site.converters.find { |c| c.class == converter_class }
|
||||
payload = { "pygments_prefix" => @converter.pygments_prefix,
|
||||
"pygments_suffix" => @converter.pygments_suffix }
|
||||
|
||||
@result = Liquid::Template.parse(content).render(payload, info)
|
||||
|
||||
if markdown
|
||||
@result = site.markdown(@result)
|
||||
else
|
||||
@result = site.textile(@result)
|
||||
end
|
||||
@result = @converter.convert(@result)
|
||||
end
|
||||
|
||||
def fill_post(code, override = {})
|
||||
|
@ -49,7 +41,7 @@ CONTENT
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
|
@ -59,7 +51,7 @@ CONTENT
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
|
@ -82,7 +74,7 @@ CONTENT
|
|||
|
||||
context "using Textile" do
|
||||
setup do
|
||||
create_post(@content, {}, false)
|
||||
create_post(@content, {}, Jekyll::TextileConverter)
|
||||
end
|
||||
|
||||
# Broken in RedCloth 4.1.9
|
||||
|
|
Loading…
Reference in New Issue